Re: [PATCH 1/1] Fix coding style of driver/staging/ccree/ssi_aead.c

2017-06-17 Thread Gilad Ben-Yossef
Hello Jhin-Ming,

Thank your for your patch!

On Fri, Jun 16, 2017 at 4:48 PM, Jhih-Ming Hunag  wrote:
> I fix some coding style errors/warnings of drivers/staging/ccree/ssi_aead.c.
> From
> total: 54 errors, 109 warnings, 2769 lines checked
> to
> total: 0 errors, 69 warnings, 2766 lines checked
>
> All of remaining warning are 'WARNING: line over 80 characters'.
> I think those can be accepted for readability.
>
> I am new to send kernel patch.
> If I did something wrong, please kindly tell me.

Unfortunately, in order to properly be able to review patches, one patch
must only fix or change a single thing a time.

For example, I've noticed your patch fixes many cases of wrong placement of
curly brackets in the code. If the patch would ONLY fix this error where ever it
is it would be fine!

However, your patch also fixes other style errors at the same time, making it
difficult to review, so unfortunately it has to be rejected as it is now.

Please feel free to send a series of patches each fixing a different style error
instead.

Thanks,
Gilad



> Thanks
>


-- 
Gilad Ben-Yossef
Chief Coffee Drinker

"If you take a class in large-scale robotics, can you end up in a
situation where the homework eats your dog?"
 -- Jean-Baptiste Queru


Re: [PATCH 1/1] Fix coding style of driver/staging/ccree/ssi_aead.c

2017-06-17 Thread Gilad Ben-Yossef
Hello Jhin-Ming,

Thank your for your patch!

On Fri, Jun 16, 2017 at 4:48 PM, Jhih-Ming Hunag  wrote:
> I fix some coding style errors/warnings of drivers/staging/ccree/ssi_aead.c.
> From
> total: 54 errors, 109 warnings, 2769 lines checked
> to
> total: 0 errors, 69 warnings, 2766 lines checked
>
> All of remaining warning are 'WARNING: line over 80 characters'.
> I think those can be accepted for readability.
>
> I am new to send kernel patch.
> If I did something wrong, please kindly tell me.

Unfortunately, in order to properly be able to review patches, one patch
must only fix or change a single thing a time.

For example, I've noticed your patch fixes many cases of wrong placement of
curly brackets in the code. If the patch would ONLY fix this error where ever it
is it would be fine!

However, your patch also fixes other style errors at the same time, making it
difficult to review, so unfortunately it has to be rejected as it is now.

Please feel free to send a series of patches each fixing a different style error
instead.

Thanks,
Gilad



> Thanks
>


-- 
Gilad Ben-Yossef
Chief Coffee Drinker

"If you take a class in large-scale robotics, can you end up in a
situation where the homework eats your dog?"
 -- Jean-Baptiste Queru


Re: [PATCH 2/5] soc: bcm: brcmstb: Add Kconfig entry point for power management

2017-06-17 Thread kbuild test robot
Hi Florian,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Florian-Fainelli/Broadcom-STB-S2-S3-S5-support-for-ARM-and-MIPS/20170618-091951
config: arm-multi_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm 

Note: the 
linux-review/Florian-Fainelli/Broadcom-STB-S2-S3-S5-support-for-ARM-and-MIPS/20170618-091951
 HEAD 353cf2b6363828f6d8a3139858d669f7098d9b69 builds fine.
  It only hurts bisectibility.

All errors (new ones prefixed by >>):

>> scripts/Makefile.modbuiltin:25: drivers/soc/bcm/brcmstb/pm/Makefile: No such 
>> file or directory
>> make[6]: *** No rule to make target 'drivers/soc/bcm/brcmstb/pm/Makefile'.
   make[6]: Failed to remake makefile 'drivers/soc/bcm/brcmstb/pm/Makefile'.
--
>> scripts/Makefile.build:44: drivers/soc/bcm/brcmstb/pm/Makefile: No such file 
>> or directory
>> make[6]: *** No rule to make target 'drivers/soc/bcm/brcmstb/pm/Makefile'.
   make[6]: Failed to remake makefile 'drivers/soc/bcm/brcmstb/pm/Makefile'.

vim +25 scripts/Makefile.modbuiltin

bc081dd6 Michal Marek 2009-12-07   9  
bc081dd6 Michal Marek 2009-12-07  10  -include include/config/auto.conf
bc081dd6 Michal Marek 2009-12-07  11  # tristate.conf sets tristate variables 
to uppercase 'Y' or 'M'
bc081dd6 Michal Marek 2009-12-07  12  # That way, we get the list of built-in 
modules in obj-Y
bc081dd6 Michal Marek 2009-12-07  13  -include include/config/tristate.conf
bc081dd6 Michal Marek 2009-12-07  14  
bc081dd6 Michal Marek 2009-12-07  15  include scripts/Kbuild.include
bc081dd6 Michal Marek 2009-12-07  16  
607b30fc Michal Marek 2010-06-10  17  ifneq ($(KBUILD_SRC),)
607b30fc Michal Marek 2010-06-10  18  # Create output directory if not already 
present
607b30fc Michal Marek 2010-06-10  19  _dummy := $(shell [ -d $(obj) ] || mkdir 
-p $(obj))
607b30fc Michal Marek 2010-06-10  20  endif
607b30fc Michal Marek 2010-06-10  21  
bc081dd6 Michal Marek 2009-12-07  22  # The filename Kbuild has precedence over 
Makefile
bc081dd6 Michal Marek 2009-12-07  23  kbuild-dir := $(if $(filter 
/%,$(src)),$(src),$(srctree)/$(src))
bc081dd6 Michal Marek 2009-12-07  24  kbuild-file := $(if $(wildcard 
$(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
bc081dd6 Michal Marek 2009-12-07 @25  include $(kbuild-file)
bc081dd6 Michal Marek 2009-12-07  26  
bc081dd6 Michal Marek 2009-12-07  27  include scripts/Makefile.lib
bc081dd6 Michal Marek 2009-12-07  28  __subdir-Y := $(patsubst 
%/,%,$(filter %/, $(obj-Y)))
bc081dd6 Michal Marek 2009-12-07  29  subdir-Y   += $(__subdir-Y)
bc081dd6 Michal Marek 2009-12-07  30  subdir-ym  := $(sort $(subdir-y) 
$(subdir-Y) $(subdir-m))
bc081dd6 Michal Marek 2009-12-07  31  subdir-ym  := $(addprefix 
$(obj)/,$(subdir-ym))
bc081dd6 Michal Marek 2009-12-07  32  obj-Y  := $(addprefix 
$(obj)/,$(obj-Y))
bc081dd6 Michal Marek 2009-12-07  33  

:: The code at line 25 was first introduced by commit
:: bc081dd6e9f622c73334dc465359168543ccaabf kbuild: generate modules.builtin

:: TO: Michal Marek 
:: CC: Michal Marek 

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH 2/5] soc: bcm: brcmstb: Add Kconfig entry point for power management

2017-06-17 Thread kbuild test robot
Hi Florian,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Florian-Fainelli/Broadcom-STB-S2-S3-S5-support-for-ARM-and-MIPS/20170618-091951
config: arm-multi_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm 

Note: the 
linux-review/Florian-Fainelli/Broadcom-STB-S2-S3-S5-support-for-ARM-and-MIPS/20170618-091951
 HEAD 353cf2b6363828f6d8a3139858d669f7098d9b69 builds fine.
  It only hurts bisectibility.

All errors (new ones prefixed by >>):

>> scripts/Makefile.modbuiltin:25: drivers/soc/bcm/brcmstb/pm/Makefile: No such 
>> file or directory
>> make[6]: *** No rule to make target 'drivers/soc/bcm/brcmstb/pm/Makefile'.
   make[6]: Failed to remake makefile 'drivers/soc/bcm/brcmstb/pm/Makefile'.
--
>> scripts/Makefile.build:44: drivers/soc/bcm/brcmstb/pm/Makefile: No such file 
>> or directory
>> make[6]: *** No rule to make target 'drivers/soc/bcm/brcmstb/pm/Makefile'.
   make[6]: Failed to remake makefile 'drivers/soc/bcm/brcmstb/pm/Makefile'.

vim +25 scripts/Makefile.modbuiltin

bc081dd6 Michal Marek 2009-12-07   9  
bc081dd6 Michal Marek 2009-12-07  10  -include include/config/auto.conf
bc081dd6 Michal Marek 2009-12-07  11  # tristate.conf sets tristate variables 
to uppercase 'Y' or 'M'
bc081dd6 Michal Marek 2009-12-07  12  # That way, we get the list of built-in 
modules in obj-Y
bc081dd6 Michal Marek 2009-12-07  13  -include include/config/tristate.conf
bc081dd6 Michal Marek 2009-12-07  14  
bc081dd6 Michal Marek 2009-12-07  15  include scripts/Kbuild.include
bc081dd6 Michal Marek 2009-12-07  16  
607b30fc Michal Marek 2010-06-10  17  ifneq ($(KBUILD_SRC),)
607b30fc Michal Marek 2010-06-10  18  # Create output directory if not already 
present
607b30fc Michal Marek 2010-06-10  19  _dummy := $(shell [ -d $(obj) ] || mkdir 
-p $(obj))
607b30fc Michal Marek 2010-06-10  20  endif
607b30fc Michal Marek 2010-06-10  21  
bc081dd6 Michal Marek 2009-12-07  22  # The filename Kbuild has precedence over 
Makefile
bc081dd6 Michal Marek 2009-12-07  23  kbuild-dir := $(if $(filter 
/%,$(src)),$(src),$(srctree)/$(src))
bc081dd6 Michal Marek 2009-12-07  24  kbuild-file := $(if $(wildcard 
$(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
bc081dd6 Michal Marek 2009-12-07 @25  include $(kbuild-file)
bc081dd6 Michal Marek 2009-12-07  26  
bc081dd6 Michal Marek 2009-12-07  27  include scripts/Makefile.lib
bc081dd6 Michal Marek 2009-12-07  28  __subdir-Y := $(patsubst 
%/,%,$(filter %/, $(obj-Y)))
bc081dd6 Michal Marek 2009-12-07  29  subdir-Y   += $(__subdir-Y)
bc081dd6 Michal Marek 2009-12-07  30  subdir-ym  := $(sort $(subdir-y) 
$(subdir-Y) $(subdir-m))
bc081dd6 Michal Marek 2009-12-07  31  subdir-ym  := $(addprefix 
$(obj)/,$(subdir-ym))
bc081dd6 Michal Marek 2009-12-07  32  obj-Y  := $(addprefix 
$(obj)/,$(obj-Y))
bc081dd6 Michal Marek 2009-12-07  33  

:: The code at line 25 was first introduced by commit
:: bc081dd6e9f622c73334dc465359168543ccaabf kbuild: generate modules.builtin

:: TO: Michal Marek 
:: CC: Michal Marek 

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [RFC PATCH 2/2] mm, fs: daxfile, an interface for byte-addressable updates to pmem

2017-06-17 Thread Andy Lutomirski
On Sat, Jun 17, 2017 at 8:15 PM, Dan Williams  wrote:
> On Sat, Jun 17, 2017 at 4:50 PM, Andy Lutomirski  wrote:
>> My other objection is that the syscall intentionally leaks a reference
>> to the file.  This means it needs overflow protection and it probably
>> shouldn't ever be allowed to use it without privilege.
>
> We only hold the one reference while S_DAXFILE is set, so I think the
> protection is there, and per Dave's original proposal this requires
> CAP_LINUX_IMMUTABLE.
>
>> Why can't the underlying issue be easily fixed, though?  Could
>> .page_mkwrite just make sure that metadata is synced when the FS uses
>> DAX?
>
> Yes, it most definitely could and that idea has been floated.
>
>> On a DAX fs, syncing metadata should be extremely fast.  This
>> could be conditioned on an madvise or mmap flag if performance might
>> be an issue.  As far as I know, this change alone should be
>> sufficient.
>
> The hang up is that it requires per-fs enabling as it needs to be
> careful to manage mmap_sem vs fs journal locks for example. I know the
> in-development NOVA [1] filesystem is planning to support this out of
> the gate. ext4 would be open to implementing it, but I think xfs is
> cold on the idea. Christoph originally proposed it here [2], before
> Dave went on to propose immutable semantics.

Hmm.  Given a choice between a very clean API that works without
privilege but is awkward to implement on XFS and an awkward-to-use
API, I'd personally choose the former.

Dave, even with the lock ordering issue, couldn't XFS implement
MAP_PMEM_AWARE by having .page_mkwrite work roughly like this:

if (metadata is dirty) {
  up_write(_sem);
  sync the metadata;
  down_write(_sem);
  return 0;  /* retry the fault */
} else {
  return whatever success code;
}

This might require returning VM_FAULT_RETRY instead of 0 and it might
require auditing the core mm code to make sure that it can handle
mmap_sem being dropped like this.  I don't see why it couldn't work in
principle, though.


Re: [RFC PATCH 2/2] mm, fs: daxfile, an interface for byte-addressable updates to pmem

2017-06-17 Thread Andy Lutomirski
On Sat, Jun 17, 2017 at 8:15 PM, Dan Williams  wrote:
> On Sat, Jun 17, 2017 at 4:50 PM, Andy Lutomirski  wrote:
>> My other objection is that the syscall intentionally leaks a reference
>> to the file.  This means it needs overflow protection and it probably
>> shouldn't ever be allowed to use it without privilege.
>
> We only hold the one reference while S_DAXFILE is set, so I think the
> protection is there, and per Dave's original proposal this requires
> CAP_LINUX_IMMUTABLE.
>
>> Why can't the underlying issue be easily fixed, though?  Could
>> .page_mkwrite just make sure that metadata is synced when the FS uses
>> DAX?
>
> Yes, it most definitely could and that idea has been floated.
>
>> On a DAX fs, syncing metadata should be extremely fast.  This
>> could be conditioned on an madvise or mmap flag if performance might
>> be an issue.  As far as I know, this change alone should be
>> sufficient.
>
> The hang up is that it requires per-fs enabling as it needs to be
> careful to manage mmap_sem vs fs journal locks for example. I know the
> in-development NOVA [1] filesystem is planning to support this out of
> the gate. ext4 would be open to implementing it, but I think xfs is
> cold on the idea. Christoph originally proposed it here [2], before
> Dave went on to propose immutable semantics.

Hmm.  Given a choice between a very clean API that works without
privilege but is awkward to implement on XFS and an awkward-to-use
API, I'd personally choose the former.

Dave, even with the lock ordering issue, couldn't XFS implement
MAP_PMEM_AWARE by having .page_mkwrite work roughly like this:

if (metadata is dirty) {
  up_write(_sem);
  sync the metadata;
  down_write(_sem);
  return 0;  /* retry the fault */
} else {
  return whatever success code;
}

This might require returning VM_FAULT_RETRY instead of 0 and it might
require auditing the core mm code to make sure that it can handle
mmap_sem being dropped like this.  I don't see why it couldn't work in
principle, though.


Re: [PATCH 3/5] soc: bcm: brcmstb: Add support for S2/S3/S5 suspend states (ARM)

2017-06-17 Thread kbuild test robot
Hi Brian,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Florian-Fainelli/Broadcom-STB-S2-S3-S5-support-for-ARM-and-MIPS/20170618-091951
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/soc/bcm/brcmstb/pm/s2-arm.S: Assembler messages:
>> drivers/soc/bcm/brcmstb/pm/s2-arm.S:35: Error: selected processor does not 
>> support `dsb' in ARM mode

vim +35 drivers/soc/bcm/brcmstb/pm/s2-arm.S

29  ENTRY(brcmstb_pm_do_s2)
30  stmfd   sp!, {r4-r11, lr}
31  mov AON_CTRL_REG, r0
32  mov DDR_PHY_STATUS_REG, r1
33  
34  /* Flush memory transactions */
  > 35  dsb
36  
37  /* Cache DDR_PHY_STATUS_REG translation */
38  ldr r0, [DDR_PHY_STATUS_REG]

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH 3/5] soc: bcm: brcmstb: Add support for S2/S3/S5 suspend states (ARM)

2017-06-17 Thread kbuild test robot
Hi Brian,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Florian-Fainelli/Broadcom-STB-S2-S3-S5-support-for-ARM-and-MIPS/20170618-091951
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/soc/bcm/brcmstb/pm/s2-arm.S: Assembler messages:
>> drivers/soc/bcm/brcmstb/pm/s2-arm.S:35: Error: selected processor does not 
>> support `dsb' in ARM mode

vim +35 drivers/soc/bcm/brcmstb/pm/s2-arm.S

29  ENTRY(brcmstb_pm_do_s2)
30  stmfd   sp!, {r4-r11, lr}
31  mov AON_CTRL_REG, r0
32  mov DDR_PHY_STATUS_REG, r1
33  
34  /* Flush memory transactions */
  > 35  dsb
36  
37  /* Cache DDR_PHY_STATUS_REG translation */
38  ldr r0, [DDR_PHY_STATUS_REG]

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH v11 5/6] i2c: designware: add SLAVE mode functions

2017-06-17 Thread kbuild test robot
Hi Luis,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Luis-Oliveira/i2c-designware-add-I2C-SLAVE-support/20170615-014456
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git 
i2c/for-next
config: x86_64-randconfig-a0-06181216 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/i2c/busses/i2c-designware-slave.c: In function 
'i2c_dw_irq_handler_slave':
>> drivers/i2c/busses/i2c-designware-slave.c:285:3: error: implicit declaration 
>> of function 'i2c_slave_event' [-Werror=implicit-function-declaration]
  i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, );
  ^~~
>> drivers/i2c/busses/i2c-designware-slave.c:285:31: error: 
>> 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function)
  i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, );
  ^
   drivers/i2c/busses/i2c-designware-slave.c:285:31: note: each undeclared 
identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-designware-slave.c:293:12: error: 
>> 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function)
   I2C_SLAVE_WRITE_RECEIVED,
   ^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:306:11: error: 
>> 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function)
  I2C_SLAVE_READ_REQUESTED,
  ^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:313:36: error: 
>> 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function)
  if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
   ^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:317:31: error: 'I2C_SLAVE_STOP' 
>> undeclared (first use in this function)
  i2c_slave_event(dev->slave, I2C_SLAVE_STOP, );
  ^~
   drivers/i2c/busses/i2c-designware-slave.c: At top level:
>> drivers/i2c/busses/i2c-designware-slave.c:353:2: error: unknown field 
>> 'reg_slave' specified in initializer
 .reg_slave = i2c_dw_reg_slave,
 ^
   drivers/i2c/busses/i2c-designware-slave.c:353:15: warning: excess elements 
in struct initializer
 .reg_slave = i2c_dw_reg_slave,
  ^~~~
   drivers/i2c/busses/i2c-designware-slave.c:353:15: note: (near initialization 
for 'i2c_dw_algo')
>> drivers/i2c/busses/i2c-designware-slave.c:354:2: error: unknown field 
>> 'unreg_slave' specified in initializer
 .unreg_slave = i2c_dw_unreg_slave,
 ^
   drivers/i2c/busses/i2c-designware-slave.c:354:17: warning: excess elements 
in struct initializer
 .unreg_slave = i2c_dw_unreg_slave,
^~
   drivers/i2c/busses/i2c-designware-slave.c:354:17: note: (near initialization 
for 'i2c_dw_algo')
   cc1: some warnings being treated as errors

vim +/i2c_slave_event +285 drivers/i2c/busses/i2c-designware-slave.c

   279  dev_dbg(dev->dev,
   280  "%#x STAUTS SLAVE_ACTTVITY=%#x : RAW_INTR_STAT=%#x"
   281  " : INTR_STAT=%#x\n",
   282  enabled, slave_activity, raw_stat, stat);
   283  
   284  if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET))
 > 285  i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, 
 > );
   286  
   287  if (stat & DW_IC_INTR_RD_REQ) {
   288  if (slave_activity) {
   289  if (stat & DW_IC_INTR_RX_FULL) {
   290  val = dw_readl(dev, DW_IC_DATA_CMD);
   291  
   292  if (!i2c_slave_event(dev->slave,
 > 293   
 > I2C_SLAVE_WRITE_RECEIVED,
   294   )) {
   295  dev_vdbg(dev->dev, "Byte %X 
acked!",
   296   val);
   297  }
   298  dw_readl(dev, DW_IC_CLR_RD_REQ);
   299  stat = 
i2c_dw_read_clear_intrbits_slave(dev);
   300  } else {
   301  dw_readl(dev, DW_IC_CLR_RD_REQ);
   302  dw_readl(dev, DW_IC_CLR_RX_UNDER);
   303  stat = 
i2c_dw_read_clear_intrbits_slave(dev);
   304  }
   305  if (!i2c_slave_event(dev->slave,
 > 306   

Re: [PATCH v11 5/6] i2c: designware: add SLAVE mode functions

2017-06-17 Thread kbuild test robot
Hi Luis,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Luis-Oliveira/i2c-designware-add-I2C-SLAVE-support/20170615-014456
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git 
i2c/for-next
config: x86_64-randconfig-a0-06181216 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/i2c/busses/i2c-designware-slave.c: In function 
'i2c_dw_irq_handler_slave':
>> drivers/i2c/busses/i2c-designware-slave.c:285:3: error: implicit declaration 
>> of function 'i2c_slave_event' [-Werror=implicit-function-declaration]
  i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, );
  ^~~
>> drivers/i2c/busses/i2c-designware-slave.c:285:31: error: 
>> 'I2C_SLAVE_WRITE_REQUESTED' undeclared (first use in this function)
  i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, );
  ^
   drivers/i2c/busses/i2c-designware-slave.c:285:31: note: each undeclared 
identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-designware-slave.c:293:12: error: 
>> 'I2C_SLAVE_WRITE_RECEIVED' undeclared (first use in this function)
   I2C_SLAVE_WRITE_RECEIVED,
   ^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:306:11: error: 
>> 'I2C_SLAVE_READ_REQUESTED' undeclared (first use in this function)
  I2C_SLAVE_READ_REQUESTED,
  ^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:313:36: error: 
>> 'I2C_SLAVE_READ_PROCESSED' undeclared (first use in this function)
  if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
   ^~~~
>> drivers/i2c/busses/i2c-designware-slave.c:317:31: error: 'I2C_SLAVE_STOP' 
>> undeclared (first use in this function)
  i2c_slave_event(dev->slave, I2C_SLAVE_STOP, );
  ^~
   drivers/i2c/busses/i2c-designware-slave.c: At top level:
>> drivers/i2c/busses/i2c-designware-slave.c:353:2: error: unknown field 
>> 'reg_slave' specified in initializer
 .reg_slave = i2c_dw_reg_slave,
 ^
   drivers/i2c/busses/i2c-designware-slave.c:353:15: warning: excess elements 
in struct initializer
 .reg_slave = i2c_dw_reg_slave,
  ^~~~
   drivers/i2c/busses/i2c-designware-slave.c:353:15: note: (near initialization 
for 'i2c_dw_algo')
>> drivers/i2c/busses/i2c-designware-slave.c:354:2: error: unknown field 
>> 'unreg_slave' specified in initializer
 .unreg_slave = i2c_dw_unreg_slave,
 ^
   drivers/i2c/busses/i2c-designware-slave.c:354:17: warning: excess elements 
in struct initializer
 .unreg_slave = i2c_dw_unreg_slave,
^~
   drivers/i2c/busses/i2c-designware-slave.c:354:17: note: (near initialization 
for 'i2c_dw_algo')
   cc1: some warnings being treated as errors

vim +/i2c_slave_event +285 drivers/i2c/busses/i2c-designware-slave.c

   279  dev_dbg(dev->dev,
   280  "%#x STAUTS SLAVE_ACTTVITY=%#x : RAW_INTR_STAT=%#x"
   281  " : INTR_STAT=%#x\n",
   282  enabled, slave_activity, raw_stat, stat);
   283  
   284  if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET))
 > 285  i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, 
 > );
   286  
   287  if (stat & DW_IC_INTR_RD_REQ) {
   288  if (slave_activity) {
   289  if (stat & DW_IC_INTR_RX_FULL) {
   290  val = dw_readl(dev, DW_IC_DATA_CMD);
   291  
   292  if (!i2c_slave_event(dev->slave,
 > 293   
 > I2C_SLAVE_WRITE_RECEIVED,
   294   )) {
   295  dev_vdbg(dev->dev, "Byte %X 
acked!",
   296   val);
   297  }
   298  dw_readl(dev, DW_IC_CLR_RD_REQ);
   299  stat = 
i2c_dw_read_clear_intrbits_slave(dev);
   300  } else {
   301  dw_readl(dev, DW_IC_CLR_RD_REQ);
   302  dw_readl(dev, DW_IC_CLR_RX_UNDER);
   303  stat = 
i2c_dw_read_clear_intrbits_slave(dev);
   304  }
   305  if (!i2c_slave_event(dev->slave,
 > 306   

[PATCH 11/13] bcache: use kmalloc to allocate bio in bch_data_verify()

2017-06-17 Thread NeilBrown
This function allocates a bio, then a collection
of pages.  It copes with failure.

It currently uses a mempool() to allocate the bio,
but alloc_page() to allocate the pages.  These fail
in different ways, so the usage is inconsistent.

Change the bio_clone() to bio_clone_kmalloc()
so that no pool is used either for the bio or the pages.

Reviewed-by: Christoph Hellwig 
Acked-by: Kent Overstreet 
Reviewed-by : Ming Lei 
Signed-off-by: NeilBrown 
---
 drivers/md/bcache/debug.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 06f55056aaae..35a5a7210e51 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -110,7 +110,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
struct bio_vec bv, cbv;
struct bvec_iter iter, citer = { 0 };
 
-   check = bio_clone(bio, GFP_NOIO);
+   check = bio_clone_kmalloc(bio, GFP_NOIO);
if (!check)
return;
check->bi_opf = REQ_OP_READ;




[PATCH 11/13] bcache: use kmalloc to allocate bio in bch_data_verify()

2017-06-17 Thread NeilBrown
This function allocates a bio, then a collection
of pages.  It copes with failure.

It currently uses a mempool() to allocate the bio,
but alloc_page() to allocate the pages.  These fail
in different ways, so the usage is inconsistent.

Change the bio_clone() to bio_clone_kmalloc()
so that no pool is used either for the bio or the pages.

Reviewed-by: Christoph Hellwig 
Acked-by: Kent Overstreet 
Reviewed-by : Ming Lei 
Signed-off-by: NeilBrown 
---
 drivers/md/bcache/debug.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 06f55056aaae..35a5a7210e51 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -110,7 +110,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
struct bio_vec bv, cbv;
struct bvec_iter iter, citer = { 0 };
 
-   check = bio_clone(bio, GFP_NOIO);
+   check = bio_clone_kmalloc(bio, GFP_NOIO);
if (!check)
return;
check->bi_opf = REQ_OP_READ;




Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.

2017-06-17 Thread NeilBrown
On Fri, Jun 16 2017, Jens Axboe wrote:

> On 06/16/2017 01:34 AM, Christoph Hellwig wrote:
>> On Fri, Jun 16, 2017 at 05:30:50PM +1000, NeilBrown wrote:
>>> I've pushed the new version to the same place.  Do you actually want
>>> me to re-post all the patches?
>> 
>> I personally prefer to always have patches on the list, but I can't
>> speak for Jens of course.
>
> Yes please, I'd prefer them posted again as well.

Done.
Thanks,
NeilBrown


signature.asc
Description: PGP signature


[PATCH 10/13] xen-blkfront: remove bio splitting.

2017-06-17 Thread NeilBrown
bios that are re-submitted will pass through blk_queue_split() when
blk_queue_bio() is called, and this will split the bio if necessary.
There is no longer any need to do this splitting in xen-blkfront.

Acked-by: Roger Pau Monné 
Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/xen-blkfront.c |   54 ++
 1 file changed, 3 insertions(+), 51 deletions(-)

diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index e3be666c2776..ac90093fcb25 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -110,11 +110,6 @@ struct blk_shadow {
unsigned long associated_id;
 };
 
-struct split_bio {
-   struct bio *bio;
-   atomic_t pending;
-};
-
 struct blkif_req {
int error;
 };
@@ -2000,28 +1995,13 @@ static int blkfront_probe(struct xenbus_device *dev,
return 0;
 }
 
-static void split_bio_end(struct bio *bio)
-{
-   struct split_bio *split_bio = bio->bi_private;
-
-   if (atomic_dec_and_test(_bio->pending)) {
-   split_bio->bio->bi_phys_segments = 0;
-   split_bio->bio->bi_status = bio->bi_status;
-   bio_endio(split_bio->bio);
-   kfree(split_bio);
-   }
-   bio_put(bio);
-}
-
 static int blkif_recover(struct blkfront_info *info)
 {
-   unsigned int i, r_index;
+   unsigned int r_index;
struct request *req, *n;
int rc;
-   struct bio *bio, *cloned_bio;
-   unsigned int segs, offset;
-   int pending, size;
-   struct split_bio *split_bio;
+   struct bio *bio;
+   unsigned int segs;
 
blkfront_gather_backend_features(info);
/* Reset limits changed by blk_mq_update_nr_hw_queues(). */
@@ -2060,34 +2040,6 @@ static int blkif_recover(struct blkfront_info *info)
 
while ((bio = bio_list_pop(>bio_list)) != NULL) {
/* Traverse the list of pending bios and re-queue them */
-   if (bio_segments(bio) > segs) {
-   /*
-* This bio has more segments than what we can
-* handle, we have to split it.
-*/
-   pending = (bio_segments(bio) + segs - 1) / segs;
-   split_bio = kzalloc(sizeof(*split_bio), GFP_NOIO);
-   BUG_ON(split_bio == NULL);
-   atomic_set(_bio->pending, pending);
-   split_bio->bio = bio;
-   for (i = 0; i < pending; i++) {
-   offset = (i * segs * XEN_PAGE_SIZE) >> 9;
-   size = min((unsigned int)(segs * XEN_PAGE_SIZE) 
>> 9,
-  (unsigned int)bio_sectors(bio) - 
offset);
-   cloned_bio = bio_clone(bio, GFP_NOIO);
-   BUG_ON(cloned_bio == NULL);
-   bio_trim(cloned_bio, offset, size);
-   cloned_bio->bi_private = split_bio;
-   cloned_bio->bi_end_io = split_bio_end;
-   submit_bio(cloned_bio);
-   }
-   /*
-* Now we have to wait for all those smaller bios to
-* end, so we can also end the "parent" bio.
-*/
-   continue;
-   }
-   /* We don't need to split this bio */
submit_bio(bio);
}
 




[PATCH 09/13] lightnvm/pblk-read: use bio_clone_fast()

2017-06-17 Thread NeilBrown
pblk_submit_read() uses bio_clone_bioset() but doesn't change the
io_vec, so bio_clone_fast() is a better choice.

It also uses fs_bio_set which is intended for filesystems.  Using it
in a device driver can deadlock.
So allocate a new bioset, and and use bio_clone_fast().

Reviewed-by: Christoph Hellwig 
Reviewed-by: Javier González 
Tested-by: Javier González 
Signed-off-by: NeilBrown 
---
 drivers/lightnvm/pblk-init.c |   12 +++-
 drivers/lightnvm/pblk-read.c |2 +-
 drivers/lightnvm/pblk.h  |1 +
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index b3fec8ec55b8..aaefbccce30e 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -23,6 +23,7 @@
 static struct kmem_cache *pblk_blk_ws_cache, *pblk_rec_cache, *pblk_r_rq_cache,
*pblk_w_rq_cache, *pblk_line_meta_cache;
 static DECLARE_RWSEM(pblk_lock);
+struct bio_set *pblk_bio_set;
 
 static int pblk_rw_io(struct request_queue *q, struct pblk *pblk,
  struct bio *bio)
@@ -946,11 +947,20 @@ static struct nvm_tgt_type tt_pblk = {
 
 static int __init pblk_module_init(void)
 {
-   return nvm_register_tgt_type(_pblk);
+   int ret;
+
+   pblk_bio_set = bioset_create(BIO_POOL_SIZE, 0, 0);
+   if (!pblk_bio_set)
+   return -ENOMEM;
+   ret = nvm_register_tgt_type(_pblk);
+   if (ret)
+   bioset_free(pblk_bio_set);
+   return ret;
 }
 
 static void pblk_module_exit(void)
 {
+   bioset_free(pblk_bio_set);
nvm_unregister_tgt_type(_pblk);
 }
 
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 762c0b73cb67..74d3fc53022e 100644
--- a/drivers/lightnvm/pblk-read.c
+++ b/drivers/lightnvm/pblk-read.c
@@ -342,7 +342,7 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
struct pblk_r_ctx *r_ctx = nvm_rq_to_pdu(rqd);
 
/* Clone read bio to deal with read errors internally */
-   int_bio = bio_clone_bioset(bio, GFP_KERNEL, fs_bio_set);
+   int_bio = bio_clone_fast(bio, GFP_KERNEL, pblk_bio_set);
if (!int_bio) {
pr_err("pblk: could not clone read bio\n");
return NVM_IO_ERR;
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 99f3186b5288..95b665f23925 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -702,6 +702,7 @@ void pblk_write_should_kick(struct pblk *pblk);
 /*
  * pblk read path
  */
+extern struct bio_set *pblk_bio_set;
 int pblk_submit_read(struct pblk *pblk, struct bio *bio);
 int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
unsigned int nr_secs, unsigned int *secs_to_gc,




Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.

2017-06-17 Thread NeilBrown
On Fri, Jun 16 2017, Jens Axboe wrote:

> On 06/16/2017 01:34 AM, Christoph Hellwig wrote:
>> On Fri, Jun 16, 2017 at 05:30:50PM +1000, NeilBrown wrote:
>>> I've pushed the new version to the same place.  Do you actually want
>>> me to re-post all the patches?
>> 
>> I personally prefer to always have patches on the list, but I can't
>> speak for Jens of course.
>
> Yes please, I'd prefer them posted again as well.

Done.
Thanks,
NeilBrown


signature.asc
Description: PGP signature


[PATCH 10/13] xen-blkfront: remove bio splitting.

2017-06-17 Thread NeilBrown
bios that are re-submitted will pass through blk_queue_split() when
blk_queue_bio() is called, and this will split the bio if necessary.
There is no longer any need to do this splitting in xen-blkfront.

Acked-by: Roger Pau Monné 
Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/xen-blkfront.c |   54 ++
 1 file changed, 3 insertions(+), 51 deletions(-)

diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index e3be666c2776..ac90093fcb25 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -110,11 +110,6 @@ struct blk_shadow {
unsigned long associated_id;
 };
 
-struct split_bio {
-   struct bio *bio;
-   atomic_t pending;
-};
-
 struct blkif_req {
int error;
 };
@@ -2000,28 +1995,13 @@ static int blkfront_probe(struct xenbus_device *dev,
return 0;
 }
 
-static void split_bio_end(struct bio *bio)
-{
-   struct split_bio *split_bio = bio->bi_private;
-
-   if (atomic_dec_and_test(_bio->pending)) {
-   split_bio->bio->bi_phys_segments = 0;
-   split_bio->bio->bi_status = bio->bi_status;
-   bio_endio(split_bio->bio);
-   kfree(split_bio);
-   }
-   bio_put(bio);
-}
-
 static int blkif_recover(struct blkfront_info *info)
 {
-   unsigned int i, r_index;
+   unsigned int r_index;
struct request *req, *n;
int rc;
-   struct bio *bio, *cloned_bio;
-   unsigned int segs, offset;
-   int pending, size;
-   struct split_bio *split_bio;
+   struct bio *bio;
+   unsigned int segs;
 
blkfront_gather_backend_features(info);
/* Reset limits changed by blk_mq_update_nr_hw_queues(). */
@@ -2060,34 +2040,6 @@ static int blkif_recover(struct blkfront_info *info)
 
while ((bio = bio_list_pop(>bio_list)) != NULL) {
/* Traverse the list of pending bios and re-queue them */
-   if (bio_segments(bio) > segs) {
-   /*
-* This bio has more segments than what we can
-* handle, we have to split it.
-*/
-   pending = (bio_segments(bio) + segs - 1) / segs;
-   split_bio = kzalloc(sizeof(*split_bio), GFP_NOIO);
-   BUG_ON(split_bio == NULL);
-   atomic_set(_bio->pending, pending);
-   split_bio->bio = bio;
-   for (i = 0; i < pending; i++) {
-   offset = (i * segs * XEN_PAGE_SIZE) >> 9;
-   size = min((unsigned int)(segs * XEN_PAGE_SIZE) 
>> 9,
-  (unsigned int)bio_sectors(bio) - 
offset);
-   cloned_bio = bio_clone(bio, GFP_NOIO);
-   BUG_ON(cloned_bio == NULL);
-   bio_trim(cloned_bio, offset, size);
-   cloned_bio->bi_private = split_bio;
-   cloned_bio->bi_end_io = split_bio_end;
-   submit_bio(cloned_bio);
-   }
-   /*
-* Now we have to wait for all those smaller bios to
-* end, so we can also end the "parent" bio.
-*/
-   continue;
-   }
-   /* We don't need to split this bio */
submit_bio(bio);
}
 




[PATCH 09/13] lightnvm/pblk-read: use bio_clone_fast()

2017-06-17 Thread NeilBrown
pblk_submit_read() uses bio_clone_bioset() but doesn't change the
io_vec, so bio_clone_fast() is a better choice.

It also uses fs_bio_set which is intended for filesystems.  Using it
in a device driver can deadlock.
So allocate a new bioset, and and use bio_clone_fast().

Reviewed-by: Christoph Hellwig 
Reviewed-by: Javier González 
Tested-by: Javier González 
Signed-off-by: NeilBrown 
---
 drivers/lightnvm/pblk-init.c |   12 +++-
 drivers/lightnvm/pblk-read.c |2 +-
 drivers/lightnvm/pblk.h  |1 +
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index b3fec8ec55b8..aaefbccce30e 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -23,6 +23,7 @@
 static struct kmem_cache *pblk_blk_ws_cache, *pblk_rec_cache, *pblk_r_rq_cache,
*pblk_w_rq_cache, *pblk_line_meta_cache;
 static DECLARE_RWSEM(pblk_lock);
+struct bio_set *pblk_bio_set;
 
 static int pblk_rw_io(struct request_queue *q, struct pblk *pblk,
  struct bio *bio)
@@ -946,11 +947,20 @@ static struct nvm_tgt_type tt_pblk = {
 
 static int __init pblk_module_init(void)
 {
-   return nvm_register_tgt_type(_pblk);
+   int ret;
+
+   pblk_bio_set = bioset_create(BIO_POOL_SIZE, 0, 0);
+   if (!pblk_bio_set)
+   return -ENOMEM;
+   ret = nvm_register_tgt_type(_pblk);
+   if (ret)
+   bioset_free(pblk_bio_set);
+   return ret;
 }
 
 static void pblk_module_exit(void)
 {
+   bioset_free(pblk_bio_set);
nvm_unregister_tgt_type(_pblk);
 }
 
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 762c0b73cb67..74d3fc53022e 100644
--- a/drivers/lightnvm/pblk-read.c
+++ b/drivers/lightnvm/pblk-read.c
@@ -342,7 +342,7 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
struct pblk_r_ctx *r_ctx = nvm_rq_to_pdu(rqd);
 
/* Clone read bio to deal with read errors internally */
-   int_bio = bio_clone_bioset(bio, GFP_KERNEL, fs_bio_set);
+   int_bio = bio_clone_fast(bio, GFP_KERNEL, pblk_bio_set);
if (!int_bio) {
pr_err("pblk: could not clone read bio\n");
return NVM_IO_ERR;
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 99f3186b5288..95b665f23925 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -702,6 +702,7 @@ void pblk_write_should_kick(struct pblk *pblk);
 /*
  * pblk read path
  */
+extern struct bio_set *pblk_bio_set;
 int pblk_submit_read(struct pblk *pblk, struct bio *bio);
 int pblk_submit_read_gc(struct pblk *pblk, u64 *lba_list, void *data,
unsigned int nr_secs, unsigned int *secs_to_gc,




[PATCH 08/13] pktcdvd: use bio_clone_fast() instead of bio_clone()

2017-06-17 Thread NeilBrown
pktcdvd doesn't change the bi_io_vec of the clone bio,
so it is more efficient to use bio_clone_fast(), and not clone
the bi_io_vec.
This requires providing a bio_set, and it is safest to
provide a dedicated bio_set rather than sharing
fs_bio_set, which filesytems use.
This new bio_set, pkt_bio_set, can also be use for the bio_split()
call as the two allocations (bio_clone_fast, and bio_split) are
independent, neither can block a bio allocated by the other.

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/pktcdvd.c |   12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 1f363638b453..26c04baae967 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -98,6 +98,7 @@ static int write_congestion_on  = PKT_WRITE_CONGESTION_ON;
 static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
 static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
 static mempool_t *psd_pool;
+static struct bio_set *pkt_bio_set;
 
 static struct class*class_pktcdvd = NULL;/* /sys/class/pktcdvd */
 static struct dentry   *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd 
*/
@@ -2310,7 +2311,7 @@ static void pkt_end_io_read_cloned(struct bio *bio)
 
 static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio)
 {
-   struct bio *cloned_bio = bio_clone(bio, GFP_NOIO);
+   struct bio *cloned_bio = bio_clone_fast(bio, GFP_NOIO, pkt_bio_set);
struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO);
 
psd->pd = pd;
@@ -2455,7 +2456,7 @@ static blk_qc_t pkt_make_request(struct request_queue *q, 
struct bio *bio)
 
split = bio_split(bio, last_zone -
  bio->bi_iter.bi_sector,
- GFP_NOIO, fs_bio_set);
+ GFP_NOIO, pkt_bio_set);
bio_chain(split, bio);
} else {
split = bio;
@@ -2924,6 +2925,11 @@ static int __init pkt_init(void)
sizeof(struct packet_stacked_data));
if (!psd_pool)
return -ENOMEM;
+   pkt_bio_set = bioset_create(BIO_POOL_SIZE, 0, 0);
+   if (!pkt_bio_set) {
+   mempool_destroy(psd_pool);
+   return -ENOMEM;
+   }
 
ret = register_blkdev(pktdev_major, DRIVER_NAME);
if (ret < 0) {
@@ -2956,6 +2962,7 @@ static int __init pkt_init(void)
unregister_blkdev(pktdev_major, DRIVER_NAME);
 out2:
mempool_destroy(psd_pool);
+   bioset_free(pkt_bio_set);
return ret;
 }
 
@@ -2969,6 +2976,7 @@ static void __exit pkt_exit(void)
 
unregister_blkdev(pktdev_major, DRIVER_NAME);
mempool_destroy(psd_pool);
+   bioset_free(pkt_bio_set);
 }
 
 MODULE_DESCRIPTION("Packet writing layer for CD/DVD drives");




[PATCH 05/13] block: Improvements to bounce-buffer handling

2017-06-17 Thread NeilBrown
Since commit 23688bf4f830 ("block: ensure to split after potentially
bouncing a bio") blk_queue_bounce() is called *before*
blk_queue_split().
This means that:
 1/ the comments blk_queue_split() about bounce buffers are
irrelevant, and
 2/ a very large bio (more than BIO_MAX_PAGES) will no longer be
split before it arrives at blk_queue_bounce(), leading to the
possibility that bio_clone_bioset() will fail and a NULL
will be dereferenced.

Separately, blk_queue_bounce() shouldn't use fs_bio_set as the bio
being copied could be from the same set, and this could lead to a
deadlock.

So:
 - allocate 2 private biosets for blk_queue_bounce, one for
   splitting enormous bios and one for cloning bios.
 - add code to split a bio that exceeds BIO_MAX_PAGES.
 - Fix up the comments in blk_queue_split()

Credit-to: Ming Lei  (suggested using single 
bio_for_each_segment loop)
Reviewed-by: Ming Lei 
Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 block/blk-merge.c |   14 --
 block/bounce.c|   32 ++--
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/block/blk-merge.c b/block/blk-merge.c
index d59074556703..51c84540d3bb 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -117,17 +117,11 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
 * each holds at most BIO_MAX_PAGES bvecs because
 * bio_clone() can fail to allocate big bvecs.
 *
-* It should have been better to apply the limit per
-* request queue in which bio_clone() is involved,
-* instead of globally. The biggest blocker is the
-* bio_clone() in bio bounce.
+* Those drivers which will need to use bio_clone()
+* should tell us in some way.  For now, impose the
+* BIO_MAX_PAGES limit on all queues.
 *
-* If bio is splitted by this reason, we should have
-* allowed to continue bios merging, but don't do
-* that now for making the change simple.
-*
-* TODO: deal with bio bounce's bio_clone() gracefully
-* and convert the global limit into per-queue limit.
+* TODO: handle users of bio_clone() differently.
 */
if (bvecs++ >= BIO_MAX_PAGES)
goto split;
diff --git a/block/bounce.c b/block/bounce.c
index e4703181d97f..17d77613c471 100644
--- a/block/bounce.c
+++ b/block/bounce.c
@@ -26,6 +26,7 @@
 #define POOL_SIZE  64
 #define ISA_POOL_SIZE  16
 
+struct bio_set *bounce_bio_set, *bounce_bio_split;
 static mempool_t *page_pool, *isa_page_pool;
 
 #if defined(CONFIG_HIGHMEM) || defined(CONFIG_NEED_BOUNCE_POOL)
@@ -40,6 +41,14 @@ static __init int init_emergency_pool(void)
BUG_ON(!page_pool);
pr_info("pool size: %d pages\n", POOL_SIZE);
 
+   bounce_bio_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
+   BUG_ON(!bounce_bio_set);
+   if (bioset_integrity_create(bounce_bio_set, BIO_POOL_SIZE))
+   BUG_ON(1);
+
+   bounce_bio_split = bioset_create(BIO_POOL_SIZE, 0, 0);
+   BUG_ON(!bounce_bio_split);
+
return 0;
 }
 
@@ -186,15 +195,26 @@ static void __blk_queue_bounce(struct request_queue *q, 
struct bio **bio_orig,
int rw = bio_data_dir(*bio_orig);
struct bio_vec *to, from;
struct bvec_iter iter;
-   unsigned i;
+   unsigned i = 0;
+   bool bounce = false;
+   int sectors = 0;
 
-   bio_for_each_segment(from, *bio_orig, iter)
+   bio_for_each_segment(from, *bio_orig, iter) {
+   if (i++ < BIO_MAX_PAGES)
+   sectors += from.bv_len >> 9;
if (page_to_pfn(from.bv_page) > queue_bounce_pfn(q))
-   goto bounce;
+   bounce = true;
+   }
+   if (!bounce)
+   return;
 
-   return;
-bounce:
-   bio = bio_clone_bioset(*bio_orig, GFP_NOIO, fs_bio_set);
+   if (sectors < bio_sectors(*bio_orig)) {
+   bio = bio_split(*bio_orig, sectors, GFP_NOIO, bounce_bio_split);
+   bio_chain(bio, *bio_orig);
+   generic_make_request(*bio_orig);
+   *bio_orig = bio;
+   }
+   bio = bio_clone_bioset(*bio_orig, GFP_NOIO, bounce_bio_set);
 
bio_for_each_segment_all(to, bio, i) {
struct page *page = to->bv_page;




[PATCH 08/13] pktcdvd: use bio_clone_fast() instead of bio_clone()

2017-06-17 Thread NeilBrown
pktcdvd doesn't change the bi_io_vec of the clone bio,
so it is more efficient to use bio_clone_fast(), and not clone
the bi_io_vec.
This requires providing a bio_set, and it is safest to
provide a dedicated bio_set rather than sharing
fs_bio_set, which filesytems use.
This new bio_set, pkt_bio_set, can also be use for the bio_split()
call as the two allocations (bio_clone_fast, and bio_split) are
independent, neither can block a bio allocated by the other.

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/pktcdvd.c |   12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 1f363638b453..26c04baae967 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -98,6 +98,7 @@ static int write_congestion_on  = PKT_WRITE_CONGESTION_ON;
 static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
 static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
 static mempool_t *psd_pool;
+static struct bio_set *pkt_bio_set;
 
 static struct class*class_pktcdvd = NULL;/* /sys/class/pktcdvd */
 static struct dentry   *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd 
*/
@@ -2310,7 +2311,7 @@ static void pkt_end_io_read_cloned(struct bio *bio)
 
 static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio)
 {
-   struct bio *cloned_bio = bio_clone(bio, GFP_NOIO);
+   struct bio *cloned_bio = bio_clone_fast(bio, GFP_NOIO, pkt_bio_set);
struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO);
 
psd->pd = pd;
@@ -2455,7 +2456,7 @@ static blk_qc_t pkt_make_request(struct request_queue *q, 
struct bio *bio)
 
split = bio_split(bio, last_zone -
  bio->bi_iter.bi_sector,
- GFP_NOIO, fs_bio_set);
+ GFP_NOIO, pkt_bio_set);
bio_chain(split, bio);
} else {
split = bio;
@@ -2924,6 +2925,11 @@ static int __init pkt_init(void)
sizeof(struct packet_stacked_data));
if (!psd_pool)
return -ENOMEM;
+   pkt_bio_set = bioset_create(BIO_POOL_SIZE, 0, 0);
+   if (!pkt_bio_set) {
+   mempool_destroy(psd_pool);
+   return -ENOMEM;
+   }
 
ret = register_blkdev(pktdev_major, DRIVER_NAME);
if (ret < 0) {
@@ -2956,6 +2962,7 @@ static int __init pkt_init(void)
unregister_blkdev(pktdev_major, DRIVER_NAME);
 out2:
mempool_destroy(psd_pool);
+   bioset_free(pkt_bio_set);
return ret;
 }
 
@@ -2969,6 +2976,7 @@ static void __exit pkt_exit(void)
 
unregister_blkdev(pktdev_major, DRIVER_NAME);
mempool_destroy(psd_pool);
+   bioset_free(pkt_bio_set);
 }
 
 MODULE_DESCRIPTION("Packet writing layer for CD/DVD drives");




[PATCH 05/13] block: Improvements to bounce-buffer handling

2017-06-17 Thread NeilBrown
Since commit 23688bf4f830 ("block: ensure to split after potentially
bouncing a bio") blk_queue_bounce() is called *before*
blk_queue_split().
This means that:
 1/ the comments blk_queue_split() about bounce buffers are
irrelevant, and
 2/ a very large bio (more than BIO_MAX_PAGES) will no longer be
split before it arrives at blk_queue_bounce(), leading to the
possibility that bio_clone_bioset() will fail and a NULL
will be dereferenced.

Separately, blk_queue_bounce() shouldn't use fs_bio_set as the bio
being copied could be from the same set, and this could lead to a
deadlock.

So:
 - allocate 2 private biosets for blk_queue_bounce, one for
   splitting enormous bios and one for cloning bios.
 - add code to split a bio that exceeds BIO_MAX_PAGES.
 - Fix up the comments in blk_queue_split()

Credit-to: Ming Lei  (suggested using single 
bio_for_each_segment loop)
Reviewed-by: Ming Lei 
Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 block/blk-merge.c |   14 --
 block/bounce.c|   32 ++--
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/block/blk-merge.c b/block/blk-merge.c
index d59074556703..51c84540d3bb 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -117,17 +117,11 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
 * each holds at most BIO_MAX_PAGES bvecs because
 * bio_clone() can fail to allocate big bvecs.
 *
-* It should have been better to apply the limit per
-* request queue in which bio_clone() is involved,
-* instead of globally. The biggest blocker is the
-* bio_clone() in bio bounce.
+* Those drivers which will need to use bio_clone()
+* should tell us in some way.  For now, impose the
+* BIO_MAX_PAGES limit on all queues.
 *
-* If bio is splitted by this reason, we should have
-* allowed to continue bios merging, but don't do
-* that now for making the change simple.
-*
-* TODO: deal with bio bounce's bio_clone() gracefully
-* and convert the global limit into per-queue limit.
+* TODO: handle users of bio_clone() differently.
 */
if (bvecs++ >= BIO_MAX_PAGES)
goto split;
diff --git a/block/bounce.c b/block/bounce.c
index e4703181d97f..17d77613c471 100644
--- a/block/bounce.c
+++ b/block/bounce.c
@@ -26,6 +26,7 @@
 #define POOL_SIZE  64
 #define ISA_POOL_SIZE  16
 
+struct bio_set *bounce_bio_set, *bounce_bio_split;
 static mempool_t *page_pool, *isa_page_pool;
 
 #if defined(CONFIG_HIGHMEM) || defined(CONFIG_NEED_BOUNCE_POOL)
@@ -40,6 +41,14 @@ static __init int init_emergency_pool(void)
BUG_ON(!page_pool);
pr_info("pool size: %d pages\n", POOL_SIZE);
 
+   bounce_bio_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
+   BUG_ON(!bounce_bio_set);
+   if (bioset_integrity_create(bounce_bio_set, BIO_POOL_SIZE))
+   BUG_ON(1);
+
+   bounce_bio_split = bioset_create(BIO_POOL_SIZE, 0, 0);
+   BUG_ON(!bounce_bio_split);
+
return 0;
 }
 
@@ -186,15 +195,26 @@ static void __blk_queue_bounce(struct request_queue *q, 
struct bio **bio_orig,
int rw = bio_data_dir(*bio_orig);
struct bio_vec *to, from;
struct bvec_iter iter;
-   unsigned i;
+   unsigned i = 0;
+   bool bounce = false;
+   int sectors = 0;
 
-   bio_for_each_segment(from, *bio_orig, iter)
+   bio_for_each_segment(from, *bio_orig, iter) {
+   if (i++ < BIO_MAX_PAGES)
+   sectors += from.bv_len >> 9;
if (page_to_pfn(from.bv_page) > queue_bounce_pfn(q))
-   goto bounce;
+   bounce = true;
+   }
+   if (!bounce)
+   return;
 
-   return;
-bounce:
-   bio = bio_clone_bioset(*bio_orig, GFP_NOIO, fs_bio_set);
+   if (sectors < bio_sectors(*bio_orig)) {
+   bio = bio_split(*bio_orig, sectors, GFP_NOIO, bounce_bio_split);
+   bio_chain(bio, *bio_orig);
+   generic_make_request(*bio_orig);
+   *bio_orig = bio;
+   }
+   bio = bio_clone_bioset(*bio_orig, GFP_NOIO, bounce_bio_set);
 
bio_for_each_segment_all(to, bio, i) {
struct page *page = to->bv_page;




[PATCH 12/13] block: remove bio_clone() and all references.

2017-06-17 Thread NeilBrown
bio_clone() is no longer used.
Only bio_clone_bioset() or bio_clone_fast().
This is for the best, as bio_clone() used fs_bio_set,
and filesystems are unlikely to want to use bio_clone().

So remove bio_clone() and all references.
This includes a fix to some incorrect documentation.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 Documentation/block/biodoc.txt |2 +-
 block/bio.c|2 +-
 block/blk-merge.c  |6 +++---
 drivers/md/md.c|2 +-
 include/linux/bio.h|5 -
 5 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 01ddeaf64b0f..9490f2845f06 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -632,7 +632,7 @@ to i/o submission, if the bio fields are likely to be 
accessed after the
 i/o is issued (since the bio may otherwise get freed in case i/o completion
 happens in the meantime).
 
-The bio_clone() routine may be used to duplicate a bio, where the clone
+The bio_clone_fast() routine may be used to duplicate a bio, where the clone
 shares the bio_vec_list with the original bio (i.e. both point to the
 same bio_vec_list). This would typically be used for splitting i/o requests
 in lvm or md.
diff --git a/block/bio.c b/block/bio.c
index 36984bf382c7..3f4ac6366d1d 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -547,7 +547,7 @@ EXPORT_SYMBOL(zero_fill_bio);
  *
  * Description:
  *   Put a reference to a  bio, either one you have gotten with
- *   bio_alloc, bio_get or bio_clone. The last put of a bio will free it.
+ *   bio_alloc, bio_get or bio_clone_*. The last put of a bio will free it.
  **/
 void bio_put(struct bio *bio)
 {
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 51c84540d3bb..e7862e9dcc39 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -115,13 +115,13 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
 * With arbitrary bio size, the incoming bio may be very
 * big. We have to split the bio into small bios so that
 * each holds at most BIO_MAX_PAGES bvecs because
-* bio_clone() can fail to allocate big bvecs.
+* bio_clone_bioset() can fail to allocate big bvecs.
 *
-* Those drivers which will need to use bio_clone()
+* Those drivers which will need to use bio_clone_bioset()
 * should tell us in some way.  For now, impose the
 * BIO_MAX_PAGES limit on all queues.
 *
-* TODO: handle users of bio_clone() differently.
+* TODO: handle users of bio_clone_bioset() differently.
 */
if (bvecs++ >= BIO_MAX_PAGES)
goto split;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 7e2b79408e37..d60958c84500 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -185,7 +185,7 @@ static int start_readonly;
 static bool create_on_open = true;
 
 /* bio_clone_mddev
- * like bio_clone, but with a local bio set
+ * like bio_clone_bioset, but with a local bio set
  */
 
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 32c786baa10a..40d054185277 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -395,11 +395,6 @@ static inline struct bio *bio_alloc(gfp_t gfp_mask, 
unsigned int nr_iovecs)
return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
 }
 
-static inline struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
-{
-   return bio_clone_bioset(bio, gfp_mask, fs_bio_set);
-}
-
 static inline struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
return bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);




Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.

2017-06-17 Thread NeilBrown
On Fri, Jun 16 2017, Jens Axboe wrote:

> On 06/16/2017 01:34 AM, Christoph Hellwig wrote:
>> On Fri, Jun 16, 2017 at 05:30:50PM +1000, NeilBrown wrote:
>>> I've pushed the new version to the same place.  Do you actually want
>>> me to re-post all the patches?
>> 
>> I personally prefer to always have patches on the list, but I can't
>> speak for Jens of course.
>
> Yes please, I'd prefer them posted again as well.

Done - to lkml and linux-block.

Thanks,
NeilBrown


signature.asc
Description: PGP signature


Re: [PATCH 00/13] block: assorted cleanup for bio splitting and cloning.

2017-06-17 Thread NeilBrown
On Fri, Jun 16 2017, Jens Axboe wrote:

> On 06/16/2017 01:34 AM, Christoph Hellwig wrote:
>> On Fri, Jun 16, 2017 at 05:30:50PM +1000, NeilBrown wrote:
>>> I've pushed the new version to the same place.  Do you actually want
>>> me to re-post all the patches?
>> 
>> I personally prefer to always have patches on the list, but I can't
>> speak for Jens of course.
>
> Yes please, I'd prefer them posted again as well.

Done - to lkml and linux-block.

Thanks,
NeilBrown


signature.asc
Description: PGP signature


[PATCH 12/13] block: remove bio_clone() and all references.

2017-06-17 Thread NeilBrown
bio_clone() is no longer used.
Only bio_clone_bioset() or bio_clone_fast().
This is for the best, as bio_clone() used fs_bio_set,
and filesystems are unlikely to want to use bio_clone().

So remove bio_clone() and all references.
This includes a fix to some incorrect documentation.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 Documentation/block/biodoc.txt |2 +-
 block/bio.c|2 +-
 block/blk-merge.c  |6 +++---
 drivers/md/md.c|2 +-
 include/linux/bio.h|5 -
 5 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 01ddeaf64b0f..9490f2845f06 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -632,7 +632,7 @@ to i/o submission, if the bio fields are likely to be 
accessed after the
 i/o is issued (since the bio may otherwise get freed in case i/o completion
 happens in the meantime).
 
-The bio_clone() routine may be used to duplicate a bio, where the clone
+The bio_clone_fast() routine may be used to duplicate a bio, where the clone
 shares the bio_vec_list with the original bio (i.e. both point to the
 same bio_vec_list). This would typically be used for splitting i/o requests
 in lvm or md.
diff --git a/block/bio.c b/block/bio.c
index 36984bf382c7..3f4ac6366d1d 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -547,7 +547,7 @@ EXPORT_SYMBOL(zero_fill_bio);
  *
  * Description:
  *   Put a reference to a  bio, either one you have gotten with
- *   bio_alloc, bio_get or bio_clone. The last put of a bio will free it.
+ *   bio_alloc, bio_get or bio_clone_*. The last put of a bio will free it.
  **/
 void bio_put(struct bio *bio)
 {
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 51c84540d3bb..e7862e9dcc39 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -115,13 +115,13 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
 * With arbitrary bio size, the incoming bio may be very
 * big. We have to split the bio into small bios so that
 * each holds at most BIO_MAX_PAGES bvecs because
-* bio_clone() can fail to allocate big bvecs.
+* bio_clone_bioset() can fail to allocate big bvecs.
 *
-* Those drivers which will need to use bio_clone()
+* Those drivers which will need to use bio_clone_bioset()
 * should tell us in some way.  For now, impose the
 * BIO_MAX_PAGES limit on all queues.
 *
-* TODO: handle users of bio_clone() differently.
+* TODO: handle users of bio_clone_bioset() differently.
 */
if (bvecs++ >= BIO_MAX_PAGES)
goto split;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 7e2b79408e37..d60958c84500 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -185,7 +185,7 @@ static int start_readonly;
 static bool create_on_open = true;
 
 /* bio_clone_mddev
- * like bio_clone, but with a local bio set
+ * like bio_clone_bioset, but with a local bio set
  */
 
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 32c786baa10a..40d054185277 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -395,11 +395,6 @@ static inline struct bio *bio_alloc(gfp_t gfp_mask, 
unsigned int nr_iovecs)
return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
 }
 
-static inline struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
-{
-   return bio_clone_bioset(bio, gfp_mask, fs_bio_set);
-}
-
 static inline struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
return bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);




[PATCH 03/13] blk: make the bioset rescue_workqueue optional.

2017-06-17 Thread NeilBrown
This patch converts bioset_create() to not create a workqueue by
default, so alloctions will never trigger punt_bios_to_rescuer().  It
also introduces a new flag BIOSET_NEED_RESCUER which tells
bioset_create() to preserve the old behavior.

All callers of bioset_create() that are inside block device drivers,
are given the BIOSET_NEED_RESCUER flag.

biosets used by filesystems or other top-level users do not
need rescuing as the bio can never be queued behind other
bios.  This includes fs_bio_set, blkdev_dio_pool,
btrfs_bioset, xfs_ioend_bioset, and one allocated by
target_core_iblock.c.

biosets used by md/raid do not need rescuing as
their usage was recently audited and revised to never
risk deadlock.

It is hoped that most, if not all, of the remaining biosets
can end up being the non-rescued version.

Reviewed-by: Christoph Hellwig 
Credit-to: Ming Lei  (minor fixes)
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 block/bio.c|   13 +++--
 block/blk-core.c   |3 ++-
 drivers/block/drbd/drbd_main.c |4 +++-
 drivers/md/bcache/super.c  |8 ++--
 drivers/md/dm-crypt.c  |3 ++-
 drivers/md/dm-io.c |3 ++-
 drivers/md/dm.c|5 +++--
 include/linux/bio.h|1 +
 8 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index f81545ba44bf..36984bf382c7 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -363,6 +363,8 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
struct bio_list punt, nopunt;
struct bio *bio;
 
+   if (WARN_ON_ONCE(!bs->rescue_workqueue))
+   return;
/*
 * In order to guarantee forward progress we must punt only bios that
 * were allocated from this bio_set; otherwise, if there was a bio on
@@ -474,7 +476,8 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, unsigned int 
nr_iovecs,
 
if (current->bio_list &&
(!bio_list_empty(>bio_list[0]) ||
-!bio_list_empty(>bio_list[1])))
+!bio_list_empty(>bio_list[1])) &&
+   bs->rescue_workqueue)
gfp_mask &= ~__GFP_DIRECT_RECLAIM;
 
p = mempool_alloc(bs->bio_pool, gfp_mask);
@@ -1925,7 +1928,8 @@ EXPORT_SYMBOL(bioset_free);
  * bioset_create  - Create a bio_set
  * @pool_size: Number of bio and bio_vecs to cache in the mempool
  * @front_pad: Number of bytes to allocate in front of the returned bio
- * @flags: Flags to modify behavior, currently only %BIOSET_NEED_BVECS
+ * @flags: Flags to modify behavior, currently %BIOSET_NEED_BVECS
+ *  and %BIOSET_NEED_RESCUER
  *
  * Description:
  *Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller
@@ -1936,6 +1940,8 @@ EXPORT_SYMBOL(bioset_free);
  *or things will break badly.
  *If %BIOSET_NEED_BVECS is set in @flags, a separate pool will be allocated
  *for allocating iovecs.  This pool is not needed e.g. for 
bio_clone_fast().
+ *If %BIOSET_NEED_RESCUER is set, a workqueue is created which can be used 
to
+ *dispatch queued requests when the mempool runs out of space.
  *
  */
 struct bio_set *bioset_create(unsigned int pool_size,
@@ -1971,6 +1977,9 @@ struct bio_set *bioset_create(unsigned int pool_size,
goto bad;
}
 
+   if (!(flags & BIOSET_NEED_RESCUER))
+   return bs;
+
bs->rescue_workqueue = alloc_workqueue("bioset", WQ_MEM_RECLAIM, 0);
if (!bs->rescue_workqueue)
goto bad;
diff --git a/block/blk-core.c b/block/blk-core.c
index 62cf92550512..9bd10c46a538 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -790,7 +790,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, 
int node_id)
if (q->id < 0)
goto fail_q;
 
-   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
+   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, (BIOSET_NEED_BVECS |
+   BIOSET_NEED_RESCUER));
if (!q->bio_split)
goto fail_id;
 
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index b395fe391171..bdf51b6977cf 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2165,7 +2165,9 @@ static int drbd_create_mempools(void)
goto Enomem;
 
/* mempools */
-   drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0, 
BIOSET_NEED_BVECS);
+   drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0,
+  BIOSET_NEED_BVECS |
+  BIOSET_NEED_RESCUER);
if (drbd_md_io_bio_set == NULL)
goto Enomem;
 
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 

[PATCH 04/13] blk: use non-rescuing bioset for q->bio_split.

2017-06-17 Thread NeilBrown
A rescuing bioset is only useful if there might be bios from
that same bioset on the bio_list_on_stack queue at a time
when bio_alloc_bioset() is called.  This never applies to
q->bio_split.

Allocations from q->bio_split are only ever made from
blk_queue_split() which is only ever called early in each of
various make_request_fn()s.  The original bio (call this A)
is then passed to generic_make_request() and is placed on
the bio_list_on_stack queue, and the bio that was allocated
from q->bio_split (B) is processed.

The processing of this may cause other bios to be passed to
generic_make_request() or may even cause the bio B itself to
be passed, possible after some prefix has been split off
(using some other bioset).

generic_make_request() now guarantees that all of these bios
(B and dependants) will be fully processed before the tail
of the original bio A gets handled.  None of these early bios
can possible trigger an allocation from the original
q->bio_split as they are either too small to require
splitting or (more likely) are destined for a different queue.

The next time that the original q->bio_split might be used
by this thread is when A is processed again, as it might
still be too big to handle directly.  By this time there
cannot be any other bios allocated from q->bio_split in the
generic_make_request() queue.  So no rescuing will ever be
needed.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 block/blk-core.c |3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 9bd10c46a538..62cf92550512 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -790,8 +790,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, 
int node_id)
if (q->id < 0)
goto fail_q;
 
-   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, (BIOSET_NEED_BVECS |
-   BIOSET_NEED_RESCUER));
+   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
if (!q->bio_split)
goto fail_id;
 




[PATCH 07/13] drbd: use bio_clone_fast() instead of bio_clone()

2017-06-17 Thread NeilBrown
drbd does not modify the bi_io_vec of the cloned bio,
so there is no need to clone that part.  So bio_clone_fast()
is the better choice.
For bio_clone_fast() we need to specify a bio_set.
We could use fs_bio_set, which bio_clone() uses, or
drbd_md_io_bio_set, which drbd uses for metadata, but it is
generally best to avoid sharing bio_sets unless you can
be certain that there are no interdependencies.

So create a new bio_set, drbd_io_bio_set, and use bio_clone_fast().

Also remove a "XXX cannot fail ???" comment because it definitely
cannot fail - bio_clone_fast() doesn't fail if the GFP flags allow for
sleeping.

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/drbd/drbd_int.h  |3 +++
 drivers/block/drbd/drbd_main.c |9 +
 drivers/block/drbd/drbd_req.h  |2 +-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 76761b4ca13e..d17b6e6393c7 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1441,6 +1441,9 @@ extern struct bio_set *drbd_md_io_bio_set;
 /* to allocate from that set */
 extern struct bio *bio_alloc_drbd(gfp_t gfp_mask);
 
+/* And a bio_set for cloning */
+extern struct bio_set *drbd_io_bio_set;
+
 extern struct mutex resources_mutex;
 
 extern int conn_lowest_minor(struct drbd_connection *connection);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index bdf51b6977cf..90680034ef57 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -128,6 +128,7 @@ mempool_t *drbd_request_mempool;
 mempool_t *drbd_ee_mempool;
 mempool_t *drbd_md_io_page_pool;
 struct bio_set *drbd_md_io_bio_set;
+struct bio_set *drbd_io_bio_set;
 
 /* I do not use a standard mempool, because:
1) I want to hand out the pre-allocated objects first.
@@ -2098,6 +2099,8 @@ static void drbd_destroy_mempools(void)
 
/* D_ASSERT(device, atomic_read(_pp_vacant)==0); */
 
+   if (drbd_io_bio_set)
+   bioset_free(drbd_io_bio_set);
if (drbd_md_io_bio_set)
bioset_free(drbd_md_io_bio_set);
if (drbd_md_io_page_pool)
@@ -2115,6 +2118,7 @@ static void drbd_destroy_mempools(void)
if (drbd_al_ext_cache)
kmem_cache_destroy(drbd_al_ext_cache);
 
+   drbd_io_bio_set  = NULL;
drbd_md_io_bio_set   = NULL;
drbd_md_io_page_pool = NULL;
drbd_ee_mempool  = NULL;
@@ -2142,6 +2146,7 @@ static int drbd_create_mempools(void)
drbd_pp_pool = NULL;
drbd_md_io_page_pool = NULL;
drbd_md_io_bio_set   = NULL;
+   drbd_io_bio_set  = NULL;
 
/* caches */
drbd_request_cache = kmem_cache_create(
@@ -2165,6 +2170,10 @@ static int drbd_create_mempools(void)
goto Enomem;
 
/* mempools */
+   drbd_io_bio_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_RESCUER);
+   if (drbd_io_bio_set == NULL)
+   goto Enomem;
+
drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0,
   BIOSET_NEED_BVECS |
   BIOSET_NEED_RESCUER);
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index eb49e7f2da91..9e1866ab238f 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -263,7 +263,7 @@ enum drbd_req_state_bits {
 static inline void drbd_req_make_private_bio(struct drbd_request *req, struct 
bio *bio_src)
 {
struct bio *bio;
-   bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+   bio = bio_clone_fast(bio_src, GFP_NOIO, drbd_io_bio_set);
 
req->private_bio = bio;
 




[PATCH 03/13] blk: make the bioset rescue_workqueue optional.

2017-06-17 Thread NeilBrown
This patch converts bioset_create() to not create a workqueue by
default, so alloctions will never trigger punt_bios_to_rescuer().  It
also introduces a new flag BIOSET_NEED_RESCUER which tells
bioset_create() to preserve the old behavior.

All callers of bioset_create() that are inside block device drivers,
are given the BIOSET_NEED_RESCUER flag.

biosets used by filesystems or other top-level users do not
need rescuing as the bio can never be queued behind other
bios.  This includes fs_bio_set, blkdev_dio_pool,
btrfs_bioset, xfs_ioend_bioset, and one allocated by
target_core_iblock.c.

biosets used by md/raid do not need rescuing as
their usage was recently audited and revised to never
risk deadlock.

It is hoped that most, if not all, of the remaining biosets
can end up being the non-rescued version.

Reviewed-by: Christoph Hellwig 
Credit-to: Ming Lei  (minor fixes)
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 block/bio.c|   13 +++--
 block/blk-core.c   |3 ++-
 drivers/block/drbd/drbd_main.c |4 +++-
 drivers/md/bcache/super.c  |8 ++--
 drivers/md/dm-crypt.c  |3 ++-
 drivers/md/dm-io.c |3 ++-
 drivers/md/dm.c|5 +++--
 include/linux/bio.h|1 +
 8 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index f81545ba44bf..36984bf382c7 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -363,6 +363,8 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
struct bio_list punt, nopunt;
struct bio *bio;
 
+   if (WARN_ON_ONCE(!bs->rescue_workqueue))
+   return;
/*
 * In order to guarantee forward progress we must punt only bios that
 * were allocated from this bio_set; otherwise, if there was a bio on
@@ -474,7 +476,8 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, unsigned int 
nr_iovecs,
 
if (current->bio_list &&
(!bio_list_empty(>bio_list[0]) ||
-!bio_list_empty(>bio_list[1])))
+!bio_list_empty(>bio_list[1])) &&
+   bs->rescue_workqueue)
gfp_mask &= ~__GFP_DIRECT_RECLAIM;
 
p = mempool_alloc(bs->bio_pool, gfp_mask);
@@ -1925,7 +1928,8 @@ EXPORT_SYMBOL(bioset_free);
  * bioset_create  - Create a bio_set
  * @pool_size: Number of bio and bio_vecs to cache in the mempool
  * @front_pad: Number of bytes to allocate in front of the returned bio
- * @flags: Flags to modify behavior, currently only %BIOSET_NEED_BVECS
+ * @flags: Flags to modify behavior, currently %BIOSET_NEED_BVECS
+ *  and %BIOSET_NEED_RESCUER
  *
  * Description:
  *Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller
@@ -1936,6 +1940,8 @@ EXPORT_SYMBOL(bioset_free);
  *or things will break badly.
  *If %BIOSET_NEED_BVECS is set in @flags, a separate pool will be allocated
  *for allocating iovecs.  This pool is not needed e.g. for 
bio_clone_fast().
+ *If %BIOSET_NEED_RESCUER is set, a workqueue is created which can be used 
to
+ *dispatch queued requests when the mempool runs out of space.
  *
  */
 struct bio_set *bioset_create(unsigned int pool_size,
@@ -1971,6 +1977,9 @@ struct bio_set *bioset_create(unsigned int pool_size,
goto bad;
}
 
+   if (!(flags & BIOSET_NEED_RESCUER))
+   return bs;
+
bs->rescue_workqueue = alloc_workqueue("bioset", WQ_MEM_RECLAIM, 0);
if (!bs->rescue_workqueue)
goto bad;
diff --git a/block/blk-core.c b/block/blk-core.c
index 62cf92550512..9bd10c46a538 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -790,7 +790,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, 
int node_id)
if (q->id < 0)
goto fail_q;
 
-   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
+   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, (BIOSET_NEED_BVECS |
+   BIOSET_NEED_RESCUER));
if (!q->bio_split)
goto fail_id;
 
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index b395fe391171..bdf51b6977cf 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2165,7 +2165,9 @@ static int drbd_create_mempools(void)
goto Enomem;
 
/* mempools */
-   drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0, 
BIOSET_NEED_BVECS);
+   drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0,
+  BIOSET_NEED_BVECS |
+  BIOSET_NEED_RESCUER);
if (drbd_md_io_bio_set == NULL)
goto Enomem;
 
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index abd6e825b39b..8352fad765f6 100644
--- a/drivers/md/bcache/super.c
+++ 

[PATCH 04/13] blk: use non-rescuing bioset for q->bio_split.

2017-06-17 Thread NeilBrown
A rescuing bioset is only useful if there might be bios from
that same bioset on the bio_list_on_stack queue at a time
when bio_alloc_bioset() is called.  This never applies to
q->bio_split.

Allocations from q->bio_split are only ever made from
blk_queue_split() which is only ever called early in each of
various make_request_fn()s.  The original bio (call this A)
is then passed to generic_make_request() and is placed on
the bio_list_on_stack queue, and the bio that was allocated
from q->bio_split (B) is processed.

The processing of this may cause other bios to be passed to
generic_make_request() or may even cause the bio B itself to
be passed, possible after some prefix has been split off
(using some other bioset).

generic_make_request() now guarantees that all of these bios
(B and dependants) will be fully processed before the tail
of the original bio A gets handled.  None of these early bios
can possible trigger an allocation from the original
q->bio_split as they are either too small to require
splitting or (more likely) are destined for a different queue.

The next time that the original q->bio_split might be used
by this thread is when A is processed again, as it might
still be too big to handle directly.  By this time there
cannot be any other bios allocated from q->bio_split in the
generic_make_request() queue.  So no rescuing will ever be
needed.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 block/blk-core.c |3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 9bd10c46a538..62cf92550512 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -790,8 +790,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, 
int node_id)
if (q->id < 0)
goto fail_q;
 
-   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, (BIOSET_NEED_BVECS |
-   BIOSET_NEED_RESCUER));
+   q->bio_split = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
if (!q->bio_split)
goto fail_id;
 




[PATCH 07/13] drbd: use bio_clone_fast() instead of bio_clone()

2017-06-17 Thread NeilBrown
drbd does not modify the bi_io_vec of the cloned bio,
so there is no need to clone that part.  So bio_clone_fast()
is the better choice.
For bio_clone_fast() we need to specify a bio_set.
We could use fs_bio_set, which bio_clone() uses, or
drbd_md_io_bio_set, which drbd uses for metadata, but it is
generally best to avoid sharing bio_sets unless you can
be certain that there are no interdependencies.

So create a new bio_set, drbd_io_bio_set, and use bio_clone_fast().

Also remove a "XXX cannot fail ???" comment because it definitely
cannot fail - bio_clone_fast() doesn't fail if the GFP flags allow for
sleeping.

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/drbd/drbd_int.h  |3 +++
 drivers/block/drbd/drbd_main.c |9 +
 drivers/block/drbd/drbd_req.h  |2 +-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 76761b4ca13e..d17b6e6393c7 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1441,6 +1441,9 @@ extern struct bio_set *drbd_md_io_bio_set;
 /* to allocate from that set */
 extern struct bio *bio_alloc_drbd(gfp_t gfp_mask);
 
+/* And a bio_set for cloning */
+extern struct bio_set *drbd_io_bio_set;
+
 extern struct mutex resources_mutex;
 
 extern int conn_lowest_minor(struct drbd_connection *connection);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index bdf51b6977cf..90680034ef57 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -128,6 +128,7 @@ mempool_t *drbd_request_mempool;
 mempool_t *drbd_ee_mempool;
 mempool_t *drbd_md_io_page_pool;
 struct bio_set *drbd_md_io_bio_set;
+struct bio_set *drbd_io_bio_set;
 
 /* I do not use a standard mempool, because:
1) I want to hand out the pre-allocated objects first.
@@ -2098,6 +2099,8 @@ static void drbd_destroy_mempools(void)
 
/* D_ASSERT(device, atomic_read(_pp_vacant)==0); */
 
+   if (drbd_io_bio_set)
+   bioset_free(drbd_io_bio_set);
if (drbd_md_io_bio_set)
bioset_free(drbd_md_io_bio_set);
if (drbd_md_io_page_pool)
@@ -2115,6 +2118,7 @@ static void drbd_destroy_mempools(void)
if (drbd_al_ext_cache)
kmem_cache_destroy(drbd_al_ext_cache);
 
+   drbd_io_bio_set  = NULL;
drbd_md_io_bio_set   = NULL;
drbd_md_io_page_pool = NULL;
drbd_ee_mempool  = NULL;
@@ -2142,6 +2146,7 @@ static int drbd_create_mempools(void)
drbd_pp_pool = NULL;
drbd_md_io_page_pool = NULL;
drbd_md_io_bio_set   = NULL;
+   drbd_io_bio_set  = NULL;
 
/* caches */
drbd_request_cache = kmem_cache_create(
@@ -2165,6 +2170,10 @@ static int drbd_create_mempools(void)
goto Enomem;
 
/* mempools */
+   drbd_io_bio_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_RESCUER);
+   if (drbd_io_bio_set == NULL)
+   goto Enomem;
+
drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0,
   BIOSET_NEED_BVECS |
   BIOSET_NEED_RESCUER);
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index eb49e7f2da91..9e1866ab238f 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -263,7 +263,7 @@ enum drbd_req_state_bits {
 static inline void drbd_req_make_private_bio(struct drbd_request *req, struct 
bio *bio_src)
 {
struct bio *bio;
-   bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+   bio = bio_clone_fast(bio_src, GFP_NOIO, drbd_io_bio_set);
 
req->private_bio = bio;
 




[PATCH 13/13] block: don't check for BIO_MAX_PAGES in blk_bio_segment_split()

2017-06-17 Thread NeilBrown
blk_bio_segment_split() makes sure bios have no more than
BIO_MAX_PAGES entries in the bi_io_vec.
This was done because bio_clone_bioset() (when given a
mempool bioset) could not handle larger io_vecs.

No driver uses bio_clone_bioset() any more, they all
use bio_clone_fast() if anything, and bio_clone_fast()
doesn't clone the bi_io_vec.

The main user of of bio_clone_bioset() at this level
is bounce.c, and bouncing now happens before blk_bio_segment_split(),
so that is not of concern.

So remove the big helpful comment and the code.

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 block/blk-merge.c |   16 
 1 file changed, 16 deletions(-)

diff --git a/block/blk-merge.c b/block/blk-merge.c
index e7862e9dcc39..cea544ec5d96 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -108,25 +108,9 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
bool do_split = true;
struct bio *new = NULL;
const unsigned max_sectors = get_max_io_size(q, bio);
-   unsigned bvecs = 0;
 
bio_for_each_segment(bv, bio, iter) {
/*
-* With arbitrary bio size, the incoming bio may be very
-* big. We have to split the bio into small bios so that
-* each holds at most BIO_MAX_PAGES bvecs because
-* bio_clone_bioset() can fail to allocate big bvecs.
-*
-* Those drivers which will need to use bio_clone_bioset()
-* should tell us in some way.  For now, impose the
-* BIO_MAX_PAGES limit on all queues.
-*
-* TODO: handle users of bio_clone_bioset() differently.
-*/
-   if (bvecs++ >= BIO_MAX_PAGES)
-   goto split;
-
-   /*
 * If the queue doesn't support SG gaps and adding this
 * offset would create a gap, disallow it.
 */




[PATCH 06/13] rbd: use bio_clone_fast() instead of bio_clone()

2017-06-17 Thread NeilBrown
bio_clone() makes a copy of the bi_io_vec, but rbd never changes that,
so there is no need for a copy.
bio_clone_fast() can be used instead, which avoids making the copy.

This requires that we provide a bio_set.  bio_clone() uses fs_bio_set,
but it isn't, in general, safe to use the same bio_set at different
levels of the stack, as that can lead to deadlocks.  As filesystems
use fs_bio_set, block devices shouldn't.

As rbd never stacks, it is safe to have a single global bio_set for
all rbd devices to use.  So allocate that when the module is
initialised, and use it with bio_clone_fast().

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/rbd.c |   16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 5420bc40c544..b008b6a98098 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -442,6 +442,8 @@ static DEFINE_SPINLOCK(rbd_client_list_lock);
 static struct kmem_cache   *rbd_img_request_cache;
 static struct kmem_cache   *rbd_obj_request_cache;
 
+static struct bio_set  *rbd_bio_clone;
+
 static int rbd_major;
 static DEFINE_IDA(rbd_dev_id_ida);
 
@@ -1363,7 +1365,7 @@ static struct bio *bio_clone_range(struct bio *bio_src,
 {
struct bio *bio;
 
-   bio = bio_clone(bio_src, gfpmask);
+   bio = bio_clone_fast(bio_src, gfpmask, rbd_bio_clone);
if (!bio)
return NULL;/* ENOMEM */
 
@@ -6416,8 +6418,16 @@ static int rbd_slab_init(void)
if (!rbd_obj_request_cache)
goto out_err;
 
+   rbd_assert(!rbd_bio_clone);
+   rbd_bio_clone = bioset_create(BIO_POOL_SIZE, 0, 0);
+   if (!rbd_bio_clone)
+   goto out_err_clone;
+
return 0;
 
+out_err_clone:
+   kmem_cache_destroy(rbd_obj_request_cache);
+   rbd_obj_request_cache = NULL;
 out_err:
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
@@ -6433,6 +6443,10 @@ static void rbd_slab_exit(void)
rbd_assert(rbd_img_request_cache);
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
+
+   rbd_assert(rbd_bio_clone);
+   bioset_free(rbd_bio_clone);
+   rbd_bio_clone = NULL;
 }
 
 static int __init rbd_init(void)




[PATCH 13/13] block: don't check for BIO_MAX_PAGES in blk_bio_segment_split()

2017-06-17 Thread NeilBrown
blk_bio_segment_split() makes sure bios have no more than
BIO_MAX_PAGES entries in the bi_io_vec.
This was done because bio_clone_bioset() (when given a
mempool bioset) could not handle larger io_vecs.

No driver uses bio_clone_bioset() any more, they all
use bio_clone_fast() if anything, and bio_clone_fast()
doesn't clone the bi_io_vec.

The main user of of bio_clone_bioset() at this level
is bounce.c, and bouncing now happens before blk_bio_segment_split(),
so that is not of concern.

So remove the big helpful comment and the code.

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 block/blk-merge.c |   16 
 1 file changed, 16 deletions(-)

diff --git a/block/blk-merge.c b/block/blk-merge.c
index e7862e9dcc39..cea544ec5d96 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -108,25 +108,9 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
bool do_split = true;
struct bio *new = NULL;
const unsigned max_sectors = get_max_io_size(q, bio);
-   unsigned bvecs = 0;
 
bio_for_each_segment(bv, bio, iter) {
/*
-* With arbitrary bio size, the incoming bio may be very
-* big. We have to split the bio into small bios so that
-* each holds at most BIO_MAX_PAGES bvecs because
-* bio_clone_bioset() can fail to allocate big bvecs.
-*
-* Those drivers which will need to use bio_clone_bioset()
-* should tell us in some way.  For now, impose the
-* BIO_MAX_PAGES limit on all queues.
-*
-* TODO: handle users of bio_clone_bioset() differently.
-*/
-   if (bvecs++ >= BIO_MAX_PAGES)
-   goto split;
-
-   /*
 * If the queue doesn't support SG gaps and adding this
 * offset would create a gap, disallow it.
 */




[PATCH 06/13] rbd: use bio_clone_fast() instead of bio_clone()

2017-06-17 Thread NeilBrown
bio_clone() makes a copy of the bi_io_vec, but rbd never changes that,
so there is no need for a copy.
bio_clone_fast() can be used instead, which avoids making the copy.

This requires that we provide a bio_set.  bio_clone() uses fs_bio_set,
but it isn't, in general, safe to use the same bio_set at different
levels of the stack, as that can lead to deadlocks.  As filesystems
use fs_bio_set, block devices shouldn't.

As rbd never stacks, it is safe to have a single global bio_set for
all rbd devices to use.  So allocate that when the module is
initialised, and use it with bio_clone_fast().

Reviewed-by: Christoph Hellwig 
Signed-off-by: NeilBrown 
---
 drivers/block/rbd.c |   16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 5420bc40c544..b008b6a98098 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -442,6 +442,8 @@ static DEFINE_SPINLOCK(rbd_client_list_lock);
 static struct kmem_cache   *rbd_img_request_cache;
 static struct kmem_cache   *rbd_obj_request_cache;
 
+static struct bio_set  *rbd_bio_clone;
+
 static int rbd_major;
 static DEFINE_IDA(rbd_dev_id_ida);
 
@@ -1363,7 +1365,7 @@ static struct bio *bio_clone_range(struct bio *bio_src,
 {
struct bio *bio;
 
-   bio = bio_clone(bio_src, gfpmask);
+   bio = bio_clone_fast(bio_src, gfpmask, rbd_bio_clone);
if (!bio)
return NULL;/* ENOMEM */
 
@@ -6416,8 +6418,16 @@ static int rbd_slab_init(void)
if (!rbd_obj_request_cache)
goto out_err;
 
+   rbd_assert(!rbd_bio_clone);
+   rbd_bio_clone = bioset_create(BIO_POOL_SIZE, 0, 0);
+   if (!rbd_bio_clone)
+   goto out_err_clone;
+
return 0;
 
+out_err_clone:
+   kmem_cache_destroy(rbd_obj_request_cache);
+   rbd_obj_request_cache = NULL;
 out_err:
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
@@ -6433,6 +6443,10 @@ static void rbd_slab_exit(void)
rbd_assert(rbd_img_request_cache);
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
+
+   rbd_assert(rbd_bio_clone);
+   bioset_free(rbd_bio_clone);
+   rbd_bio_clone = NULL;
 }
 
 static int __init rbd_init(void)




[PATCH 00/13] block: assorted cleanup for bio splitting and cloning.

2017-06-17 Thread NeilBrown
This is a resend of my series of patches working
towards removing the bioset work queues.

This set is based on for-4.13/block.

It incorporates the revised versions of all the patches that were
resent following feedback on the last set.

It also includes a minor grammatic improvement to a comment, and
simple changes to compensate for a couple of changes to the block tree
since the last posting.

I hope to eventually get rid of the new BIOSET_NEED_RESCUER flag,
but that needs work in dm and probably bcache first.

Thanks,
NeilBrown


---

NeilBrown (13):
  blk: remove bio_set arg from blk_queue_split()
  blk: replace bioset_create_nobvec() with a flags arg to bioset_create()
  blk: make the bioset rescue_workqueue optional.
  blk: use non-rescuing bioset for q->bio_split.
  block: Improvements to bounce-buffer handling
  rbd: use bio_clone_fast() instead of bio_clone()
  drbd: use bio_clone_fast() instead of bio_clone()
  pktcdvd: use bio_clone_fast() instead of bio_clone()
  lightnvm/pblk-read: use bio_clone_fast()
  xen-blkfront: remove bio splitting.
  bcache: use kmalloc to allocate bio in bch_data_verify()
  block: remove bio_clone() and all references.
  block: don't check for BIO_MAX_PAGES in blk_bio_segment_split()


 Documentation/block/biodoc.txt  |2 -
 block/bio.c |   73 ---
 block/blk-core.c|4 +-
 block/blk-merge.c   |   31 ++-
 block/blk-mq.c  |2 -
 block/bounce.c  |   32 ---
 drivers/block/drbd/drbd_int.h   |3 +
 drivers/block/drbd/drbd_main.c  |   13 ++
 drivers/block/drbd/drbd_req.c   |2 -
 drivers/block/drbd/drbd_req.h   |2 -
 drivers/block/pktcdvd.c |   14 +--
 drivers/block/ps3vram.c |2 -
 drivers/block/rbd.c |   16 +++-
 drivers/block/rsxx/dev.c|2 -
 drivers/block/umem.c|2 -
 drivers/block/xen-blkfront.c|   54 +-
 drivers/lightnvm/pblk-init.c|   16 ++--
 drivers/lightnvm/pblk-read.c|2 -
 drivers/lightnvm/pblk.h |1 
 drivers/lightnvm/rrpc.c |2 -
 drivers/md/bcache/debug.c   |2 -
 drivers/md/bcache/super.c   |8 +++-
 drivers/md/dm-crypt.c   |3 +
 drivers/md/dm-io.c  |3 +
 drivers/md/dm.c |5 +-
 drivers/md/md.c |6 +--
 drivers/md/raid1.c  |2 -
 drivers/md/raid10.c |2 -
 drivers/md/raid5-cache.c|2 -
 drivers/md/raid5-ppl.c  |2 -
 drivers/md/raid5.c  |2 -
 drivers/s390/block/dcssblk.c|2 -
 drivers/s390/block/xpram.c  |2 -
 drivers/target/target_core_iblock.c |2 -
 fs/block_dev.c  |2 -
 fs/btrfs/extent_io.c|3 +
 fs/xfs/xfs_super.c  |3 +
 include/linux/bio.h |   12 ++
 include/linux/blkdev.h  |3 -
 39 files changed, 168 insertions(+), 173 deletions(-)

--
Signature



[PATCH 00/13] block: assorted cleanup for bio splitting and cloning.

2017-06-17 Thread NeilBrown
This is a resend of my series of patches working
towards removing the bioset work queues.

This set is based on for-4.13/block.

It incorporates the revised versions of all the patches that were
resent following feedback on the last set.

It also includes a minor grammatic improvement to a comment, and
simple changes to compensate for a couple of changes to the block tree
since the last posting.

I hope to eventually get rid of the new BIOSET_NEED_RESCUER flag,
but that needs work in dm and probably bcache first.

Thanks,
NeilBrown


---

NeilBrown (13):
  blk: remove bio_set arg from blk_queue_split()
  blk: replace bioset_create_nobvec() with a flags arg to bioset_create()
  blk: make the bioset rescue_workqueue optional.
  blk: use non-rescuing bioset for q->bio_split.
  block: Improvements to bounce-buffer handling
  rbd: use bio_clone_fast() instead of bio_clone()
  drbd: use bio_clone_fast() instead of bio_clone()
  pktcdvd: use bio_clone_fast() instead of bio_clone()
  lightnvm/pblk-read: use bio_clone_fast()
  xen-blkfront: remove bio splitting.
  bcache: use kmalloc to allocate bio in bch_data_verify()
  block: remove bio_clone() and all references.
  block: don't check for BIO_MAX_PAGES in blk_bio_segment_split()


 Documentation/block/biodoc.txt  |2 -
 block/bio.c |   73 ---
 block/blk-core.c|4 +-
 block/blk-merge.c   |   31 ++-
 block/blk-mq.c  |2 -
 block/bounce.c  |   32 ---
 drivers/block/drbd/drbd_int.h   |3 +
 drivers/block/drbd/drbd_main.c  |   13 ++
 drivers/block/drbd/drbd_req.c   |2 -
 drivers/block/drbd/drbd_req.h   |2 -
 drivers/block/pktcdvd.c |   14 +--
 drivers/block/ps3vram.c |2 -
 drivers/block/rbd.c |   16 +++-
 drivers/block/rsxx/dev.c|2 -
 drivers/block/umem.c|2 -
 drivers/block/xen-blkfront.c|   54 +-
 drivers/lightnvm/pblk-init.c|   16 ++--
 drivers/lightnvm/pblk-read.c|2 -
 drivers/lightnvm/pblk.h |1 
 drivers/lightnvm/rrpc.c |2 -
 drivers/md/bcache/debug.c   |2 -
 drivers/md/bcache/super.c   |8 +++-
 drivers/md/dm-crypt.c   |3 +
 drivers/md/dm-io.c  |3 +
 drivers/md/dm.c |5 +-
 drivers/md/md.c |6 +--
 drivers/md/raid1.c  |2 -
 drivers/md/raid10.c |2 -
 drivers/md/raid5-cache.c|2 -
 drivers/md/raid5-ppl.c  |2 -
 drivers/md/raid5.c  |2 -
 drivers/s390/block/dcssblk.c|2 -
 drivers/s390/block/xpram.c  |2 -
 drivers/target/target_core_iblock.c |2 -
 fs/block_dev.c  |2 -
 fs/btrfs/extent_io.c|3 +
 fs/xfs/xfs_super.c  |3 +
 include/linux/bio.h |   12 ++
 include/linux/blkdev.h  |3 -
 39 files changed, 168 insertions(+), 173 deletions(-)

--
Signature



[PATCH 02/13] blk: replace bioset_create_nobvec() with a flags arg to bioset_create()

2017-06-17 Thread NeilBrown
"flags" arguments are often seen as good API design as they allow
easy extensibility.
bioset_create_nobvec() is implemented internally as a variation in
flags passed to __bioset_create().

To support future extension, make the internal structure part of the
API.
i.e. add a 'flags' argument to bioset_create() and discard
bioset_create_nobvec().

Note that the bio_split allocations in drivers/md/raid* do not need
the bvec mempool - they should have used bioset_create_nobvec().

Suggested-by: Christoph Hellwig 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 block/bio.c |   60 +--
 block/blk-core.c|2 +
 drivers/block/drbd/drbd_main.c  |2 +
 drivers/md/bcache/super.c   |4 +-
 drivers/md/dm-crypt.c   |2 +
 drivers/md/dm-io.c  |2 +
 drivers/md/dm.c |2 +
 drivers/md/md.c |2 +
 drivers/md/raid1.c  |2 +
 drivers/md/raid10.c |2 +
 drivers/md/raid5-cache.c|2 +
 drivers/md/raid5-ppl.c  |2 +
 drivers/md/raid5.c  |2 +
 drivers/target/target_core_iblock.c |2 +
 fs/block_dev.c  |2 +
 fs/btrfs/extent_io.c|3 +-
 fs/xfs/xfs_super.c  |3 +-
 include/linux/bio.h |6 ++--
 18 files changed, 45 insertions(+), 57 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 7a5c8ed27f42..f81545ba44bf 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1921,9 +1921,26 @@ void bioset_free(struct bio_set *bs)
 }
 EXPORT_SYMBOL(bioset_free);
 
-static struct bio_set *__bioset_create(unsigned int pool_size,
-  unsigned int front_pad,
-  bool create_bvec_pool)
+/**
+ * bioset_create  - Create a bio_set
+ * @pool_size: Number of bio and bio_vecs to cache in the mempool
+ * @front_pad: Number of bytes to allocate in front of the returned bio
+ * @flags: Flags to modify behavior, currently only %BIOSET_NEED_BVECS
+ *
+ * Description:
+ *Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller
+ *to ask for a number of bytes to be allocated in front of the bio.
+ *Front pad allocation is useful for embedding the bio inside
+ *another structure, to avoid allocating extra data to go with the bio.
+ *Note that the bio must be embedded at the END of that structure always,
+ *or things will break badly.
+ *If %BIOSET_NEED_BVECS is set in @flags, a separate pool will be allocated
+ *for allocating iovecs.  This pool is not needed e.g. for 
bio_clone_fast().
+ *
+ */
+struct bio_set *bioset_create(unsigned int pool_size,
+ unsigned int front_pad,
+ int flags)
 {
unsigned int back_pad = BIO_INLINE_VECS * sizeof(struct bio_vec);
struct bio_set *bs;
@@ -1948,7 +1965,7 @@ static struct bio_set *__bioset_create(unsigned int 
pool_size,
if (!bs->bio_pool)
goto bad;
 
-   if (create_bvec_pool) {
+   if (flags & BIOSET_NEED_BVECS) {
bs->bvec_pool = biovec_create_pool(pool_size);
if (!bs->bvec_pool)
goto bad;
@@ -1963,41 +1980,8 @@ static struct bio_set *__bioset_create(unsigned int 
pool_size,
bioset_free(bs);
return NULL;
 }
-
-/**
- * bioset_create  - Create a bio_set
- * @pool_size: Number of bio and bio_vecs to cache in the mempool
- * @front_pad: Number of bytes to allocate in front of the returned bio
- *
- * Description:
- *Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller
- *to ask for a number of bytes to be allocated in front of the bio.
- *Front pad allocation is useful for embedding the bio inside
- *another structure, to avoid allocating extra data to go with the bio.
- *Note that the bio must be embedded at the END of that structure always,
- *or things will break badly.
- */
-struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad)
-{
-   return __bioset_create(pool_size, front_pad, true);
-}
 EXPORT_SYMBOL(bioset_create);
 
-/**
- * bioset_create_nobvec  - Create a bio_set without bio_vec mempool
- * @pool_size: Number of bio to cache in the mempool
- * @front_pad: Number of bytes to allocate in front of the returned bio
- *
- * Description:
- *Same functionality as bioset_create() except that mempool is not
- *created for bio_vecs. Saving some memory for bio_clone_fast() users.
- */
-struct bio_set *bioset_create_nobvec(unsigned int pool_size, unsigned int 
front_pad)
-{
-   return __bioset_create(pool_size, front_pad, false);
-}
-EXPORT_SYMBOL(bioset_create_nobvec);
-
 #ifdef CONFIG_BLK_CGROUP
 
 /**
@@ 

[PATCH 01/13] blk: remove bio_set arg from blk_queue_split()

2017-06-17 Thread NeilBrown
blk_queue_split() is always called with the last arg being q->bio_split,
where 'q' is the first arg.

Also blk_queue_split() sometimes uses the passed-in 'bs' and sometimes uses
q->bio_split.

This is inconsistent and unnecessary.  Remove the last arg and always use
q->bio_split inside blk_queue_split()

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Credit-to: Javier González  (Noticed that lightnvm was missed)
Reviewed-by: Javier González 
Tested-by: Javier González 
Signed-off-by: NeilBrown 
---
 block/blk-core.c  |2 +-
 block/blk-merge.c |9 -
 block/blk-mq.c|2 +-
 drivers/block/drbd/drbd_req.c |2 +-
 drivers/block/pktcdvd.c   |2 +-
 drivers/block/ps3vram.c   |2 +-
 drivers/block/rsxx/dev.c  |2 +-
 drivers/block/umem.c  |2 +-
 drivers/lightnvm/pblk-init.c  |4 ++--
 drivers/lightnvm/rrpc.c   |2 +-
 drivers/md/md.c   |2 +-
 drivers/s390/block/dcssblk.c  |2 +-
 drivers/s390/block/xpram.c|2 +-
 include/linux/blkdev.h|3 +--
 14 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 8592409db272..31b5ece6b18e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1723,7 +1723,7 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, 
struct bio *bio)
 */
blk_queue_bounce(q, );
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
bio->bi_status = BLK_STS_IOERR;
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 3990ae406341..d59074556703 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -202,8 +202,7 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
return do_split ? new : NULL;
 }
 
-void blk_queue_split(struct request_queue *q, struct bio **bio,
-struct bio_set *bs)
+void blk_queue_split(struct request_queue *q, struct bio **bio)
 {
struct bio *split, *res;
unsigned nsegs;
@@ -211,13 +210,13 @@ void blk_queue_split(struct request_queue *q, struct bio 
**bio,
switch (bio_op(*bio)) {
case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
-   split = blk_bio_discard_split(q, *bio, bs, );
+   split = blk_bio_discard_split(q, *bio, q->bio_split, );
break;
case REQ_OP_WRITE_ZEROES:
-   split = blk_bio_write_zeroes_split(q, *bio, bs, );
+   split = blk_bio_write_zeroes_split(q, *bio, q->bio_split, 
);
break;
case REQ_OP_WRITE_SAME:
-   split = blk_bio_write_same_split(q, *bio, bs, );
+   split = blk_bio_write_same_split(q, *bio, q->bio_split, );
break;
default:
split = blk_bio_segment_split(q, *bio, q->bio_split, );
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 359d2dc0d414..4780200fd11b 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1477,7 +1477,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue 
*q, struct bio *bio)
 
blk_queue_bounce(q, );
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
bio_io_error(bio);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index fca6b9914948..f6e865b2d543 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1560,7 +1560,7 @@ blk_qc_t drbd_make_request(struct request_queue *q, 
struct bio *bio)
struct drbd_device *device = (struct drbd_device *) q->queuedata;
unsigned long start_jif;
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
start_jif = jiffies;
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index e8a381161db6..1f363638b453 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2414,7 +2414,7 @@ static blk_qc_t pkt_make_request(struct request_queue *q, 
struct bio *bio)
 
blk_queue_bounce(q, );
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
pd = q->queuedata;
if (!pd) {
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 6fa2b8197013..e0e81cacd781 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -606,7 +606,7 @@ static blk_qc_t ps3vram_make_request(struct request_queue 
*q, struct bio *bio)
 
dev_dbg(>core, "%s\n", __func__);
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
spin_lock_irq(>lock);
busy = !bio_list_empty(>list);
diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c
index 0b0a0a902355..4e8bdfa0aa31 100644
--- a/drivers/block/rsxx/dev.c

[PATCH 02/13] blk: replace bioset_create_nobvec() with a flags arg to bioset_create()

2017-06-17 Thread NeilBrown
"flags" arguments are often seen as good API design as they allow
easy extensibility.
bioset_create_nobvec() is implemented internally as a variation in
flags passed to __bioset_create().

To support future extension, make the internal structure part of the
API.
i.e. add a 'flags' argument to bioset_create() and discard
bioset_create_nobvec().

Note that the bio_split allocations in drivers/md/raid* do not need
the bvec mempool - they should have used bioset_create_nobvec().

Suggested-by: Christoph Hellwig 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Signed-off-by: NeilBrown 
---
 block/bio.c |   60 +--
 block/blk-core.c|2 +
 drivers/block/drbd/drbd_main.c  |2 +
 drivers/md/bcache/super.c   |4 +-
 drivers/md/dm-crypt.c   |2 +
 drivers/md/dm-io.c  |2 +
 drivers/md/dm.c |2 +
 drivers/md/md.c |2 +
 drivers/md/raid1.c  |2 +
 drivers/md/raid10.c |2 +
 drivers/md/raid5-cache.c|2 +
 drivers/md/raid5-ppl.c  |2 +
 drivers/md/raid5.c  |2 +
 drivers/target/target_core_iblock.c |2 +
 fs/block_dev.c  |2 +
 fs/btrfs/extent_io.c|3 +-
 fs/xfs/xfs_super.c  |3 +-
 include/linux/bio.h |6 ++--
 18 files changed, 45 insertions(+), 57 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 7a5c8ed27f42..f81545ba44bf 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1921,9 +1921,26 @@ void bioset_free(struct bio_set *bs)
 }
 EXPORT_SYMBOL(bioset_free);
 
-static struct bio_set *__bioset_create(unsigned int pool_size,
-  unsigned int front_pad,
-  bool create_bvec_pool)
+/**
+ * bioset_create  - Create a bio_set
+ * @pool_size: Number of bio and bio_vecs to cache in the mempool
+ * @front_pad: Number of bytes to allocate in front of the returned bio
+ * @flags: Flags to modify behavior, currently only %BIOSET_NEED_BVECS
+ *
+ * Description:
+ *Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller
+ *to ask for a number of bytes to be allocated in front of the bio.
+ *Front pad allocation is useful for embedding the bio inside
+ *another structure, to avoid allocating extra data to go with the bio.
+ *Note that the bio must be embedded at the END of that structure always,
+ *or things will break badly.
+ *If %BIOSET_NEED_BVECS is set in @flags, a separate pool will be allocated
+ *for allocating iovecs.  This pool is not needed e.g. for 
bio_clone_fast().
+ *
+ */
+struct bio_set *bioset_create(unsigned int pool_size,
+ unsigned int front_pad,
+ int flags)
 {
unsigned int back_pad = BIO_INLINE_VECS * sizeof(struct bio_vec);
struct bio_set *bs;
@@ -1948,7 +1965,7 @@ static struct bio_set *__bioset_create(unsigned int 
pool_size,
if (!bs->bio_pool)
goto bad;
 
-   if (create_bvec_pool) {
+   if (flags & BIOSET_NEED_BVECS) {
bs->bvec_pool = biovec_create_pool(pool_size);
if (!bs->bvec_pool)
goto bad;
@@ -1963,41 +1980,8 @@ static struct bio_set *__bioset_create(unsigned int 
pool_size,
bioset_free(bs);
return NULL;
 }
-
-/**
- * bioset_create  - Create a bio_set
- * @pool_size: Number of bio and bio_vecs to cache in the mempool
- * @front_pad: Number of bytes to allocate in front of the returned bio
- *
- * Description:
- *Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller
- *to ask for a number of bytes to be allocated in front of the bio.
- *Front pad allocation is useful for embedding the bio inside
- *another structure, to avoid allocating extra data to go with the bio.
- *Note that the bio must be embedded at the END of that structure always,
- *or things will break badly.
- */
-struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad)
-{
-   return __bioset_create(pool_size, front_pad, true);
-}
 EXPORT_SYMBOL(bioset_create);
 
-/**
- * bioset_create_nobvec  - Create a bio_set without bio_vec mempool
- * @pool_size: Number of bio to cache in the mempool
- * @front_pad: Number of bytes to allocate in front of the returned bio
- *
- * Description:
- *Same functionality as bioset_create() except that mempool is not
- *created for bio_vecs. Saving some memory for bio_clone_fast() users.
- */
-struct bio_set *bioset_create_nobvec(unsigned int pool_size, unsigned int 
front_pad)
-{
-   return __bioset_create(pool_size, front_pad, false);
-}
-EXPORT_SYMBOL(bioset_create_nobvec);
-
 #ifdef CONFIG_BLK_CGROUP
 
 /**
@@ -2112,7 +2096,7 @@ static int __init init_bio(void)

[PATCH 01/13] blk: remove bio_set arg from blk_queue_split()

2017-06-17 Thread NeilBrown
blk_queue_split() is always called with the last arg being q->bio_split,
where 'q' is the first arg.

Also blk_queue_split() sometimes uses the passed-in 'bs' and sometimes uses
q->bio_split.

This is inconsistent and unnecessary.  Remove the last arg and always use
q->bio_split inside blk_queue_split()

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ming Lei 
Credit-to: Javier González  (Noticed that lightnvm was missed)
Reviewed-by: Javier González 
Tested-by: Javier González 
Signed-off-by: NeilBrown 
---
 block/blk-core.c  |2 +-
 block/blk-merge.c |9 -
 block/blk-mq.c|2 +-
 drivers/block/drbd/drbd_req.c |2 +-
 drivers/block/pktcdvd.c   |2 +-
 drivers/block/ps3vram.c   |2 +-
 drivers/block/rsxx/dev.c  |2 +-
 drivers/block/umem.c  |2 +-
 drivers/lightnvm/pblk-init.c  |4 ++--
 drivers/lightnvm/rrpc.c   |2 +-
 drivers/md/md.c   |2 +-
 drivers/s390/block/dcssblk.c  |2 +-
 drivers/s390/block/xpram.c|2 +-
 include/linux/blkdev.h|3 +--
 14 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 8592409db272..31b5ece6b18e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1723,7 +1723,7 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, 
struct bio *bio)
 */
blk_queue_bounce(q, );
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
bio->bi_status = BLK_STS_IOERR;
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 3990ae406341..d59074556703 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -202,8 +202,7 @@ static struct bio *blk_bio_segment_split(struct 
request_queue *q,
return do_split ? new : NULL;
 }
 
-void blk_queue_split(struct request_queue *q, struct bio **bio,
-struct bio_set *bs)
+void blk_queue_split(struct request_queue *q, struct bio **bio)
 {
struct bio *split, *res;
unsigned nsegs;
@@ -211,13 +210,13 @@ void blk_queue_split(struct request_queue *q, struct bio 
**bio,
switch (bio_op(*bio)) {
case REQ_OP_DISCARD:
case REQ_OP_SECURE_ERASE:
-   split = blk_bio_discard_split(q, *bio, bs, );
+   split = blk_bio_discard_split(q, *bio, q->bio_split, );
break;
case REQ_OP_WRITE_ZEROES:
-   split = blk_bio_write_zeroes_split(q, *bio, bs, );
+   split = blk_bio_write_zeroes_split(q, *bio, q->bio_split, 
);
break;
case REQ_OP_WRITE_SAME:
-   split = blk_bio_write_same_split(q, *bio, bs, );
+   split = blk_bio_write_same_split(q, *bio, q->bio_split, );
break;
default:
split = blk_bio_segment_split(q, *bio, q->bio_split, );
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 359d2dc0d414..4780200fd11b 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1477,7 +1477,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue 
*q, struct bio *bio)
 
blk_queue_bounce(q, );
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
bio_io_error(bio);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index fca6b9914948..f6e865b2d543 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1560,7 +1560,7 @@ blk_qc_t drbd_make_request(struct request_queue *q, 
struct bio *bio)
struct drbd_device *device = (struct drbd_device *) q->queuedata;
unsigned long start_jif;
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
start_jif = jiffies;
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index e8a381161db6..1f363638b453 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2414,7 +2414,7 @@ static blk_qc_t pkt_make_request(struct request_queue *q, 
struct bio *bio)
 
blk_queue_bounce(q, );
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
pd = q->queuedata;
if (!pd) {
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 6fa2b8197013..e0e81cacd781 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -606,7 +606,7 @@ static blk_qc_t ps3vram_make_request(struct request_queue 
*q, struct bio *bio)
 
dev_dbg(>core, "%s\n", __func__);
 
-   blk_queue_split(q, , q->bio_split);
+   blk_queue_split(q, );
 
spin_lock_irq(>lock);
busy = !bio_list_empty(>list);
diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c
index 0b0a0a902355..4e8bdfa0aa31 100644
--- a/drivers/block/rsxx/dev.c
+++ b/drivers/block/rsxx/dev.c
@@ -151,7 +151,7 @@ static blk_qc_t rsxx_make_request(struct request_queue *q, 

Re: [PATCH 0/2] Two fixes for loop devices

2017-06-17 Thread NeilBrown
On Fri, Jun 16 2017, Jens Axboe wrote:

> On 06/15/2017 11:02 PM, NeilBrown wrote:
>> Hi Jens,
>>  one of these is a resend of a patch I sent a while back.
>>  The other is new - loop closes files differently from close()
>>  and in a way that can confuse NFS.
>
> Are you wanting to get these into 4.12, or defer to 4.13?

I'm happy either way.  I just want them to land eventually, so I can
tick them off my list.

The conversation with Al might result in a different fix for the
flip_close() problem, but I think that it is still more correct to call
filp_close(), because what loop is doing is a lot like closing a file
that it has been writing to.

Thanks,
NeilBrown


signature.asc
Description: PGP signature


Re: [PATCH 0/2] Two fixes for loop devices

2017-06-17 Thread NeilBrown
On Fri, Jun 16 2017, Jens Axboe wrote:

> On 06/15/2017 11:02 PM, NeilBrown wrote:
>> Hi Jens,
>>  one of these is a resend of a patch I sent a while back.
>>  The other is new - loop closes files differently from close()
>>  and in a way that can confuse NFS.
>
> Are you wanting to get these into 4.12, or defer to 4.13?

I'm happy either way.  I just want them to land eventually, so I can
tick them off my list.

The conversation with Al might result in a different fix for the
flip_close() problem, but I think that it is still more correct to call
filp_close(), because what loop is doing is a lot like closing a file
that it has been writing to.

Thanks,
NeilBrown


signature.asc
Description: PGP signature


Re: [PATCH 1/2] loop: use filp_close() rather than fput()

2017-06-17 Thread NeilBrown
On Sat, Jun 17 2017, Al Viro wrote:

> On Fri, Jun 16, 2017 at 03:02:09PM +1000, NeilBrown wrote:
>> When a loop device is being shutdown the backing file is
>> closed with fput().  This is different from how close(2)
>> closes files - it uses filp_close().
>> 
>> The difference is important for filesystems which provide a ->flush
>> file operation such as NFS.  NFS assumes a flush will always
>> be called on last close, and gets confused otherwise.
>
> Huh?  You do realize that mmap() + close() + modify + msync() + munmap()
> will have IO done *after* the last flush, right?

Yes I do ... or rather I did.  I didn't make that connection this time.

The sequence you describe causes exactly the same sort of problem.
I sent a patch to Trond to add a vfs_fsync() call to nfs_file_release()
but he claims the current behaviour is "working as expected".  I didn't
quite know what to make of that..

https://www.spinics.net/lists/linux-nfs/msg62603.html

To provide the full picture:
 When an NFS file has dirty pages, they (indirectly) hold extra
 references on the superblock, using nfs_sb_active().
 This means that when the filesystem is unmounted, the superblock
 remains active until all the writes complete.  This contrasts with
 every other filesystems where all writes will complete before the
 umount returns.

 When you open/write/close, there will be no dirty pages at umount time
 (because close() flushes) so this doesn't cause a problem.  But when
 you mmap, or use a loop device, then dirty pages can still be around to
 keep the superblock alive.

 The observable symptom that brought this to my attention was that
umount -a -t nfs
disable network
sync

 can hang in sync, because the NFS filesystems can still be waiting to
 write out data.

If nfs_file_release() adds vfs_fsync(), or maybe if __fput() calls
filp->f_op->flush(), then loop.c wouldn't need to use filp_close().

Which would you prefer?

Thanks,
NeilBrown


signature.asc
Description: PGP signature


Re: [PATCH 1/2] loop: use filp_close() rather than fput()

2017-06-17 Thread NeilBrown
On Sat, Jun 17 2017, Al Viro wrote:

> On Fri, Jun 16, 2017 at 03:02:09PM +1000, NeilBrown wrote:
>> When a loop device is being shutdown the backing file is
>> closed with fput().  This is different from how close(2)
>> closes files - it uses filp_close().
>> 
>> The difference is important for filesystems which provide a ->flush
>> file operation such as NFS.  NFS assumes a flush will always
>> be called on last close, and gets confused otherwise.
>
> Huh?  You do realize that mmap() + close() + modify + msync() + munmap()
> will have IO done *after* the last flush, right?

Yes I do ... or rather I did.  I didn't make that connection this time.

The sequence you describe causes exactly the same sort of problem.
I sent a patch to Trond to add a vfs_fsync() call to nfs_file_release()
but he claims the current behaviour is "working as expected".  I didn't
quite know what to make of that..

https://www.spinics.net/lists/linux-nfs/msg62603.html

To provide the full picture:
 When an NFS file has dirty pages, they (indirectly) hold extra
 references on the superblock, using nfs_sb_active().
 This means that when the filesystem is unmounted, the superblock
 remains active until all the writes complete.  This contrasts with
 every other filesystems where all writes will complete before the
 umount returns.

 When you open/write/close, there will be no dirty pages at umount time
 (because close() flushes) so this doesn't cause a problem.  But when
 you mmap, or use a loop device, then dirty pages can still be around to
 keep the superblock alive.

 The observable symptom that brought this to my attention was that
umount -a -t nfs
disable network
sync

 can hang in sync, because the NFS filesystems can still be waiting to
 write out data.

If nfs_file_release() adds vfs_fsync(), or maybe if __fput() calls
filp->f_op->flush(), then loop.c wouldn't need to use filp_close().

Which would you prefer?

Thanks,
NeilBrown


signature.asc
Description: PGP signature


Dear From Mr Majd

2017-06-17 Thread Mr.Firas Majd
Good Day,
May you permit me to express that I have interest to set up a Joint investment 
and partnership with you in your country.My names are Firas Majd,The Finance 
Manager,Cham Bank Syria.Aleppo Branch. In clarity, I am willing to enter into 
any possible discussion that will bring about a business relationship or a Join 
Venture under your managerial commitment.
I will be pleased to further explain my proposed investment areas after 
receiving your feed back.Most Importantly, I want our possible future business 
to be carried out legally and transparently.

Firas Majd
Financial Manager
Cham Bank Syria
Aleppo Branch - Al Faisal Str.  
 
P.O.Box : 5505 Aleppo-Syri


Dear From Mr Majd

2017-06-17 Thread Mr.Firas Majd
Good Day,
May you permit me to express that I have interest to set up a Joint investment 
and partnership with you in your country.My names are Firas Majd,The Finance 
Manager,Cham Bank Syria.Aleppo Branch. In clarity, I am willing to enter into 
any possible discussion that will bring about a business relationship or a Join 
Venture under your managerial commitment.
I will be pleased to further explain my proposed investment areas after 
receiving your feed back.Most Importantly, I want our possible future business 
to be carried out legally and transparently.

Firas Majd
Financial Manager
Cham Bank Syria
Aleppo Branch - Al Faisal Str.  
 
P.O.Box : 5505 Aleppo-Syri


Re: [RFC PATCH 2/2] mm, fs: daxfile, an interface for byte-addressable updates to pmem

2017-06-17 Thread Dan Williams
On Sat, Jun 17, 2017 at 4:50 PM, Andy Lutomirski  wrote:
> On Sat, Jun 17, 2017 at 2:52 PM, Dan Williams  
> wrote:
>> On Sat, Jun 17, 2017 at 9:25 AM, Andy Lutomirski  wrote:
>>>
>>> Can you remind those of us who haven't played with DAX in a while what
>>> the problem is with mmapping a DAX file without this patchset?  If
>>> there's some bookkkeeping needed to make sure that the filesystem will
>>> invalidate all the mappings if it decides to move the file, maybe that
>>> should be the default rather than needing a new syscall.
>>
>> The bookkeeping to invalidate mappings when the filesystem moves a
>> block is already there.
>>
>> Without this patchset an application needs to call fsync/msync after
>> any write to a DAX mapping otherwise there is no guarantee the
>> filesystem has written the metadata to find the updated block after a
>> crash or power loss event. Even if the sync operation is reduced to a
>> minimal cmpxchg in userspace to check if the filesystem-metadata is
>> dirty, that mechanism doesn't translate to a virtualized environment,
>> as requiring guests to trigger host fsync()s is not feasible. It's a
>> half-step solution when you can instead just ask the filesystem to
>> never move blocks, as Dave proposed many months back.
>>
>> We stepped back from that proposal when it looked like a significant
>> amount of per-filesystem work to introduce the capability and it was
>> not clear that application developers would tolerate the side effects
>> of this 'immutable' semantic. However, the implementation is dead
>> simple since ext4 and xfs already need to make
>> block-allocation-immutable semantics available for swapfiles. We also
>> have application developers telling us they are ok with the semantics,
>> especially because it catches Linux up to other operating environments
>> that are already on board with allowing this type of access to pmem
>> through a filesystem. This patchset gives pmem application developers
>> what they want without any additional burden on filesystem
>> implementations.
>
> I see.
>
> I have a couple of minor-ish issues with the current proposal, then.
> One is that I think the terminology should be changed to still make
> sense if filesystems or VFS improves to make this approach
> unnecessary.  Rather than saying "this file is now static", perhaps
> users should set a flag with the explicit semantics that "mmaps of
> this file are guaranteed not to lose data due to the kernel's
> activities", IOW that mmaps will be at least as durable as a direct
> mapping of DAX memory.  Then the kernel has the flexibility to add a
> future implementation in which, instead of pinning the file, the
> filesystem just knows to keep metadata synced before allowing
> page_mkwrite to re-enable writes to an mmapped DAX file.

Yes, sounds good to me. Rename the flag to DAXCTL_F_SYNC to indicate
updates via mmap to this file are synchronous as far as block
allocation metadata is concerned. Future filesystems are then free to
always support this synchronous mode without using the swapfile hack.

> My other objection is that the syscall intentionally leaks a reference
> to the file.  This means it needs overflow protection and it probably
> shouldn't ever be allowed to use it without privilege.

We only hold the one reference while S_DAXFILE is set, so I think the
protection is there, and per Dave's original proposal this requires
CAP_LINUX_IMMUTABLE.

> Why can't the underlying issue be easily fixed, though?  Could
> .page_mkwrite just make sure that metadata is synced when the FS uses
> DAX?

Yes, it most definitely could and that idea has been floated.

> On a DAX fs, syncing metadata should be extremely fast.  This
> could be conditioned on an madvise or mmap flag if performance might
> be an issue.  As far as I know, this change alone should be
> sufficient.

The hang up is that it requires per-fs enabling as it needs to be
careful to manage mmap_sem vs fs journal locks for example. I know the
in-development NOVA [1] filesystem is planning to support this out of
the gate. ext4 would be open to implementing it, but I think xfs is
cold on the idea. Christoph originally proposed it here [2], before
Dave went on to propose immutable semantics.

[1]: https://github.com/NVSL/NOVA
[2]: https://lists.01.org/pipermail/linux-nvdimm/2016-February/004609.html


Re: [RFC PATCH 2/2] mm, fs: daxfile, an interface for byte-addressable updates to pmem

2017-06-17 Thread Dan Williams
On Sat, Jun 17, 2017 at 4:50 PM, Andy Lutomirski  wrote:
> On Sat, Jun 17, 2017 at 2:52 PM, Dan Williams  
> wrote:
>> On Sat, Jun 17, 2017 at 9:25 AM, Andy Lutomirski  wrote:
>>>
>>> Can you remind those of us who haven't played with DAX in a while what
>>> the problem is with mmapping a DAX file without this patchset?  If
>>> there's some bookkkeeping needed to make sure that the filesystem will
>>> invalidate all the mappings if it decides to move the file, maybe that
>>> should be the default rather than needing a new syscall.
>>
>> The bookkeeping to invalidate mappings when the filesystem moves a
>> block is already there.
>>
>> Without this patchset an application needs to call fsync/msync after
>> any write to a DAX mapping otherwise there is no guarantee the
>> filesystem has written the metadata to find the updated block after a
>> crash or power loss event. Even if the sync operation is reduced to a
>> minimal cmpxchg in userspace to check if the filesystem-metadata is
>> dirty, that mechanism doesn't translate to a virtualized environment,
>> as requiring guests to trigger host fsync()s is not feasible. It's a
>> half-step solution when you can instead just ask the filesystem to
>> never move blocks, as Dave proposed many months back.
>>
>> We stepped back from that proposal when it looked like a significant
>> amount of per-filesystem work to introduce the capability and it was
>> not clear that application developers would tolerate the side effects
>> of this 'immutable' semantic. However, the implementation is dead
>> simple since ext4 and xfs already need to make
>> block-allocation-immutable semantics available for swapfiles. We also
>> have application developers telling us they are ok with the semantics,
>> especially because it catches Linux up to other operating environments
>> that are already on board with allowing this type of access to pmem
>> through a filesystem. This patchset gives pmem application developers
>> what they want without any additional burden on filesystem
>> implementations.
>
> I see.
>
> I have a couple of minor-ish issues with the current proposal, then.
> One is that I think the terminology should be changed to still make
> sense if filesystems or VFS improves to make this approach
> unnecessary.  Rather than saying "this file is now static", perhaps
> users should set a flag with the explicit semantics that "mmaps of
> this file are guaranteed not to lose data due to the kernel's
> activities", IOW that mmaps will be at least as durable as a direct
> mapping of DAX memory.  Then the kernel has the flexibility to add a
> future implementation in which, instead of pinning the file, the
> filesystem just knows to keep metadata synced before allowing
> page_mkwrite to re-enable writes to an mmapped DAX file.

Yes, sounds good to me. Rename the flag to DAXCTL_F_SYNC to indicate
updates via mmap to this file are synchronous as far as block
allocation metadata is concerned. Future filesystems are then free to
always support this synchronous mode without using the swapfile hack.

> My other objection is that the syscall intentionally leaks a reference
> to the file.  This means it needs overflow protection and it probably
> shouldn't ever be allowed to use it without privilege.

We only hold the one reference while S_DAXFILE is set, so I think the
protection is there, and per Dave's original proposal this requires
CAP_LINUX_IMMUTABLE.

> Why can't the underlying issue be easily fixed, though?  Could
> .page_mkwrite just make sure that metadata is synced when the FS uses
> DAX?

Yes, it most definitely could and that idea has been floated.

> On a DAX fs, syncing metadata should be extremely fast.  This
> could be conditioned on an madvise or mmap flag if performance might
> be an issue.  As far as I know, this change alone should be
> sufficient.

The hang up is that it requires per-fs enabling as it needs to be
careful to manage mmap_sem vs fs journal locks for example. I know the
in-development NOVA [1] filesystem is planning to support this out of
the gate. ext4 would be open to implementing it, but I think xfs is
cold on the idea. Christoph originally proposed it here [2], before
Dave went on to propose immutable semantics.

[1]: https://github.com/NVSL/NOVA
[2]: https://lists.01.org/pipermail/linux-nvdimm/2016-February/004609.html


[PATCH net-next 01/10] net: dsa: mv88e6xxx: add irl_init_all op

2017-06-17 Thread Vivien Didelot
Some Marvell chips have an Ingress Rate Limit unit. But the command
values slightly differs between models: 88E6352 use 3-bit for operations
while 88E6390 use different 2-bit operations.

This commit kills the IRL flags in favor of a new operation implementing
the "Init all resources to the initial state" operation.

This fixes the operation of 88E6390 family where 0x1000 means Read the
selected resource 0, register 0 on port 16, instead of init all.

A mv88e6xxx_irl_setup helper is added to wrap the operation call.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 47 +
 drivers/net/dsa/mv88e6xxx/chip.h| 19 +++---
 drivers/net/dsa/mv88e6xxx/global2.c | 52 ++---
 drivers/net/dsa/mv88e6xxx/global2.h | 44 ++-
 4 files changed, 113 insertions(+), 49 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 19772e3dd67e..53b088166c28 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -941,6 +941,26 @@ static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
return mv88e6xxx_g1_atu_set_age_time(chip, 30);
 }
 
+static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
+{
+   int port;
+   int err;
+
+   if (!chip->info->ops->irl_init_all)
+   return 0;
+
+   for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+   /* Disable ingress rate limiting by resetting all per port
+* ingress rate limit resources to their initial state.
+*/
+   err = chip->info->ops->irl_init_all(chip, port);
+   if (err)
+   return err;
+   }
+
+   return 0;
+}
+
 static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
 {
u16 pvlan = 0;
@@ -2102,6 +2122,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
goto unlock;
}
 
+   err = mv88e6xxx_irl_setup(chip);
+   if (err)
+   goto unlock;
+
err = mv88e6xxx_phy_setup(chip);
if (err)
goto unlock;
@@ -2339,6 +2363,7 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
 
 static const struct mv88e6xxx_ops mv88e6085_ops = {
/* MV88E6XXX_FAMILY_6097 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6185_phy_ppu_read,
.phy_write = mv88e6185_phy_ppu_write,
@@ -2393,6 +2418,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
 
 static const struct mv88e6xxx_ops mv88e6097_ops = {
/* MV88E6XXX_FAMILY_6097 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2423,6 +2449,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
 
 static const struct mv88e6xxx_ops mv88e6123_ops = {
/* MV88E6XXX_FAMILY_6165 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2479,6 +2506,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
 
 static const struct mv88e6xxx_ops mv88e6141_ops = {
/* MV88E6XXX_FAMILY_6341 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -2512,6 +2540,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
 
 static const struct mv88e6xxx_ops mv88e6161_ops = {
/* MV88E6XXX_FAMILY_6165 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2542,6 +2571,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
 
 static const struct mv88e6xxx_ops mv88e6165_ops = {
/* MV88E6XXX_FAMILY_6165 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6165_phy_read,
.phy_write = mv88e6165_phy_write,
@@ -2565,6 +2595,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
 
 static const struct mv88e6xxx_ops mv88e6171_ops = {
/* MV88E6XXX_FAMILY_6351 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2596,6 +2627,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
 
 static const struct mv88e6xxx_ops mv88e6172_ops = {
/* MV88E6XXX_FAMILY_6352 */
+   .irl_init_all = 

[PATCH net-next 01/10] net: dsa: mv88e6xxx: add irl_init_all op

2017-06-17 Thread Vivien Didelot
Some Marvell chips have an Ingress Rate Limit unit. But the command
values slightly differs between models: 88E6352 use 3-bit for operations
while 88E6390 use different 2-bit operations.

This commit kills the IRL flags in favor of a new operation implementing
the "Init all resources to the initial state" operation.

This fixes the operation of 88E6390 family where 0x1000 means Read the
selected resource 0, register 0 on port 16, instead of init all.

A mv88e6xxx_irl_setup helper is added to wrap the operation call.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/chip.c| 47 +
 drivers/net/dsa/mv88e6xxx/chip.h| 19 +++---
 drivers/net/dsa/mv88e6xxx/global2.c | 52 ++---
 drivers/net/dsa/mv88e6xxx/global2.h | 44 ++-
 4 files changed, 113 insertions(+), 49 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 19772e3dd67e..53b088166c28 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -941,6 +941,26 @@ static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
return mv88e6xxx_g1_atu_set_age_time(chip, 30);
 }
 
+static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip)
+{
+   int port;
+   int err;
+
+   if (!chip->info->ops->irl_init_all)
+   return 0;
+
+   for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+   /* Disable ingress rate limiting by resetting all per port
+* ingress rate limit resources to their initial state.
+*/
+   err = chip->info->ops->irl_init_all(chip, port);
+   if (err)
+   return err;
+   }
+
+   return 0;
+}
+
 static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
 {
u16 pvlan = 0;
@@ -2102,6 +2122,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
goto unlock;
}
 
+   err = mv88e6xxx_irl_setup(chip);
+   if (err)
+   goto unlock;
+
err = mv88e6xxx_phy_setup(chip);
if (err)
goto unlock;
@@ -2339,6 +2363,7 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
 
 static const struct mv88e6xxx_ops mv88e6085_ops = {
/* MV88E6XXX_FAMILY_6097 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6185_phy_ppu_read,
.phy_write = mv88e6185_phy_ppu_write,
@@ -2393,6 +2418,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
 
 static const struct mv88e6xxx_ops mv88e6097_ops = {
/* MV88E6XXX_FAMILY_6097 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2423,6 +2449,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
 
 static const struct mv88e6xxx_ops mv88e6123_ops = {
/* MV88E6XXX_FAMILY_6165 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2479,6 +2506,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
 
 static const struct mv88e6xxx_ops mv88e6141_ops = {
/* MV88E6XXX_FAMILY_6341 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom8,
.set_eeprom = mv88e6xxx_g2_set_eeprom8,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -2512,6 +2540,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
 
 static const struct mv88e6xxx_ops mv88e6161_ops = {
/* MV88E6XXX_FAMILY_6165 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2542,6 +2571,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
 
 static const struct mv88e6xxx_ops mv88e6165_ops = {
/* MV88E6XXX_FAMILY_6165 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6165_phy_read,
.phy_write = mv88e6165_phy_write,
@@ -2565,6 +2595,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
 
 static const struct mv88e6xxx_ops mv88e6171_ops = {
/* MV88E6XXX_FAMILY_6351 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -2596,6 +2627,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
 
 static const struct mv88e6xxx_ops mv88e6172_ops = {
/* MV88E6XXX_FAMILY_6352 */
+   .irl_init_all = mv88e6352_g2_irl_init_all,

[PATCH net-next 10/10] net: dsa: mv88e6xxx: prefix Global 2 remaining macros

2017-06-17 Thread Vivien Didelot
Prefix and document the remaining Global 2 registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 27 ---
 drivers/net/dsa/mv88e6xxx/global2.h | 65 +
 2 files changed, 57 insertions(+), 35 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index ab72eaa92cc3..158d0f499874 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -1,6 +1,5 @@
 /*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address
- * 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
@@ -23,22 +22,22 @@
 
 static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
 {
-   return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
+   return mv88e6xxx_read(chip, MV88E6XXX_G2, reg, val);
 }
 
 static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
 {
-   return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
+   return mv88e6xxx_write(chip, MV88E6XXX_G2, reg, val);
 }
 
 static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 
update)
 {
-   return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
+   return mv88e6xxx_update(chip, MV88E6XXX_G2, reg, update);
 }
 
 static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
 {
-   return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
+   return mv88e6xxx_wait(chip, MV88E6XXX_G2, reg, mask);
 }
 
 /* Offset 0x02: Management Enable 2x */
@@ -258,7 +257,7 @@ static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip 
*chip, int pointer,
 {
u16 val = (pointer << 8) | (data & 0x7);
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_PRIO_OVERRIDE, val);
 }
 
 static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
@@ -864,7 +863,7 @@ static int mv88e6xxx_g2_watchdog_setup(struct 
mv88e6xxx_chip *chip)
int err;
 
chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain,
- GLOBAL2_INT_SOURCE_WATCHDOG);
+ MV88E6XXX_G2_INT_SOURCE_WATCHDOG);
if (chip->watchdog_irq < 0)
return chip->watchdog_irq;
 
@@ -891,16 +890,16 @@ static int mv88e6xxx_g2_misc_5_bit_port(struct 
mv88e6xxx_chip *chip,
u16 val;
int err;
 
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_MISC, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_MISC, );
if (err)
return err;
 
if (port_5_bit)
-   val |= GLOBAL2_MISC_5_BIT_PORT;
+   val |= MV88E6XXX_G2_MISC_5_BIT_PORT;
else
-   val &= ~GLOBAL2_MISC_5_BIT_PORT;
+   val &= ~MV88E6XXX_G2_MISC_5_BIT_PORT;
 
-   return mv88e6xxx_g2_write(chip, GLOBAL2_MISC, val);
+   return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MISC, val);
 }
 
 int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
@@ -934,7 +933,7 @@ static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void 
*dev_id)
u16 reg;
 
mutex_lock(>reg_lock);
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SOURCE, );
mutex_unlock(>reg_lock);
if (err)
goto out;
@@ -961,7 +960,7 @@ static void mv88e6xxx_g2_irq_bus_sync_unlock(struct 
irq_data *d)
 {
struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
+   mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, ~chip->g2_irq.masked);
 
mutex_unlock(>reg_lock);
 }
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 211e136dd7d9..392f1c493611 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -1,5 +1,5 @@
 /*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
@@ -17,11 +17,14 @@
 
 #include "chip.h"
 
-#define ADDR_GLOBAL2   0x1c
+#define MV88E6XXX_G2   0x1c
 
-#define GLOBAL2_INT_SOURCE 0x00
-#define GLOBAL2_INT_SOURCE_WATCHDOG15
-#define GLOBAL2_INT_MASK   0x01
+/* Offset 0x00: Interrupt Source Register */
+#define MV88E6XXX_G2_INT_SOURCE0x00
+#define MV88E6XXX_G2_INT_SOURCE_WATCHDOG   15
+
+/* Offset 0x01: Interrupt Mask Register */
+#define MV88E6XXX_G2_INT_MASK  0x01
 
 /* Offset 0x02: MGMT Enable Register 2x */
 #define MV88E6XXX_G2_MGMT_EN_2X0x02
@@ -29,7 +32,8 @@
 /* Offset 0x03: MGMT Enable Register 0x */
 #define MV88E6XXX_G2_MGMT_EN_0X0x03
 
-#define GLOBAL2_FLOW_CONTROL   0x04
+/* Offset 

[PATCH net-next 10/10] net: dsa: mv88e6xxx: prefix Global 2 remaining macros

2017-06-17 Thread Vivien Didelot
Prefix and document the remaining Global 2 registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 27 ---
 drivers/net/dsa/mv88e6xxx/global2.h | 65 +
 2 files changed, 57 insertions(+), 35 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index ab72eaa92cc3..158d0f499874 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -1,6 +1,5 @@
 /*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address
- * 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
@@ -23,22 +22,22 @@
 
 static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
 {
-   return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
+   return mv88e6xxx_read(chip, MV88E6XXX_G2, reg, val);
 }
 
 static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
 {
-   return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
+   return mv88e6xxx_write(chip, MV88E6XXX_G2, reg, val);
 }
 
 static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 
update)
 {
-   return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
+   return mv88e6xxx_update(chip, MV88E6XXX_G2, reg, update);
 }
 
 static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
 {
-   return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
+   return mv88e6xxx_wait(chip, MV88E6XXX_G2, reg, mask);
 }
 
 /* Offset 0x02: Management Enable 2x */
@@ -258,7 +257,7 @@ static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip 
*chip, int pointer,
 {
u16 val = (pointer << 8) | (data & 0x7);
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_PRIO_OVERRIDE, val);
 }
 
 static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
@@ -864,7 +863,7 @@ static int mv88e6xxx_g2_watchdog_setup(struct 
mv88e6xxx_chip *chip)
int err;
 
chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain,
- GLOBAL2_INT_SOURCE_WATCHDOG);
+ MV88E6XXX_G2_INT_SOURCE_WATCHDOG);
if (chip->watchdog_irq < 0)
return chip->watchdog_irq;
 
@@ -891,16 +890,16 @@ static int mv88e6xxx_g2_misc_5_bit_port(struct 
mv88e6xxx_chip *chip,
u16 val;
int err;
 
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_MISC, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_MISC, );
if (err)
return err;
 
if (port_5_bit)
-   val |= GLOBAL2_MISC_5_BIT_PORT;
+   val |= MV88E6XXX_G2_MISC_5_BIT_PORT;
else
-   val &= ~GLOBAL2_MISC_5_BIT_PORT;
+   val &= ~MV88E6XXX_G2_MISC_5_BIT_PORT;
 
-   return mv88e6xxx_g2_write(chip, GLOBAL2_MISC, val);
+   return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MISC, val);
 }
 
 int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
@@ -934,7 +933,7 @@ static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void 
*dev_id)
u16 reg;
 
mutex_lock(>reg_lock);
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SOURCE, );
mutex_unlock(>reg_lock);
if (err)
goto out;
@@ -961,7 +960,7 @@ static void mv88e6xxx_g2_irq_bus_sync_unlock(struct 
irq_data *d)
 {
struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
+   mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, ~chip->g2_irq.masked);
 
mutex_unlock(>reg_lock);
 }
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 211e136dd7d9..392f1c493611 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -1,5 +1,5 @@
 /*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
@@ -17,11 +17,14 @@
 
 #include "chip.h"
 
-#define ADDR_GLOBAL2   0x1c
+#define MV88E6XXX_G2   0x1c
 
-#define GLOBAL2_INT_SOURCE 0x00
-#define GLOBAL2_INT_SOURCE_WATCHDOG15
-#define GLOBAL2_INT_MASK   0x01
+/* Offset 0x00: Interrupt Source Register */
+#define MV88E6XXX_G2_INT_SOURCE0x00
+#define MV88E6XXX_G2_INT_SOURCE_WATCHDOG   15
+
+/* Offset 0x01: Interrupt Mask Register */
+#define MV88E6XXX_G2_INT_MASK  0x01
 
 /* Offset 0x02: MGMT Enable Register 2x */
 #define MV88E6XXX_G2_MGMT_EN_2X0x02
@@ -29,7 +32,8 @@
 /* Offset 0x03: MGMT Enable Register 0x */
 #define MV88E6XXX_G2_MGMT_EN_0X0x03
 
-#define GLOBAL2_FLOW_CONTROL   0x04
+/* Offset 0x04: Flow Control Delay Register */

[PATCH net-next 08/10] net: dsa: mv88e6xxx: prefix Global 2 Switch MAC macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Switch MAC registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 2 +-
 drivers/net/dsa/mv88e6xxx/global2.h | 7 ++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index 8621f5893406..0977ba1697a6 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -235,7 +235,7 @@ static int mv88e6xxx_g2_switch_mac_write(struct 
mv88e6xxx_chip *chip,
 {
u16 val = (pointer << 8) | data;
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SWITCH_MAC, val);
 }
 
 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index dab6a7ff7d0f..b3561a9fac2d 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -92,7 +92,12 @@
 #define MV88E6XXX_G2_PVT_DATA  0x0c
 #define MV88E6XXX_G2_PVT_DATA_MASK 0x7f
 
-#define GLOBAL2_SWITCH_MAC 0x0d
+/* Offset 0x0D: Switch MAC/WoL/WoF Register */
+#define MV88E6XXX_G2_SWITCH_MAC0x0d
+#define MV88E6XXX_G2_SWITCH_MAC_UPDATE 0x8000
+#define MV88E6XXX_G2_SWITCH_MAC_PTR_MASK   0x1f00
+#define MV88E6XXX_G2_SWITCH_MAC_DATA_MASK  0x00ff
+
 #define GLOBAL2_ATU_STATS  0x0e
 #define GLOBAL2_PRIO_OVERRIDE  0x0f
 #define GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP  BIT(7)
-- 
2.13.1



[PATCH net-next 07/10] net: dsa: mv88e6xxx: prefix Global 2 EEPROM macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 EEPROM registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 32 +---
 drivers/net/dsa/mv88e6xxx/global2.h | 31 +--
 2 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index dc6c0f5fd605..8621f5893406 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -282,16 +282,17 @@ static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip 
*chip)
 
 static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
-GLOBAL2_EEPROM_CMD_BUSY |
-GLOBAL2_EEPROM_CMD_RUNNING);
+   return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_EEPROM_CMD,
+MV88E6XXX_G2_EEPROM_CMD_BUSY |
+MV88E6XXX_G2_EEPROM_CMD_RUNNING);
 }
 
 static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
 {
int err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_EEPROM_CMD,
+MV88E6XXX_G2_EEPROM_CMD_BUSY | cmd);
if (err)
return err;
 
@@ -301,14 +302,14 @@ static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip 
*chip, u16 cmd)
 static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip,
 u16 addr, u8 *data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr);
+   err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
if (err)
return err;
 
@@ -316,7 +317,7 @@ static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip 
*chip,
if (err)
return err;
 
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, );
if (err)
return err;
 
@@ -328,14 +329,15 @@ static int mv88e6xxx_g2_eeprom_read8(struct 
mv88e6xxx_chip *chip,
 static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip,
  u16 addr, u8 data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | GLOBAL2_EEPROM_CMD_WRITE_EN;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE |
+   MV88E6XXX_G2_EEPROM_CMD_WRITE_EN;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr);
+   err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
if (err)
return err;
 
@@ -345,7 +347,7 @@ static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip 
*chip,
 static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
  u8 addr, u16 *data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ | addr;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
@@ -356,20 +358,20 @@ static int mv88e6xxx_g2_eeprom_read16(struct 
mv88e6xxx_chip *chip,
if (err)
return err;
 
-   return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
+   return mv88e6xxx_g2_read(chip, MV88E6352_G2_EEPROM_DATA, data);
 }
 
 static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
   u8 addr, u16 data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | addr;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
+   err = mv88e6xxx_g2_write(chip, MV88E6352_G2_EEPROM_DATA, data);
if (err)
return err;
 
@@ -481,11 +483,11 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
int err;
 
/* Ensure the RO WriteEn bit is set */
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, );
if (err)
return err;
 
-   if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
+   if (!(val & MV88E6XXX_G2_EEPROM_CMD_WRITE_EN))
return -EROFS;
 
eeprom->len = 0;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index be2e2a30cd0a..dab6a7ff7d0f 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -99,16 +99,27 @@
 #define 

[PATCH net-next 08/10] net: dsa: mv88e6xxx: prefix Global 2 Switch MAC macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Switch MAC registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 2 +-
 drivers/net/dsa/mv88e6xxx/global2.h | 7 ++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index 8621f5893406..0977ba1697a6 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -235,7 +235,7 @@ static int mv88e6xxx_g2_switch_mac_write(struct 
mv88e6xxx_chip *chip,
 {
u16 val = (pointer << 8) | data;
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SWITCH_MAC, val);
 }
 
 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index dab6a7ff7d0f..b3561a9fac2d 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -92,7 +92,12 @@
 #define MV88E6XXX_G2_PVT_DATA  0x0c
 #define MV88E6XXX_G2_PVT_DATA_MASK 0x7f
 
-#define GLOBAL2_SWITCH_MAC 0x0d
+/* Offset 0x0D: Switch MAC/WoL/WoF Register */
+#define MV88E6XXX_G2_SWITCH_MAC0x0d
+#define MV88E6XXX_G2_SWITCH_MAC_UPDATE 0x8000
+#define MV88E6XXX_G2_SWITCH_MAC_PTR_MASK   0x1f00
+#define MV88E6XXX_G2_SWITCH_MAC_DATA_MASK  0x00ff
+
 #define GLOBAL2_ATU_STATS  0x0e
 #define GLOBAL2_PRIO_OVERRIDE  0x0f
 #define GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP  BIT(7)
-- 
2.13.1



[PATCH net-next 07/10] net: dsa: mv88e6xxx: prefix Global 2 EEPROM macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 EEPROM registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 32 +---
 drivers/net/dsa/mv88e6xxx/global2.h | 31 +--
 2 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index dc6c0f5fd605..8621f5893406 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -282,16 +282,17 @@ static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip 
*chip)
 
 static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
-GLOBAL2_EEPROM_CMD_BUSY |
-GLOBAL2_EEPROM_CMD_RUNNING);
+   return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_EEPROM_CMD,
+MV88E6XXX_G2_EEPROM_CMD_BUSY |
+MV88E6XXX_G2_EEPROM_CMD_RUNNING);
 }
 
 static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
 {
int err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_EEPROM_CMD,
+MV88E6XXX_G2_EEPROM_CMD_BUSY | cmd);
if (err)
return err;
 
@@ -301,14 +302,14 @@ static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip 
*chip, u16 cmd)
 static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip,
 u16 addr, u8 *data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr);
+   err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
if (err)
return err;
 
@@ -316,7 +317,7 @@ static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip 
*chip,
if (err)
return err;
 
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, );
if (err)
return err;
 
@@ -328,14 +329,15 @@ static int mv88e6xxx_g2_eeprom_read8(struct 
mv88e6xxx_chip *chip,
 static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip,
  u16 addr, u8 data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | GLOBAL2_EEPROM_CMD_WRITE_EN;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE |
+   MV88E6XXX_G2_EEPROM_CMD_WRITE_EN;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr);
+   err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr);
if (err)
return err;
 
@@ -345,7 +347,7 @@ static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip 
*chip,
 static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
  u8 addr, u16 *data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ | addr;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
@@ -356,20 +358,20 @@ static int mv88e6xxx_g2_eeprom_read16(struct 
mv88e6xxx_chip *chip,
if (err)
return err;
 
-   return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
+   return mv88e6xxx_g2_read(chip, MV88E6352_G2_EEPROM_DATA, data);
 }
 
 static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
   u8 addr, u16 data)
 {
-   u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
+   u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | addr;
int err;
 
err = mv88e6xxx_g2_eeprom_wait(chip);
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
+   err = mv88e6xxx_g2_write(chip, MV88E6352_G2_EEPROM_DATA, data);
if (err)
return err;
 
@@ -481,11 +483,11 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
int err;
 
/* Ensure the RO WriteEn bit is set */
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, );
+   err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, );
if (err)
return err;
 
-   if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
+   if (!(val & MV88E6XXX_G2_EEPROM_CMD_WRITE_EN))
return -EROFS;
 
eeprom->len = 0;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index be2e2a30cd0a..dab6a7ff7d0f 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -99,16 +99,27 @@
 #define GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT  4
 #define 

[PATCH net-next 05/10] net: dsa: mv88e6xxx: prefix Global 2 MGMT macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 MGMT registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 11 ++-
 drivers/net/dsa/mv88e6xxx/global2.h | 23 +++
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index d5239c4f3a9b..718bc9bf430d 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -52,7 +52,7 @@ int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
 * addresses matching 01:80:c2:00:00:2x as MGMT.
 */
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0x);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, 0x);
if (err)
return err;
}
@@ -61,7 +61,8 @@ int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
 * addresses matching 01:80:c2:00:00:0x as MGMT.
 */
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
-   return mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0x);
+   return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X,
+ 0x);
 
return 0;
 }
@@ -1056,11 +1057,11 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
 * highest, and send all special multicast frames to the CPU
 * port at the highest priority.
 */
-   reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
+   reg = MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI | (0x7 << 4);
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
-   reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
+   reg |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU | 0x7;
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, reg);
if (err)
return err;
 
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 21a865225e63..7312e1723058 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -22,15 +22,22 @@
 #define GLOBAL2_INT_SOURCE 0x00
 #define GLOBAL2_INT_SOURCE_WATCHDOG15
 #define GLOBAL2_INT_MASK   0x01
-#define GLOBAL2_MGMT_EN_2X 0x02
-#define GLOBAL2_MGMT_EN_0X 0x03
+
+/* Offset 0x02: MGMT Enable Register 2x */
+#define MV88E6XXX_G2_MGMT_EN_2X0x02
+
+/* Offset 0x03: MGMT Enable Register 0x */
+#define MV88E6XXX_G2_MGMT_EN_0X0x03
+
 #define GLOBAL2_FLOW_CONTROL   0x04
-#define GLOBAL2_SWITCH_MGMT0x05
-#define GLOBAL2_SWITCH_MGMT_USE_DOUBLE_TAG_DATABIT(15)
-#define GLOBAL2_SWITCH_MGMT_PREVENT_LOOPS  BIT(14)
-#define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG   BIT(13)
-#define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRIBIT(7)
-#define GLOBAL2_SWITCH_MGMT_RSVD2CPU   BIT(3)
+
+/* Offset 0x05: Switch Management Register */
+#define MV88E6XXX_G2_SWITCH_MGMT   0x05
+#define MV88E6XXX_G2_SWITCH_MGMT_USE_DOUBLE_TAG_DATA   0x8000
+#define MV88E6XXX_G2_SWITCH_MGMT_PREVENT_LOOPS 0x4000
+#define MV88E6XXX_G2_SWITCH_MGMT_FLOW_CTL_MSG  0x2000
+#define MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI0x0080
+#define MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU  0x0008
 
 /* Offset 0x06: Device Mapping Table Register */
 #define MV88E6XXX_G2_DEVICE_MAPPING0x06
-- 
2.13.1



[PATCH net-next 04/10] net: dsa: mv88e6xxx: prefix Global 2 Device Mapping macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Device Mapping macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c |  2 +-
 drivers/net/dsa/mv88e6xxx/global2.h | 10 ++
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index d821b9591a8f..d5239c4f3a9b 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -73,7 +73,7 @@ static int mv88e6xxx_g2_device_mapping_write(struct 
mv88e6xxx_chip *chip,
 {
u16 val = (target << 8) | (port & 0xf);
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val);
 }
 
 static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index bb09224c73c6..21a865225e63 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -31,10 +31,12 @@
 #define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG   BIT(13)
 #define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRIBIT(7)
 #define GLOBAL2_SWITCH_MGMT_RSVD2CPU   BIT(3)
-#define GLOBAL2_DEVICE_MAPPING 0x06
-#define GLOBAL2_DEVICE_MAPPING_UPDATE  BIT(15)
-#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT8
-#define GLOBAL2_DEVICE_MAPPING_PORT_MASK   0x0f
+
+/* Offset 0x06: Device Mapping Table Register */
+#define MV88E6XXX_G2_DEVICE_MAPPING0x06
+#define MV88E6XXX_G2_DEVICE_MAPPING_UPDATE 0x8000
+#define MV88E6XXX_G2_DEVICE_MAPPING_DEV_MASK   0x1f00
+#define MV88E6XXX_G2_DEVICE_MAPPING_PORT_MASK  0x000f
 
 /* Offset 0x07: Trunk Mask Table Register */
 #define MV88E6XXX_G2_TRUNK_MASK0x07
-- 
2.13.1



[PATCH net-next 05/10] net: dsa: mv88e6xxx: prefix Global 2 MGMT macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 MGMT registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 11 ++-
 drivers/net/dsa/mv88e6xxx/global2.h | 23 +++
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index d5239c4f3a9b..718bc9bf430d 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -52,7 +52,7 @@ int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
 * addresses matching 01:80:c2:00:00:2x as MGMT.
 */
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0x);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, 0x);
if (err)
return err;
}
@@ -61,7 +61,8 @@ int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
 * addresses matching 01:80:c2:00:00:0x as MGMT.
 */
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
-   return mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0x);
+   return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X,
+ 0x);
 
return 0;
 }
@@ -1056,11 +1057,11 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
 * highest, and send all special multicast frames to the CPU
 * port at the highest priority.
 */
-   reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
+   reg = MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI | (0x7 << 4);
if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
-   reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
+   reg |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU | 0x7;
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, reg);
if (err)
return err;
 
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 21a865225e63..7312e1723058 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -22,15 +22,22 @@
 #define GLOBAL2_INT_SOURCE 0x00
 #define GLOBAL2_INT_SOURCE_WATCHDOG15
 #define GLOBAL2_INT_MASK   0x01
-#define GLOBAL2_MGMT_EN_2X 0x02
-#define GLOBAL2_MGMT_EN_0X 0x03
+
+/* Offset 0x02: MGMT Enable Register 2x */
+#define MV88E6XXX_G2_MGMT_EN_2X0x02
+
+/* Offset 0x03: MGMT Enable Register 0x */
+#define MV88E6XXX_G2_MGMT_EN_0X0x03
+
 #define GLOBAL2_FLOW_CONTROL   0x04
-#define GLOBAL2_SWITCH_MGMT0x05
-#define GLOBAL2_SWITCH_MGMT_USE_DOUBLE_TAG_DATABIT(15)
-#define GLOBAL2_SWITCH_MGMT_PREVENT_LOOPS  BIT(14)
-#define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG   BIT(13)
-#define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRIBIT(7)
-#define GLOBAL2_SWITCH_MGMT_RSVD2CPU   BIT(3)
+
+/* Offset 0x05: Switch Management Register */
+#define MV88E6XXX_G2_SWITCH_MGMT   0x05
+#define MV88E6XXX_G2_SWITCH_MGMT_USE_DOUBLE_TAG_DATA   0x8000
+#define MV88E6XXX_G2_SWITCH_MGMT_PREVENT_LOOPS 0x4000
+#define MV88E6XXX_G2_SWITCH_MGMT_FLOW_CTL_MSG  0x2000
+#define MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI0x0080
+#define MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU  0x0008
 
 /* Offset 0x06: Device Mapping Table Register */
 #define MV88E6XXX_G2_DEVICE_MAPPING0x06
-- 
2.13.1



[PATCH net-next 04/10] net: dsa: mv88e6xxx: prefix Global 2 Device Mapping macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Device Mapping macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c |  2 +-
 drivers/net/dsa/mv88e6xxx/global2.h | 10 ++
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index d821b9591a8f..d5239c4f3a9b 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -73,7 +73,7 @@ static int mv88e6xxx_g2_device_mapping_write(struct 
mv88e6xxx_chip *chip,
 {
u16 val = (target << 8) | (port & 0xf);
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val);
 }
 
 static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index bb09224c73c6..21a865225e63 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -31,10 +31,12 @@
 #define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG   BIT(13)
 #define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRIBIT(7)
 #define GLOBAL2_SWITCH_MGMT_RSVD2CPU   BIT(3)
-#define GLOBAL2_DEVICE_MAPPING 0x06
-#define GLOBAL2_DEVICE_MAPPING_UPDATE  BIT(15)
-#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT8
-#define GLOBAL2_DEVICE_MAPPING_PORT_MASK   0x0f
+
+/* Offset 0x06: Device Mapping Table Register */
+#define MV88E6XXX_G2_DEVICE_MAPPING0x06
+#define MV88E6XXX_G2_DEVICE_MAPPING_UPDATE 0x8000
+#define MV88E6XXX_G2_DEVICE_MAPPING_DEV_MASK   0x1f00
+#define MV88E6XXX_G2_DEVICE_MAPPING_PORT_MASK  0x000f
 
 /* Offset 0x07: Trunk Mask Table Register */
 #define MV88E6XXX_G2_TRUNK_MASK0x07
-- 
2.13.1



[PATCH net-next 09/10] net: dsa: mv88e6xxx: prefix Global 2 Watchdog macros

2017-06-17 Thread Vivien Didelot
The Marvell 88E6352 family has a Global 2 register dedicated to the
watchdog setup. But the 88E6390 turned it into an indirect table.

Prefix and document that.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 48 +++--
 drivers/net/dsa/mv88e6xxx/global2.h | 47 
 2 files changed, 52 insertions(+), 43 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index 0977ba1697a6..ab72eaa92cc3 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -752,7 +752,7 @@ static int mv88e6097_watchdog_action(struct mv88e6xxx_chip 
*chip, int irq)
 {
u16 reg;
 
-   mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, );
 
dev_info(chip->dev, "Watchdog event: 0x%04x", reg);
 
@@ -763,20 +763,20 @@ static void mv88e6097_watchdog_free(struct mv88e6xxx_chip 
*chip)
 {
u16 reg;
 
-   mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, );
 
-   reg &= ~(GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
-GLOBAL2_WDOG_CONTROL_QC_ENABLE);
+   reg &= ~(MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |
+MV88E6352_G2_WDOG_CTL_QC_ENABLE);
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, reg);
+   mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL, reg);
 }
 
 static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL,
- GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
- GLOBAL2_WDOG_CONTROL_QC_ENABLE |
- GLOBAL2_WDOG_CONTROL_SWRESET);
+   return mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL,
+ MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |
+ MV88E6352_G2_WDOG_CTL_QC_ENABLE |
+ MV88E6352_G2_WDOG_CTL_SWRESET);
 }
 
 const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
@@ -787,12 +787,12 @@ const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
 
 static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
-  GLOBAL2_WDOG_INT_ENABLE |
-  GLOBAL2_WDOG_CUT_THROUGH |
-  GLOBAL2_WDOG_QUEUE_CONTROLLER |
-  GLOBAL2_WDOG_EGRESS |
-  GLOBAL2_WDOG_FORCE_IRQ);
+   return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
+  MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE |
+  MV88E6390_G2_WDOG_CTL_CUT_THROUGH |
+  MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER |
+  MV88E6390_G2_WDOG_CTL_EGRESS |
+  MV88E6390_G2_WDOG_CTL_FORCE_IRQ);
 }
 
 static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
@@ -800,17 +800,19 @@ static int mv88e6390_watchdog_action(struct 
mv88e6xxx_chip *chip, int irq)
int err;
u16 reg;
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_EVENT);
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+  MV88E6390_G2_WDOG_CTL_PTR_EVENT);
+   err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, );
 
dev_info(chip->dev, "Watchdog event: 0x%04x",
-reg & GLOBAL2_WDOG_DATA_MASK);
+reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_HISTORY);
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+  MV88E6390_G2_WDOG_CTL_PTR_HISTORY);
+   err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, );
 
dev_info(chip->dev, "Watchdog history: 0x%04x",
-reg & GLOBAL2_WDOG_DATA_MASK);
+reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);
 
/* Trigger a software reset to try to recover the switch */
if (chip->info->ops->reset)
@@ -823,8 +825,8 @@ static int mv88e6390_watchdog_action(struct mv88e6xxx_chip 
*chip, int irq)
 
 static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)
 {
-   mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
-   GLOBAL2_WDOG_INT_ENABLE);
+   mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
+   MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE);
 }
 
 const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 

[PATCH net-next 00/10] net: dsa: Global 2 cosmetics

2017-06-17 Thread Vivien Didelot
Similarly to what has been done for the Port and Global 1 registers,
this patch series prefixes and documents the macros of Global 2.

It brings no functional changes except for 1/10 which fixes the IRL init
for 88E6390 family.

Vivien Didelot (10):
  net: dsa: mv88e6xxx: add irl_init_all op
  net: dsa: mv88e6xxx: clarify SMI PHY functions
  net: dsa: mv88e6xxx: prefix Global 2 Trunk macros
  net: dsa: mv88e6xxx: prefix Global 2 Device Mapping macros
  net: dsa: mv88e6xxx: prefix Global 2 MGMT macros
  net: dsa: mv88e6xxx: prefix Global 2 PVT macros
  net: dsa: mv88e6xxx: prefix Global 2 EEPROM macros
  net: dsa: mv88e6xxx: prefix Global 2 Switch MAC macros
  net: dsa: mv88e6xxx: prefix Global 2 Watchdog macros
  net: dsa: mv88e6xxx: prefix Global 2 remaining macros

 drivers/net/dsa/mv88e6xxx/chip.c|  47 
 drivers/net/dsa/mv88e6xxx/chip.h|  19 +-
 drivers/net/dsa/mv88e6xxx/global2.c | 449 
 drivers/net/dsa/mv88e6xxx/global2.h | 309 -
 4 files changed, 501 insertions(+), 323 deletions(-)

-- 
2.13.1



[PATCH net-next 09/10] net: dsa: mv88e6xxx: prefix Global 2 Watchdog macros

2017-06-17 Thread Vivien Didelot
The Marvell 88E6352 family has a Global 2 register dedicated to the
watchdog setup. But the 88E6390 turned it into an indirect table.

Prefix and document that.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 48 +++--
 drivers/net/dsa/mv88e6xxx/global2.h | 47 
 2 files changed, 52 insertions(+), 43 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index 0977ba1697a6..ab72eaa92cc3 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -752,7 +752,7 @@ static int mv88e6097_watchdog_action(struct mv88e6xxx_chip 
*chip, int irq)
 {
u16 reg;
 
-   mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, );
 
dev_info(chip->dev, "Watchdog event: 0x%04x", reg);
 
@@ -763,20 +763,20 @@ static void mv88e6097_watchdog_free(struct mv88e6xxx_chip 
*chip)
 {
u16 reg;
 
-   mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, );
 
-   reg &= ~(GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
-GLOBAL2_WDOG_CONTROL_QC_ENABLE);
+   reg &= ~(MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |
+MV88E6352_G2_WDOG_CTL_QC_ENABLE);
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, reg);
+   mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL, reg);
 }
 
 static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL,
- GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
- GLOBAL2_WDOG_CONTROL_QC_ENABLE |
- GLOBAL2_WDOG_CONTROL_SWRESET);
+   return mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL,
+ MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE |
+ MV88E6352_G2_WDOG_CTL_QC_ENABLE |
+ MV88E6352_G2_WDOG_CTL_SWRESET);
 }
 
 const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
@@ -787,12 +787,12 @@ const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
 
 static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
-  GLOBAL2_WDOG_INT_ENABLE |
-  GLOBAL2_WDOG_CUT_THROUGH |
-  GLOBAL2_WDOG_QUEUE_CONTROLLER |
-  GLOBAL2_WDOG_EGRESS |
-  GLOBAL2_WDOG_FORCE_IRQ);
+   return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
+  MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE |
+  MV88E6390_G2_WDOG_CTL_CUT_THROUGH |
+  MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER |
+  MV88E6390_G2_WDOG_CTL_EGRESS |
+  MV88E6390_G2_WDOG_CTL_FORCE_IRQ);
 }
 
 static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
@@ -800,17 +800,19 @@ static int mv88e6390_watchdog_action(struct 
mv88e6xxx_chip *chip, int irq)
int err;
u16 reg;
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_EVENT);
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+  MV88E6390_G2_WDOG_CTL_PTR_EVENT);
+   err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, );
 
dev_info(chip->dev, "Watchdog event: 0x%04x",
-reg & GLOBAL2_WDOG_DATA_MASK);
+reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);
 
-   mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_HISTORY);
-   err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, );
+   mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+  MV88E6390_G2_WDOG_CTL_PTR_HISTORY);
+   err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, );
 
dev_info(chip->dev, "Watchdog history: 0x%04x",
-reg & GLOBAL2_WDOG_DATA_MASK);
+reg & MV88E6390_G2_WDOG_CTL_DATA_MASK);
 
/* Trigger a software reset to try to recover the switch */
if (chip->info->ops->reset)
@@ -823,8 +825,8 @@ static int mv88e6390_watchdog_action(struct mv88e6xxx_chip 
*chip, int irq)
 
 static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)
 {
-   mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
-   GLOBAL2_WDOG_INT_ENABLE);
+   mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
+   MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE);
 }
 
 const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index b3561a9fac2d..211e136dd7d9 100644
--- 

[PATCH net-next 00/10] net: dsa: Global 2 cosmetics

2017-06-17 Thread Vivien Didelot
Similarly to what has been done for the Port and Global 1 registers,
this patch series prefixes and documents the macros of Global 2.

It brings no functional changes except for 1/10 which fixes the IRL init
for 88E6390 family.

Vivien Didelot (10):
  net: dsa: mv88e6xxx: add irl_init_all op
  net: dsa: mv88e6xxx: clarify SMI PHY functions
  net: dsa: mv88e6xxx: prefix Global 2 Trunk macros
  net: dsa: mv88e6xxx: prefix Global 2 Device Mapping macros
  net: dsa: mv88e6xxx: prefix Global 2 MGMT macros
  net: dsa: mv88e6xxx: prefix Global 2 PVT macros
  net: dsa: mv88e6xxx: prefix Global 2 EEPROM macros
  net: dsa: mv88e6xxx: prefix Global 2 Switch MAC macros
  net: dsa: mv88e6xxx: prefix Global 2 Watchdog macros
  net: dsa: mv88e6xxx: prefix Global 2 remaining macros

 drivers/net/dsa/mv88e6xxx/chip.c|  47 
 drivers/net/dsa/mv88e6xxx/chip.h|  19 +-
 drivers/net/dsa/mv88e6xxx/global2.c | 449 
 drivers/net/dsa/mv88e6xxx/global2.h | 309 -
 4 files changed, 501 insertions(+), 323 deletions(-)

-- 
2.13.1



[PATCH net-next 06/10] net: dsa: mv88e6xxx: prefix Global 2 PVT macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Cross-chip Port VLAN registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 14 --
 drivers/net/dsa/mv88e6xxx/global2.h | 19 +--
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index 718bc9bf430d..dc6c0f5fd605 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -188,7 +188,8 @@ int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, 
int port)
 
 static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_wait(chip, GLOBAL2_PVT_ADDR, GLOBAL2_PVT_ADDR_BUSY);
+   return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_PVT_ADDR,
+MV88E6XXX_G2_PVT_ADDR_BUSY);
 }
 
 static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev,
@@ -196,13 +197,14 @@ static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip 
*chip, int src_dev,
 {
int err;
 
-   /* 9-bit Cross-chip PVT pointer: with GLOBAL2_MISC_5_BIT_PORT cleared,
-* source device is 5-bit, source port is 4-bit.
+   /* 9-bit Cross-chip PVT pointer: with MV88E6XXX_G2_MISC_5_BIT_PORT
+* cleared, source device is 5-bit, source port is 4-bit.
 */
+   op |= MV88E6XXX_G2_PVT_ADDR_BUSY;
op |= (src_dev & 0x1f) << 4;
op |= (src_port & 0xf);
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR, op);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_ADDR, op);
if (err)
return err;
 
@@ -218,12 +220,12 @@ int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, 
int src_dev,
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_DATA, data);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_DATA, data);
if (err)
return err;
 
return mv88e6xxx_g2_pvt_op(chip, src_dev, src_port,
-  GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN);
+  MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN);
 }
 
 /* Offset 0x0D: Switch MAC/WoL/WoF register */
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 7312e1723058..be2e2a30cd0a 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -79,12 +79,19 @@
 #define MV88E6XXX_G2_IRL_DATA  0x0a
 #define MV88E6XXX_G2_IRL_DATA_MASK 0x
 
-#define GLOBAL2_PVT_ADDR   0x0b
-#define GLOBAL2_PVT_ADDR_BUSY  BIT(15)
-#define GLOBAL2_PVT_ADDR_OP_INIT_ONES  ((0x01 << 12) | GLOBAL2_PVT_ADDR_BUSY)
-#define GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN((0x03 << 12) | 
GLOBAL2_PVT_ADDR_BUSY)
-#define GLOBAL2_PVT_ADDR_OP_READ   ((0x04 << 12) | GLOBAL2_PVT_ADDR_BUSY)
-#define GLOBAL2_PVT_DATA   0x0c
+/* Offset 0x0B: Cross-chip Port VLAN Register */
+#define MV88E6XXX_G2_PVT_ADDR  0x0b
+#define MV88E6XXX_G2_PVT_ADDR_BUSY 0x8000
+#define MV88E6XXX_G2_PVT_ADDR_OP_MASK  0x7000
+#define MV88E6XXX_G2_PVT_ADDR_OP_INIT_ONES 0x1000
+#define MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN   0x3000
+#define MV88E6XXX_G2_PVT_ADDR_OP_READ  0x4000
+#define MV88E6XXX_G2_PVT_ADDR_PTR_MASK 0x01ff
+
+/* Offset 0x0C: Cross-chip Port VLAN Data Register */
+#define MV88E6XXX_G2_PVT_DATA  0x0c
+#define MV88E6XXX_G2_PVT_DATA_MASK 0x7f
+
 #define GLOBAL2_SWITCH_MAC 0x0d
 #define GLOBAL2_ATU_STATS  0x0e
 #define GLOBAL2_PRIO_OVERRIDE  0x0f
-- 
2.13.1



[PATCH net-next] net: dsa: mv88e6xxx: better IEEE Prio Mapping Table description

2017-06-17 Thread Vivien Didelot
Kill the remaining shift macro in favor of calculating at compile time
its value from the more descriptive mask, which gives us a better
representation of the register layout.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/port.c | 11 +--
 drivers/net/dsa/mv88e6xxx/port.h |  4 +++-
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 73d825e08be3..a7801f6668a5 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include 
 #include 
 #include 
 
@@ -912,15 +913,13 @@ int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, 
int port)
 }
 
 static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
-   int port, u16 table,
-   u8 pointer, u16 data)
+   int port, u16 table, u8 ptr, u16 data)
 {
u16 reg;
 
-   reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
-   table |
-   (pointer << MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
-   data;
+   reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
+   (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
+   (data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
 
return mv88e6xxx_port_write(chip, port,
MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 8a34ea7c868a..8f3991bf1851 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -222,6 +222,7 @@
 /* Offset 0x18: IEEE Priority Mapping Table */
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE  0x8000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_MASK0x7000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP 0x
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP0x1000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP   0x2000
@@ -229,7 +230,8 @@
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP   0x5000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP  0x6000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP 0x7000
-#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT   9
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK0x0e00
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK   0x01ff
 
 /* Offset 0x18: Port IEEE Priority Remapping Registers (0-3) */
 #define MV88E6095_PORT_IEEE_PRIO_REMAP_01230x18
-- 
2.13.1



[PATCH net-next 03/10] net: dsa: mv88e6xxx: prefix Global 2 Trunk macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Trunk registers macros. At the same
time, fix the hask -> hash typo and use the mv88e6xxx_port_mask helper.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 13 ++---
 drivers/net/dsa/mv88e6xxx/global2.h | 18 +++---
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index f20a60af35cb..d821b9591a8f 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -102,15 +102,14 @@ static int mv88e6xxx_g2_set_device_mapping(struct 
mv88e6xxx_chip *chip)
 /* Offset 0x07: Trunk Mask Table register */
 
 static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
-bool hask, u16 mask)
+bool hash, u16 mask)
 {
-   const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
-   u16 val = (num << 12) | (mask & port_mask);
+   u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip));
 
-   if (hask)
-   val |= GLOBAL2_TRUNK_MASK_HASK;
+   if (hash)
+   val |= MV88E6XXX_G2_TRUNK_MASK_HASH;
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MASK, val);
 }
 
 /* Offset 0x08: Trunk Mapping Table register */
@@ -121,7 +120,7 @@ static int mv88e6xxx_g2_trunk_mapping_write(struct 
mv88e6xxx_chip *chip, int id,
const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
u16 val = (id << 11) | (map & port_mask);
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val);
 }
 
 static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index e4b40e896709..bb09224c73c6 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -35,13 +35,17 @@
 #define GLOBAL2_DEVICE_MAPPING_UPDATE  BIT(15)
 #define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT8
 #define GLOBAL2_DEVICE_MAPPING_PORT_MASK   0x0f
-#define GLOBAL2_TRUNK_MASK 0x07
-#define GLOBAL2_TRUNK_MASK_UPDATE  BIT(15)
-#define GLOBAL2_TRUNK_MASK_NUM_SHIFT   12
-#define GLOBAL2_TRUNK_MASK_HASKBIT(11)
-#define GLOBAL2_TRUNK_MAPPING  0x08
-#define GLOBAL2_TRUNK_MAPPING_UPDATE   BIT(15)
-#define GLOBAL2_TRUNK_MAPPING_ID_SHIFT 11
+
+/* Offset 0x07: Trunk Mask Table Register */
+#define MV88E6XXX_G2_TRUNK_MASK0x07
+#define MV88E6XXX_G2_TRUNK_MASK_UPDATE 0x8000
+#define MV88E6XXX_G2_TRUNK_MASK_NUM_MASK   0x7000
+#define MV88E6XXX_G2_TRUNK_MASK_HASH   0x0800
+
+/* Offset 0x08: Trunk Mapping Table Register */
+#define MV88E6XXX_G2_TRUNK_MAPPING 0x08
+#define MV88E6XXX_G2_TRUNK_MAPPING_UPDATE  0x8000
+#define MV88E6XXX_G2_TRUNK_MAPPING_ID_MASK 0x7800
 
 /* Offset 0x09: Ingress Rate Command Register */
 #define MV88E6XXX_G2_IRL_CMD   0x09
-- 
2.13.1



[PATCH net-next 06/10] net: dsa: mv88e6xxx: prefix Global 2 PVT macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Cross-chip Port VLAN registers macros.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 14 --
 drivers/net/dsa/mv88e6xxx/global2.h | 19 +--
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index 718bc9bf430d..dc6c0f5fd605 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -188,7 +188,8 @@ int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, 
int port)
 
 static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_wait(chip, GLOBAL2_PVT_ADDR, GLOBAL2_PVT_ADDR_BUSY);
+   return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_PVT_ADDR,
+MV88E6XXX_G2_PVT_ADDR_BUSY);
 }
 
 static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev,
@@ -196,13 +197,14 @@ static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip 
*chip, int src_dev,
 {
int err;
 
-   /* 9-bit Cross-chip PVT pointer: with GLOBAL2_MISC_5_BIT_PORT cleared,
-* source device is 5-bit, source port is 4-bit.
+   /* 9-bit Cross-chip PVT pointer: with MV88E6XXX_G2_MISC_5_BIT_PORT
+* cleared, source device is 5-bit, source port is 4-bit.
 */
+   op |= MV88E6XXX_G2_PVT_ADDR_BUSY;
op |= (src_dev & 0x1f) << 4;
op |= (src_port & 0xf);
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR, op);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_ADDR, op);
if (err)
return err;
 
@@ -218,12 +220,12 @@ int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, 
int src_dev,
if (err)
return err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_DATA, data);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_DATA, data);
if (err)
return err;
 
return mv88e6xxx_g2_pvt_op(chip, src_dev, src_port,
-  GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN);
+  MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN);
 }
 
 /* Offset 0x0D: Switch MAC/WoL/WoF register */
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index 7312e1723058..be2e2a30cd0a 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -79,12 +79,19 @@
 #define MV88E6XXX_G2_IRL_DATA  0x0a
 #define MV88E6XXX_G2_IRL_DATA_MASK 0x
 
-#define GLOBAL2_PVT_ADDR   0x0b
-#define GLOBAL2_PVT_ADDR_BUSY  BIT(15)
-#define GLOBAL2_PVT_ADDR_OP_INIT_ONES  ((0x01 << 12) | GLOBAL2_PVT_ADDR_BUSY)
-#define GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN((0x03 << 12) | 
GLOBAL2_PVT_ADDR_BUSY)
-#define GLOBAL2_PVT_ADDR_OP_READ   ((0x04 << 12) | GLOBAL2_PVT_ADDR_BUSY)
-#define GLOBAL2_PVT_DATA   0x0c
+/* Offset 0x0B: Cross-chip Port VLAN Register */
+#define MV88E6XXX_G2_PVT_ADDR  0x0b
+#define MV88E6XXX_G2_PVT_ADDR_BUSY 0x8000
+#define MV88E6XXX_G2_PVT_ADDR_OP_MASK  0x7000
+#define MV88E6XXX_G2_PVT_ADDR_OP_INIT_ONES 0x1000
+#define MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN   0x3000
+#define MV88E6XXX_G2_PVT_ADDR_OP_READ  0x4000
+#define MV88E6XXX_G2_PVT_ADDR_PTR_MASK 0x01ff
+
+/* Offset 0x0C: Cross-chip Port VLAN Data Register */
+#define MV88E6XXX_G2_PVT_DATA  0x0c
+#define MV88E6XXX_G2_PVT_DATA_MASK 0x7f
+
 #define GLOBAL2_SWITCH_MAC 0x0d
 #define GLOBAL2_ATU_STATS  0x0e
 #define GLOBAL2_PRIO_OVERRIDE  0x0f
-- 
2.13.1



[PATCH net-next] net: dsa: mv88e6xxx: better IEEE Prio Mapping Table description

2017-06-17 Thread Vivien Didelot
Kill the remaining shift macro in favor of calculating at compile time
its value from the more descriptive mask, which gives us a better
representation of the register layout.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/port.c | 11 +--
 drivers/net/dsa/mv88e6xxx/port.h |  4 +++-
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 73d825e08be3..a7801f6668a5 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include 
 #include 
 #include 
 
@@ -912,15 +913,13 @@ int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, 
int port)
 }
 
 static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
-   int port, u16 table,
-   u8 pointer, u16 data)
+   int port, u16 table, u8 ptr, u16 data)
 {
u16 reg;
 
-   reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
-   table |
-   (pointer << MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
-   data;
+   reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
+   (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
+   (data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
 
return mv88e6xxx_port_write(chip, port,
MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 8a34ea7c868a..8f3991bf1851 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -222,6 +222,7 @@
 /* Offset 0x18: IEEE Priority Mapping Table */
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE  0x8000
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_MASK0x7000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP 0x
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP0x1000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP   0x2000
@@ -229,7 +230,8 @@
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP   0x5000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP  0x6000
 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP 0x7000
-#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT   9
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK0x0e00
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK   0x01ff
 
 /* Offset 0x18: Port IEEE Priority Remapping Registers (0-3) */
 #define MV88E6095_PORT_IEEE_PRIO_REMAP_01230x18
-- 
2.13.1



[PATCH net-next 03/10] net: dsa: mv88e6xxx: prefix Global 2 Trunk macros

2017-06-17 Thread Vivien Didelot
Prefix and document the Global 2 Trunk registers macros. At the same
time, fix the hask -> hash typo and use the mv88e6xxx_port_mask helper.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 13 ++---
 drivers/net/dsa/mv88e6xxx/global2.h | 18 +++---
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index f20a60af35cb..d821b9591a8f 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -102,15 +102,14 @@ static int mv88e6xxx_g2_set_device_mapping(struct 
mv88e6xxx_chip *chip)
 /* Offset 0x07: Trunk Mask Table register */
 
 static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
-bool hask, u16 mask)
+bool hash, u16 mask)
 {
-   const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
-   u16 val = (num << 12) | (mask & port_mask);
+   u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip));
 
-   if (hask)
-   val |= GLOBAL2_TRUNK_MASK_HASK;
+   if (hash)
+   val |= MV88E6XXX_G2_TRUNK_MASK_HASH;
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MASK, val);
 }
 
 /* Offset 0x08: Trunk Mapping Table register */
@@ -121,7 +120,7 @@ static int mv88e6xxx_g2_trunk_mapping_write(struct 
mv88e6xxx_chip *chip, int id,
const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
u16 val = (id << 11) | (map & port_mask);
 
-   return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
+   return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val);
 }
 
 static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h 
b/drivers/net/dsa/mv88e6xxx/global2.h
index e4b40e896709..bb09224c73c6 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -35,13 +35,17 @@
 #define GLOBAL2_DEVICE_MAPPING_UPDATE  BIT(15)
 #define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT8
 #define GLOBAL2_DEVICE_MAPPING_PORT_MASK   0x0f
-#define GLOBAL2_TRUNK_MASK 0x07
-#define GLOBAL2_TRUNK_MASK_UPDATE  BIT(15)
-#define GLOBAL2_TRUNK_MASK_NUM_SHIFT   12
-#define GLOBAL2_TRUNK_MASK_HASKBIT(11)
-#define GLOBAL2_TRUNK_MAPPING  0x08
-#define GLOBAL2_TRUNK_MAPPING_UPDATE   BIT(15)
-#define GLOBAL2_TRUNK_MAPPING_ID_SHIFT 11
+
+/* Offset 0x07: Trunk Mask Table Register */
+#define MV88E6XXX_G2_TRUNK_MASK0x07
+#define MV88E6XXX_G2_TRUNK_MASK_UPDATE 0x8000
+#define MV88E6XXX_G2_TRUNK_MASK_NUM_MASK   0x7000
+#define MV88E6XXX_G2_TRUNK_MASK_HASH   0x0800
+
+/* Offset 0x08: Trunk Mapping Table Register */
+#define MV88E6XXX_G2_TRUNK_MAPPING 0x08
+#define MV88E6XXX_G2_TRUNK_MAPPING_UPDATE  0x8000
+#define MV88E6XXX_G2_TRUNK_MAPPING_ID_MASK 0x7800
 
 /* Offset 0x09: Ingress Rate Command Register */
 #define MV88E6XXX_G2_IRL_CMD   0x09
-- 
2.13.1



[PATCH net-next 02/10] net: dsa: mv88e6xxx: clarify SMI PHY functions

2017-06-17 Thread Vivien Didelot
Marvell chips with an SMI PHY access in Global 2 registers handle both
Clause 22 and Clause 45 of IEEE 802.3.

The 88E6390 family has addition bits to target the internal or external
PHYs connected to the device, and a Setup function in addition to the
default (register) Access function.

Prefix the SMI PHY Command and Data registers macros, implement clear
helpers for Clause 22 and 44 Access functions, rename variable to match
the SMI and switch vocabulary (device and register addresses for Clause
22 and port and device class for Clause 45.)

Finally do not use complex macros but simple 16-bit mask to document the
registers organization.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 248 +---
 drivers/net/dsa/mv88e6xxx/global2.h |  41 +++---
 2 files changed, 166 insertions(+), 123 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index baa86b1abad3..f20a60af35cb 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -13,6 +13,7 @@
  * (at your option) any later version.
  */
 
+#include 
 #include 
 #include 
 
@@ -541,171 +542,206 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip 
*chip,
 
 static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
-GLOBAL2_SMI_PHY_CMD_BUSY);
+   return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_SMI_PHY_CMD,
+MV88E6XXX_G2_SMI_PHY_CMD_BUSY);
 }
 
 static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
 {
int err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_CMD,
+MV88E6XXX_G2_SMI_PHY_CMD_BUSY | cmd);
if (err)
return err;
 
return mv88e6xxx_g2_smi_phy_wait(chip);
 }
 
-static int mv88e6xxx_g2_smi_phy_write_addr(struct mv88e6xxx_chip *chip,
-  int addr, int device, int reg,
-  bool external)
+static int mv88e6xxx_g2_smi_phy_access(struct mv88e6xxx_chip *chip,
+  bool external, bool c45, u16 op, int dev,
+  int reg)
 {
-   int cmd = SMI_CMD_OP_45_WRITE_ADDR | (addr << 5) | device;
-   int err;
+   u16 cmd = op;
 
if (external)
-   cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+   cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL;
+   else
+   cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL; /* empty mask */
 
-   err = mv88e6xxx_g2_smi_phy_wait(chip);
-   if (err)
-   return err;
+   if (c45)
+   cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_45; /* empty mask */
+   else
+   cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_22;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, reg);
-   if (err)
-   return err;
+   dev <<= __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK);
+   cmd |= dev & MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK;
+   cmd |= reg & MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK;
 
return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
 }
 
+static int mv88e6xxx_g2_smi_phy_access_c22(struct mv88e6xxx_chip *chip,
+  bool external, u16 op, int dev,
+  int reg)
+{
+   return mv88e6xxx_g2_smi_phy_access(chip, external, false, op, dev, reg);
+}
+
+/* IEEE 802.3 Clause 22 Read Data Register */
+static int mv88e6xxx_g2_smi_phy_read_data_c22(struct mv88e6xxx_chip *chip,
+ bool external, int dev, int reg,
+ u16 *data)
+{
+   u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA;
+   int err;
+
+   err = mv88e6xxx_g2_smi_phy_wait(chip);
+   if (err)
+   return err;
+
+   err = mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
+   if (err)
+   return err;
+
+   return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
+}
+
+/* IEEE 802.3 Clause 22 Write Data Register */
+static int mv88e6xxx_g2_smi_phy_write_data_c22(struct mv88e6xxx_chip *chip,
+  bool external, int dev, int reg,
+  u16 data)
+{
+   u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA;
+   int err;
+
+   err = mv88e6xxx_g2_smi_phy_wait(chip);
+   if (err)
+   return err;
+
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
+   if (err)
+   return err;
+
+   return mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
+}
+
+static int 

[PATCH net-next 02/10] net: dsa: mv88e6xxx: clarify SMI PHY functions

2017-06-17 Thread Vivien Didelot
Marvell chips with an SMI PHY access in Global 2 registers handle both
Clause 22 and Clause 45 of IEEE 802.3.

The 88E6390 family has addition bits to target the internal or external
PHYs connected to the device, and a Setup function in addition to the
default (register) Access function.

Prefix the SMI PHY Command and Data registers macros, implement clear
helpers for Clause 22 and 44 Access functions, rename variable to match
the SMI and switch vocabulary (device and register addresses for Clause
22 and port and device class for Clause 45.)

Finally do not use complex macros but simple 16-bit mask to document the
registers organization.

Signed-off-by: Vivien Didelot 
---
 drivers/net/dsa/mv88e6xxx/global2.c | 248 +---
 drivers/net/dsa/mv88e6xxx/global2.h |  41 +++---
 2 files changed, 166 insertions(+), 123 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c 
b/drivers/net/dsa/mv88e6xxx/global2.c
index baa86b1abad3..f20a60af35cb 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -13,6 +13,7 @@
  * (at your option) any later version.
  */
 
+#include 
 #include 
 #include 
 
@@ -541,171 +542,206 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip 
*chip,
 
 static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
 {
-   return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
-GLOBAL2_SMI_PHY_CMD_BUSY);
+   return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_SMI_PHY_CMD,
+MV88E6XXX_G2_SMI_PHY_CMD_BUSY);
 }
 
 static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
 {
int err;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_CMD,
+MV88E6XXX_G2_SMI_PHY_CMD_BUSY | cmd);
if (err)
return err;
 
return mv88e6xxx_g2_smi_phy_wait(chip);
 }
 
-static int mv88e6xxx_g2_smi_phy_write_addr(struct mv88e6xxx_chip *chip,
-  int addr, int device, int reg,
-  bool external)
+static int mv88e6xxx_g2_smi_phy_access(struct mv88e6xxx_chip *chip,
+  bool external, bool c45, u16 op, int dev,
+  int reg)
 {
-   int cmd = SMI_CMD_OP_45_WRITE_ADDR | (addr << 5) | device;
-   int err;
+   u16 cmd = op;
 
if (external)
-   cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+   cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL;
+   else
+   cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL; /* empty mask */
 
-   err = mv88e6xxx_g2_smi_phy_wait(chip);
-   if (err)
-   return err;
+   if (c45)
+   cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_45; /* empty mask */
+   else
+   cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_22;
 
-   err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, reg);
-   if (err)
-   return err;
+   dev <<= __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK);
+   cmd |= dev & MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK;
+   cmd |= reg & MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK;
 
return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
 }
 
+static int mv88e6xxx_g2_smi_phy_access_c22(struct mv88e6xxx_chip *chip,
+  bool external, u16 op, int dev,
+  int reg)
+{
+   return mv88e6xxx_g2_smi_phy_access(chip, external, false, op, dev, reg);
+}
+
+/* IEEE 802.3 Clause 22 Read Data Register */
+static int mv88e6xxx_g2_smi_phy_read_data_c22(struct mv88e6xxx_chip *chip,
+ bool external, int dev, int reg,
+ u16 *data)
+{
+   u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA;
+   int err;
+
+   err = mv88e6xxx_g2_smi_phy_wait(chip);
+   if (err)
+   return err;
+
+   err = mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
+   if (err)
+   return err;
+
+   return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
+}
+
+/* IEEE 802.3 Clause 22 Write Data Register */
+static int mv88e6xxx_g2_smi_phy_write_data_c22(struct mv88e6xxx_chip *chip,
+  bool external, int dev, int reg,
+  u16 data)
+{
+   u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA;
+   int err;
+
+   err = mv88e6xxx_g2_smi_phy_wait(chip);
+   if (err)
+   return err;
+
+   err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data);
+   if (err)
+   return err;
+
+   return mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg);
+}
+
+static int mv88e6xxx_g2_smi_phy_access_c45(struct mv88e6xxx_chip *chip,
+

Re: [PATCH 3/3] selftest/net/Makefile: Specify output with $(OUTPUT)

2017-06-17 Thread David Miller
From: SeongJae Park 
Date: Sun, 18 Jun 2017 09:56:04 +0900

> After commit a8ba798bc8ec ("selftests: enable O and KBUILD_OUTPUT"),
> net selftest build fails because it points output file without $(OUTPUT)
> yet.  This commit fixes the error.
> 
> Signed-off-by: SeongJae Park 
> Fixes: a8ba798bc8ec ("selftests: enable O and KBUILD_OUTPUT")

Acked-by: David S. Miller 


Re: [PATCH 3/3] selftest/net/Makefile: Specify output with $(OUTPUT)

2017-06-17 Thread David Miller
From: SeongJae Park 
Date: Sun, 18 Jun 2017 09:56:04 +0900

> After commit a8ba798bc8ec ("selftests: enable O and KBUILD_OUTPUT"),
> net selftest build fails because it points output file without $(OUTPUT)
> yet.  This commit fixes the error.
> 
> Signed-off-by: SeongJae Park 
> Fixes: a8ba798bc8ec ("selftests: enable O and KBUILD_OUTPUT")

Acked-by: David S. Miller 


Re: [PATCH 03/15] spi: qup: Add completion timeout for dma mode

2017-06-17 Thread kbuild test robot
Hi Varadarajan,

[auto build test ERROR on spi/for-next]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64 

Note: the 
linux-review/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
 HEAD 6d576268af40336063b1df090673a480642ce26d builds fine.
  It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/spi/spi-qup.c: In function 'spi_qup_do_dma':
>> drivers/spi/spi-qup.c:356:62: error: 'timeout' undeclared (first use in this 
>> function)
 if (xfer->rx_buf && !wait_for_completion_timeout(>rxc, timeout))
 ^~~
   drivers/spi/spi-qup.c:356:62: note: each undeclared identifier is reported 
only once for each function it appears in

vim +/timeout +356 drivers/spi/spi-qup.c

   350  if (ret)
   351  return ret;
   352  
   353  dma_async_issue_pending(master->dma_tx);
   354  }
   355  
 > 356  if (xfer->rx_buf && !wait_for_completion_timeout(>rxc, 
 > timeout))
   357  return -ETIMEDOUT;
   358  
   359  if (xfer->tx_buf && !wait_for_completion_timeout(>txc, 
timeout))

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH 03/15] spi: qup: Add completion timeout for dma mode

2017-06-17 Thread kbuild test robot
Hi Varadarajan,

[auto build test ERROR on spi/for-next]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64 

Note: the 
linux-review/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
 HEAD 6d576268af40336063b1df090673a480642ce26d builds fine.
  It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/spi/spi-qup.c: In function 'spi_qup_do_dma':
>> drivers/spi/spi-qup.c:356:62: error: 'timeout' undeclared (first use in this 
>> function)
 if (xfer->rx_buf && !wait_for_completion_timeout(>rxc, timeout))
 ^~~
   drivers/spi/spi-qup.c:356:62: note: each undeclared identifier is reported 
only once for each function it appears in

vim +/timeout +356 drivers/spi/spi-qup.c

   350  if (ret)
   351  return ret;
   352  
   353  dma_async_issue_pending(master->dma_tx);
   354  }
   355  
 > 356  if (xfer->rx_buf && !wait_for_completion_timeout(>rxc, 
 > timeout))
   357  return -ETIMEDOUT;
   358  
   359  if (xfer->tx_buf && !wait_for_completion_timeout(>txc, 
timeout))

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH 07/15] spi: qup: Fix transaction done signaling

2017-06-17 Thread kbuild test robot
Hi Varadarajan,

[auto build test ERROR on spi/for-next]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64 

Note: the 
linux-review/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
 HEAD 6d576268af40336063b1df090673a480642ce26d builds fine.
  It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/spi/spi-qup.c: In function 'spi_qup_do_pio':
   drivers/spi/spi-qup.c:382:24: warning: format '%s' expects a matching 'char 
*' argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
   ^
   drivers/spi/spi-qup.c:382:27: warning: format '%d' expects a matching 'int' 
argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
  ^
   drivers/spi/spi-qup.c:388:24: warning: format '%s' expects a matching 'char 
*' argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set PAUSE state\n");
   ^
   drivers/spi/spi-qup.c:388:27: warning: format '%d' expects a matching 'int' 
argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set PAUSE state\n");
  ^
   drivers/spi/spi-qup.c:396:24: warning: format '%s' expects a matching 'char 
*' argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
   ^
   drivers/spi/spi-qup.c:396:27: warning: format '%d' expects a matching 'int' 
argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
  ^
   drivers/spi/spi-qup.c: In function 'spi_qup_qup_irq':
>> drivers/spi/spi-qup.c:445:34: error: 'xfer' undeclared (first use in this 
>> function)
   spi_qup_fifo_read(controller, xfer);
 ^~~~
   drivers/spi/spi-qup.c:445:34: note: each undeclared identifier is reported 
only once for each function it appears in

vim +/xfer +445 drivers/spi/spi-qup.c

612762e8 Andy Gross2015-03-04  390  }
612762e8 Andy Gross2015-03-04  391  
612762e8 Andy Gross2015-03-04  392  spi_qup_fifo_write(qup, 
xfer);
612762e8 Andy Gross2015-03-04  393  
4c05e25b Varadarajan Narayanan 2017-06-16  394  ret = 
spi_qup_set_state(qup, QUP_STATE_RUN);
4c05e25b Varadarajan Narayanan 2017-06-16  395  if (ret) {
4c05e25b Varadarajan Narayanan 2017-06-16 @396  
dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
4c05e25b Varadarajan Narayanan 2017-06-16  397  return ret;
4c05e25b Varadarajan Narayanan 2017-06-16  398  }
4c05e25b Varadarajan Narayanan 2017-06-16  399  
dd4ce14d Varadarajan Narayanan 2017-06-16  400  if 
(!wait_for_completion_timeout(>done, timeout))
dd4ce14d Varadarajan Narayanan 2017-06-16  401  return 
-ETIMEDOUT;
dd4ce14d Varadarajan Narayanan 2017-06-16  402  
612762e8 Andy Gross2015-03-04  403  return 0;
612762e8 Andy Gross2015-03-04  404  }
612762e8 Andy Gross2015-03-04  405  
64ff247a Ivan T. Ivanov2014-02-13  406  static irqreturn_t 
spi_qup_qup_irq(int irq, void *dev_id)
64ff247a Ivan T. Ivanov2014-02-13  407  {
64ff247a Ivan T. Ivanov2014-02-13  408  struct spi_qup 
*controller = dev_id;
64ff247a Ivan T. Ivanov2014-02-13  409  u32 opflags, qup_err, 
spi_err;
64ff247a Ivan T. Ivanov2014-02-13  410  int error = 0;
64ff247a Ivan T. Ivanov2014-02-13  411  
64ff247a Ivan T. Ivanov2014-02-13  412  qup_err = 
readl_relaxed(controller->base + QUP_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  413  spi_err = 
readl_relaxed(controller->base + SPI_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  414  opflags = 
readl_relaxed(controller->base + QUP_OPERATIONAL);
64ff247a Ivan T. Ivanov2014-02-13  415  
64ff247a Ivan T. Ivanov2014-02-13  416  writel_relaxed(qup_err, 
controller->base + QUP_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  417  writel_relaxed(spi_err, 
controller->base + SPI_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  418  
64ff247a Ivan T. Ivanov2014-02-13  419  if (qup_err) {
64ff247a Ivan T. Ivanov   

Re: [PATCH 07/15] spi: qup: Fix transaction done signaling

2017-06-17 Thread kbuild test robot
Hi Varadarajan,

[auto build test ERROR on spi/for-next]
[also build test ERROR on v4.12-rc5 next-20170616]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64 

Note: the 
linux-review/Varadarajan-Narayanan/spi-qup-Fixes-and-add-support-for-64k-transfers/20170618-072148
 HEAD 6d576268af40336063b1df090673a480642ce26d builds fine.
  It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/spi/spi-qup.c: In function 'spi_qup_do_pio':
   drivers/spi/spi-qup.c:382:24: warning: format '%s' expects a matching 'char 
*' argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
   ^
   drivers/spi/spi-qup.c:382:27: warning: format '%d' expects a matching 'int' 
argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
  ^
   drivers/spi/spi-qup.c:388:24: warning: format '%s' expects a matching 'char 
*' argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set PAUSE state\n");
   ^
   drivers/spi/spi-qup.c:388:27: warning: format '%d' expects a matching 'int' 
argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set PAUSE state\n");
  ^
   drivers/spi/spi-qup.c:396:24: warning: format '%s' expects a matching 'char 
*' argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
   ^
   drivers/spi/spi-qup.c:396:27: warning: format '%d' expects a matching 'int' 
argument [-Wformat=]
  dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
  ^
   drivers/spi/spi-qup.c: In function 'spi_qup_qup_irq':
>> drivers/spi/spi-qup.c:445:34: error: 'xfer' undeclared (first use in this 
>> function)
   spi_qup_fifo_read(controller, xfer);
 ^~~~
   drivers/spi/spi-qup.c:445:34: note: each undeclared identifier is reported 
only once for each function it appears in

vim +/xfer +445 drivers/spi/spi-qup.c

612762e8 Andy Gross2015-03-04  390  }
612762e8 Andy Gross2015-03-04  391  
612762e8 Andy Gross2015-03-04  392  spi_qup_fifo_write(qup, 
xfer);
612762e8 Andy Gross2015-03-04  393  
4c05e25b Varadarajan Narayanan 2017-06-16  394  ret = 
spi_qup_set_state(qup, QUP_STATE_RUN);
4c05e25b Varadarajan Narayanan 2017-06-16  395  if (ret) {
4c05e25b Varadarajan Narayanan 2017-06-16 @396  
dev_warn(qup->dev, "%s(%d): cannot set RUN state\n");
4c05e25b Varadarajan Narayanan 2017-06-16  397  return ret;
4c05e25b Varadarajan Narayanan 2017-06-16  398  }
4c05e25b Varadarajan Narayanan 2017-06-16  399  
dd4ce14d Varadarajan Narayanan 2017-06-16  400  if 
(!wait_for_completion_timeout(>done, timeout))
dd4ce14d Varadarajan Narayanan 2017-06-16  401  return 
-ETIMEDOUT;
dd4ce14d Varadarajan Narayanan 2017-06-16  402  
612762e8 Andy Gross2015-03-04  403  return 0;
612762e8 Andy Gross2015-03-04  404  }
612762e8 Andy Gross2015-03-04  405  
64ff247a Ivan T. Ivanov2014-02-13  406  static irqreturn_t 
spi_qup_qup_irq(int irq, void *dev_id)
64ff247a Ivan T. Ivanov2014-02-13  407  {
64ff247a Ivan T. Ivanov2014-02-13  408  struct spi_qup 
*controller = dev_id;
64ff247a Ivan T. Ivanov2014-02-13  409  u32 opflags, qup_err, 
spi_err;
64ff247a Ivan T. Ivanov2014-02-13  410  int error = 0;
64ff247a Ivan T. Ivanov2014-02-13  411  
64ff247a Ivan T. Ivanov2014-02-13  412  qup_err = 
readl_relaxed(controller->base + QUP_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  413  spi_err = 
readl_relaxed(controller->base + SPI_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  414  opflags = 
readl_relaxed(controller->base + QUP_OPERATIONAL);
64ff247a Ivan T. Ivanov2014-02-13  415  
64ff247a Ivan T. Ivanov2014-02-13  416  writel_relaxed(qup_err, 
controller->base + QUP_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  417  writel_relaxed(spi_err, 
controller->base + SPI_ERROR_FLAGS);
64ff247a Ivan T. Ivanov2014-02-13  418  
64ff247a Ivan T. Ivanov2014-02-13  419  if (qup_err) {
64ff247a Ivan T. Ivanov   

[PATCH V1 9/9] arm64: dts: add ccu for SC9860

2017-06-17 Thread Chunyan Zhang
Now we have clock driver, so add clock dt for SC9860 platform.
This patch also removed "ext-26m" from whale2.dtsi since it
is described in sc9860-ccu.dtsi.

Signed-off-by: Chunyan Zhang 
---
 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi | 67 
 arch/arm64/boot/dts/sprd/sc9860.dtsi |  2 +
 arch/arm64/boot/dts/sprd/whale2.dtsi |  8 
 3 files changed, 69 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi

diff --git a/arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi 
b/arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi
new file mode 100644
index 000..e15bf2d
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi
@@ -0,0 +1,67 @@
+/*
+ * Spreadtrum SC9860 SoC CCU
+ *
+ * Copyright (C) 2017, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+ {
+   ext_26m: ext-26m {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <2600>;
+   clock-output-names = "ext-26m";
+   };
+
+   ext_32m_sine0: ext-32m-sine0 {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <3200>;
+   clock-output-names = "ext-32m-sine0";
+   };
+
+   ext_32m_sine1: ext-32m-sine1 {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <3200>;
+   clock-output-names = "ext-32m-sine1";
+   };
+
+   ext_rco_100m: ext-rco-100m {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <1>;
+   clock-output-names = "ext-rco-100m";
+   };
+
+   ext_32k: ext-32k {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <32768>;
+   clock-output-names = "ext-32k";
+   };
+
+   ccu: clk {
+   compatible = "sprd,sc9860-ccu";
+   #clock-cells = <1>;
+   reg = <0 0x2000 0 0x400>,
+ <0 0x2021 0 0x3000>,
+ <0 0x402b 0 0x4000>,
+ <0 0x402d 0 0x400>,
+ <0 0x402e 0 0x4000>,
+ <0 0x4040 0 0x400>,
+ <0 0x4088 0 0x400>,
+ <0 0x415e 0 0x400>,
+ <0 0x6020 0 0x400>,
+ <0 0x6100 0 0x400>,
+ <0 0x6110 0 0x3000>,
+ <0 0x6200 0 0x4000>,
+ <0 0x6210 0 0x4000>,
+ <0 0x6300 0 0x400>,
+ <0 0x6310 0 0x3000>,
+ <0 0x70b0 0 0x3000>;
+   clocks = <_26m>, <_rco_100m>, <_32k>;
+   clock-names = "ext-26m", "ext-rco-100m", "ext-32k";
+   };
+};
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi 
b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index 7b7d8ce..10ff7c6 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -7,7 +7,9 @@
  */
 
 #include 
+#include 
 #include "whale2.dtsi"
+#include "sc9860-ccu.dtsi"
 
 / {
cpus {
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi 
b/arch/arm64/boot/dts/sprd/whale2.dtsi
index 7c217c5..9d69b84 100644
--- a/arch/arm64/boot/dts/sprd/whale2.dtsi
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -59,13 +59,5 @@
status = "disabled";
};
};
-
-   };
-
-   ext_26m: ext-26m {
-   compatible = "fixed-clock";
-   #clock-cells = <0>;
-   clock-frequency = <2600>;
-   clock-output-names = "ext_26m";
};
 };
-- 
2.7.4



[PATCH V1 9/9] arm64: dts: add ccu for SC9860

2017-06-17 Thread Chunyan Zhang
Now we have clock driver, so add clock dt for SC9860 platform.
This patch also removed "ext-26m" from whale2.dtsi since it
is described in sc9860-ccu.dtsi.

Signed-off-by: Chunyan Zhang 
---
 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi | 67 
 arch/arm64/boot/dts/sprd/sc9860.dtsi |  2 +
 arch/arm64/boot/dts/sprd/whale2.dtsi |  8 
 3 files changed, 69 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi

diff --git a/arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi 
b/arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi
new file mode 100644
index 000..e15bf2d
--- /dev/null
+++ b/arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi
@@ -0,0 +1,67 @@
+/*
+ * Spreadtrum SC9860 SoC CCU
+ *
+ * Copyright (C) 2017, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+ {
+   ext_26m: ext-26m {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <2600>;
+   clock-output-names = "ext-26m";
+   };
+
+   ext_32m_sine0: ext-32m-sine0 {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <3200>;
+   clock-output-names = "ext-32m-sine0";
+   };
+
+   ext_32m_sine1: ext-32m-sine1 {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <3200>;
+   clock-output-names = "ext-32m-sine1";
+   };
+
+   ext_rco_100m: ext-rco-100m {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <1>;
+   clock-output-names = "ext-rco-100m";
+   };
+
+   ext_32k: ext-32k {
+   compatible = "fixed-clock";
+   #clock-cells = <0>;
+   clock-frequency = <32768>;
+   clock-output-names = "ext-32k";
+   };
+
+   ccu: clk {
+   compatible = "sprd,sc9860-ccu";
+   #clock-cells = <1>;
+   reg = <0 0x2000 0 0x400>,
+ <0 0x2021 0 0x3000>,
+ <0 0x402b 0 0x4000>,
+ <0 0x402d 0 0x400>,
+ <0 0x402e 0 0x4000>,
+ <0 0x4040 0 0x400>,
+ <0 0x4088 0 0x400>,
+ <0 0x415e 0 0x400>,
+ <0 0x6020 0 0x400>,
+ <0 0x6100 0 0x400>,
+ <0 0x6110 0 0x3000>,
+ <0 0x6200 0 0x4000>,
+ <0 0x6210 0 0x4000>,
+ <0 0x6300 0 0x400>,
+ <0 0x6310 0 0x3000>,
+ <0 0x70b0 0 0x3000>;
+   clocks = <_26m>, <_rco_100m>, <_32k>;
+   clock-names = "ext-26m", "ext-rco-100m", "ext-32k";
+   };
+};
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi 
b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index 7b7d8ce..10ff7c6 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -7,7 +7,9 @@
  */
 
 #include 
+#include 
 #include "whale2.dtsi"
+#include "sc9860-ccu.dtsi"
 
 / {
cpus {
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi 
b/arch/arm64/boot/dts/sprd/whale2.dtsi
index 7c217c5..9d69b84 100644
--- a/arch/arm64/boot/dts/sprd/whale2.dtsi
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -59,13 +59,5 @@
status = "disabled";
};
};
-
-   };
-
-   ext_26m: ext-26m {
-   compatible = "fixed-clock";
-   #clock-cells = <0>;
-   clock-frequency = <2600>;
-   clock-output-names = "ext_26m";
};
 };
-- 
2.7.4



[PATCH V1 6/9] clk: sprd: add composite clock support

2017-06-17 Thread Chunyan Zhang
This patch introduced composite driver whose functions are simply
consisted of divider and mux clocks.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile|  2 +-
 drivers/clk/sprd/ccu_composite.c | 62 
 drivers/clk/sprd/ccu_composite.h | 47 ++
 3 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_composite.c
 create mode 100644 drivers/clk/sprd/ccu_composite.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index d129c0a8..83232e5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o
 endif
diff --git a/drivers/clk/sprd/ccu_composite.c b/drivers/clk/sprd/ccu_composite.c
new file mode 100644
index 000..6a64fb1
--- /dev/null
+++ b/drivers/clk/sprd/ccu_composite.c
@@ -0,0 +1,62 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+
+#include "ccu_composite.h"
+
+DEFINE_SPINLOCK(comp_lock);
+
+static long ccu_comp_round_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long *parent_rate)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_div_helper_round_rate(>common, >div,
+rate, parent_rate);
+}
+
+static unsigned long ccu_comp_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_div_helper_recalc_rate(>common, >div, parent_rate);
+}
+
+static int ccu_comp_set_rate(struct clk_hw *hw, unsigned long rate,
+unsigned long parent_rate)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_div_helper_set_rate(>common, >div,
+  rate, parent_rate);
+}
+
+static u8 ccu_comp_get_parent(struct clk_hw *hw)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_mux_helper_get_parent(>common, >mux);
+}
+
+static int ccu_comp_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_mux_helper_set_parent(>common, >mux, index);
+}
+
+const struct clk_ops ccu_comp_ops = {
+   .get_parent = ccu_comp_get_parent,
+   .set_parent = ccu_comp_set_parent,
+
+   .round_rate = ccu_comp_round_rate,
+   .recalc_rate= ccu_comp_recalc_rate,
+   .set_rate   = ccu_comp_set_rate,
+};
diff --git a/drivers/clk/sprd/ccu_composite.h b/drivers/clk/sprd/ccu_composite.h
new file mode 100644
index 000..c99c919
--- /dev/null
+++ b/drivers/clk/sprd/ccu_composite.h
@@ -0,0 +1,47 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_COMPOSITE_H_
+#define _CCU_COMPOSITE_H_
+
+#include "ccu_common.h"
+#include "ccu_mux.h"
+#include "ccu_div.h"
+
+struct ccu_comp {
+   struct ccu_mux_internal mux;
+   struct ccu_div_internal div;
+   struct ccu_common   common;
+};
+
+#define SPRD_CCU_COMP(_struct, _name, _parent, _reg, _table,   \
+   _mshift, _mwidth, _dshift, _dwidth, _flags) \
+   struct ccu_comp _struct = { \
+   .mux= _SPRD_CCU_MUX(_mshift, _mwidth, _table),  \
+   .div= _SPRD_CCU_DIV(_dshift, _dwidth),  \
+   .common = { \
+.reg   = _reg, \
+.lock  = _lock,   \
+.hw.init   = CLK_HW_INIT_PARENTS(_name,\
+ _parent,  \
+   _comp_ops,  \
+ _flags),  \
+}  \
+   }
+
+static inline struct ccu_comp *hw_to_ccu_comp(struct clk_hw *hw)
+{
+   struct ccu_common *common = hw_to_ccu_common(hw);
+
+   return container_of(common, struct ccu_comp, common);
+}
+
+extern const struct clk_ops ccu_comp_ops;
+extern spinlock_t comp_lock;
+
+#endif /* _CCU_COMPOSITE_H_ */
-- 
2.7.4



[PATCH V1 7/9] clk: sprd: add adjustable pll support

2017-06-17 Thread Chunyan Zhang
Introduced a common adjustable pll clock driver for Spreadtrum SoCs.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |   2 +-
 drivers/clk/sprd/ccu_pll.c | 241 +
 drivers/clk/sprd/ccu_pll.h | 123 +++
 3 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_pll.c
 create mode 100644 drivers/clk/sprd/ccu_pll.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 83232e5..c593a93 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o ccu_pll.o
 endif
diff --git a/drivers/clk/sprd/ccu_pll.c b/drivers/clk/sprd/ccu_pll.c
new file mode 100644
index 000..6c908e4
--- /dev/null
+++ b/drivers/clk/sprd/ccu_pll.c
@@ -0,0 +1,241 @@
+/*
+ * Spreadtrum pll clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ccu_pll.h"
+
+#define CCU_PLL_1M 100
+#define CCU_PLL_10M(CCU_PLL_1M * 10)
+
+#define pindex(pll, member)\
+   (pll->factors[member].shift / (8 * sizeof(pll->regs[0])))
+
+#define pshift(pll, member)\
+   (pll->factors[member].shift % (8 * sizeof(pll->regs[0])))
+
+#define pwidth(pll, member)\
+   pll->factors[member].width
+
+#define pmask(pll, member) \
+   ((pwidth(pll, member)) ?\
+   GENMASK(pwidth(pll, member) + pshift(pll, member) - 1,  \
+   pshift(pll, member)) : 0)
+
+#define pinternal(pll, cfg, member)\
+   (cfg[pindex(pll, member)] & pmask(pll, member))
+
+#define pinternal_val(pll, cfg, member)\
+   (pinternal(pll, cfg, member) >> pshift(pll, member))
+
+static unsigned long pll_get_refin_rate(struct ccu_pll *pll)
+{
+   u8 shift, index, refin_id = 3;
+   u32 mask;
+   const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+   if (pwidth(pll, PLL_REFIN)) {
+   index = pindex(pll, PLL_REFIN);
+   shift = pshift(pll, PLL_REFIN);
+   mask = pmask(pll, PLL_REFIN);
+   refin_id = (ccu_pll_readl(pll, index) & mask) >> shift;
+   if (refin_id > 3)
+   refin_id = 3;
+   }
+
+   return refin[refin_id];
+}
+
+static u8 pll_get_ibias(unsigned long rate, const u64 *table)
+{
+   u64 i;
+   u8 num = table[0];
+
+   for (i = 0; i < num; i++)
+   if (rate <= table[i + 1])
+   break;
+
+   return i == num ? num - 1 : i;
+}
+
+static unsigned long ccu_pll_helper_recalc_rate(struct ccu_pll *pll,
+   unsigned long parent_rate)
+{
+   unsigned long rate, refin, k1, k2;
+   unsigned long kint = 0, nint;
+   u32 reg_num = pll->regs[0];
+   u32 *cfg;
+   u32 i;
+   u32 mask;
+
+   cfg = kcalloc(reg_num, sizeof(*cfg), GFP_KERNEL);
+   if (!cfg)
+   return -ENOMEM;
+
+   for (i = 0; i < reg_num; i++)
+   cfg[i] = ccu_pll_readl(pll, i);
+
+   refin = pll_get_refin_rate(pll);
+
+   if (pinternal(pll, cfg, PLL_PREDIV))
+   refin = refin * 2;
+
+   if (pwidth(pll, PLL_POSTDIV) &&
+   ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
+(!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV
+   refin = refin / 2;
+
+   if (!pinternal(pll, cfg, PLL_DIV_S))
+   rate = refin * pinternal_val(pll, cfg, PLL_N) * CCU_PLL_10M;
+   else {
+   nint = pinternal_val(pll, cfg, PLL_NINT);
+   if (pinternal(pll, cfg, PLL_SDM_EN))
+   kint = pinternal_val(pll, cfg, PLL_KINT);
+
+   mask = pmask(pll, PLL_KINT);
+#ifdef CONFIG_64BIT
+   k1 = 1000;
+   k2 = 1000;
+   rate = DIV_ROUND_CLOSEST(refin * kint * k1,
+((mask >> __ffs(mask)) + 1)) *
+k2 + refin * nint * CCU_PLL_1M;
+#else
+   k1 = 100;
+   k2 = 1;
+   i = pwidth(pll, PLL_KINT);
+   i = i < 21 ? 0 : i - 21;
+   rate = DIV_ROUND_CLOSEST(refin * (kint >> i) * k1,
+((mask >> (__ffs(mask) + i)) + 1)) *
+k2 + refin * nint * CCU_PLL_1M;
+#endif
+   }
+
+   return rate;
+}
+
+static int ccu_pll_helper_set_rate(struct ccu_pll *pll,
+  unsigned long rate,
+  unsigned long parent_rate)
+{
+   u32 mask, shift, 

[PATCH V1 8/9] clk: sprd: add clocks support for SC9860

2017-06-17 Thread Chunyan Zhang
Add the list of clocks in SC9860 CCU.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |1 +
 drivers/clk/sprd/ccu-sc9860.c  | 1742 
 drivers/clk/sprd/ccu-sc9860.h  |  379 +++
 include/dt-bindings/clock/sc9860-ccu.h |   19 +
 4 files changed, 2141 insertions(+)
 create mode 100644 drivers/clk/sprd/ccu-sc9860.c
 create mode 100644 drivers/clk/sprd/ccu-sc9860.h
 create mode 100644 include/dt-bindings/clock/sc9860-ccu.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index c593a93..0d90b40 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,4 @@
 ifneq ($(CONFIG_OF),)
 obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o ccu_pll.o
+obj-y  += ccu-sc9860.o
 endif
diff --git a/drivers/clk/sprd/ccu-sc9860.c b/drivers/clk/sprd/ccu-sc9860.c
new file mode 100644
index 000..6cd4dc5
--- /dev/null
+++ b/drivers/clk/sprd/ccu-sc9860.c
@@ -0,0 +1,1742 @@
+/*
+ * Spreatrum SC9860 clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ccu_composite.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mux.h"
+#include "ccu_pll.h"
+
+#include "ccu-sc9860.h"
+
+static CLK_FIXED_FACTOR(fac_4m,"fac-4m",   "ext-26m",
+   6, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_2m,"fac-2m",   "ext-26m",
+   13, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_1m,"fac-1m",   "ext-26m",
+   26, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_250k,  "fac-250k", "ext-26m",
+   104, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rpll0_26m, "rpll0-26m","ext-26m",
+   1, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rpll1_26m, "rpll1-26m","ext-26m",
+   1, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rco_25m,   "rco-25m",  "ext-rc0-100m",
+   4, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rco_4m,"rco-4m",   "ext-rc0-100m",
+   25, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rco_2m,"rco-2m",   "ext-rc0-100m",
+   50, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_3k2,   "fac-3k2",  "ext-32k",
+   10, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_1k,"fac-1k",   "ext-32k",
+   32, 1, CLK_IS_BASIC);
+
+#define SC9860_GATE_FLAGS (CLK_IGNORE_UNUSED | CLK_IS_BASIC)
+static SPRD_CCU_GATE(rpll0_gate,   "rpll0-gate",   "ext-26m", 0x402b016c,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(rpll1_gate,   "rpll1-gate",   "ext-26m", 0x402b016c,
+0x1000, BIT(18), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(mpll0_gate,   "mpll0-gate",   "ext-26m", 0x402b00b0,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(mpll1_gate,   "mpll1-gate",   "ext-26m", 0x402b00b0,
+0x1000, BIT(18), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(dpll0_gate,   "dpll0-gate",   "ext-26m", 0x402b00b4,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(dpll1_gate,   "dpll1-gate",   "ext-26m", 0x402b00b4,
+0x1000, BIT(18), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(gpll_gate,"gpll-gate","ext-26m", 
0x402b032c,
+0x1000, BIT(0), SC9860_GATE_FLAGS,
+CLK_GATE_SET_TO_DISABLE);
+static SPRD_CCU_GATE(cppll_gate,   "cppll-gate",   "ext-26m", 0x402b02b4,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(ltepll0_gate, "ltepll0-gate", "ext-26m", 0x402b00b8,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(ltepll1_gate, "ltepll1-gate", "ext-26m", 0x402b010c,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(twpll_gate,   "twpll-gate",   "ext-26m", 0x402b00bc,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio0_2x_en,"sdio0-2x-en",  0x402e013c,
+  0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio0_1x_en,"sdio0-1x-en",  0x402e013c,
+  0x1000, BIT(3), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio1_2x_en,"sdio1-2x-en",  0x402e013c,
+  0x1000, BIT(4), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio1_1x_en,"sdio1-1x-en",  0x402e013c,
+  0x1000, BIT(5), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio2_2x_en,

[PATCH V1 5/9] clk: sprd: add divider clock support

2017-06-17 Thread Chunyan Zhang
This is a feature that can also be found in sprd composite clocks,
provide a bunch of helpers that can be reused later on.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |  2 +-
 drivers/clk/sprd/ccu_div.c | 93 ++
 drivers/clk/sprd/ccu_div.h | 77 ++
 3 files changed, 171 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_div.c
 create mode 100644 drivers/clk/sprd/ccu_div.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index dc89790..d129c0a8 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o ccu_mux.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o
 endif
diff --git a/drivers/clk/sprd/ccu_div.c b/drivers/clk/sprd/ccu_div.c
new file mode 100644
index 000..0d0f1e9
--- /dev/null
+++ b/drivers/clk/sprd/ccu_div.c
@@ -0,0 +1,93 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+
+#include "ccu_div.h"
+
+DEFINE_SPINLOCK(div_lock);
+
+long ccu_div_helper_round_rate(struct ccu_common *common,
+  struct ccu_div_internal *div,
+  unsigned long rate,
+  unsigned long *parent_rate)
+{
+   return divider_round_rate(>hw, rate, parent_rate,
+ NULL, div->width, 0);
+}
+
+static long ccu_div_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *parent_rate)
+{
+   struct ccu_div *cd = hw_to_ccu_div(hw);
+
+   return ccu_div_helper_round_rate(>common, >div,
+rate, parent_rate);
+}
+
+unsigned long ccu_div_helper_recalc_rate(struct ccu_common *common,
+struct ccu_div_internal *div,
+unsigned long parent_rate)
+{
+   unsigned long val;
+   u32 reg;
+
+   reg = ccu_readl(common);
+   val = reg >> div->shift;
+   val &= (1 << div->width) - 1;
+
+   return divider_recalc_rate(>hw, parent_rate, val, NULL, 0);
+}
+
+static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct ccu_div *cd = hw_to_ccu_div(hw);
+
+   return ccu_div_helper_recalc_rate(>common, >div, parent_rate);
+}
+
+int ccu_div_helper_set_rate(struct ccu_common *common,
+   struct ccu_div_internal *div,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   unsigned long flags;
+   unsigned long val;
+   u32 reg;
+
+   val = divider_get_val(rate, parent_rate, NULL,
+   div->width, 0);
+
+   spin_lock_irqsave(common->lock, flags);
+
+   reg = ccu_readl(common);
+   reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
+
+   ccu_writel(reg | (val << div->shift), common);
+
+   spin_unlock_irqrestore(common->lock, flags);
+
+   return 0;
+
+}
+
+static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct ccu_div *cd = hw_to_ccu_div(hw);
+
+   return ccu_div_helper_set_rate(>common, >div,
+  rate, parent_rate);
+}
+
+const struct clk_ops ccu_div_ops = {
+   .recalc_rate = ccu_div_recalc_rate,
+   .round_rate = ccu_div_round_rate,
+   .set_rate = ccu_div_set_rate,
+};
diff --git a/drivers/clk/sprd/ccu_div.h b/drivers/clk/sprd/ccu_div.h
new file mode 100644
index 000..cb13ed7
--- /dev/null
+++ b/drivers/clk/sprd/ccu_div.h
@@ -0,0 +1,77 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_DIV_H_
+#define _CCU_DIV_H_
+
+#include "ccu_common.h"
+
+/**
+ * struct ccu_div_internal - Internal divider description
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ *
+ * That structure represents a single divider, and is meant to be
+ * embedded in other structures representing the various clock
+ * classes.
+ */
+struct ccu_div_internal {
+   u8  shift;
+   u8  width;
+};
+
+#define _SPRD_CCU_DIV(_shift, _width)  \
+   {   \
+   .shift  = _shift,   \
+   .width  = _width,   \
+   }
+
+struct ccu_div {
+   struct ccu_div_internal div;
+   struct ccu_common   common;
+};
+
+#define SPRD_CCU_DIV(_struct, _name, _parent, _reg,\
+   _shift, _width, _flags) \
+   struct 

[PATCH V1 6/9] clk: sprd: add composite clock support

2017-06-17 Thread Chunyan Zhang
This patch introduced composite driver whose functions are simply
consisted of divider and mux clocks.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile|  2 +-
 drivers/clk/sprd/ccu_composite.c | 62 
 drivers/clk/sprd/ccu_composite.h | 47 ++
 3 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_composite.c
 create mode 100644 drivers/clk/sprd/ccu_composite.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index d129c0a8..83232e5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o
 endif
diff --git a/drivers/clk/sprd/ccu_composite.c b/drivers/clk/sprd/ccu_composite.c
new file mode 100644
index 000..6a64fb1
--- /dev/null
+++ b/drivers/clk/sprd/ccu_composite.c
@@ -0,0 +1,62 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+
+#include "ccu_composite.h"
+
+DEFINE_SPINLOCK(comp_lock);
+
+static long ccu_comp_round_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long *parent_rate)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_div_helper_round_rate(>common, >div,
+rate, parent_rate);
+}
+
+static unsigned long ccu_comp_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_div_helper_recalc_rate(>common, >div, parent_rate);
+}
+
+static int ccu_comp_set_rate(struct clk_hw *hw, unsigned long rate,
+unsigned long parent_rate)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_div_helper_set_rate(>common, >div,
+  rate, parent_rate);
+}
+
+static u8 ccu_comp_get_parent(struct clk_hw *hw)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_mux_helper_get_parent(>common, >mux);
+}
+
+static int ccu_comp_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct ccu_comp *cc = hw_to_ccu_comp(hw);
+
+   return ccu_mux_helper_set_parent(>common, >mux, index);
+}
+
+const struct clk_ops ccu_comp_ops = {
+   .get_parent = ccu_comp_get_parent,
+   .set_parent = ccu_comp_set_parent,
+
+   .round_rate = ccu_comp_round_rate,
+   .recalc_rate= ccu_comp_recalc_rate,
+   .set_rate   = ccu_comp_set_rate,
+};
diff --git a/drivers/clk/sprd/ccu_composite.h b/drivers/clk/sprd/ccu_composite.h
new file mode 100644
index 000..c99c919
--- /dev/null
+++ b/drivers/clk/sprd/ccu_composite.h
@@ -0,0 +1,47 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_COMPOSITE_H_
+#define _CCU_COMPOSITE_H_
+
+#include "ccu_common.h"
+#include "ccu_mux.h"
+#include "ccu_div.h"
+
+struct ccu_comp {
+   struct ccu_mux_internal mux;
+   struct ccu_div_internal div;
+   struct ccu_common   common;
+};
+
+#define SPRD_CCU_COMP(_struct, _name, _parent, _reg, _table,   \
+   _mshift, _mwidth, _dshift, _dwidth, _flags) \
+   struct ccu_comp _struct = { \
+   .mux= _SPRD_CCU_MUX(_mshift, _mwidth, _table),  \
+   .div= _SPRD_CCU_DIV(_dshift, _dwidth),  \
+   .common = { \
+.reg   = _reg, \
+.lock  = _lock,   \
+.hw.init   = CLK_HW_INIT_PARENTS(_name,\
+ _parent,  \
+   _comp_ops,  \
+ _flags),  \
+}  \
+   }
+
+static inline struct ccu_comp *hw_to_ccu_comp(struct clk_hw *hw)
+{
+   struct ccu_common *common = hw_to_ccu_common(hw);
+
+   return container_of(common, struct ccu_comp, common);
+}
+
+extern const struct clk_ops ccu_comp_ops;
+extern spinlock_t comp_lock;
+
+#endif /* _CCU_COMPOSITE_H_ */
-- 
2.7.4



[PATCH V1 7/9] clk: sprd: add adjustable pll support

2017-06-17 Thread Chunyan Zhang
Introduced a common adjustable pll clock driver for Spreadtrum SoCs.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |   2 +-
 drivers/clk/sprd/ccu_pll.c | 241 +
 drivers/clk/sprd/ccu_pll.h | 123 +++
 3 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_pll.c
 create mode 100644 drivers/clk/sprd/ccu_pll.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 83232e5..c593a93 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o ccu_pll.o
 endif
diff --git a/drivers/clk/sprd/ccu_pll.c b/drivers/clk/sprd/ccu_pll.c
new file mode 100644
index 000..6c908e4
--- /dev/null
+++ b/drivers/clk/sprd/ccu_pll.c
@@ -0,0 +1,241 @@
+/*
+ * Spreadtrum pll clock driver
+ *
+ * Copyright (C) 2015~2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ccu_pll.h"
+
+#define CCU_PLL_1M 100
+#define CCU_PLL_10M(CCU_PLL_1M * 10)
+
+#define pindex(pll, member)\
+   (pll->factors[member].shift / (8 * sizeof(pll->regs[0])))
+
+#define pshift(pll, member)\
+   (pll->factors[member].shift % (8 * sizeof(pll->regs[0])))
+
+#define pwidth(pll, member)\
+   pll->factors[member].width
+
+#define pmask(pll, member) \
+   ((pwidth(pll, member)) ?\
+   GENMASK(pwidth(pll, member) + pshift(pll, member) - 1,  \
+   pshift(pll, member)) : 0)
+
+#define pinternal(pll, cfg, member)\
+   (cfg[pindex(pll, member)] & pmask(pll, member))
+
+#define pinternal_val(pll, cfg, member)\
+   (pinternal(pll, cfg, member) >> pshift(pll, member))
+
+static unsigned long pll_get_refin_rate(struct ccu_pll *pll)
+{
+   u8 shift, index, refin_id = 3;
+   u32 mask;
+   const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+   if (pwidth(pll, PLL_REFIN)) {
+   index = pindex(pll, PLL_REFIN);
+   shift = pshift(pll, PLL_REFIN);
+   mask = pmask(pll, PLL_REFIN);
+   refin_id = (ccu_pll_readl(pll, index) & mask) >> shift;
+   if (refin_id > 3)
+   refin_id = 3;
+   }
+
+   return refin[refin_id];
+}
+
+static u8 pll_get_ibias(unsigned long rate, const u64 *table)
+{
+   u64 i;
+   u8 num = table[0];
+
+   for (i = 0; i < num; i++)
+   if (rate <= table[i + 1])
+   break;
+
+   return i == num ? num - 1 : i;
+}
+
+static unsigned long ccu_pll_helper_recalc_rate(struct ccu_pll *pll,
+   unsigned long parent_rate)
+{
+   unsigned long rate, refin, k1, k2;
+   unsigned long kint = 0, nint;
+   u32 reg_num = pll->regs[0];
+   u32 *cfg;
+   u32 i;
+   u32 mask;
+
+   cfg = kcalloc(reg_num, sizeof(*cfg), GFP_KERNEL);
+   if (!cfg)
+   return -ENOMEM;
+
+   for (i = 0; i < reg_num; i++)
+   cfg[i] = ccu_pll_readl(pll, i);
+
+   refin = pll_get_refin_rate(pll);
+
+   if (pinternal(pll, cfg, PLL_PREDIV))
+   refin = refin * 2;
+
+   if (pwidth(pll, PLL_POSTDIV) &&
+   ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
+(!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV
+   refin = refin / 2;
+
+   if (!pinternal(pll, cfg, PLL_DIV_S))
+   rate = refin * pinternal_val(pll, cfg, PLL_N) * CCU_PLL_10M;
+   else {
+   nint = pinternal_val(pll, cfg, PLL_NINT);
+   if (pinternal(pll, cfg, PLL_SDM_EN))
+   kint = pinternal_val(pll, cfg, PLL_KINT);
+
+   mask = pmask(pll, PLL_KINT);
+#ifdef CONFIG_64BIT
+   k1 = 1000;
+   k2 = 1000;
+   rate = DIV_ROUND_CLOSEST(refin * kint * k1,
+((mask >> __ffs(mask)) + 1)) *
+k2 + refin * nint * CCU_PLL_1M;
+#else
+   k1 = 100;
+   k2 = 1;
+   i = pwidth(pll, PLL_KINT);
+   i = i < 21 ? 0 : i - 21;
+   rate = DIV_ROUND_CLOSEST(refin * (kint >> i) * k1,
+((mask >> (__ffs(mask) + i)) + 1)) *
+k2 + refin * nint * CCU_PLL_1M;
+#endif
+   }
+
+   return rate;
+}
+
+static int ccu_pll_helper_set_rate(struct ccu_pll *pll,
+  unsigned long rate,
+  unsigned long parent_rate)
+{
+   u32 mask, shift, width, ibias_val, index, kint, nint;
+   u32 reg_num = 

[PATCH V1 8/9] clk: sprd: add clocks support for SC9860

2017-06-17 Thread Chunyan Zhang
Add the list of clocks in SC9860 CCU.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |1 +
 drivers/clk/sprd/ccu-sc9860.c  | 1742 
 drivers/clk/sprd/ccu-sc9860.h  |  379 +++
 include/dt-bindings/clock/sc9860-ccu.h |   19 +
 4 files changed, 2141 insertions(+)
 create mode 100644 drivers/clk/sprd/ccu-sc9860.c
 create mode 100644 drivers/clk/sprd/ccu-sc9860.h
 create mode 100644 include/dt-bindings/clock/sc9860-ccu.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index c593a93..0d90b40 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,4 @@
 ifneq ($(CONFIG_OF),)
 obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o ccu_composite.o ccu_pll.o
+obj-y  += ccu-sc9860.o
 endif
diff --git a/drivers/clk/sprd/ccu-sc9860.c b/drivers/clk/sprd/ccu-sc9860.c
new file mode 100644
index 000..6cd4dc5
--- /dev/null
+++ b/drivers/clk/sprd/ccu-sc9860.c
@@ -0,0 +1,1742 @@
+/*
+ * Spreatrum SC9860 clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ccu_composite.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mux.h"
+#include "ccu_pll.h"
+
+#include "ccu-sc9860.h"
+
+static CLK_FIXED_FACTOR(fac_4m,"fac-4m",   "ext-26m",
+   6, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_2m,"fac-2m",   "ext-26m",
+   13, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_1m,"fac-1m",   "ext-26m",
+   26, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_250k,  "fac-250k", "ext-26m",
+   104, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rpll0_26m, "rpll0-26m","ext-26m",
+   1, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rpll1_26m, "rpll1-26m","ext-26m",
+   1, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rco_25m,   "rco-25m",  "ext-rc0-100m",
+   4, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rco_4m,"rco-4m",   "ext-rc0-100m",
+   25, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_rco_2m,"rco-2m",   "ext-rc0-100m",
+   50, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_3k2,   "fac-3k2",  "ext-32k",
+   10, 1, CLK_IS_BASIC);
+static CLK_FIXED_FACTOR(fac_1k,"fac-1k",   "ext-32k",
+   32, 1, CLK_IS_BASIC);
+
+#define SC9860_GATE_FLAGS (CLK_IGNORE_UNUSED | CLK_IS_BASIC)
+static SPRD_CCU_GATE(rpll0_gate,   "rpll0-gate",   "ext-26m", 0x402b016c,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(rpll1_gate,   "rpll1-gate",   "ext-26m", 0x402b016c,
+0x1000, BIT(18), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(mpll0_gate,   "mpll0-gate",   "ext-26m", 0x402b00b0,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(mpll1_gate,   "mpll1-gate",   "ext-26m", 0x402b00b0,
+0x1000, BIT(18), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(dpll0_gate,   "dpll0-gate",   "ext-26m", 0x402b00b4,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(dpll1_gate,   "dpll1-gate",   "ext-26m", 0x402b00b4,
+0x1000, BIT(18), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(gpll_gate,"gpll-gate","ext-26m", 
0x402b032c,
+0x1000, BIT(0), SC9860_GATE_FLAGS,
+CLK_GATE_SET_TO_DISABLE);
+static SPRD_CCU_GATE(cppll_gate,   "cppll-gate",   "ext-26m", 0x402b02b4,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(ltepll0_gate, "ltepll0-gate", "ext-26m", 0x402b00b8,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(ltepll1_gate, "ltepll1-gate", "ext-26m", 0x402b010c,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE(twpll_gate,   "twpll-gate",   "ext-26m", 0x402b00bc,
+0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio0_2x_en,"sdio0-2x-en",  0x402e013c,
+  0x1000, BIT(2), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio0_1x_en,"sdio0-1x-en",  0x402e013c,
+  0x1000, BIT(3), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio1_2x_en,"sdio1-2x-en",  0x402e013c,
+  0x1000, BIT(4), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio1_1x_en,"sdio1-1x-en",  0x402e013c,
+  0x1000, BIT(5), SC9860_GATE_FLAGS, 0);
+static SPRD_CCU_GATE_NO_PARENT(sdio2_2x_en,"sdio2-2x-en",  0x402e013c,
+  0x1000, 

[PATCH V1 5/9] clk: sprd: add divider clock support

2017-06-17 Thread Chunyan Zhang
This is a feature that can also be found in sprd composite clocks,
provide a bunch of helpers that can be reused later on.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |  2 +-
 drivers/clk/sprd/ccu_div.c | 93 ++
 drivers/clk/sprd/ccu_div.h | 77 ++
 3 files changed, 171 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_div.c
 create mode 100644 drivers/clk/sprd/ccu_div.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index dc89790..d129c0a8 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o ccu_mux.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o ccu_div.o
 endif
diff --git a/drivers/clk/sprd/ccu_div.c b/drivers/clk/sprd/ccu_div.c
new file mode 100644
index 000..0d0f1e9
--- /dev/null
+++ b/drivers/clk/sprd/ccu_div.c
@@ -0,0 +1,93 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+
+#include "ccu_div.h"
+
+DEFINE_SPINLOCK(div_lock);
+
+long ccu_div_helper_round_rate(struct ccu_common *common,
+  struct ccu_div_internal *div,
+  unsigned long rate,
+  unsigned long *parent_rate)
+{
+   return divider_round_rate(>hw, rate, parent_rate,
+ NULL, div->width, 0);
+}
+
+static long ccu_div_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *parent_rate)
+{
+   struct ccu_div *cd = hw_to_ccu_div(hw);
+
+   return ccu_div_helper_round_rate(>common, >div,
+rate, parent_rate);
+}
+
+unsigned long ccu_div_helper_recalc_rate(struct ccu_common *common,
+struct ccu_div_internal *div,
+unsigned long parent_rate)
+{
+   unsigned long val;
+   u32 reg;
+
+   reg = ccu_readl(common);
+   val = reg >> div->shift;
+   val &= (1 << div->width) - 1;
+
+   return divider_recalc_rate(>hw, parent_rate, val, NULL, 0);
+}
+
+static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct ccu_div *cd = hw_to_ccu_div(hw);
+
+   return ccu_div_helper_recalc_rate(>common, >div, parent_rate);
+}
+
+int ccu_div_helper_set_rate(struct ccu_common *common,
+   struct ccu_div_internal *div,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   unsigned long flags;
+   unsigned long val;
+   u32 reg;
+
+   val = divider_get_val(rate, parent_rate, NULL,
+   div->width, 0);
+
+   spin_lock_irqsave(common->lock, flags);
+
+   reg = ccu_readl(common);
+   reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
+
+   ccu_writel(reg | (val << div->shift), common);
+
+   spin_unlock_irqrestore(common->lock, flags);
+
+   return 0;
+
+}
+
+static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct ccu_div *cd = hw_to_ccu_div(hw);
+
+   return ccu_div_helper_set_rate(>common, >div,
+  rate, parent_rate);
+}
+
+const struct clk_ops ccu_div_ops = {
+   .recalc_rate = ccu_div_recalc_rate,
+   .round_rate = ccu_div_round_rate,
+   .set_rate = ccu_div_set_rate,
+};
diff --git a/drivers/clk/sprd/ccu_div.h b/drivers/clk/sprd/ccu_div.h
new file mode 100644
index 000..cb13ed7
--- /dev/null
+++ b/drivers/clk/sprd/ccu_div.h
@@ -0,0 +1,77 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_DIV_H_
+#define _CCU_DIV_H_
+
+#include "ccu_common.h"
+
+/**
+ * struct ccu_div_internal - Internal divider description
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ *
+ * That structure represents a single divider, and is meant to be
+ * embedded in other structures representing the various clock
+ * classes.
+ */
+struct ccu_div_internal {
+   u8  shift;
+   u8  width;
+};
+
+#define _SPRD_CCU_DIV(_shift, _width)  \
+   {   \
+   .shift  = _shift,   \
+   .width  = _width,   \
+   }
+
+struct ccu_div {
+   struct ccu_div_internal div;
+   struct ccu_common   common;
+};
+
+#define SPRD_CCU_DIV(_struct, _name, _parent, _reg,\
+   _shift, _width, _flags) \
+   struct ccu_div _struct = {  \
+  

[PATCH V1 4/9] clk: sprd: add mux clock support

2017-06-17 Thread Chunyan Zhang
This is a feature that can also be found in sprd composite clocks,
provide two helpers that can be reused later on.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |  2 +-
 drivers/clk/sprd/ccu_mux.c | 82 ++
 drivers/clk/sprd/ccu_mux.h | 63 +++
 3 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_mux.c
 create mode 100644 drivers/clk/sprd/ccu_mux.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 333e2b2..dc89790 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o
 endif
diff --git a/drivers/clk/sprd/ccu_mux.c b/drivers/clk/sprd/ccu_mux.c
new file mode 100644
index 000..51c744e
--- /dev/null
+++ b/drivers/clk/sprd/ccu_mux.c
@@ -0,0 +1,82 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "ccu_mux.h"
+
+DEFINE_SPINLOCK(mux_lock);
+
+u8 ccu_mux_helper_get_parent(struct ccu_common *common,
+struct ccu_mux_internal *mux)
+{
+   u32 reg;
+   u8 parent;
+   int num_parents;
+   int i;
+
+   reg = ccu_readl(common);
+   parent = reg >> mux->shift;
+   parent &= (1 << mux->width) - 1;
+
+   if (mux->table) {
+   num_parents = clk_hw_get_num_parents(>hw);
+
+   for (i = 0; i < num_parents; i++)
+   if (parent == mux->table[i] ||
+   (i < (num_parents - 1) && parent > mux->table[i] &&
+parent < mux->table[i + 1]))
+   return i;
+   if (i == num_parents)
+   return i - 1;
+   }
+
+   return parent;
+}
+
+static u8 ccu_mux_get_parent(struct clk_hw *hw)
+{
+   struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+   return ccu_mux_helper_get_parent(>common, >mux);
+}
+
+int ccu_mux_helper_set_parent(struct ccu_common *common,
+ struct ccu_mux_internal *mux,
+ u8 index)
+{
+   unsigned long flags = 0;
+   u32 reg;
+
+   if (mux->table)
+   index = mux->table[index];
+
+   spin_lock_irqsave(common->lock, flags);
+
+   reg = ccu_readl(common);
+   reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
+   ccu_writel(reg | (index << mux->shift), common);
+
+   spin_unlock_irqrestore(common->lock, flags);
+
+   return 0;
+}
+
+static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+   return ccu_mux_helper_set_parent(>common, >mux, index);
+}
+
+const struct clk_ops ccu_mux_ops = {
+   .get_parent = ccu_mux_get_parent,
+   .set_parent = ccu_mux_set_parent,
+   .determine_rate = __clk_mux_determine_rate,
+};
diff --git a/drivers/clk/sprd/ccu_mux.h b/drivers/clk/sprd/ccu_mux.h
new file mode 100644
index 000..f3e3fb4
--- /dev/null
+++ b/drivers/clk/sprd/ccu_mux.h
@@ -0,0 +1,63 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_MUX_H_
+#define _CCU_MUX_H_
+
+#include "ccu_common.h"
+
+struct ccu_mux_internal {
+   u8  shift;
+   u8  width;
+   const u8*table;
+};
+
+struct ccu_mux {
+   struct ccu_mux_internal mux;
+   struct ccu_common   common;
+};
+
+#define _SPRD_CCU_MUX(_shift, _width, _table)  \
+   {   \
+   .shift  = _shift,   \
+   .width  = _width,   \
+   .table  = _table,   \
+   }
+
+#define SPRD_CCU_MUX(_struct, _name, _parents, _table, \
+_reg, _shift, _width,  \
+_flags)\
+   struct ccu_mux _struct = {  \
+   .mux= _SPRD_CCU_MUX(_shift, _width, _table),\
+   .common = { \
+   .reg= _reg, \
+   .lock   = _lock,\
+   .hw.init= CLK_HW_INIT_PARENTS(_name,\
+ _parents, \
+ _mux_ops,\
+ _flags),  \
+   }  

[PATCH V1 3/9] clk: sprd: add gate clock support

2017-06-17 Thread Chunyan Zhang
Some clocks on the Spreadtrum's SoCs are just simple gates. Add
support for those clocks.

Also, some gate clocks are orphan, so this patch also added
registration code for those.

Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile   |   2 +-
 drivers/clk/sprd/ccu_gate.c | 102 
 drivers/clk/sprd/ccu_gate.h |  73 +++
 3 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_gate.c
 create mode 100644 drivers/clk/sprd/ccu_gate.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 8f802b2..333e2b2 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o
+obj-y  += ccu_common.o ccu_gate.o
 endif
diff --git a/drivers/clk/sprd/ccu_gate.c b/drivers/clk/sprd/ccu_gate.c
new file mode 100644
index 000..3d27615
--- /dev/null
+++ b/drivers/clk/sprd/ccu_gate.c
@@ -0,0 +1,102 @@
+/*
+ * Spreadtrum gate clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+
+#include "ccu_gate.h"
+
+DEFINE_SPINLOCK(gate_lock);
+
+static void ccu_gate_endisable(struct ccu_gate *cg, u32 en)
+{
+   struct ccu_common *common = >common;
+   unsigned long flags = 0;
+   u32 reg;
+   int set = cg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+
+   set ^= en;
+
+   spin_lock_irqsave(common->lock, flags);
+
+   reg = ccu_readl(common);
+
+   if (set)
+   reg |= cg->op_bit;
+   else
+   reg &= ~cg->op_bit;
+
+   ccu_writel(reg, common);
+
+   spin_unlock_irqrestore(common->lock, flags);
+}
+
+static void ccu_sc_gate_endisable(struct ccu_gate *cg, u32 en)
+{
+   struct ccu_common *common = >common;
+   unsigned long flags = 0;
+   int set = cg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+   u32 offset;
+
+   set ^= en;
+
+   /*
+* Each set/clear gate clock has three registers:
+* common->reg  - base register
+* common->reg + offset - set register
+* common->reg + 2 * offset - clear register
+*/
+   offset = set ? cg->sc_offset : cg->sc_offset * 2;
+
+   spin_lock_irqsave(common->lock, flags);
+   ccu_writel_offset(cg->op_bit, common, offset);
+   spin_unlock_irqrestore(common->lock, flags);
+}
+
+static void ccu_gate_disable(struct clk_hw *hw)
+{
+   struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+   if (cg->sc_offset)
+   ccu_sc_gate_endisable(cg, 0);
+   else
+   ccu_gate_endisable(cg, 0);
+}
+
+static int ccu_gate_enable(struct clk_hw *hw)
+{
+   struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+   if (cg->sc_offset)
+   ccu_sc_gate_endisable(cg, 1);
+   else
+   ccu_gate_endisable(cg, 1);
+
+   return 0;
+}
+
+static int ccu_gate_is_enabled(struct clk_hw *hw)
+{
+   struct ccu_gate *cg = hw_to_ccu_gate(hw);
+   struct ccu_common *common = >common;
+   u32 reg;
+
+   reg = ccu_readl(common);
+
+   if (cg->flags & CLK_GATE_SET_TO_DISABLE)
+   reg ^= cg->op_bit;
+
+   reg &= cg->op_bit;
+
+   return reg ? 1 : 0;
+}
+
+const struct clk_ops ccu_gate_ops = {
+   .disable= ccu_gate_disable,
+   .enable = ccu_gate_enable,
+   .is_enabled = ccu_gate_is_enabled,
+};
diff --git a/drivers/clk/sprd/ccu_gate.h b/drivers/clk/sprd/ccu_gate.h
new file mode 100644
index 000..bc40169
--- /dev/null
+++ b/drivers/clk/sprd/ccu_gate.h
@@ -0,0 +1,73 @@
+/*
+ * Spreadtrum gate clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_GATE_H_
+#define _CCU_GATE_H_
+
+#include "ccu_common.h"
+
+struct ccu_gate {
+   u32 op_bit;
+   u16 flags;
+   u16 sc_offset;
+
+   struct ccu_common   common;
+};
+
+#define SPRD_CCU_GATE(_struct, _name, _parent, _reg, _sc_offset,   \
+ _op_bit, _flags, _gate_flags) \
+   struct ccu_gate _struct = { \
+   .op_bit = _op_bit,  \
+   .sc_offset  = _sc_offset,   \
+   .flags  = _gate_flags,  \
+   .common = { \
+   .reg= _reg, \
+   .lock   = _lock,   \
+   .hw.init= CLK_HW_INIT(_name,\
+ _parent,  \
+ _gate_ops,\
+ 

[PATCH V1 0/9] add clock driver for Spreadtrum platforms

2017-06-17 Thread Chunyan Zhang
In the last cycle, the patches support Whale2 sc9860 mobile chip have been
merged. This patchset adds clock driver which is used on almost all
Spreadtrum SoCs.

This is a rewrite of Spreadtrum's original clock driver[1] according to the
comments[2] from Stephen Boyd.

This series also adds Spreadtrum clock binding documentation and devicetree
data.

Any comments would be greatly appreciated.

Thanks,
Chunyan

[1] https://lwn.net/Articles/722739/
[2] https://www.spinics.net/lists/arm-kernel/msg582017.html

Chunyan Zhang (9):
  dt-bindings: Add Spreadtrum CCU binding documentation
  clk: sprd: Add common infrastructure
  clk: sprd: add gate clock support
  clk: sprd: add mux clock support
  clk: sprd: add divider clock support
  clk: sprd: add composite clock support
  clk: sprd: add adjustable pll support
  clk: sprd: add clock support for SC9860
  arm64: dts: add ccu for SC9860

 .../devicetree/bindings/clock/sprd-ccu.txt |   46 +
 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi   |   67 +
 arch/arm64/boot/dts/sprd/sc9860.dtsi   |2 +
 arch/arm64/boot/dts/sprd/whale2.dtsi   |8 -
 drivers/clk/Makefile   |1 +
 drivers/clk/sprd/Makefile  |4 +
 drivers/clk/sprd/ccu-sc9860.c  | 1742 
 drivers/clk/sprd/ccu-sc9860.h  |  379 +
 drivers/clk/sprd/ccu_common.c  |   78 +
 drivers/clk/sprd/ccu_common.h  |   90 +
 drivers/clk/sprd/ccu_composite.c   |   62 +
 drivers/clk/sprd/ccu_composite.h   |   47 +
 drivers/clk/sprd/ccu_div.c |   93 ++
 drivers/clk/sprd/ccu_div.h |   77 +
 drivers/clk/sprd/ccu_gate.c|  102 ++
 drivers/clk/sprd/ccu_gate.h|   73 +
 drivers/clk/sprd/ccu_mux.c |   82 +
 drivers/clk/sprd/ccu_mux.h |   63 +
 drivers/clk/sprd/ccu_pll.c |  241 +++
 drivers/clk/sprd/ccu_pll.h |  123 ++
 include/dt-bindings/clock/sc9860-ccu.h |   19 +
 21 files changed, 3391 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd-ccu.txt
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/ccu-sc9860.c
 create mode 100644 drivers/clk/sprd/ccu-sc9860.h
 create mode 100644 drivers/clk/sprd/ccu_common.c
 create mode 100644 drivers/clk/sprd/ccu_common.h
 create mode 100644 drivers/clk/sprd/ccu_composite.c
 create mode 100644 drivers/clk/sprd/ccu_composite.h
 create mode 100644 drivers/clk/sprd/ccu_div.c
 create mode 100644 drivers/clk/sprd/ccu_div.h
 create mode 100644 drivers/clk/sprd/ccu_gate.c
 create mode 100644 drivers/clk/sprd/ccu_gate.h
 create mode 100644 drivers/clk/sprd/ccu_mux.c
 create mode 100644 drivers/clk/sprd/ccu_mux.h
 create mode 100644 drivers/clk/sprd/ccu_pll.c
 create mode 100644 drivers/clk/sprd/ccu_pll.h
 create mode 100644 include/dt-bindings/clock/sc9860-ccu.h

-- 
2.7.4



[PATCH V1 2/9] clk: sprd: Add common infrastructure

2017-06-17 Thread Chunyan Zhang
Added Spreadtrum's clock driver common structure and registration code.

Signed-off-by: Chunyan Zhang 
---
 drivers/clk/Makefile  |  1 +
 drivers/clk/sprd/Makefile |  3 ++
 drivers/clk/sprd/ccu_common.c | 78 +
 drivers/clk/sprd/ccu_common.h | 90 +++
 4 files changed, 172 insertions(+)
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/ccu_common.c
 create mode 100644 drivers/clk/sprd/ccu_common.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c19983a..1d62721 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG)  += samsung/
 obj-$(CONFIG_ARCH_SIRF)+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)   += spear/
+obj-$(CONFIG_ARCH_SPRD)+= sprd/
 obj-$(CONFIG_ARCH_STI) += st/
 obj-$(CONFIG_ARCH_SUNXI)   += sunxi/
 obj-$(CONFIG_ARCH_SUNXI)   += sunxi-ng/
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 000..8f802b2
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+ifneq ($(CONFIG_OF),)
+obj-y  += ccu_common.o
+endif
diff --git a/drivers/clk/sprd/ccu_common.c b/drivers/clk/sprd/ccu_common.c
new file mode 100644
index 000..911f4ba
--- /dev/null
+++ b/drivers/clk/sprd/ccu_common.c
@@ -0,0 +1,78 @@
+/*
+ * Spreadtrum clock infrastructure
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include "ccu_common.h"
+
+static inline void __iomem *ccu_find_base(struct ccu_addr_map *maps,
+ unsigned int num, unsigned int reg)
+{
+   int i;
+
+   for (i = 0; i < num; i++)
+   if ((reg & 0x) == maps[i].phy)
+   return maps[i].virt;
+
+   return 0;
+}
+
+int sprd_ccu_probe(struct device_node *node, struct ccu_addr_map *maps,
+  unsigned int count, const struct sprd_ccu_desc *desc)
+{
+   int i, ret = 0;
+   struct ccu_common *cclk;
+   struct clk_hw *hw;
+
+   for (i = 0; i < desc->num_ccu_clks; i++) {
+   cclk = desc->ccu_clks[i];
+   if (!cclk)
+   continue;
+
+   cclk->base = ccu_find_base(maps, count, cclk->reg);
+   if (!cclk->base) {
+   pr_err("%s: No mapped address found for clock(0x%x)\n",
+   __func__, cclk->reg);
+   return -EINVAL;
+   }
+   cclk->reg = cclk->reg & 0x;
+   }
+
+   for (i = 0; i < desc->hw_clks->num; i++) {
+
+   hw = desc->hw_clks->hws[i];
+
+   if (!hw)
+   continue;
+
+   ret = clk_hw_register(NULL, hw);
+   if (ret) {
+   pr_err("Couldn't register clock %d - %s\n",
+  i, hw->init->name);
+   goto err_clk_unreg;
+   }
+   }
+
+   ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+desc->hw_clks);
+   if (ret) {
+   pr_err("Failed to add clock provider.\n");
+   goto err_clk_unreg;
+   }
+
+   return 0;
+
+err_clk_unreg:
+   while (--i >= 0) {
+   hw = desc->hw_clks->hws[i];
+   if (!hw)
+   continue;
+
+   clk_hw_unregister(hw);
+   }
+
+   return ret;
+}
diff --git a/drivers/clk/sprd/ccu_common.h b/drivers/clk/sprd/ccu_common.h
new file mode 100644
index 000..ff07772
--- /dev/null
+++ b/drivers/clk/sprd/ccu_common.h
@@ -0,0 +1,90 @@
+/*
+ * Spreadtrum clock infrastructure
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_COMMON_H_
+#define _CCU_COMMON_H_
+
+#include 
+
+struct device_node;
+
+#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \
+   (&(struct clk_init_data) {  \
+   .flags  = _flags,   \
+   .name   = _name,\
+   .parent_names   = NULL, \
+   .num_parents= 0,\
+   .ops= _ops, \
+   })
+
+#define CLK_HW_INIT(_name, _parent, _ops, _flags)  \
+   (&(struct clk_init_data) {  \
+   .flags  = _flags,   \
+   .name   = _name,\
+   .parent_names   = (const char *[]) { _parent }, \
+   .num_parents= 1,\
+   .ops= _ops, \
+   })
+
+#define 

[PATCH V1 1/9] dt-bindings: Add Spreadtrum CCU binding documentation

2017-06-17 Thread Chunyan Zhang
Introduce a new binding with its documentation for Spreadtrum clock
sub-framework.

Signed-off-by: Chunyan Zhang 
---
 .../devicetree/bindings/clock/sprd-ccu.txt | 46 ++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd-ccu.txt

diff --git a/Documentation/devicetree/bindings/clock/sprd-ccu.txt 
b/Documentation/devicetree/bindings/clock/sprd-ccu.txt
new file mode 100644
index 000..7a1aa4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd-ccu.txt
@@ -0,0 +1,46 @@
+Spreadtrum Clock Control Unit Binding
+
+
+This binding uses the common clock binding[1].
+
+Required properties:
+- compatible: must contain the following compatible:
+- "sprd,sc9860-ccu" (only support SC9860 for the time being)
+
+- reg: Must contain the registers base address and length.
+   Clocks on most of Spreadtrum's SoCs were designed to locate in a few
+   different address areas, so there would be more than one items under
+   this property.
+
+- clock-names: Must contain the following clock names:
+   - "ext-26m", "ext-rco-100m", "ext-32k"
+- #clock-cells: must be 1
+
+Example:
+
+ccu: clk {
+   compatible = "sprd,sc9860-ccu";
+   #clock-cells = <1>;
+   reg = <0 0x2000 0 0x400>,
+ <0 0x2021 0 0x3000>,
+ <0 0x402b 0 0x4000>,
+ <0 0x402d 0 0x400>,
+ <0 0x402e 0 0x4000>,
+ <0 0x4040 0 0x400>,
+ <0 0x4088 0 0x400>,
+ <0 0x415e 0 0x400>,
+ <0 0x6020 0 0x400>,
+ <0 0x6100 0 0x400>,
+ <0 0x6110 0 0x3000>,
+ <0 0x6200 0 0x4000>,
+ <0 0x6210 0 0x4000>,
+ <0 0x6300 0 0x400>,
+ <0 0x6310 0 0x3000>,
+ <0 0x70b0 0 0x3000>;
+   clocks = <_26m>, <_rco_100m>, <_32k>;
+   clock-names = "ext-26m", "ext-rco-100m", "ext-32k";
+};
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+
-- 
2.7.4



[PATCH V1 4/9] clk: sprd: add mux clock support

2017-06-17 Thread Chunyan Zhang
This is a feature that can also be found in sprd composite clocks,
provide two helpers that can be reused later on.

Original-by: Xiaolong Zhang 
Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile  |  2 +-
 drivers/clk/sprd/ccu_mux.c | 82 ++
 drivers/clk/sprd/ccu_mux.h | 63 +++
 3 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_mux.c
 create mode 100644 drivers/clk/sprd/ccu_mux.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 333e2b2..dc89790 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o ccu_gate.o
+obj-y  += ccu_common.o ccu_gate.o ccu_mux.o
 endif
diff --git a/drivers/clk/sprd/ccu_mux.c b/drivers/clk/sprd/ccu_mux.c
new file mode 100644
index 000..51c744e
--- /dev/null
+++ b/drivers/clk/sprd/ccu_mux.c
@@ -0,0 +1,82 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+#include 
+
+#include "ccu_mux.h"
+
+DEFINE_SPINLOCK(mux_lock);
+
+u8 ccu_mux_helper_get_parent(struct ccu_common *common,
+struct ccu_mux_internal *mux)
+{
+   u32 reg;
+   u8 parent;
+   int num_parents;
+   int i;
+
+   reg = ccu_readl(common);
+   parent = reg >> mux->shift;
+   parent &= (1 << mux->width) - 1;
+
+   if (mux->table) {
+   num_parents = clk_hw_get_num_parents(>hw);
+
+   for (i = 0; i < num_parents; i++)
+   if (parent == mux->table[i] ||
+   (i < (num_parents - 1) && parent > mux->table[i] &&
+parent < mux->table[i + 1]))
+   return i;
+   if (i == num_parents)
+   return i - 1;
+   }
+
+   return parent;
+}
+
+static u8 ccu_mux_get_parent(struct clk_hw *hw)
+{
+   struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+   return ccu_mux_helper_get_parent(>common, >mux);
+}
+
+int ccu_mux_helper_set_parent(struct ccu_common *common,
+ struct ccu_mux_internal *mux,
+ u8 index)
+{
+   unsigned long flags = 0;
+   u32 reg;
+
+   if (mux->table)
+   index = mux->table[index];
+
+   spin_lock_irqsave(common->lock, flags);
+
+   reg = ccu_readl(common);
+   reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
+   ccu_writel(reg | (index << mux->shift), common);
+
+   spin_unlock_irqrestore(common->lock, flags);
+
+   return 0;
+}
+
+static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+   return ccu_mux_helper_set_parent(>common, >mux, index);
+}
+
+const struct clk_ops ccu_mux_ops = {
+   .get_parent = ccu_mux_get_parent,
+   .set_parent = ccu_mux_set_parent,
+   .determine_rate = __clk_mux_determine_rate,
+};
diff --git a/drivers/clk/sprd/ccu_mux.h b/drivers/clk/sprd/ccu_mux.h
new file mode 100644
index 000..f3e3fb4
--- /dev/null
+++ b/drivers/clk/sprd/ccu_mux.h
@@ -0,0 +1,63 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_MUX_H_
+#define _CCU_MUX_H_
+
+#include "ccu_common.h"
+
+struct ccu_mux_internal {
+   u8  shift;
+   u8  width;
+   const u8*table;
+};
+
+struct ccu_mux {
+   struct ccu_mux_internal mux;
+   struct ccu_common   common;
+};
+
+#define _SPRD_CCU_MUX(_shift, _width, _table)  \
+   {   \
+   .shift  = _shift,   \
+   .width  = _width,   \
+   .table  = _table,   \
+   }
+
+#define SPRD_CCU_MUX(_struct, _name, _parents, _table, \
+_reg, _shift, _width,  \
+_flags)\
+   struct ccu_mux _struct = {  \
+   .mux= _SPRD_CCU_MUX(_shift, _width, _table),\
+   .common = { \
+   .reg= _reg, \
+   .lock   = _lock,\
+   .hw.init= CLK_HW_INIT_PARENTS(_name,\
+ _parents, \
+ _mux_ops,\
+ _flags),  \
+   }   \
+   }
+
+static inline struct ccu_mux 

[PATCH V1 3/9] clk: sprd: add gate clock support

2017-06-17 Thread Chunyan Zhang
Some clocks on the Spreadtrum's SoCs are just simple gates. Add
support for those clocks.

Also, some gate clocks are orphan, so this patch also added
registration code for those.

Signed-off-by: Chunyan Zhang 
---
 drivers/clk/sprd/Makefile   |   2 +-
 drivers/clk/sprd/ccu_gate.c | 102 
 drivers/clk/sprd/ccu_gate.h |  73 +++
 3 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sprd/ccu_gate.c
 create mode 100644 drivers/clk/sprd/ccu_gate.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 8f802b2..333e2b2 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_OF),)
-obj-y  += ccu_common.o
+obj-y  += ccu_common.o ccu_gate.o
 endif
diff --git a/drivers/clk/sprd/ccu_gate.c b/drivers/clk/sprd/ccu_gate.c
new file mode 100644
index 000..3d27615
--- /dev/null
+++ b/drivers/clk/sprd/ccu_gate.c
@@ -0,0 +1,102 @@
+/*
+ * Spreadtrum gate clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include 
+
+#include "ccu_gate.h"
+
+DEFINE_SPINLOCK(gate_lock);
+
+static void ccu_gate_endisable(struct ccu_gate *cg, u32 en)
+{
+   struct ccu_common *common = >common;
+   unsigned long flags = 0;
+   u32 reg;
+   int set = cg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+
+   set ^= en;
+
+   spin_lock_irqsave(common->lock, flags);
+
+   reg = ccu_readl(common);
+
+   if (set)
+   reg |= cg->op_bit;
+   else
+   reg &= ~cg->op_bit;
+
+   ccu_writel(reg, common);
+
+   spin_unlock_irqrestore(common->lock, flags);
+}
+
+static void ccu_sc_gate_endisable(struct ccu_gate *cg, u32 en)
+{
+   struct ccu_common *common = >common;
+   unsigned long flags = 0;
+   int set = cg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+   u32 offset;
+
+   set ^= en;
+
+   /*
+* Each set/clear gate clock has three registers:
+* common->reg  - base register
+* common->reg + offset - set register
+* common->reg + 2 * offset - clear register
+*/
+   offset = set ? cg->sc_offset : cg->sc_offset * 2;
+
+   spin_lock_irqsave(common->lock, flags);
+   ccu_writel_offset(cg->op_bit, common, offset);
+   spin_unlock_irqrestore(common->lock, flags);
+}
+
+static void ccu_gate_disable(struct clk_hw *hw)
+{
+   struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+   if (cg->sc_offset)
+   ccu_sc_gate_endisable(cg, 0);
+   else
+   ccu_gate_endisable(cg, 0);
+}
+
+static int ccu_gate_enable(struct clk_hw *hw)
+{
+   struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+   if (cg->sc_offset)
+   ccu_sc_gate_endisable(cg, 1);
+   else
+   ccu_gate_endisable(cg, 1);
+
+   return 0;
+}
+
+static int ccu_gate_is_enabled(struct clk_hw *hw)
+{
+   struct ccu_gate *cg = hw_to_ccu_gate(hw);
+   struct ccu_common *common = >common;
+   u32 reg;
+
+   reg = ccu_readl(common);
+
+   if (cg->flags & CLK_GATE_SET_TO_DISABLE)
+   reg ^= cg->op_bit;
+
+   reg &= cg->op_bit;
+
+   return reg ? 1 : 0;
+}
+
+const struct clk_ops ccu_gate_ops = {
+   .disable= ccu_gate_disable,
+   .enable = ccu_gate_enable,
+   .is_enabled = ccu_gate_is_enabled,
+};
diff --git a/drivers/clk/sprd/ccu_gate.h b/drivers/clk/sprd/ccu_gate.h
new file mode 100644
index 000..bc40169
--- /dev/null
+++ b/drivers/clk/sprd/ccu_gate.h
@@ -0,0 +1,73 @@
+/*
+ * Spreadtrum gate clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_GATE_H_
+#define _CCU_GATE_H_
+
+#include "ccu_common.h"
+
+struct ccu_gate {
+   u32 op_bit;
+   u16 flags;
+   u16 sc_offset;
+
+   struct ccu_common   common;
+};
+
+#define SPRD_CCU_GATE(_struct, _name, _parent, _reg, _sc_offset,   \
+ _op_bit, _flags, _gate_flags) \
+   struct ccu_gate _struct = { \
+   .op_bit = _op_bit,  \
+   .sc_offset  = _sc_offset,   \
+   .flags  = _gate_flags,  \
+   .common = { \
+   .reg= _reg, \
+   .lock   = _lock,   \
+   .hw.init= CLK_HW_INIT(_name,\
+ _parent,  \
+ _gate_ops,\
+ _flags),  \
+

[PATCH V1 0/9] add clock driver for Spreadtrum platforms

2017-06-17 Thread Chunyan Zhang
In the last cycle, the patches support Whale2 sc9860 mobile chip have been
merged. This patchset adds clock driver which is used on almost all
Spreadtrum SoCs.

This is a rewrite of Spreadtrum's original clock driver[1] according to the
comments[2] from Stephen Boyd.

This series also adds Spreadtrum clock binding documentation and devicetree
data.

Any comments would be greatly appreciated.

Thanks,
Chunyan

[1] https://lwn.net/Articles/722739/
[2] https://www.spinics.net/lists/arm-kernel/msg582017.html

Chunyan Zhang (9):
  dt-bindings: Add Spreadtrum CCU binding documentation
  clk: sprd: Add common infrastructure
  clk: sprd: add gate clock support
  clk: sprd: add mux clock support
  clk: sprd: add divider clock support
  clk: sprd: add composite clock support
  clk: sprd: add adjustable pll support
  clk: sprd: add clock support for SC9860
  arm64: dts: add ccu for SC9860

 .../devicetree/bindings/clock/sprd-ccu.txt |   46 +
 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi   |   67 +
 arch/arm64/boot/dts/sprd/sc9860.dtsi   |2 +
 arch/arm64/boot/dts/sprd/whale2.dtsi   |8 -
 drivers/clk/Makefile   |1 +
 drivers/clk/sprd/Makefile  |4 +
 drivers/clk/sprd/ccu-sc9860.c  | 1742 
 drivers/clk/sprd/ccu-sc9860.h  |  379 +
 drivers/clk/sprd/ccu_common.c  |   78 +
 drivers/clk/sprd/ccu_common.h  |   90 +
 drivers/clk/sprd/ccu_composite.c   |   62 +
 drivers/clk/sprd/ccu_composite.h   |   47 +
 drivers/clk/sprd/ccu_div.c |   93 ++
 drivers/clk/sprd/ccu_div.h |   77 +
 drivers/clk/sprd/ccu_gate.c|  102 ++
 drivers/clk/sprd/ccu_gate.h|   73 +
 drivers/clk/sprd/ccu_mux.c |   82 +
 drivers/clk/sprd/ccu_mux.h |   63 +
 drivers/clk/sprd/ccu_pll.c |  241 +++
 drivers/clk/sprd/ccu_pll.h |  123 ++
 include/dt-bindings/clock/sc9860-ccu.h |   19 +
 21 files changed, 3391 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd-ccu.txt
 create mode 100644 arch/arm64/boot/dts/sprd/sc9860-ccu.dtsi
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/ccu-sc9860.c
 create mode 100644 drivers/clk/sprd/ccu-sc9860.h
 create mode 100644 drivers/clk/sprd/ccu_common.c
 create mode 100644 drivers/clk/sprd/ccu_common.h
 create mode 100644 drivers/clk/sprd/ccu_composite.c
 create mode 100644 drivers/clk/sprd/ccu_composite.h
 create mode 100644 drivers/clk/sprd/ccu_div.c
 create mode 100644 drivers/clk/sprd/ccu_div.h
 create mode 100644 drivers/clk/sprd/ccu_gate.c
 create mode 100644 drivers/clk/sprd/ccu_gate.h
 create mode 100644 drivers/clk/sprd/ccu_mux.c
 create mode 100644 drivers/clk/sprd/ccu_mux.h
 create mode 100644 drivers/clk/sprd/ccu_pll.c
 create mode 100644 drivers/clk/sprd/ccu_pll.h
 create mode 100644 include/dt-bindings/clock/sc9860-ccu.h

-- 
2.7.4



[PATCH V1 2/9] clk: sprd: Add common infrastructure

2017-06-17 Thread Chunyan Zhang
Added Spreadtrum's clock driver common structure and registration code.

Signed-off-by: Chunyan Zhang 
---
 drivers/clk/Makefile  |  1 +
 drivers/clk/sprd/Makefile |  3 ++
 drivers/clk/sprd/ccu_common.c | 78 +
 drivers/clk/sprd/ccu_common.h | 90 +++
 4 files changed, 172 insertions(+)
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/ccu_common.c
 create mode 100644 drivers/clk/sprd/ccu_common.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c19983a..1d62721 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG)  += samsung/
 obj-$(CONFIG_ARCH_SIRF)+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)   += spear/
+obj-$(CONFIG_ARCH_SPRD)+= sprd/
 obj-$(CONFIG_ARCH_STI) += st/
 obj-$(CONFIG_ARCH_SUNXI)   += sunxi/
 obj-$(CONFIG_ARCH_SUNXI)   += sunxi-ng/
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 000..8f802b2
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+ifneq ($(CONFIG_OF),)
+obj-y  += ccu_common.o
+endif
diff --git a/drivers/clk/sprd/ccu_common.c b/drivers/clk/sprd/ccu_common.c
new file mode 100644
index 000..911f4ba
--- /dev/null
+++ b/drivers/clk/sprd/ccu_common.c
@@ -0,0 +1,78 @@
+/*
+ * Spreadtrum clock infrastructure
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include "ccu_common.h"
+
+static inline void __iomem *ccu_find_base(struct ccu_addr_map *maps,
+ unsigned int num, unsigned int reg)
+{
+   int i;
+
+   for (i = 0; i < num; i++)
+   if ((reg & 0x) == maps[i].phy)
+   return maps[i].virt;
+
+   return 0;
+}
+
+int sprd_ccu_probe(struct device_node *node, struct ccu_addr_map *maps,
+  unsigned int count, const struct sprd_ccu_desc *desc)
+{
+   int i, ret = 0;
+   struct ccu_common *cclk;
+   struct clk_hw *hw;
+
+   for (i = 0; i < desc->num_ccu_clks; i++) {
+   cclk = desc->ccu_clks[i];
+   if (!cclk)
+   continue;
+
+   cclk->base = ccu_find_base(maps, count, cclk->reg);
+   if (!cclk->base) {
+   pr_err("%s: No mapped address found for clock(0x%x)\n",
+   __func__, cclk->reg);
+   return -EINVAL;
+   }
+   cclk->reg = cclk->reg & 0x;
+   }
+
+   for (i = 0; i < desc->hw_clks->num; i++) {
+
+   hw = desc->hw_clks->hws[i];
+
+   if (!hw)
+   continue;
+
+   ret = clk_hw_register(NULL, hw);
+   if (ret) {
+   pr_err("Couldn't register clock %d - %s\n",
+  i, hw->init->name);
+   goto err_clk_unreg;
+   }
+   }
+
+   ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+desc->hw_clks);
+   if (ret) {
+   pr_err("Failed to add clock provider.\n");
+   goto err_clk_unreg;
+   }
+
+   return 0;
+
+err_clk_unreg:
+   while (--i >= 0) {
+   hw = desc->hw_clks->hws[i];
+   if (!hw)
+   continue;
+
+   clk_hw_unregister(hw);
+   }
+
+   return ret;
+}
diff --git a/drivers/clk/sprd/ccu_common.h b/drivers/clk/sprd/ccu_common.h
new file mode 100644
index 000..ff07772
--- /dev/null
+++ b/drivers/clk/sprd/ccu_common.h
@@ -0,0 +1,90 @@
+/*
+ * Spreadtrum clock infrastructure
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CCU_COMMON_H_
+#define _CCU_COMMON_H_
+
+#include 
+
+struct device_node;
+
+#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \
+   (&(struct clk_init_data) {  \
+   .flags  = _flags,   \
+   .name   = _name,\
+   .parent_names   = NULL, \
+   .num_parents= 0,\
+   .ops= _ops, \
+   })
+
+#define CLK_HW_INIT(_name, _parent, _ops, _flags)  \
+   (&(struct clk_init_data) {  \
+   .flags  = _flags,   \
+   .name   = _name,\
+   .parent_names   = (const char *[]) { _parent }, \
+   .num_parents= 1,\
+   .ops= _ops, \
+   })
+
+#define CLK_HW_INIT_PARENTS(_name, 

[PATCH V1 1/9] dt-bindings: Add Spreadtrum CCU binding documentation

2017-06-17 Thread Chunyan Zhang
Introduce a new binding with its documentation for Spreadtrum clock
sub-framework.

Signed-off-by: Chunyan Zhang 
---
 .../devicetree/bindings/clock/sprd-ccu.txt | 46 ++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd-ccu.txt

diff --git a/Documentation/devicetree/bindings/clock/sprd-ccu.txt 
b/Documentation/devicetree/bindings/clock/sprd-ccu.txt
new file mode 100644
index 000..7a1aa4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd-ccu.txt
@@ -0,0 +1,46 @@
+Spreadtrum Clock Control Unit Binding
+
+
+This binding uses the common clock binding[1].
+
+Required properties:
+- compatible: must contain the following compatible:
+- "sprd,sc9860-ccu" (only support SC9860 for the time being)
+
+- reg: Must contain the registers base address and length.
+   Clocks on most of Spreadtrum's SoCs were designed to locate in a few
+   different address areas, so there would be more than one items under
+   this property.
+
+- clock-names: Must contain the following clock names:
+   - "ext-26m", "ext-rco-100m", "ext-32k"
+- #clock-cells: must be 1
+
+Example:
+
+ccu: clk {
+   compatible = "sprd,sc9860-ccu";
+   #clock-cells = <1>;
+   reg = <0 0x2000 0 0x400>,
+ <0 0x2021 0 0x3000>,
+ <0 0x402b 0 0x4000>,
+ <0 0x402d 0 0x400>,
+ <0 0x402e 0 0x4000>,
+ <0 0x4040 0 0x400>,
+ <0 0x4088 0 0x400>,
+ <0 0x415e 0 0x400>,
+ <0 0x6020 0 0x400>,
+ <0 0x6100 0 0x400>,
+ <0 0x6110 0 0x3000>,
+ <0 0x6200 0 0x4000>,
+ <0 0x6210 0 0x4000>,
+ <0 0x6300 0 0x400>,
+ <0 0x6310 0 0x3000>,
+ <0 0x70b0 0 0x3000>;
+   clocks = <_26m>, <_rco_100m>, <_32k>;
+   clock-names = "ext-26m", "ext-rco-100m", "ext-32k";
+};
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+
-- 
2.7.4



  1   2   3   4   5   6   7   8   >