[PATCH net] net: marvell: prestera: fix port event handling on init

2021-04-20 Thread Vadym Kochan
From: Vadym Kochan 

For some reason there might be a crash during ports creation if port
events are handling at the same time  because fw may send initial
port event with down state.

The crash points to cancel_delayed_work() which is called when port went
is down.  Currently I did not find out the real cause of the issue, so
fixed it by cancel port stats work only if previous port's state was up
& runnig.

The following is the crash which can be triggered:

[   28.311104] Unable to handle kernel paging request at virtual address
71775f776600
[   28.319097] Mem abort info:
[   28.321914]   ESR = 0x9604
[   28.324996]   EC = 0x25: DABT (current EL), IL = 32 bits
[   28.330350]   SET = 0, FnV = 0
[   28.333430]   EA = 0, S1PTW = 0
[   28.336597] Data abort info:
[   28.339499]   ISV = 0, ISS = 0x0004
[   28.343362]   CM = 0, WnR = 0
[   28.346354] user pgtable: 4k pages, 48-bit VAs, pgdp=000100bf7000
[   28.352842] [71775f776600] pgd=,
p4d=
[   28.359695] Internal error: Oops: 9604 [#1] PREEMPT SMP
[   28.365310] Modules linked in: prestera_pci(+) prestera
uio_pdrv_genirq
[   28.372005] CPU: 0 PID: 1291 Comm: kworker/0:1H Not tainted
5.11.0-rc4 #1
[   28.378846] Hardware name: DNI AmazonGo1 A7040 board (DT)
[   28.384283] Workqueue: prestera_fw_wq prestera_fw_evt_work_fn
[prestera_pci]
[   28.391413] pstate: 6085 (nZCv daIf -PAN -UAO -TCO BTYPE=--)
[   28.397468] pc : get_work_pool+0x48/0x60
[   28.401442] lr : try_to_grab_pending+0x6c/0x1b0
[   28.406018] sp : 80001391bc60
[   28.409358] x29: 80001391bc60 x28: 
[   28.414725] x27: 000104fc8b40 x26: 80001127de88
[   28.420089] x25:  x24: 000106119760
[   28.425452] x23: 00010775dd60 x22: 00010567e000
[   28.430814] x21:  x20: 80001391bcb0
[   28.436175] x19: 00010775deb8 x18: 00c0
[   28.441537] x17:  x16: 8d9b0e88
[   28.446898] x15: 0001 x14: 02ba
[   28.452261] x13: 80a3002c0002 x12: 05f4
[   28.457622] x11: 0030 x10: 000c
[   28.462985] x9 : 000c x8 : 0030
[   28.468346] x7 : 80001440 x6 : 000106119758
[   28.473708] x5 : 0003 x4 : 00010775dc60
[   28.479068] x3 :  x2 : 0060
[   28.484429] x1 : 71775f776600 x0 : 00010775deb8
[   28.489791] Call trace:
[   28.492259]  get_work_pool+0x48/0x60
[   28.495874]  cancel_delayed_work+0x38/0xb0
[   28.500011]  prestera_port_handle_event+0x90/0xa0 [prestera]
[   28.505743]  prestera_evt_recv+0x98/0xe0 [prestera]
[   28.510683]  prestera_fw_evt_work_fn+0x180/0x228 [prestera_pci]
[   28.516660]  process_one_work+0x1e8/0x360
[   28.520710]  worker_thread+0x44/0x480
[   28.524412]  kthread+0x154/0x160
[   28.527670]  ret_from_fork+0x10/0x38
[   28.531290] Code: a8c17bfd d50323bf d65f03c0 9278dc21 (f9400020)
[   28.537429] ---[ end trace 5eced933df3a080b ]---

Fixes: 501ef3066c89 ("net: marvell: prestera: Add driver for Prestera family 
ASIC devices")
Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/prestera_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c 
b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 25dd903a3e92..d849b0f65de2 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -431,7 +431,8 @@ static void prestera_port_handle_event(struct 
prestera_switch *sw,
netif_carrier_on(port->dev);
if (!delayed_work_pending(caching_dw))
queue_delayed_work(prestera_wq, caching_dw, 0);
-   } else {
+   } else if (netif_running(port->dev) &&
+  netif_carrier_ok(port->dev)) {
netif_carrier_off(port->dev);
if (delayed_work_pending(caching_dw))
cancel_delayed_work(caching_dw);
-- 
2.17.1



[PATCH RESEND net-next] net: marvell: prestera: add support for AC3X 98DX3265 device

2021-04-16 Thread Vadym Kochan
From: Vadym Kochan 

Add PCI match for AC3X 98DX3265 device which is supported by the current
driver and firmware.

Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/prestera_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index be5677623455..298110119272 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -756,6 +756,7 @@ static void prestera_pci_remove(struct pci_dev *pdev)
 
 static const struct pci_device_id prestera_pci_devices[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC804) },
+   { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC80C) },
{ }
 };
 MODULE_DEVICE_TABLE(pci, prestera_pci_devices);
-- 
2.17.1



Re: [PATCH] net: marvell: prestera: add support for AC3X 98DX3265 device

2021-04-16 Thread Vadym Kochan
On Sat, Apr 17, 2021 at 02:02:02AM +0300, Vadym Kochan wrote:
> From: Vadym Kochan 
> 
> Add PCI match for AC3X 98DX3265 device which is supported by the current
> driver and firmware.
> 
> Signed-off-by: Vadym Kochan 
> ---
>  drivers/net/ethernet/marvell/prestera/prestera_pci.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
> b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
> index be5677623455..298110119272 100644
> --- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
> +++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
> @@ -756,6 +756,7 @@ static void prestera_pci_remove(struct pci_dev *pdev)
>  
>  static const struct pci_device_id prestera_pci_devices[] = {
>   { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC804) },
> + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC80C) },
>   { }
>  };
>  MODULE_DEVICE_TABLE(pci, prestera_pci_devices);
> -- 
> 2.17.1
> 

Sorry, will re-send it with net-next label.


[PATCH] net: marvell: prestera: add support for AC3X 98DX3265 device

2021-04-16 Thread Vadym Kochan
From: Vadym Kochan 

Add PCI match for AC3X 98DX3265 device which is supported by the current
driver and firmware.

Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/prestera_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index be5677623455..298110119272 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -756,6 +756,7 @@ static void prestera_pci_remove(struct pci_dev *pdev)
 
 static const struct pci_device_id prestera_pci_devices[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC804) },
+   { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC80C) },
{ }
 };
 MODULE_DEVICE_TABLE(pci, prestera_pci_devices);
-- 
2.17.1



Re: [RFC] net: core: devlink: add port_params_ops for devlink port parameters altering

2021-04-09 Thread Vadym Kochan
Hi Sridhar,

On Fri, Apr 09, 2021 at 09:51:13AM -0700, Samudrala, Sridhar wrote:
> On 4/9/2021 9:22 AM, Oleksandr Mazur wrote:
> > I'd like to discuss a possibility of handling devlink port parameters
> > with devlink port pointer supplied.
> > 
> > Current design makes it impossible to distinguish which port's parameter
> > should get altered (set) or retrieved (get) whenever there's a single
> > parameter registered within a few ports.
> 
> I also noticed this issue recently when trying to add port parameters and
> I have a patch that handles this in a different way. The ops in devlink_param
> struct can be updated to include port_index as an argument
> 

We were thinking on this direction but rather decided to have more strict
cb signature which reflects that we are working with devlink_port only.

> devlink: Fix devlink_param function pointers
> 
> devlink_param function pointers are used to register device parameters
> as well as port parameters. So we need port_index also as an argument
> to enable port specific parameters.
> 
> Signed-off-by: Sridhar Samudrala 
> 
> diff --git a/include/net/devlink.h b/include/net/devlink.h
> index 57251d12b0fc..bf55acdf98ae 100644
> --- a/include/net/devlink.h
> +++ b/include/net/devlink.h
> @@ -469,12 +469,12 @@ struct devlink_param {
> bool generic;
> enum devlink_param_type type;
> unsigned long supported_cmodes;
> -   int (*get)(struct devlink *devlink, u32 id,
> -  struct devlink_param_gset_ctx *ctx);
> -   int (*set)(struct devlink *devlink, u32 id,
> -  struct devlink_param_gset_ctx *ctx);
> -   int (*validate)(struct devlink *devlink, u32 id,
> -   union devlink_param_value val,
> +   int (*get)(struct devlink *devlink, unsigned int port_index,
> +  u32 id, struct devlink_param_gset_ctx *ctx);
> +   int (*set)(struct devlink *devlink, unsigned int port_index,
> +  u32 id, struct devlink_param_gset_ctx *ctx);
> +   int (*validate)(struct devlink *devlink, unsigned int port_index,
> +   u32 id, union devlink_param_value val,
> struct netlink_ext_ack *extack);
>  };
> 
> diff --git a/net/core/devlink.c b/net/core/devlink.c
> index 151f60af0c4a..65a819ead3d9 100644
> --- a/net/core/devlink.c
> +++ b/net/core/devlink.c
> @@ -3826,21 +3826,23 @@ devlink_param_cmode_is_supported(const struct 
> devlink_param *param,
>  }
> 
>  static int devlink_param_get(struct devlink *devlink,
> +unsigned int port_index,
>  const struct devlink_param *param,
>  struct devlink_param_gset_ctx *ctx)
>  {
> if (!param->get)
> return -EOPNOTSUPP;
> -   return param->get(devlink, param->id, ctx);
> +   return param->get(devlink, port_index, param->id, ctx);
>  }
> 
>  static int devlink_param_set(struct devlink *devlink,
> +unsigned int port_index,
>  const struct devlink_param *param,
>  struct devlink_param_gset_ctx *ctx)
>  {
> if (!param->set)
> return -EOPNOTSUPP;
> -   return param->set(devlink, param->id, ctx);
> +   return param->set(devlink, port_index, param->id, ctx);
>  }
> 
>  static int
> @@ -3941,7 +3943,8 @@ static int devlink_nl_param_fill(struct sk_buff *msg, 
> struct devlink *devlink,
> if (!param_item->published)
> continue;
> ctx.cmode = i;
> -   err = devlink_param_get(devlink, param, );
> +   err = devlink_param_get(devlink, port_index, param,
> +   );
> if (err)
> return err;
> param_value[i] = ctx.val;
> @@ -4216,7 +4219,8 @@ static int __devlink_nl_cmd_param_set_doit(struct 
> devlink *devlink,
> if (err)
> return err;
> if (param->validate) {
> -   err = param->validate(devlink, param->id, value, 
> info->extack);
> +   err = param->validate(devlink, port_index, param->id, value,
> + info->extack);
> if (err)
> return err;
> }
> @@ -4238,7 +4242,7 @@ static int __devlink_nl_cmd_param_set_doit(struct 
> devlink *devlink,
> return -EOPNOTSUPP;
> ctx.val = value;
> ctx.cmode = cmode;
> -   err = devlink_param_set(devlink, param, );
> +   err = devlink_param_set(devlink, port_index, param, );
> if (err)
> return err;
> }
> 
> > 
> > This patch aims to show how this can be changed:
> >- introduce structure port_params_ops that has callbacks for 
> > 

Re: [PATCH net-next 7/7] net: marvell: prestera: fix port event handling on init

2021-02-05 Thread Vadym Kochan
Hi Jakub,

On Thu, Feb 04, 2021 at 09:19:34PM -0800, Jakub Kicinski wrote:
> On Wed,  3 Feb 2021 18:54:58 +0200 Vadym Kochan wrote:
> > For some reason there might be a crash during ports creation if port
> > events are handling at the same time  because fw may send initial
> > port event with down state.
> > 
> > The crash points to cancel_delayed_work() which is called when port went
> > is down.  Currently I did not find out the real cause of the issue, so
> > fixed it by cancel port stats work only if previous port's state was up
> > & runnig.
> 
> Maybe you just need to move the DELAYED_WORK_INIT() earlier?
> Not sure why it's at the end of prestera_port_create(), it 
> just initializes some fields.
> 

Thanks for suggestion, but it does not help. Will try to find-out the
real root cause but this is the only fix I 'v came up.

> > [   28.489791] Call trace:
> > [   28.492259]  get_work_pool+0x48/0x60
> > [   28.495874]  cancel_delayed_work+0x38/0xb0
> > [   28.500011]  prestera_port_handle_event+0x90/0xa0 [prestera]
> > [   28.505743]  prestera_evt_recv+0x98/0xe0 [prestera]
> > [   28.510683]  prestera_fw_evt_work_fn+0x180/0x228 [prestera_pci]
> > [   28.516660]  process_one_work+0x1e8/0x360
> > [   28.520710]  worker_thread+0x44/0x480
> > [   28.524412]  kthread+0x154/0x160
> > [   28.527670]  ret_from_fork+0x10/0x38
> > [   28.531290] Code: a8c17bfd d50323bf d65f03c0 9278dc21 (f9400020)
> > [   28.537429] ---[ end trace 5eced933df3a080b ]---
> > 
> > Signed-off-by: Vadym Kochan 
> > ---
> >  drivers/net/ethernet/marvell/prestera/prestera_main.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c 
> > b/drivers/net/ethernet/marvell/prestera/prestera_main.c
> > index 39465e65d09b..122324dae47d 100644
> > --- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
> > +++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
> > @@ -433,7 +433,8 @@ static void prestera_port_handle_event(struct 
> > prestera_switch *sw,
> > netif_carrier_on(port->dev);
> > if (!delayed_work_pending(caching_dw))
> > queue_delayed_work(prestera_wq, caching_dw, 0);
> > -   } else {
> > +   } else if (netif_running(port->dev) &&
> > +  netif_carrier_ok(port->dev)) {
> > netif_carrier_off(port->dev);
> > if (delayed_work_pending(caching_dw))
> > cancel_delayed_work(caching_dw);
> 


Re: [PATCH net-next 2/7] net: marvell: prestera: disable events interrupt while handling

2021-02-05 Thread Vadym Kochan
Hi Jakub,

On Thu, Feb 04, 2021 at 09:10:12PM -0800, Jakub Kicinski wrote:
> On Wed,  3 Feb 2021 18:54:53 +0200 Vadym Kochan wrote:
> > There are change in firmware which requires that receiver will
> > disable event interrupts before handling them and enable them
> > after finish with handling. Events still may come into the queue
> > but without receiver interruption.
> 
> Sounds like you should do a major version bump for this.
> 
> Old driver will not work correctly with new FW.

Right, the old driver version should fail with new fw version.

Thanks, I will re-send new fw version.


[PATCH net-next 3/7] net: marvell: prestera: add support for AC3X 98DX3265 device

2021-02-03 Thread Vadym Kochan
Add PCI match for AC3X 98DX3265 device which is supported by the current
driver and firmware.

Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/prestera_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index f7b27ef02624..b698a6b4a985 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -775,6 +775,7 @@ static void prestera_pci_remove(struct pci_dev *pdev)
 
 static const struct pci_device_id prestera_pci_devices[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC804) },
+   { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC80C) },
{ }
 };
 MODULE_DEVICE_TABLE(pci, prestera_pci_devices);
-- 
2.17.1



[PATCH net-next 6/7] net: marvell: prestera: align flood setting according to latest firmware version

2021-02-03 Thread Vadym Kochan
Latest FW IPC floow message format was changed to configure uc/mc
flooding separately, so change code according to this.

Signed-off-by: Vadym Kochan 
---
 .../ethernet/marvell/prestera/prestera_hw.c   | 37 +--
 .../ethernet/marvell/prestera/prestera_hw.h   |  3 +-
 .../marvell/prestera/prestera_switchdev.c | 46 +++
 3 files changed, 72 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_hw.c 
b/drivers/net/ethernet/marvell/prestera/prestera_hw.c
index 8afb45f66862..75034dcb3649 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_hw.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_hw.c
@@ -90,6 +90,11 @@ enum {
PRESTERA_PORT_TP_AUTO,
 };
 
+enum {
+   PRESTERA_PORT_FLOOD_TYPE_UC = 0,
+   PRESTERA_PORT_FLOOD_TYPE_MC = 1,
+};
+
 enum {
PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
@@ -201,6 +206,11 @@ struct prestera_msg_port_mdix_param {
u8 admin_mode;
 };
 
+struct prestera_msg_port_flood_param {
+   u8 type;
+   u8 enable;
+};
+
 union prestera_msg_port_param {
u8  admin_state;
u8  oper_state;
@@ -209,7 +219,6 @@ union prestera_msg_port_param {
u8  accept_frm_type;
u32 speed;
u8 learning;
-   u8 flood;
u32 link_mode;
u8  type;
u8  duplex;
@@ -218,6 +227,7 @@ union prestera_msg_port_param {
struct prestera_msg_port_mdix_param mdix;
struct prestera_msg_port_autoneg_param autoneg;
struct prestera_msg_port_cap_param cap;
+   struct prestera_msg_port_flood_param flood;
 };
 
 struct prestera_msg_port_attr_req {
@@ -1030,14 +1040,35 @@ int prestera_hw_port_learning_set(struct prestera_port 
*port, bool enable)
, sizeof(req));
 }
 
-int prestera_hw_port_flood_set(struct prestera_port *port, bool flood)
+int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood)
+{
+   struct prestera_msg_port_attr_req req = {
+   .attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
+   .port = port->hw_id,
+   .dev = port->dev_id,
+   .param = {
+   .flood = {
+   .type = PRESTERA_PORT_FLOOD_TYPE_UC,
+   .enable = flood,
+   }
+   }
+   };
+
+   return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
+   , sizeof(req));
+}
+
+int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood)
 {
struct prestera_msg_port_attr_req req = {
.attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
.port = port->hw_id,
.dev = port->dev_id,
.param = {
-   .flood = flood,
+   .flood = {
+   .type = PRESTERA_PORT_FLOOD_TYPE_MC,
+   .enable = flood,
+   }
}
};
 
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_hw.h 
b/drivers/net/ethernet/marvell/prestera/prestera_hw.h
index 68ce41595349..03b52db6f359 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_hw.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera_hw.h
@@ -138,7 +138,8 @@ int prestera_hw_port_mdix_get(const struct prestera_port 
*port, u8 *status,
 int prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode);
 int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed);
 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable);
-int prestera_hw_port_flood_set(struct prestera_port *port, bool flood);
+int prestera_hw_port_uc_flood_set(struct prestera_port *port, bool flood);
+int prestera_hw_port_mc_flood_set(struct prestera_port *port, bool flood);
 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
 enum prestera_accept_frm_type type);
 /* Vlan API */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c 
b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
index 3750c66a550b..8449539fe944 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
@@ -443,9 +443,13 @@ prestera_bridge_1d_port_join(struct prestera_bridge_port 
*br_port,
if (err)
return err;
 
-   err = prestera_hw_port_flood_set(port, br_port->flags & BR_FLOOD);
+   err = prestera_hw_port_uc_flood_set(port, br_port->flags & BR_FLOOD);
if (err)
-   goto err_port_flood_set;
+   goto err_port_uc_flood_set;
+
+   err = prestera_hw_port_mc_flood_set(port, br_port->flags & 
BR_MCAST_FLOOD);
+   if (err)
+   goto err_port_mc_flood_set;
 
err = prestera_hw_port_learning_set(port, br_port->flags & BR_LE

[PATCH net-next 7/7] net: marvell: prestera: fix port event handling on init

2021-02-03 Thread Vadym Kochan
For some reason there might be a crash during ports creation if port
events are handling at the same time  because fw may send initial
port event with down state.

The crash points to cancel_delayed_work() which is called when port went
is down.  Currently I did not find out the real cause of the issue, so
fixed it by cancel port stats work only if previous port's state was up
& runnig.

The following is the crash which can be triggered:

[   28.311104] Unable to handle kernel paging request at virtual address
71775f776600
[   28.319097] Mem abort info:
[   28.321914]   ESR = 0x9604
[   28.324996]   EC = 0x25: DABT (current EL), IL = 32 bits
[   28.330350]   SET = 0, FnV = 0
[   28.333430]   EA = 0, S1PTW = 0
[   28.336597] Data abort info:
[   28.339499]   ISV = 0, ISS = 0x0004
[   28.343362]   CM = 0, WnR = 0
[   28.346354] user pgtable: 4k pages, 48-bit VAs, pgdp=000100bf7000
[   28.352842] [71775f776600] pgd=,
p4d=
[   28.359695] Internal error: Oops: 9604 [#1] PREEMPT SMP
[   28.365310] Modules linked in: prestera_pci(+) prestera
uio_pdrv_genirq
[   28.372005] CPU: 0 PID: 1291 Comm: kworker/0:1H Not tainted
5.11.0-rc4 #1
[   28.378846] Hardware name: DNI AmazonGo1 A7040 board (DT)
[   28.384283] Workqueue: prestera_fw_wq prestera_fw_evt_work_fn
[prestera_pci]
[   28.391413] pstate: 6085 (nZCv daIf -PAN -UAO -TCO BTYPE=--)
[   28.397468] pc : get_work_pool+0x48/0x60
[   28.401442] lr : try_to_grab_pending+0x6c/0x1b0
[   28.406018] sp : 80001391bc60
[   28.409358] x29: 80001391bc60 x28: 
[   28.414725] x27: 000104fc8b40 x26: 80001127de88
[   28.420089] x25:  x24: 000106119760
[   28.425452] x23: 00010775dd60 x22: 00010567e000
[   28.430814] x21:  x20: 80001391bcb0
[   28.436175] x19: 00010775deb8 x18: 00c0
[   28.441537] x17:  x16: 8d9b0e88
[   28.446898] x15: 0001 x14: 02ba
[   28.452261] x13: 80a3002c0002 x12: 05f4
[   28.457622] x11: 0030 x10: 000c
[   28.462985] x9 : 000c x8 : 0030
[   28.468346] x7 : 80001440 x6 : 000106119758
[   28.473708] x5 : 0003 x4 : 00010775dc60
[   28.479068] x3 :  x2 : 0060
[   28.484429] x1 : 71775f776600 x0 : 00010775deb8
[   28.489791] Call trace:
[   28.492259]  get_work_pool+0x48/0x60
[   28.495874]  cancel_delayed_work+0x38/0xb0
[   28.500011]  prestera_port_handle_event+0x90/0xa0 [prestera]
[   28.505743]  prestera_evt_recv+0x98/0xe0 [prestera]
[   28.510683]  prestera_fw_evt_work_fn+0x180/0x228 [prestera_pci]
[   28.516660]  process_one_work+0x1e8/0x360
[   28.520710]  worker_thread+0x44/0x480
[   28.524412]  kthread+0x154/0x160
[   28.527670]  ret_from_fork+0x10/0x38
[   28.531290] Code: a8c17bfd d50323bf d65f03c0 9278dc21 (f9400020)
[   28.537429] ---[ end trace 5eced933df3a080b ]---

Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/prestera_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c 
b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 39465e65d09b..122324dae47d 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -433,7 +433,8 @@ static void prestera_port_handle_event(struct 
prestera_switch *sw,
netif_carrier_on(port->dev);
if (!delayed_work_pending(caching_dw))
queue_delayed_work(prestera_wq, caching_dw, 0);
-   } else {
+   } else if (netif_running(port->dev) &&
+  netif_carrier_ok(port->dev)) {
netif_carrier_off(port->dev);
if (delayed_work_pending(caching_dw))
cancel_delayed_work(caching_dw);
-- 
2.17.1



[PATCH net-next 5/7] net: marvell: prestera: add LAG support

2021-02-03 Thread Vadym Kochan
From: Serhiy Boiko 

The following features are supported:

- LAG basic operations
- create/delete LAG
- add/remove a member to LAG
- enable/disable member in LAG
- LAG Bridge support
- LAG VLAN support
- LAG FDB support

Limitations:

- Only HASH lag tx type is supported
- The Hash parameters are not configurable. They are applied
  during the LAG creation stage.
- Enslaving a port to the LAG device that already has an
  upper device is not supported.

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Signed-off-by: Serhiy Boiko 
Signed-off-by: Vadym Kochan 
---
 .../net/ethernet/marvell/prestera/prestera.h  |  30 ++-
 .../ethernet/marvell/prestera/prestera_hw.c   | 180 -
 .../ethernet/marvell/prestera/prestera_hw.h   |  14 +
 .../ethernet/marvell/prestera/prestera_main.c | 247 +-
 .../marvell/prestera/prestera_switchdev.c | 109 ++--
 .../marvell/prestera/prestera_switchdev.h |   4 +-
 6 files changed, 538 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 55aa4bf8a27c..ad0f33a7e517 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -60,10 +60,19 @@ struct prestera_port_caps {
u8 transceiver;
 };
 
+struct prestera_lag {
+   struct net_device *dev;
+   struct list_head members;
+   u16 member_count;
+   u16 lag_id;
+};
+
 struct prestera_port {
struct net_device *dev;
struct prestera_switch *sw;
struct devlink_port dl_port;
+   struct list_head lag_member;
+   struct prestera_lag *lag;
u32 id;
u32 hw_id;
u32 dev_id;
@@ -127,6 +136,12 @@ struct prestera_port_event {
} data;
 };
 
+enum prestera_fdb_entry_type {
+   PRESTERA_FDB_ENTRY_TYPE_REG_PORT,
+   PRESTERA_FDB_ENTRY_TYPE_LAG,
+   PRESTERA_FDB_ENTRY_TYPE_MAX
+};
+
 enum prestera_fdb_event_id {
PRESTERA_FDB_EVENT_UNSPEC,
PRESTERA_FDB_EVENT_LEARNED,
@@ -134,7 +149,11 @@ enum prestera_fdb_event_id {
 };
 
 struct prestera_fdb_event {
-   u32 port_id;
+   enum prestera_fdb_entry_type type;
+   union {
+   u32 port_id;
+   u16 lag_id;
+   } dest;
u32 vid;
union {
u8 mac[ETH_ALEN];
@@ -165,6 +184,9 @@ struct prestera_switch {
u32 mtu_min;
u32 mtu_max;
u8 id;
+   struct prestera_lag *lags;
+   u8 lag_member_max;
+   u8 lag_max;
 };
 
 struct prestera_rxtx_params {
@@ -203,4 +225,10 @@ int prestera_port_pvid_set(struct prestera_port *port, u16 
vid);
 
 bool prestera_netdev_check(const struct net_device *dev);
 
+bool prestera_port_is_lag_member(const struct prestera_port *port);
+
+struct prestera_lag *prestera_lag_by_id(struct prestera_switch *sw, u16 id);
+
+u16 prestera_port_lag_id(const struct prestera_port *port);
+
 #endif /* _PRESTERA_H_ */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_hw.c 
b/drivers/net/ethernet/marvell/prestera/prestera_hw.c
index 0424718d5998..8afb45f66862 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_hw.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_hw.c
@@ -39,6 +39,11 @@ enum prestera_cmd_type_t {
PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801,
 
+   PRESTERA_CMD_TYPE_LAG_MEMBER_ADD = 0x900,
+   PRESTERA_CMD_TYPE_LAG_MEMBER_DELETE = 0x901,
+   PRESTERA_CMD_TYPE_LAG_MEMBER_ENABLE = 0x902,
+   PRESTERA_CMD_TYPE_LAG_MEMBER_DISABLE = 0x903,
+
PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
 
PRESTERA_CMD_TYPE_ACK = 0x1,
@@ -127,6 +132,12 @@ enum {
PRESTERA_FC_SYMM_ASYMM,
 };
 
+enum {
+   PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
+   PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
+   PRESTERA_HW_FDB_ENTRY_TYPE_MAX = 2,
+};
+
 struct prestera_fw_event_handler {
struct list_head list;
struct rcu_head rcu;
@@ -168,6 +179,8 @@ struct prestera_msg_switch_init_resp {
u32 port_count;
u32 mtu_max;
u8  switch_id;
+   u8  lag_max;
+   u8  lag_member_max;
 };
 
 struct prestera_msg_port_autoneg_param {
@@ -249,8 +262,13 @@ struct prestera_msg_vlan_req {
 struct prestera_msg_fdb_req {
struct prestera_msg_cmd cmd;
u8 dest_type;
-   u32 port;
-   u32 dev;
+   union {
+   struct {
+   u32 port;
+   u32 dev;
+   };
+   u16 lag_id;
+   } dest;
u8  mac[ETH_ALEN];
u16 vid;
u8  dynamic;
@@ -293,6 +311,13 @@ struct prestera_msg_rxtx_port_req {
u32 dev;
 };
 
+struct prestera_msg_lag_req {
+   struct prestera_msg_cmd cmd;
+   u32 port;
+   u32 dev;
+   u16 lag_id;
+};
+
 struct prestera_msg_event {
u16 type;
u16 id;
@@ -315,7

[PATCH net-next 4/7] net: marvell: prestera: move netdev topology validation to prestera_main

2021-02-03 Thread Vadym Kochan
Move handling of PRECHANGEUPPER event from prestera_switchdev to
prestera_main which is responsible for basic netdev events handling
and routing them to related module.

Signed-off-by: Vadym Kochan 
---
 .../ethernet/marvell/prestera/prestera_main.c | 29 +--
 .../marvell/prestera/prestera_switchdev.c | 20 -
 2 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c 
b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 25dd903a3e92..53c7628a3938 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -510,13 +510,36 @@ struct prestera_port *prestera_port_dev_lower_find(struct 
net_device *dev)
 static int prestera_netdev_port_event(struct net_device *dev,
  unsigned long event, void *ptr)
 {
+   struct netdev_notifier_changeupper_info *info = ptr;
+   struct netlink_ext_ack *extack;
+   struct net_device *upper;
+
+   extack = netdev_notifier_info_to_extack(>info);
+   upper = info->upper_dev;
+
switch (event) {
case NETDEV_PRECHANGEUPPER:
+   if (!netif_is_bridge_master(upper)) {
+   NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
+   return -EINVAL;
+   }
+
+   if (!info->linking)
+   break;
+
+   if (netdev_has_any_upper_dev(upper)) {
+   NL_SET_ERR_MSG_MOD(extack, "Upper device is already 
enslaved");
+   return -EINVAL;
+   }
+   break;
+
case NETDEV_CHANGEUPPER:
-   return prestera_bridge_port_event(dev, event, ptr);
-   default:
-   return 0;
+   if (netif_is_bridge_master(upper))
+   return prestera_bridge_port_event(dev, event, ptr);
+   break;
}
+
+   return 0;
 }
 
 static int prestera_netdev_event_handler(struct notifier_block *nb,
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c 
b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
index 8c2b03151736..7736d5f498c9 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
@@ -537,35 +537,15 @@ int prestera_bridge_port_event(struct net_device *dev, 
unsigned long event,
   void *ptr)
 {
struct netdev_notifier_changeupper_info *info = ptr;
-   struct netlink_ext_ack *extack;
struct prestera_port *port;
struct net_device *upper;
int err;
 
-   extack = netdev_notifier_info_to_extack(>info);
port = netdev_priv(dev);
upper = info->upper_dev;
 
switch (event) {
-   case NETDEV_PRECHANGEUPPER:
-   if (!netif_is_bridge_master(upper)) {
-   NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
-   return -EINVAL;
-   }
-
-   if (!info->linking)
-   break;
-
-   if (netdev_has_any_upper_dev(upper)) {
-   NL_SET_ERR_MSG_MOD(extack, "Upper device is already 
enslaved");
-   return -EINVAL;
-   }
-   break;
-
case NETDEV_CHANGEUPPER:
-   if (!netif_is_bridge_master(upper))
-   break;
-
if (info->linking) {
err = prestera_port_bridge_join(port, upper);
if (err)
-- 
2.17.1



[PATCH net-next 1/7] net: marvell: prestera: bump supported firmware version to 2.5

2021-02-03 Thread Vadym Kochan
New firmware version has some ABI and feature changes like:

- LAG support
- initial L3 support
- changed events handling logic

Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/prestera_pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index be5677623455..b8a87d249647 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -14,7 +14,7 @@
 #define PRESTERA_MSG_MAX_SIZE 1500
 
 #define PRESTERA_SUPP_FW_MAJ_VER   2
-#define PRESTERA_SUPP_FW_MIN_VER   0
+#define PRESTERA_SUPP_FW_MIN_VER   5
 
 #define PRESTERA_FW_PATH_FMT   "mrvl/prestera/mvsw_prestera_fw-v%u.%u.img"
 
-- 
2.17.1



[PATCH net-next 0/7] Marvell Prestera Switchdev misc updates

2021-02-03 Thread Vadym Kochan
This series adds support for new firmware version 2.5 (pull request
was recently send to linux-firmware):


https://lore.kernel.org/linux-firmware/20210203141748.ga18...@plvision.eu/T/#u

Add support of LAG offloading and AC3X 98DX3265 device.

Serhiy Boiko (1):
  net: marvell: prestera: add LAG support

Vadym Kochan (6):
  net: marvell: prestera: bump supported firmware version to 2.5
  net: marvell: prestera: disable events interrupt while handling
  net: marvell: prestera: add support for AC3X 98DX3265 device
  net: marvell: prestera: move netdev topology validation to
prestera_main
  net: marvell: prestera: align flood setting according to latest
firmware version
  net: marvell: prestera: fix port event handling on init

 .../net/ethernet/marvell/prestera/prestera.h  |  30 +-
 .../ethernet/marvell/prestera/prestera_hw.c   | 217 +-
 .../ethernet/marvell/prestera/prestera_hw.h   |  17 +-
 .../ethernet/marvell/prestera/prestera_main.c | 275 +-
 .../ethernet/marvell/prestera/prestera_pci.c  |  22 +-
 .../marvell/prestera/prestera_switchdev.c | 175 +++
 .../marvell/prestera/prestera_switchdev.h |   4 +-
 7 files changed, 657 insertions(+), 83 deletions(-)

-- 
2.17.1



[PATCH net-next 2/7] net: marvell: prestera: disable events interrupt while handling

2021-02-03 Thread Vadym Kochan
There are change in firmware which requires that receiver will
disable event interrupts before handling them and enable them
after finish with handling. Events still may come into the queue
but without receiver interruption.

Signed-off-by: Vadym Kochan 
---
 .../ethernet/marvell/prestera/prestera_pci.c  | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index b8a87d249647..f7b27ef02624 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
 /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
 
+#include 
 #include 
 #include 
 #include 
@@ -144,6 +145,11 @@ struct prestera_fw_regs {
 /* PRESTERA_CMD_RCV_CTL_REG flags */
 #define PRESTERA_CMD_F_REPL_SENT   BIT(0)
 
+#define PRESTERA_FW_EVT_CTL_STATUS_MASKGENMASK(1, 0)
+
+#define PRESTERA_FW_EVT_CTL_STATUS_ON  0
+#define PRESTERA_FW_EVT_CTL_STATUS_OFF 1
+
 #define PRESTERA_EVTQ_REG_OFFSET(q, f) \
(PRESTERA_FW_REG_OFFSET(evtq_list) +\
 (q) * sizeof(struct prestera_fw_evtq_regs) +   \
@@ -260,6 +266,15 @@ static u8 prestera_fw_evtq_pick(struct prestera_fw *fw)
return PRESTERA_EVT_QNUM_MAX;
 }
 
+static void prestera_fw_evt_ctl_status_set(struct prestera_fw *fw, u32 val)
+{
+   u32 status = prestera_fw_read(fw, PRESTERA_FW_STATUS_REG);
+
+   u32p_replace_bits(, val, PRESTERA_FW_EVT_CTL_STATUS_MASK);
+
+   prestera_fw_write(fw, PRESTERA_FW_STATUS_REG, status);
+}
+
 static void prestera_fw_evt_work_fn(struct work_struct *work)
 {
struct prestera_fw *fw;
@@ -269,6 +284,8 @@ static void prestera_fw_evt_work_fn(struct work_struct 
*work)
fw = container_of(work, struct prestera_fw, evt_work);
msg = fw->evt_msg;
 
+   prestera_fw_evt_ctl_status_set(fw, PRESTERA_FW_EVT_CTL_STATUS_OFF);
+
while ((qid = prestera_fw_evtq_pick(fw)) < PRESTERA_EVT_QNUM_MAX) {
u32 idx;
u32 len;
@@ -288,6 +305,8 @@ static void prestera_fw_evt_work_fn(struct work_struct 
*work)
if (fw->dev.recv_msg)
fw->dev.recv_msg(>dev, msg, len);
}
+
+   prestera_fw_evt_ctl_status_set(fw, PRESTERA_FW_EVT_CTL_STATUS_ON);
 }
 
 static int prestera_fw_wait_reg32(struct prestera_fw *fw, u32 reg, u32 cmp,
-- 
2.17.1



Re: [PATCH net] net: marvell: prestera: fix error return code in prestera_pci_probe()

2020-11-13 Thread Vadym Kochan


Hi Wang,

Wang Hai  writes:

> Fix to return a negative error code from the error handling
> case instead of 0, as done elsewhere in this function.
>
> Fixes: 4c2703dfd7fa ("net: marvell: prestera: Add PCI interface support")
> Reported-by: Hulk Robot 
> Signed-off-by: Wang Hai 
> ---
>  drivers/net/ethernet/marvell/prestera/prestera_pci.c | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
> b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
> index 1b97adae542e..be5677623455 100644
> --- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
> +++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
> @@ -676,7 +676,8 @@ static int prestera_pci_probe(struct pci_dev *pdev,
>   if (err)
>   return err;
>  
> - if (dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(30))) {
> + err = dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(30));
> + if (err) {
>   dev_err(>dev, "fail to set DMA mask\n");
>   goto err_dma_mask;
>   }
> @@ -702,8 +703,10 @@ static int prestera_pci_probe(struct pci_dev *pdev,
>   dev_info(fw->dev.dev, "Prestera FW is ready\n");
>  
>   fw->wq = alloc_workqueue("prestera_fw_wq", WQ_HIGHPRI, 1);
> - if (!fw->wq)
> + if (!fw->wq) {
> + err = -ENOMEM;
>       goto err_wq_alloc;
> + }
>  
>   INIT_WORK(>evt_work, prestera_fw_evt_work_fn);

Thank you!

Just in case it is needed:

Reviewed-by: Vadym Kochan 
Acked-by: Vadym Kochan 


[PATCH net] net: marvell: prestera: fix compilation with CONFIG_BRIDGE=m

2020-11-06 Thread Vadym Kochan
With CONFIG_BRIDGE=m the compilation fails:

ld: drivers/net/ethernet/marvell/prestera/prestera_switchdev.o: in function 
`prestera_bridge_port_event':
prestera_switchdev.c:(.text+0x2ebd): undefined reference to 
`br_vlan_enabled'

in case the driver is statically enabled.

Fix it by adding 'BRIDGE || BRIDGE=n' dependency.

Fixes: e1189d9a5fbe ("net: marvell: prestera: Add Switchdev driver 
implementation")
Reported-by: Randy Dunlap 
Signed-off-by: Vadym Kochan 
---
 drivers/net/ethernet/marvell/prestera/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index b1fcc44f566a..b6f20e2034c6 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -6,6 +6,7 @@
 config PRESTERA
tristate "Marvell Prestera Switch ASICs support"
depends on NET_SWITCHDEV && VLAN_8021Q
+   depends on BRIDGE || BRIDGE=n
select NET_DEVLINK
help
  This driver supports Marvell Prestera Switch ASICs family.
-- 
2.17.1



Re: linux-next: Tree for Nov 3 (drivers/net/ethernet/marvell/prestera/prestera_switchdev.o)

2020-11-06 Thread Vadym Kochan


Hi Randy,

Randy Dunlap  writes:

> On 11/2/20 11:19 PM, Stephen Rothwell wrote:
>> Hi all,
>> 
>> Changes since 20201102:
>> 
>
> on x86_64:
>
> when CONFIG_BRIDGE=m:
>
> ld: drivers/net/ethernet/marvell/prestera/prestera_switchdev.o: in function 
> `prestera_bridge_port_event':
> prestera_switchdev.c:(.text+0x2ebd): undefined reference to `br_vlan_enabled'
>
>
> Also please add drivers/net/ethernet/marvell/prestera/ to the
> MAINTAINERS file.
>
> thanks.

Thanks for catching this, will send fix via the "net" tree.

Regards,
Vadym Kochan


Re: linux-next: build failure after merge of the net-next tree

2020-09-30 Thread Vadym Kochan
Hi Stephen,

On Thu, Oct 01, 2020 at 08:09:16AM +1000, Stephen Rothwell wrote:
> Hi all,
> 
[CUT]
> 
> I am still getting this build failure ...
> 
> -- 

I just 've checked linux-next/master and it builds fine at least with my custom
config, do/how I need to handle this case ?

I see the changes you applied already in linux-next/master.

> Cheers,
> Stephen Rothwell




[PATCH v3] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
Fix missing 'kfree_const(cell->name)' when call to
nvmem_cell_info_to_nvmem_cell() in several places:

 * after nvmem_cell_info_to_nvmem_cell() failed during
   nvmem_add_cells()

 * during nvmem_device_cell_{read,write} when cell->name is
   kstrdup'ed() without calling kfree_const() at the end, but
   really there is no reason to do that 'dup, because the cell
   instance is allocated on the stack for some short period to be
   read/write without exposing it to the caller.

So the new nvmem_cell_info_to_nvmem_cell_nodup() helper is introduced
which is used to convert cell_info -> cell without name duplication as
a lighweight version of nvmem_cell_info_to_nvmem_cell().

Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
Signed-off-by: Vadym Kochan 
---
v3:
* rename __nvmem_cell_info_to_nvmem_cell() -> 
nvmem_cell_info_to_nvmem_cell_nodup()

* rephrase commit description a bit

* get rid of wrong func line wrapping

v2:
* remove not needed 'kfree_const(cell->name)' after 
nvmem_cell_info_to_nvmem_cell()
  failed.

 drivers/nvmem/core.c | 33 -
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..10cd935cf30e 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -361,16 +361,14 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
blocking_notifier_call_chain(_notifier, NVMEM_CELL_ADD, cell);
 }
 
-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
-  const struct nvmem_cell_info *info,
-  struct nvmem_cell *cell)
+static int nvmem_cell_info_to_nvmem_cell_nodup(struct nvmem_device *nvmem,
+   const struct nvmem_cell_info *info,
+   struct nvmem_cell *cell)
 {
cell->nvmem = nvmem;
cell->offset = info->offset;
cell->bytes = info->bytes;
-   cell->name = kstrdup_const(info->name, GFP_KERNEL);
-   if (!cell->name)
-   return -ENOMEM;
+   cell->name = info->name;
 
cell->bit_offset = info->bit_offset;
cell->nbits = info->nbits;
@@ -382,13 +380,30 @@ static int nvmem_cell_info_to_nvmem_cell(struct 
nvmem_device *nvmem,
if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
dev_err(>dev,
"cell %s unaligned to nvmem stride %d\n",
-   cell->name, nvmem->stride);
+   cell->name ?: "", nvmem->stride);
return -EINVAL;
}
 
return 0;
 }
 
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+   const struct nvmem_cell_info *info,
+   struct nvmem_cell *cell)
+{
+   int err;
+
+   err = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, cell);
+   if (err)
+   return err;
+
+   cell->name = kstrdup_const(info->name, GFP_KERNEL);
+   if (!cell->name)
+   return -ENOMEM;
+
+   return 0;
+}
+
 /**
  * nvmem_add_cells() - Add cell information to an nvmem device
  *
@@ -1460,7 +1475,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
 
-   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
+   rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, );
if (rc)
return rc;
 
@@ -1490,7 +1505,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
 
-   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
+   rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, );
if (rc)
return rc;
 
-- 
2.17.1



Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
On Wed, Sep 23, 2020 at 04:51:06PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 15:51, Vadym Kochan wrote:
> > > -   return nvmem_cell_write(, buf, cell.bytes);
> > > +   rc = nvmem_cell_write(, buf, cell.bytes);
> > > +   if (rc)
> > > +   kfree_const(cell->name);
> > > +
> > > +   return rc;
> > >   }
> > >   EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
> > >   >cut<---
> > > 
> > > --srini
> > > 
> > But is it really needed to kstrdup(cell->name) for 
> > nvmem_device_cell_{read,write} ?
> This boils down to if we want to use same api to parse nvmem_cell_info or
> not!
> 
> If we want to keep this simple, we can either explicitly add free for
> successful caller to nvmem_cell_info_to_nvmem_cell()!
> 
> Or
> 
> use something like what you did, but new api needs more clarity!
> May be renaming __nvmem_cell_info_to_nvmem_cell to
> nvmem_cell_info_to_nvmem_cell_no_alloc would clarify that a bit!
> 

Naming is most difficult thing, what about 
__nvmem_cell_info_to_nvmem_cell_{unsafe,nodup}() ?
At least this is an indication to be carefully here.

> Also can you make sure that linewrapping on function names be inline with
> existing code.
> 
> Please send v3 with that changes!
> 
> 
> --srini
> > It is used only for log error in case the unaligned access did not
> > pass the check


Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
On Wed, Sep 23, 2020 at 04:51:06PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 15:51, Vadym Kochan wrote:
> > > -   return nvmem_cell_write(, buf, cell.bytes);
> > > +   rc = nvmem_cell_write(, buf, cell.bytes);
> > > +   if (rc)
> > > +   kfree_const(cell->name);
> > > +
> > > +   return rc;
> > >   }
> > >   EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
> > >   >cut<---
> > > 
> > > --srini
> > > 
> > But is it really needed to kstrdup(cell->name) for 
> > nvmem_device_cell_{read,write} ?
> This boils down to if we want to use same api to parse nvmem_cell_info or
> not!
> 
> If we want to keep this simple, we can either explicitly add free for
> successful caller to nvmem_cell_info_to_nvmem_cell()!
> 

I think that such additional kfree_const(cell->name) handling adds more
complexity for error handling, also to my understanding usually
resource allocation should be done in the called func in case of error
was returned.

> Or
> 
> use something like what you did, but new api needs more clarity!
> May be renaming __nvmem_cell_info_to_nvmem_cell to
> nvmem_cell_info_to_nvmem_cell_no_alloc would clarify that a bit!
> 

Yes, I agree that naming should be better, actually "__" already points
to it's unsafety (no kstrdup() is used), but of course additional suffix
would be better.

> Also can you make sure that linewrapping on function names be inline with
> existing code.

You mean do not do such func attributes breaking as I did (moved them
line upper) ?

> 
> Please send v3 with that changes!
> 
> 
> --srini
> > It is used only for log error in case the unaligned access did not
> > pass the check


Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
On Wed, Sep 23, 2020 at 03:47:14PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 15:13, Vadym Kochan wrote:
> > On Wed, Sep 23, 2020 at 03:10:36PM +0100, Srinivas Kandagatla wrote:
> > > 
> > > 
> > > On 23/09/2020 14:53, Vadym Kochan wrote:
> > > > Fix missing 'kfree_const(cell->name)' when call to
> > > > nvmem_cell_info_to_nvmem_cell() in several places:
> > > > 
> > > >* after nvmem_cell_info_to_nvmem_cell() failed during
> > > >  nvmem_add_cells()
> > > > 
> > > >* during nvmem_device_cell_{read,write}. This is fixed by simply
> > > >  re-using info->name instead of duplicating it:
> > > > 
> > > >  cell->name = info->name
> > > > 
> > > > Because cell->name is not used except for error message printing in case
> > > > of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
> > > > was introduced.
> > > > 
> > > > Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
> > > > Signed-off-by: Vadym Kochan 
> > > > ---
> > > > v2:
> > > >   * remove not needed 'kfree_const(cell->name)' after 
> > > > nvmem_cell_info_to_nvmem_cell()
> > > > failed.
> > > > 
> > > >drivers/nvmem/core.c | 35 ++-
> > > >1 file changed, 26 insertions(+), 9 deletions(-)
> > > 
> > > 
> > > 
> > > Really :-)
> > > 
> > But what about nvmem_device_cell_{read,write} case ?
> > In my understanding the cell is allocated on the stack but kstrdup() is
> You are right!
> 
> That is the second issue where the caller outside would fail after
> successful call to nvmem_cell_info_to_nvmem_cell() .
> 
> Probably we cam free it in failure cases!
> something like:
> 
> >cut<---
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 6cd3edb2eaf6..fb1e756adcee 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
> nvmem_device *nvmem,
> dev_err(>dev,
> "cell %s unaligned to nvmem stride %d\n",
> cell->name, nvmem->stride);
> +   kfree_const(cell->name);
> return -EINVAL;
> }
> 
> @@ -1465,8 +1466,10 @@ ssize_t nvmem_device_cell_read(struct nvmem_device
> *nvmem,
> return rc;
> 
> rc = __nvmem_cell_read(nvmem, , buf, );
> -   if (rc)
> +   if (rc) {
> +   kfree_const(cell->name);
> return rc;
> +   }
> 
> return len;
>  }
> @@ -1494,7 +1497,11 @@ int nvmem_device_cell_write(struct nvmem_device
> *nvmem,
> if (rc)
> return rc;
> 
> -   return nvmem_cell_write(, buf, cell.bytes);
> +   rc = nvmem_cell_write(, buf, cell.bytes);
> +   if (rc)
> +   kfree_const(cell->name);
> +
> +   return rc;
>  }
>  EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
>  >cut<---
> 
> --srini
> 

But is it really needed to kstrdup(cell->name) for 
nvmem_device_cell_{read,write} ?
It is used only for log error in case the unaligned access did not
pass the check.

> > not freed in the end, or I missed something ?
> > 
> > > 
> > > Below change should just fix this the reported issue!
> > > >cut<---
> > > 
> > > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > > index 6cd3edb2eaf6..9fb9112fe75d 100644
> > > --- a/drivers/nvmem/core.c
> > > +++ b/drivers/nvmem/core.c
> > > @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
> > > nvmem_device *nvmem,
> > >  dev_err(>dev,
> > >  "cell %s unaligned to nvmem stride %d\n",
> > >  cell->name, nvmem->stride);
> > > +   kfree_const(cell->name);
> > >  return -EINVAL;
> > >  }
> > > 
> > > >cut<---
> > > 
> > > I don't see a point in the way your patch try to fix this!!
> > > 
> > > 
> > > --srini
> > > 

Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
On Wed, Sep 23, 2020 at 03:10:36PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 14:53, Vadym Kochan wrote:
> > Fix missing 'kfree_const(cell->name)' when call to
> > nvmem_cell_info_to_nvmem_cell() in several places:
> > 
> >   * after nvmem_cell_info_to_nvmem_cell() failed during
> > nvmem_add_cells()
> > 
> >   * during nvmem_device_cell_{read,write}. This is fixed by simply
> > re-using info->name instead of duplicating it:
> > 
> > cell->name = info->name
> > 
> > Because cell->name is not used except for error message printing in case
> > of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
> > was introduced.
> > 
> > Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
> > Signed-off-by: Vadym Kochan 
> > ---
> > v2:
> >  * remove not needed 'kfree_const(cell->name)' after 
> > nvmem_cell_info_to_nvmem_cell()
> >failed.
> > 
> >   drivers/nvmem/core.c | 35 ++-
> >   1 file changed, 26 insertions(+), 9 deletions(-)
> 
> 
> 
> Really :-)
> 
But what about nvmem_device_cell_{read,write} case ?
In my understanding the cell is allocated on the stack but kstrdup() is
not freed in the end, or I missed something ?

> 
> Below change should just fix this the reported issue!
> >cut<---
> 
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 6cd3edb2eaf6..9fb9112fe75d 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
> nvmem_device *nvmem,
> dev_err(>dev,
> "cell %s unaligned to nvmem stride %d\n",
> cell->name, nvmem->stride);
> +   kfree_const(cell->name);
> return -EINVAL;
> }
> 
> >cut<---
> 
> I don't see a point in the way your patch try to fix this!!
> 
> 
> --srini
> 
> > 
> > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > index 6cd3edb2eaf6..e6d1bc414faf 100644
> > --- a/drivers/nvmem/core.c
> > +++ b/drivers/nvmem/core.c
> > @@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
> > blocking_notifier_call_chain(_notifier, NVMEM_CELL_ADD, cell);
> >   }
> > -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > -  const struct nvmem_cell_info *info,
> > -  struct nvmem_cell *cell)
> > +static int
> > +__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > +   const struct nvmem_cell_info *info,
> > +   struct nvmem_cell *cell)
> >   {
> > cell->nvmem = nvmem;
> > cell->offset = info->offset;
> > cell->bytes = info->bytes;
> > -   cell->name = kstrdup_const(info->name, GFP_KERNEL);
> > -   if (!cell->name)
> > -   return -ENOMEM;
> > +   cell->name = info->name;
> > cell->bit_offset = info->bit_offset;
> > cell->nbits = info->nbits;
> > @@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct 
> > nvmem_device *nvmem,
> > if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
> > dev_err(>dev,
> > "cell %s unaligned to nvmem stride %d\n",
> > -   cell->name, nvmem->stride);
> > +   cell->name ?: "", nvmem->stride);
> > return -EINVAL;
> > }
> > return 0;
> >   }
> > +static int
> > +nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > + const struct nvmem_cell_info *info,
> > + struct nvmem_cell *cell)
> > +{
> > +   int err;
> > +
> > +   err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
> > +   if (err)
> > +   return err;
> > +
> > +   cell->name = kstrdup_const(info->name, GFP_KERNEL);
> > +   if (!cell->name)
> > +   return -ENOMEM;
> > +
> > +   return 0;
> > +}
> > +
> >   /**
> >* nvmem_add_cells() - Add cell information to an nvmem device
> >*
> > @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device 
> > *nvmem,
> > if (!nvmem)
> > return -EINVAL;
> > -   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
> > +   rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
> > if (rc)
> > return rc;
> > @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device 
> > *nvmem,
> > if (!nvmem)
> > return -EINVAL;
> > -   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
> > +   rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
> > if (rc)
> > return rc;
> > 


[PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
Fix missing 'kfree_const(cell->name)' when call to
nvmem_cell_info_to_nvmem_cell() in several places:

 * after nvmem_cell_info_to_nvmem_cell() failed during
   nvmem_add_cells()

 * during nvmem_device_cell_{read,write}. This is fixed by simply
   re-using info->name instead of duplicating it:

   cell->name = info->name

Because cell->name is not used except for error message printing in case
of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
was introduced.

Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
Signed-off-by: Vadym Kochan 
---
v2:
* remove not needed 'kfree_const(cell->name)' after 
nvmem_cell_info_to_nvmem_cell()
  failed.

 drivers/nvmem/core.c | 35 ++-
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..e6d1bc414faf 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
blocking_notifier_call_chain(_notifier, NVMEM_CELL_ADD, cell);
 }
 
-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
-  const struct nvmem_cell_info *info,
-  struct nvmem_cell *cell)
+static int
+__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+   const struct nvmem_cell_info *info,
+   struct nvmem_cell *cell)
 {
cell->nvmem = nvmem;
cell->offset = info->offset;
cell->bytes = info->bytes;
-   cell->name = kstrdup_const(info->name, GFP_KERNEL);
-   if (!cell->name)
-   return -ENOMEM;
+   cell->name = info->name;
 
cell->bit_offset = info->bit_offset;
cell->nbits = info->nbits;
@@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct 
nvmem_device *nvmem,
if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
dev_err(>dev,
"cell %s unaligned to nvmem stride %d\n",
-   cell->name, nvmem->stride);
+   cell->name ?: "", nvmem->stride);
return -EINVAL;
}
 
return 0;
 }
 
+static int
+nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info,
+ struct nvmem_cell *cell)
+{
+   int err;
+
+   err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
+   if (err)
+   return err;
+
+   cell->name = kstrdup_const(info->name, GFP_KERNEL);
+   if (!cell->name)
+   return -ENOMEM;
+
+   return 0;
+}
+
 /**
  * nvmem_add_cells() - Add cell information to an nvmem device
  *
@@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
 
-   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
+   rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
if (rc)
return rc;
 
@@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
 
-   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
+   rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
if (rc)
return rc;
 
-- 
2.17.1



Re: [PATCH] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-23 Thread Vadym Kochan
On Wed, Sep 23, 2020 at 02:50:05AM +0300, Vadym Kochan wrote:
[CUT]
>  
> +static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> +const struct nvmem_cell_info *info,
> +struct nvmem_cell *cell)
> +{
> + int err;
> +
> + err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
> + if (err)
> + return err;
> +
> + cell->name = kstrdup_const(info->name, GFP_KERNEL);
> + if (!cell->name)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
>  /**
>   * nvmem_add_cells() - Add cell information to an nvmem device
>   *
> @@ -418,6 +434,7 @@ static int nvmem_add_cells(struct nvmem_device *nvmem,
>  
>   rval = nvmem_cell_info_to_nvmem_cell(nvmem, [i], cells[i]);
>   if (rval) {
> + kfree_const(cells[i]->name);
Sorry, looks like this should not happen with new changes.

>   kfree(cells[i]);
>   goto err;
>   }
> @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device 
> *nvmem,
>   if (!nvmem)
>   return -EINVAL;
>  
> - rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
> + rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
>   if (rc)
>   return rc;
>  
> @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
>   if (!nvmem)
>   return -EINVAL;
>  
> - rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
> + rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
>   if (rc)
>   return rc;
>  
> -- 
> 2.17.1
> 


[PATCH] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()

2020-09-22 Thread Vadym Kochan
Fix missing kfree_const(cell->name) when call to
nvmem_cell_info_to_nvmem_cell() in several places:

 * after nvmem_cell_info_to_nvmem_cell() failed during nvmem_add_cells()

 * during nvmem_device_cell_{read,write}. This is fixed by simply
   re-using info->name instead of duplicating it (happens in case
   of dynamic module):

   cell->name = info->name

   because cell->name is useless in these cases except for error
   message printing in case of un-aligned access is indicated.
   For this new __nvmem_cell_info_to_nvmem_cell() helper was
   introduced.

Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
Signed-off-by: Vadym Kochan 
---
 drivers/nvmem/core.c | 35 ++-
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..d1f5a639dfca 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
blocking_notifier_call_chain(_notifier, NVMEM_CELL_ADD, cell);
 }
 
-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
-  const struct nvmem_cell_info *info,
-  struct nvmem_cell *cell)
+static int
+__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+   const struct nvmem_cell_info *info,
+   struct nvmem_cell *cell)
 {
cell->nvmem = nvmem;
cell->offset = info->offset;
cell->bytes = info->bytes;
-   cell->name = kstrdup_const(info->name, GFP_KERNEL);
-   if (!cell->name)
-   return -ENOMEM;
+   cell->name = info->name;
 
cell->bit_offset = info->bit_offset;
cell->nbits = info->nbits;
@@ -382,13 +381,30 @@ static int nvmem_cell_info_to_nvmem_cell(struct 
nvmem_device *nvmem,
if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
dev_err(>dev,
"cell %s unaligned to nvmem stride %d\n",
-   cell->name, nvmem->stride);
+   cell->name ?: "", nvmem->stride);
return -EINVAL;
}
 
return 0;
 }
 
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+  const struct nvmem_cell_info *info,
+  struct nvmem_cell *cell)
+{
+   int err;
+
+   err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
+   if (err)
+   return err;
+
+   cell->name = kstrdup_const(info->name, GFP_KERNEL);
+   if (!cell->name)
+   return -ENOMEM;
+
+   return 0;
+}
+
 /**
  * nvmem_add_cells() - Add cell information to an nvmem device
  *
@@ -418,6 +434,7 @@ static int nvmem_add_cells(struct nvmem_device *nvmem,
 
rval = nvmem_cell_info_to_nvmem_cell(nvmem, [i], cells[i]);
if (rval) {
+   kfree_const(cells[i]->name);
kfree(cells[i]);
goto err;
}
@@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
 
-   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
+   rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
if (rc)
return rc;
 
@@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
 
-   rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, );
+   rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, );
if (rc)
return rc;
 
-- 
2.17.1



Re: [PATCH 1/3] nvmem: core: introduce cells parser

2020-09-22 Thread Vadym Kochan
On Tue, Sep 22, 2020 at 10:48:27AM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 15/09/2020 13:41, Vadym Kochan wrote:
> > Currently NVMEM core does not allow to register cells for an already
> > registered nvmem device and requires that this should be done before.
> > But there might a driver which needs to parse the nvmem device and then
> > register a cells table.
> > 
> > Introduce nvmem_parser API which allows to register cells parser which
> > is called during nvmem device registration. During this stage the parser
> > can read the nvmem device and register the cells table.
> > 
> 
> Overall this approach looks okay to me!
> 
> Rather than a binding for onie cell parser, I think we should add a generic
> bindings for parser something like:
> 
> 
> nvmem-cell-parser = "onie-tlv-cells";
> 
> 
> I also think the parser matching should be done based on this string which
> can remove
> 1. new DT node for onie parser.
> 2. works for both DT and non-DT setups.
> 
> nvmem provider register will automatically parse this once it finds a
> matching parser or it will EPROBE_DEFER!
> 
> Let me know if you think it works for you!
> 
> 
> --srini

Indeed, it sounds very good and fixes the early dependency that
parser should be registered first before nvmem provider.

I will try!

> 
> > Signed-off-by: Vadym Kochan 
> > ---
> >   drivers/nvmem/core.c   | 89 ++
> >   include/linux/nvmem-provider.h | 27 +++
> >   2 files changed, 116 insertions(+)
> > 
> > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > index 6cd3edb2eaf6..82a96032bc3f 100644
> > --- a/drivers/nvmem/core.c
> > +++ b/drivers/nvmem/core.c
> > @@ -55,6 +55,14 @@ struct nvmem_cell {
> > struct list_headnode;
> >   };
> > +struct nvmem_parser {
> > +   struct device_node  *nvmem_of;
> > +   struct kref refcnt;
> > +   struct list_headhead;
> > +   nvmem_parse_t   cells_parse;
> > +   void *priv;
> > +};
> > +
> >   static DEFINE_MUTEX(nvmem_mutex);
> >   static DEFINE_IDA(nvmem_ida);
> > @@ -64,6 +72,9 @@ static LIST_HEAD(nvmem_cell_tables);
> >   static DEFINE_MUTEX(nvmem_lookup_mutex);
> >   static LIST_HEAD(nvmem_lookup_list);
> > +static DEFINE_MUTEX(nvmem_parser_mutex);
> > +static LIST_HEAD(nvmem_parser_list);
> > +
> >   static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
> >   static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
> > @@ -571,6 +582,30 @@ static int nvmem_add_cells_from_of(struct nvmem_device 
> > *nvmem)
> > return 0;
> >   }
> > +static struct nvmem_parser *
> > +__nvmem_parser_find_of(const struct nvmem_device *nvmem)
> > +{
> > +   struct nvmem_parser *parser;
> > +
> > +   list_for_each_entry(parser, _parser_list, head) {
> > +   if (dev_of_node(nvmem->base_dev) == parser->nvmem_of)
> > +   return parser;
> > +   }
> > +
> > +   return NULL;
> > +}
> > +
> > +static void nvmem_cells_parse(struct nvmem_device *nvmem)
> > +{
> > +   struct nvmem_parser *parser;
> > +
> > +   mutex_lock(_parser_mutex);
> > +   parser = __nvmem_parser_find_of(nvmem);
> > +   if (parser && parser->cells_parse)
> > +   parser->cells_parse(parser->priv, nvmem);
> > +   mutex_unlock(_parser_mutex);
> > +}
> > +
> >   /**
> >* nvmem_register() - Register a nvmem device for given nvmem_config.
> >* Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
> > @@ -674,6 +709,8 @@ struct nvmem_device *nvmem_register(const struct 
> > nvmem_config *config)
> > goto err_teardown_compat;
> > }
> > +   nvmem_cells_parse(nvmem);
> > +
> > rval = nvmem_add_cells_from_table(nvmem);
> > if (rval)
> > goto err_remove_cells;
> > @@ -1630,6 +1667,58 @@ const char *nvmem_dev_name(struct nvmem_device 
> > *nvmem)
> >   }
> >   EXPORT_SYMBOL_GPL(nvmem_dev_name);
> > +struct nvmem_parser *
> > +nvmem_parser_register(const struct nvmem_parser_config *config)
> > +{
> > +   struct device_node *nvmem_of;
> > +   struct nvmem_parser *parser;
> > +   int err;
> > +
> > +   if (!config->cells_parse)
> > +   return ERR_PTR(-EINVAL);
> > +
> > +   if (!config->dev)
> > +   return ERR_PTR(-EINVAL);
> > +
> > +   nvmem_of = of_parse_phandle(dev_

Re: [PATCH 0/3] nvmem: add ONIE NVMEM cells provider

2020-09-22 Thread Vadym Kochan
Hi Srinivas,

On Tue, Sep 22, 2020 at 10:48:23AM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 22/09/2020 00:56, Vadym Kochan wrote:
> > Hi Srinivas,
> > 
> > On Tue, Sep 15, 2020 at 03:41:13PM +0300, Vadym Kochan wrote:
> > > This series adds cells parser for the ONIE TLV attributes which are
> > > stored on NVMEM device. It adds possibility to read the mac address (and
> > > other info) by other drivers.
> > > 
> > > Because ONIE stores info in TLV format it should be parsed first and
> > > then register the cells. Current NVMEM API allows to register cell
> > > table with known cell's offset which is not guaranteed in case of TLV.
> > > 
> > > To make it properly handled the NVMEM parser object is introduced. The
> > > parser needs to be registered before target NVMEM device is registered.
> > > During the registration of NVMEM device the parser is called to parse
> > > the device's cells and reister the cell table.
> > > 
> > > Vadym Kochan (3):
> > >nvmem: core: introduce cells parser
> > >nvmem: add ONIE nvmem cells parser
> > >dt-bindings: nvmem: add description for ONIE cells parser
> > > 
> > >   .../bindings/nvmem/onie,nvmem-cells.txt   |  11 +
> > >   drivers/nvmem/Kconfig |   9 +
> > >   drivers/nvmem/Makefile|   3 +
> > >   drivers/nvmem/core.c  |  80 
> > >   drivers/nvmem/onie-cells.c| 370 ++
> > >   include/linux/nvmem-provider.h|  30 ++
> > >   6 files changed, 503 insertions(+)
> > >   create mode 100644 
> > > Documentation/devicetree/bindings/nvmem/onie,nvmem-cells.txt
> > >   create mode 100644 drivers/nvmem/onie-cells.c
> > > 
> > > -- 
> > > 2.17.1
> > > 
> 
> Hi Vdaym,
> 
> Am totally confused with this patchset, There is no versioning in any of
> your patches, you always send it with PATCH, please add version so that I
> know which one should I review!
> 
> This makes my mailbox totally confused with all the patches with same
> subject prefix!
> 
> Please note that maintenance is not my full time job, so please be patient
> and I can try shift gears as an when possible!

Thank you!

> 
> > 
> > I sent a newer version than this one which actually registers nvmem provider
> > and does not require changes in the core.c
> This is a NO-NO as onie is not a real provider here, at24 is the actual
> nvmem provider in your case.
> 
> Why do you keep changing the total approach here! what is the reasoning to
> do so!

Well, I though that maybe anyway it also better to show the code, and
try different approaches.

> As I said in my last review we were okay with this parser approach!
> 
> I don't mind having changes in core as long as it done properly!
> 
> 
> thanks,
> srini

I am really sorry for this! I was really conceptually confused about how
to make it right by design. I will use "parser" word in next series
subject update with a versioning (v2) so you can identify that this is
related to parser approach with which you are conceptually fine.

Again sorry for this!

> 
> 
> 
> 
> > 
> > Thanks,
> > Vadym Kochan
> > 


Re: [PATCH 0/3] nvmem: add ONIE NVMEM cells provider

2020-09-21 Thread Vadym Kochan
Hi Srinivas,

On Tue, Sep 15, 2020 at 03:41:13PM +0300, Vadym Kochan wrote:
> This series adds cells parser for the ONIE TLV attributes which are
> stored on NVMEM device. It adds possibility to read the mac address (and
> other info) by other drivers.
> 
> Because ONIE stores info in TLV format it should be parsed first and
> then register the cells. Current NVMEM API allows to register cell
> table with known cell's offset which is not guaranteed in case of TLV.
> 
> To make it properly handled the NVMEM parser object is introduced. The
> parser needs to be registered before target NVMEM device is registered.
> During the registration of NVMEM device the parser is called to parse
> the device's cells and reister the cell table.
> 
> Vadym Kochan (3):
>   nvmem: core: introduce cells parser
>   nvmem: add ONIE nvmem cells parser
>   dt-bindings: nvmem: add description for ONIE cells parser
> 
>  .../bindings/nvmem/onie,nvmem-cells.txt   |  11 +
>  drivers/nvmem/Kconfig |   9 +
>  drivers/nvmem/Makefile|   3 +
>  drivers/nvmem/core.c  |  80 
>  drivers/nvmem/onie-cells.c| 370 ++
>  include/linux/nvmem-provider.h|  30 ++
>  6 files changed, 503 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/nvmem/onie,nvmem-cells.txt
>  create mode 100644 drivers/nvmem/onie-cells.c
> 
> -- 
> 2.17.1
> 

I sent a newer version than this one which actually registers nvmem provider
and does not require changes in the core.c

Thanks,
Vadym Kochan


[PATCH 2/2] dt-bindings: nvmem: add description for ONIE provider

2020-09-21 Thread Vadym Kochan
Add device-tree binding description for the ONIE nvmem provider.

Signed-off-by: Vadym Kochan 
---
 .../devicetree/bindings/nvmem/onie-nvmem.txt  | 11 +++
 1 file changed, 11 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/onie-nvmem.txt

diff --git a/Documentation/devicetree/bindings/nvmem/onie-nvmem.txt 
b/Documentation/devicetree/bindings/nvmem/onie-nvmem.txt
new file mode 100644
index ..16fb903118d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/onie-nvmem.txt
@@ -0,0 +1,11 @@
+= Device tree bindings for ONIE NVMEM provider =
+
+Required properties:
+- compatible: should be "onie-nvmem"
+- nvmem: phandle to nvmem device node
+
+Example:
+   onie_cells {
+   compatible = "onie-nvmem"
+   nvmem = <>;
+   };
-- 
2.17.1



[PATCH 0/2] Add ONIE NVMEM provider

2020-09-21 Thread Vadym Kochan
This series adds NVMEM provider for the ONIE TLV attributes which are
stored on NVMEM device. It adds possibility to read the mac address (and
other info) by other drivers.

Vadym Kochan (2):
  nvmem: add ONIE nvmem provider
  dt-bindings: nvmem: add description for ONIE provider

 .../devicetree/bindings/nvmem/onie-nvmem.txt  |  11 +
 drivers/nvmem/Kconfig |   9 +
 drivers/nvmem/Makefile|   2 +
 drivers/nvmem/onie.c  | 357 ++
 4 files changed, 379 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/onie-nvmem.txt
 create mode 100644 drivers/nvmem/onie.c

-- 
2.17.1



[PATCH 1/2] nvmem: add ONIE nvmem provider

2020-09-21 Thread Vadym Kochan
ONIE is a small operating system, pre-installed on bare metal network
switches, that provides an environment for automated provisioning.

This system requires that NVMEM (EEPROM) device holds various system
information (mac address, platform name, etc) in a special TLV layout.

The driver parses ONIE TLV attributes and registers them as NVMEM cells
which can be accessed by other platform driver. Also it allows to use
of_get_mac_address() to retrieve mac address for the netdev.

The provider differs from the normal NVMEM providers that it is not
depends on particular storage but uses other nvmem as accessor for
reading the cell, and proxies the reg_read() call to this device driver.

Signed-off-by: Vadym Kochan 
---
 drivers/nvmem/Kconfig  |   9 ++
 drivers/nvmem/Makefile |   2 +
 drivers/nvmem/onie.c   | 357 +
 3 files changed, 368 insertions(+)
 create mode 100644 drivers/nvmem/onie.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 954d3b4a52ab..77387bd13105 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -270,4 +270,13 @@ config SPRD_EFUSE
  This driver can also be built as a module. If so, the module
  will be called nvmem-sprd-efuse.
 
+config NVMEM_ONIE
+   tristate "ONIE NVMEM support"
+   help
+ This is a driver to provide cells from ONIE TLV structure stored
+ on NVMEM device.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-onie.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index a7c377218341..fbf30c94447e 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -55,3 +55,5 @@ obj-$(CONFIG_NVMEM_ZYNQMP)+= nvmem_zynqmp_nvmem.o
 nvmem_zynqmp_nvmem-y   := zynqmp_nvmem.o
 obj-$(CONFIG_SPRD_EFUSE)   += nvmem_sprd_efuse.o
 nvmem_sprd_efuse-y := sprd-efuse.o
+obj-$(CONFIG_NVMEM_ONIE)   += nvmem-onie.o
+nvmem-onie-y   := onie.o
diff --git a/drivers/nvmem/onie.c b/drivers/nvmem/onie.c
new file mode 100644
index ..5f280f227b44
--- /dev/null
+++ b/drivers/nvmem/onie.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ONIE NVMEM provider
+ *
+ * Author: Vadym Kochan 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ONIE_NVMEM_TLV_MAX_LEN 2048
+
+#define ONIE_NVMEM_HDR_ID  "TlvInfo"
+
+struct onie_nvmem_hdr {
+   u8 id[8];
+   u8 version;
+   __be16 data_len;
+} __packed;
+
+struct onie_nvmem_tlv {
+   u8 type;
+   u8 len;
+   u8 val[0];
+} __packed;
+
+struct onie_nvmem_attr {
+   struct list_head head;
+   const char *name;
+   unsigned int offset;
+   unsigned int len;
+};
+
+struct onie_nvmem {
+   struct nvmem_cell_lookup *lookup;
+   struct nvmem_cell_info *cells;
+   int ncells;
+   struct nvmem_device *nvmem;
+   unsigned int attr_count;
+   struct list_head attrs;
+   struct device *dev;
+   u8 version;
+};
+
+static bool onie_nvmem_hdr_is_valid(struct onie_nvmem_hdr *hdr)
+{
+   if (memcmp(hdr->id, ONIE_NVMEM_HDR_ID, sizeof(hdr->id)) != 0)
+   return false;
+   if (hdr->version != 0x1)
+   return false;
+
+   return true;
+}
+
+static void onie_nvmem_attrs_free(struct onie_nvmem *onie)
+{
+   struct onie_nvmem_attr *attr, *tmp;
+
+   list_for_each_entry_safe(attr, tmp, >attrs, head) {
+   list_del(>head);
+   kfree(attr);
+   }
+}
+
+static const char *onie_nvmem_attr_name(u8 type)
+{
+   switch (type) {
+   case 0x21: return "product-name";
+   case 0x22: return "part-number";
+   case 0x23: return "serial-number";
+   case 0x24: return "mac-address";
+   case 0x25: return "manufacture-date";
+   case 0x26: return "device-version";
+   case 0x27: return "label-revision";
+   case 0x28: return "platforn-name";
+   case 0x29: return "onie-version";
+   case 0x2A: return "num-macs";
+   case 0x2B: return "manufacturer";
+   case 0x2C: return "country-code";
+   case 0x2D: return "vendor";
+   case 0x2E: return "diag-version";
+   case 0x2F: return "service-tag";
+   case 0xFD: return "vendor-extension";
+   case 0xFE: return "crc32";
+
+   default: return NULL;
+   }
+}
+
+static int onie_nvmem_tlv_parse(struct onie_nvmem *onie, u8 *data, u16 len)
+{
+   unsigned int hlen = sizeof(struct onie_nvmem_hdr);
+   unsigned int offset = 0;
+   int err;
+
+   onie->attr_count = 0;
+
+   while (offset < len) {
+   struct onie_nvmem_attr *attr;
+   struct onie_nvmem_tlv *tlv;
+   c

[GIT PULL] linux-firmware: Update Marvell Prestera Switchdev firmware ABI changes

2020-09-18 Thread Vadym Kochan
The following changes since commit 00a84c516078defb76fbd57543b8d5c674a9a2be:

  linux-firmware: Update AMD SEV firmware (2020-09-16 08:01:44 -0400)

are available in the Git repository at:

  https://github.com/PLVision/linux-firmware.git mrvl-prestera

for you to fetch changes up to 7a0221265cda381b5231355965a403ca264392a5:

  linux-firmware: Update Marvell Switchdev firmware with ABI changes 
(2020-09-18 16:54:29 +0300)


Vadym Kochan (1):
  linux-firmware: Update Marvell Switchdev firmware with ABI changes

 mrvl/prestera/mvsw_prestera_fw-v2.0.img | Bin 13687252 -> 13686596 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)


[PATCH net-next v9 2/6] net: marvell: prestera: Add PCI interface support

2020-09-16 Thread Vadym Kochan
Add PCI interface driver for Prestera Switch ASICs family devices, which
provides:

- Firmware loading mechanism
- Requests & events handling to/from the firmware
- Access to the firmware on the bus level

The firmware has to be loaded each time the device is reset. The driver
is loading it from:

/lib/firmware/mrvl/prestera/mvsw_prestera_fw-v{MAJOR}.{MINOR}.img

The full firmware image version is located within the internal header
and consists of 3 numbers - MAJOR.MINOR.PATCH. Additionally, driver has
hard-coded minimum supported firmware version which it can work with:

MAJOR - reflects the support on ABI level between driver and loaded
firmware, this number should be the same for driver and loaded
firmware.

MINOR - this is the minimum supported version between driver and the
firmware.

PATCH - indicates only fixes, firmware ABI is not changed.

Firmware image file name contains only MAJOR and MINOR numbers to make
driver be compatible with any PATCH version.

Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Sort includes.

2) Add missing comma for last enum member

3) Return original error code from last called func
   in places where instead other error code was used.

4) Use MSEC_PER_SEC instead of hard-coded 1000.

5) Remove 'if (status != PRESTERA_LDR_STATUS_START_FW)' by passing the 
'state'
   through the 'switch (state)' block.

6) Use common 'out_release' goto label for release_firmware().

PATCH v5:
1) Remove not-needed packed & aligned attributes

2) Convert 'u8 *' to 'void *' on path when handling/calling 
send_req/recv_msg
   callback. This allows to remove not-needed 'u8 *' casting.

3) Use USEC_PER_MSEC as multiplier when converting ms -> usec on calling
   readl_poll_timeout.

4) Removed pci_dev member from prestera_fw, there is already 'struct
   prestera_dev' which holds pointer to 'struct device'.

5) Replace pci_err (added in the previous patch) by dev_err.

PATCH v4:
1) Get rid of "packed" attribute for the fw image header, it is
   already aligned.

2) Cleanup not needed initialization of variables which are used in
   readl_poll_timeout() helpers.

3) Replace #define's of prestera_{fw,ldr}_{read,write} to static funcs.

4) Use pcim_ helpers for resource allocation

5) Use devm_zalloc() for struct prestera_fw instance allocation.

6) Use module_pci_driver(prestera_pci_driver) instead of module_{init,exit}.

7) Use _MS prefix for timeout #define's.

8) Use snprintf for firmware image path generation instead of using
   macrosses.

9) Use memcpy_xxxio helpers for IO memory copying.

   10) By default use same build type ('m' or 'y') for
   CONFIG_PRESTERA_PCI which is used by CONFIG_PRESTERA.

 drivers/net/ethernet/marvell/prestera/Kconfig |  11 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +
 .../ethernet/marvell/prestera/prestera_pci.c  | 769 ++
 3 files changed, 782 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_pci.c

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 76b68613ea7a..2a5945c455cc 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -11,3 +11,14 @@ config PRESTERA
 
  To compile this driver as a module, choose M here: the
  module will be called prestera.
+
+config PRESTERA_PCI
+   tristate "PCI interface driver for Marvell Prestera Switch ASICs family"
+   depends on PCI && HAS_IOMEM && PRESTERA
+   default PRESTERA
+   help
+ This is implementation of PCI interface support for Marvell Prestera
+ Switch ASICs family.
+
+ To compile this driver as a module, choose M here: the
+ module will be called prestera_pci.
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 610d75032b78..2146714eab21 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
   prestera_rxtx.o
+
+obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
new file mode 100644
index ..1b97adae542e
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -0,0 +1,769 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+#include 
+#include

[PATCH net-next v9 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-09-16 Thread Vadym Kochan
The following features are supported:

- VLAN-aware bridge offloading
- VLAN-unaware bridge offloading
- FDB offloading (learning, ageing)
- Switchport configuration

Currently there are some limitations like:

- Only 1 VLAN-aware bridge instance supported
- FDB ageing timeout parameter is set globally per device

Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Add missing comma for last enum member.

2) Add _ms suffix for ageing variable and struct member.

3) Add comma for last member in initialized struct in prestera_hw.c

4) Use ether_addr_copy() instead of memcpy() for mac FDB copying in 
prestera_hw.c

5) Sorted includes.

6) Fix ageing macro to be in ms instead of seconds.

7) Do not intialize 'err' where it is not needed.

8) Drop swdev->ageing_time member which is not used.

9) Simplify prestera_port_attr_br_ageing_set() by simply
   return prestera_hw_switch_ageing_set(sw, ageing_time_ms), and remove err 
handling.

10) Put license in one line.

PATCH v7:
1) Add missing destroy_workqueue(swdev_wq) in 
prestera_switchdev.c:prestera_switchdev_init()
   on error path handling.

PATCH v5:
0) Add Co-developed tag.

1) Remove "," from terminated enum entry.

2) Replace 'u8 *' -> 'void *' in prestera_fw_parse_fdb_evt(...)

3) Use ether_addr_copy() in prestera_fw_parse_fdb_evt(...)

PATCH v4:
1) Check for the prestera dev interface in switchdev event handler
   to ignore unsupported topology.

 .../net/ethernet/marvell/prestera/Makefile|3 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   31 +
 .../ethernet/marvell/prestera/prestera_hw.c   |  329 +
 .../ethernet/marvell/prestera/prestera_hw.h   |   48 +
 .../ethernet/marvell/prestera/prestera_main.c |  110 +-
 .../marvell/prestera/prestera_switchdev.c | 1277 +
 .../marvell/prestera/prestera_switchdev.h |   13 +
 7 files changed, 1807 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 7684e7047562..93129e32ebc5 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
+  prestera_rxtx.o prestera_devlink.o 
prestera_ethtool.o \
+  prestera_switchdev.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 69628632e2bd..55aa4bf8a27c 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -12,6 +12,8 @@
 
 #define PRESTERA_DRV_NAME  "prestera"
 
+#define PRESTERA_DEFAULT_VID1
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -66,11 +68,13 @@ struct prestera_port {
u32 hw_id;
u32 dev_id;
u16 fp_id;
+   u16 pvid;
bool autoneg;
u64 adver_link_modes;
u8 adver_fec;
struct prestera_port_caps caps;
struct list_head list;
+   struct list_head vlans_list;
struct {
struct prestera_port_stats stats;
struct delayed_work caching_dw;
@@ -100,6 +104,7 @@ enum prestera_event_type {
PRESTERA_EVENT_TYPE_UNSPEC,
 
PRESTERA_EVENT_TYPE_PORT,
+   PRESTERA_EVENT_TYPE_FDB,
PRESTERA_EVENT_TYPE_RXTX,
 
PRESTERA_EVENT_TYPE_MAX
@@ -122,19 +127,37 @@ struct prestera_port_event {
} data;
 };
 
+enum prestera_fdb_event_id {
+   PRESTERA_FDB_EVENT_UNSPEC,
+   PRESTERA_FDB_EVENT_LEARNED,
+   PRESTERA_FDB_EVENT_AGED,
+};
+
+struct prestera_fdb_event {
+   u32 port_id;
+   u32 vid;
+   union {
+   u8 mac[ETH_ALEN];
+   } data;
+};
+
 struct prestera_event {
u16 id;
union {
struct prestera_port_event port_evt;
+   struct prestera_fdb_event fdb_evt;
};
 };
 
+struct prestera_switchdev;
 struct prestera_rxtx;
 
 struct prestera_switch {
struct prestera_device *dev;
+   struct prestera_switchdev *swdev;
struct prestera_rxtx *rxtx;
struct list_head event_handlers;
+   struct notifier_block netdev_nb;
char base_mac[ETH_ALEN];
struct list_head port_list;
rwlock_t port_li

[PATCH net-next v9 6/6] dt-bindings: marvell,prestera: Add description for device-tree bindings

2020-09-16 Thread Vadym Kochan
Add brief description how to configure base mac address binding in
device-tree.

Describe requirement for the PCI port which is connected to the ASIC, to
allow access to the firmware related registers.

Signed-off-by: Vadym Kochan 
---
 .../bindings/net/marvell,prestera.txt | 34 +++
 1 file changed, 34 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/marvell,prestera.txt 
b/Documentation/devicetree/bindings/net/marvell,prestera.txt
index 83370ebf5b89..e28938ddfdf5 100644
--- a/Documentation/devicetree/bindings/net/marvell,prestera.txt
+++ b/Documentation/devicetree/bindings/net/marvell,prestera.txt
@@ -45,3 +45,37 @@ dfx-server {
ranges = <0 MBUS_ID(0x08, 0x00) 0 0x10>;
reg = ;
 };
+
+Marvell Prestera SwitchDev bindings
+---
+Optional properties:
+- compatible: must be "marvell,prestera"
+- base-mac-provider: describes handle to node which provides base mac address,
+   might be a static base mac address or nvme cell provider.
+
+Example:
+
+eeprom_mac_addr: eeprom-mac-addr {
+   compatible = "eeprom,mac-addr-cell";
+   status = "okay";
+
+   nvmem = <_at24>;
+};
+
+prestera {
+   compatible = "marvell,prestera";
+   status = "okay";
+
+   base-mac-provider = <_mac_addr>;
+};
+
+The current implementation of Prestera Switchdev PCI interface driver requires
+that BAR2 is assigned to 0xf600 as base address from the PCI IO range:
+
+_pcie0 {
+   ranges = <0x8100 0x0 0xfb00 0x0 0xfb00 0x0 0xf
+   0x8200 0x0 0xf600 0x0 0xf600 0x0 0x200
+   0x8200 0x0 0xf900 0x0 0xf900 0x0 0x10>;
+   phys = <_comphy0 0>;
+   status = "okay";
+};
-- 
2.17.1



[PATCH 1/3] eeprom: at24: set type id as EEPROM

2020-09-16 Thread Vadym Kochan
Set type as NVMEM_TYPE_EEPROM to expose this info via
sysfs:

$ cat /sys/bus/nvmem/devices/{DEVICE}/type
EEPROM

Signed-off-by: Vadym Kochan 
---
 drivers/misc/eeprom/at24.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 2591c21b2b5d..800300296c74 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -678,6 +678,7 @@ static int at24_probe(struct i2c_client *client)
return err;
}
 
+   nvmem_config.type = NVMEM_TYPE_EEPROM;
nvmem_config.name = dev_name(dev);
nvmem_config.dev = dev;
nvmem_config.read_only = !writable;
-- 
2.17.1



[PATCH] misc: eeprom: set type id as EEPROM for nvmem devices

2020-09-16 Thread Vadym Kochan
Set type as NVMEM_TYPE_EEPROM to expose this info via
sysfs:

$ cat /sys/bus/nvmem/devices/0-00560/type
EEPROM

Signed-off-by: Vadym Kochan 
---
Checked only with at24.

 drivers/misc/eeprom/at24.c  | 1 +
 drivers/misc/eeprom/at25.c  | 1 +
 drivers/misc/eeprom/eeprom_93xx46.c | 1 +
 3 files changed, 3 insertions(+)

diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 2591c21b2b5d..800300296c74 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -678,6 +678,7 @@ static int at24_probe(struct i2c_client *client)
return err;
}
 
+   nvmem_config.type = NVMEM_TYPE_EEPROM;
nvmem_config.name = dev_name(dev);
nvmem_config.dev = dev;
nvmem_config.read_only = !writable;
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index ed8d38b09925..3a586a7c4b1a 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -348,6 +348,7 @@ static int at25_probe(struct spi_device *spi)
spi_set_drvdata(spi, at25);
at25->addrlen = addrlen;
 
+   at25->nvmem_config.type = NVMEM_TYPE_EEPROM;
at25->nvmem_config.name = dev_name(>dev);
at25->nvmem_config.dev = >dev;
at25->nvmem_config.read_only = chip.flags & EE_READONLY;
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c 
b/drivers/misc/eeprom/eeprom_93xx46.c
index 94cfb675fe4e..7c45f82b4302 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -455,6 +455,7 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
edev->pdata = pd;
 
edev->size = 128;
+   edev->nvmem_config.type = NVMEM_TYPE_EEPROM;
edev->nvmem_config.name = dev_name(>dev);
edev->nvmem_config.dev = >dev;
edev->nvmem_config.read_only = pd->flags & EE_READONLY;
-- 
2.17.1



[PATCH net-next v9 3/6] net: marvell: prestera: Add basic devlink support

2020-09-16 Thread Vadym Kochan
Add very basic support for devlink interface:

- driver name
- fw version
- devlink ports

Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Put license in one line.

2) Use traditional error handling pattern in 
prestera_devlink_port_register():

   err = F();
   if (err)
   return err;

3) Initialize 'sw' and 'dl' on definition.

PATCH v5:
1) Simplified some error path handling by simple return error code in:

   - prestera_dl_info_get(...)

2) Remove not-needed err assignment in:
   - prestera_dl_info_get(...)

3) Use dev_err() in prestera_devlink_register(...).

 drivers/net/ethernet/marvell/prestera/Kconfig |   1 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   4 +
 .../marvell/prestera/prestera_devlink.c   | 112 ++
 .../marvell/prestera/prestera_devlink.h   |  23 
 .../ethernet/marvell/prestera/prestera_main.c |  28 -
 6 files changed, 165 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 2a5945c455cc..b1fcc44f566a 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -6,6 +6,7 @@
 config PRESTERA
tristate "Marvell Prestera Switch ASICs support"
depends on NET_SWITCHDEV && VLAN_8021Q
+   select NET_DEVLINK
help
  This driver supports Marvell Prestera Switch ASICs family.
 
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 2146714eab21..babd71fba809 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o
+  prestera_rxtx.o prestera_devlink.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index c5bf0fe8d59e..0a34d7ca4823 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -7,8 +7,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#define PRESTERA_DRV_NAME  "prestera"
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -58,6 +61,7 @@ struct prestera_port_caps {
 struct prestera_port {
struct net_device *dev;
struct prestera_switch *sw;
+   struct devlink_port dl_port;
u32 id;
u32 hw_id;
u32 dev_id;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_devlink.c 
b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
new file mode 100644
index ..94c185a0e2b8
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+
+#include "prestera_devlink.h"
+
+static int prestera_dl_info_get(struct devlink *dl,
+   struct devlink_info_req *req,
+   struct netlink_ext_ack *extack)
+{
+   struct prestera_switch *sw = devlink_priv(dl);
+   char buf[16];
+   int err;
+
+   err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME);
+   if (err)
+   return err;
+
+   snprintf(buf, sizeof(buf), "%d.%d.%d",
+sw->dev->fw_rev.maj,
+sw->dev->fw_rev.min,
+sw->dev->fw_rev.sub);
+
+   return devlink_info_version_running_put(req,
+  DEVLINK_INFO_VERSION_GENERIC_FW,
+  buf);
+}
+
+static const struct devlink_ops prestera_dl_ops = {
+   .info_get = prestera_dl_info_get,
+};
+
+struct prestera_switch *prestera_devlink_alloc(void)
+{
+   struct devlink *dl;
+
+   dl = devlink_alloc(_dl_ops, sizeof(struct prestera_switch));
+
+   return devlink_priv(dl);
+}
+
+void prestera_devlink_free(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_free(dl);
+}
+
+int prestera_devlink_register(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+   int err;
+
+   err = devlink_register(dl, sw->dev->dev);
+   if (err)
+   dev_err(prestera_dev(sw), "devlink_register failed: %d\n", err);
+
+   return err;
+}
+
+void pre

[PATCH 0/3] misc: eeprom: set type id as EEPROM for nvmem devices

2020-09-16 Thread Vadym Kochan
Set type as NVMEM_TYPE_EEPROM to expose this info via
sysfs:

$ cat /sys/bus/nvmem/devices/0-00560/type
EEPROM

Tested only with at24 device.

Vadym Kochan (3):
  eeprom: at24: set type id as EEPROM
  eeprom: at25: set type id as EEPROM
  eeprom: 93xx46: set type id as EEPROM

 drivers/misc/eeprom/at24.c  | 1 +
 drivers/misc/eeprom/at25.c  | 1 +
 drivers/misc/eeprom/eeprom_93xx46.c | 1 +
 3 files changed, 3 insertions(+)

-- 
2.17.1



[PATCH 3/3] eeprom: 93xx46: set type id as EEPROM

2020-09-16 Thread Vadym Kochan
Set type as NVMEM_TYPE_EEPROM to expose this info via
sysfs:

$ cat /sys/bus/nvmem/devices/{DEVICE}/type
EEPROM

Signed-off-by: Vadym Kochan 
---
 drivers/misc/eeprom/eeprom_93xx46.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/eeprom/eeprom_93xx46.c 
b/drivers/misc/eeprom/eeprom_93xx46.c
index 94cfb675fe4e..7c45f82b4302 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -455,6 +455,7 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
edev->pdata = pd;
 
edev->size = 128;
+   edev->nvmem_config.type = NVMEM_TYPE_EEPROM;
edev->nvmem_config.name = dev_name(>dev);
edev->nvmem_config.dev = >dev;
edev->nvmem_config.read_only = pd->flags & EE_READONLY;
-- 
2.17.1



[PATCH 2/3] eeprom: at25: set type id as EEPROM

2020-09-16 Thread Vadym Kochan
Set type as NVMEM_TYPE_EEPROM to expose this info via
sysfs:

$ cat /sys/bus/nvmem/devices/{DEVICE}/type
EEPROM

Signed-off-by: Vadym Kochan 
---
 drivers/misc/eeprom/at25.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index ed8d38b09925..3a586a7c4b1a 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -348,6 +348,7 @@ static int at25_probe(struct spi_device *spi)
spi_set_drvdata(spi, at25);
at25->addrlen = addrlen;
 
+   at25->nvmem_config.type = NVMEM_TYPE_EEPROM;
at25->nvmem_config.name = dev_name(>dev);
at25->nvmem_config.dev = >dev;
at25->nvmem_config.read_only = chip.flags & EE_READONLY;
-- 
2.17.1



[PATCH net-next v9 4/6] net: marvell: prestera: Add ethtool interface support

2020-09-16 Thread Vadym Kochan
The ethtool API provides support for the configuration of the following
features: speed and duplex, auto-negotiation, MDI-x, forward error
correction, port media type. The API also provides information about the
port status, hardware and software statistic. The following limitation
exists:

- port media type should be configured before speed setting
- ethtool -m option is not supported
- ethtool -p option is not supported
- ethtool -r option is supported for RJ45 port only
- the following combination of parameters is not supported:

  ethtool -s sw1pX port XX autoneg on

- forward error correction feature is supported only on SFP ports, 10G
  speed

- auto-negotiation and MDI-x features are not supported on
  Copper-to-Fiber SFP module

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Sorted includes.

2) Use traditional error handling pattern:

   err = F();
   if (err)
   return err;

3) Invert '!err ? speed : SPEED_UNKNOWN' into 'err ? SPEED_UNKNOWN : speed'

4) Return original error code from last called func
   in places where instead other error code was used.

5) Put license in one line.

6) Add missing comma for last enum member

7) Add comma for last member in initialized struct in prestera_hw.c

PATCH v5:

1) Convert following error check:

if (func(...))
or
if (!func(...))

to use err variable:

err = func(...)
if (err)

2) Remove "," from terminated enum entry.

PATCH v4:
1) Export only prestera_ethtool_ops instead of
   each ethtool handler.

2) Get rid of not needed cast in prestera_ethtool_get_stats(...)
   when doing memcpy.

 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   3 +
 .../marvell/prestera/prestera_ethtool.c   | 780 ++
 .../marvell/prestera/prestera_ethtool.h   |  11 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 299 +++
 .../ethernet/marvell/prestera/prestera_hw.h   |  65 ++
 .../ethernet/marvell/prestera/prestera_main.c |  28 +-
 7 files changed, 1182 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index babd71fba809..7684e7047562 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o
+  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 0a34d7ca4823..69628632e2bd 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -169,4 +169,7 @@ void prestera_device_unregister(struct prestera_device 
*dev);
 struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
 u32 dev_id, u32 hw_id);
 
+int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
+ u64 adver_link_modes, u8 adver_fec);
+
 #endif /* _PRESTERA_H_ */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c 
b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
new file mode 100644
index ..93a5e2baf808
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
@@ -0,0 +1,780 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+
+#include "prestera_ethtool.h"
+#include "prestera.h"
+#include "prestera_hw.h"
+
+#define PRESTERA_STATS_CNT \
+   (sizeof(struct prestera_port_stats) / sizeof(u64))
+#define PRESTERA_STATS_IDX(name) \
+   (offsetof(struct prestera_port_stats, name) / sizeof(u64))
+#define PRESTERA_STATS_FIELD(name) \
+   [PRESTERA_STATS_IDX(name)] = __stringify(name)
+
+static const char driver_kind[] = "prestera";
+
+static const struct prestera_link_mode {
+   enum ethtool_link_mode_bit_indices eth_mode;
+   u32 speed;
+   u64 pr_mask;
+   u8 duplex;
+   u8 port_type;
+} port_link_modes[PRESTERA_LINK_MODE_MAX] = {
+   [PRESTERA_LINK_MODE_10baseT_Half] = {
+   .eth_mode =  ETHTOOL_LINK_

[PATCH net-next v9 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX3255 (AC3x)

2020-09-16 Thread Vadym Kochan
cro usage for sending fw requests in prestera_hw.c

10) Add base_mac setting as module parameter. base_mac is required for
generation default port's mac.

Vadym Kochan (6):
  net: marvell: prestera: Add driver for Prestera family ASIC devices
  net: marvell: prestera: Add PCI interface support
  net: marvell: prestera: Add basic devlink support
  net: marvell: prestera: Add ethtool interface support
  net: marvell: prestera: Add Switchdev driver implementation
  dt-bindings: marvell,prestera: Add description for device-tree
bindings

 .../bindings/net/marvell,prestera.txt |   34 +
 drivers/net/ethernet/marvell/Kconfig  |1 +
 drivers/net/ethernet/marvell/Makefile |1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |   25 +
 .../net/ethernet/marvell/prestera/Makefile|7 +
 .../net/ethernet/marvell/prestera/prestera.h  |  206 +++
 .../marvell/prestera/prestera_devlink.c   |  112 ++
 .../marvell/prestera/prestera_devlink.h   |   23 +
 .../ethernet/marvell/prestera/prestera_dsa.c  |  104 ++
 .../ethernet/marvell/prestera/prestera_dsa.h  |   35 +
 .../marvell/prestera/prestera_ethtool.c   |  780 ++
 .../marvell/prestera/prestera_ethtool.h   |   11 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 1253 
 .../ethernet/marvell/prestera/prestera_hw.h   |  182 +++
 .../ethernet/marvell/prestera/prestera_main.c |  663 +
 .../ethernet/marvell/prestera/prestera_pci.c  |  769 ++
 .../ethernet/marvell/prestera/prestera_rxtx.c |  820 +++
 .../ethernet/marvell/prestera/prestera_rxtx.h |   19 +
 .../marvell/prestera/prestera_switchdev.c | 1277 +
 .../marvell/prestera/prestera_switchdev.h |   13 +
 20 files changed, 6335 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_main.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_pci.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

-- 
2.17.1



[PATCH net-next v9 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-16 Thread Vadym Kochan
Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
wireless SMB deployment.

The current implementation supports only boards designed for the Marvell
Switchdev solution and requires special firmware.

The core Prestera switching logic is implemented in prestera_main.c,
there is an intermediate hw layer between core logic and firmware. It is
implemented in prestera_hw.c, the purpose of it is to encapsulate hw
related logic, in future there is a plan to support more devices with
different HW related configurations.

This patch contains only basic switch initialization and RX/TX support
over SDMA mechanism.

Currently supported devices have DMA access range <= 32bit and require
ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
allocated in proper range supported by the Prestera device.

Also meanwhile there is no TX interrupt support in current firmware
version so recycling work is scheduled on each xmit.

Port's mac address is generated from the switch base mac which may be
provided via device-tree (static one or as nvme cell), or randomly
generated. This is required by the firmware.

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Co-developed-by: Volodymyr Mytnyk 
Signed-off-by: Volodymyr Mytnyk 
Signed-off-by: Vadym Kochan 
---
PATCH v9:
1) Replace read_poll_timeout_atomic() by original 'do {} while()' loop
   because it works much better than read_poll_timeout_atomic()
   considering the TX rate. Also it fixes warning reported on v8.

2) Use ENOENT instead of EEXIST when item is not found in few
   places - prestera_hw.c and prestera_rxtx.c

PATCH v8:
1) Put license in one line.

2) Sort includes.

3) Add missing comma for last enum member

4) Use PRESTERA_DSA_ as macro prefix in prestera_dsa.c

5) Return original error code from last called func
   in places where instead other error code was used.

6) Add comma for last member in initialized struct in prestera_hw.c

7) Split prestera_port_state_set() func body into prestera_port_open()
   and prestera_port_close().

8) Do not initialize 'int err = 0' where it is not needed.

9) Simplify device-tree "marvell,prestera" node parsing by removing not
   needed checking on 'np == NULL'.

10) Remove extra () in PRESTERA_SDMA_RX_DESC_IS_RCVD macro in 
prestera_rxtx.c

11) Use u32p_replace_bits() instead of open-coded ((word & ~mask) | val)

12) Use dev_warn_ratelimited() instead of pr_warn_ratelimited to indicate 
the device
instance in prestera_rxtx.c

13) Simplify circular buffer list creation in prestera_sdma_{rx,tx}_init() 
by using
do { } while (prev != tail) construction.

14) Use read_poll_timeout_atomic() instead of custom spinning 'while' logic 
in
prestera_rxtx.c:prestera_sdma_tx_wait()

15) Remove "prestera.h" inclusion but use force declaration for
struct prestera_port and struct prestera_switch.

PATCH v7:
1) Use ether_addr_copy() in prestera_main.c:prestera_port_set_mac_address()
   instead of memcpy().

2) Removed not needed device's DMA address range check on
   dma_pool_alloc() in prestera_rxtx.c:prestera_sdma_buf_init(),
   this should be handled by dma_xxx() API considerig device's DMA mask.

3) Removed not needed device's DMA address range check on
   dma_map_single() in prestera_rxtx.c:prestera_sdma_rx_skb_alloc(),
   this should be handled by dma_xxx() API considerig device's DMA mask.

4) Add comment about port mac address limitation in the code where
   it is used and checked - prestera_main.c:

   - prestera_is_valid_mac_addr()
   - prestera_port_create()

 drivers/net/ethernet/marvell/Kconfig  |   1 +
 drivers/net/ethernet/marvell/Makefile |   1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |  13 +
 .../net/ethernet/marvell/prestera/Makefile|   4 +
 .../net/ethernet/marvell/prestera/prestera.h  | 168 
 .../ethernet/marvell/prestera/prestera_dsa.c  | 104 +++
 .../ethernet/marvell/prestera/prestera_dsa.h  |  35 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 625 +
 .../ethernet/marvell/prestera/prestera_hw.h   |  69 ++
 .../ethernet/marvell/prestera/prestera_main.c | 521 +++
 .../ethernet/marvell/prestera/prestera_rxtx.c | 820 ++
 .../ethernet/marvell/prestera/prestera_rxtx.h |  19 +
 12 files changed, 2380 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/pre

[PATCH 3/3] dt-bindings: nvmem: add description for ONIE cells parser

2020-09-15 Thread Vadym Kochan
Add device-tree binding description for the ONIE cells parser.

Signed-off-by: Vadym Kochan 
---
 .../devicetree/bindings/nvmem/onie-nvmem-cells.txt| 11 +++
 1 file changed, 11 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/onie-nvmem-cells.txt

diff --git a/Documentation/devicetree/bindings/nvmem/onie-nvmem-cells.txt 
b/Documentation/devicetree/bindings/nvmem/onie-nvmem-cells.txt
new file mode 100644
index ..db06d8b297b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/onie-nvmem-cells.txt
@@ -0,0 +1,11 @@
+= Device tree bindings for ONIE cells parser =
+
+Required properties:
+- compatible: should be "onie-nvmem-cells"
+- nvmem: phandle to nvmem device node
+
+Example:
+   onie_cells {
+   compatible = "onie-nvmem-cells"
+   nvmem = <>;
+   };
-- 
2.17.1



[PATCH] nvmem: core: fix missing of_node_put() in of_nvmem_device_get()

2020-09-15 Thread Vadym Kochan
of_parse_phandle() returns device_node with incremented ref count
which needs to be decremented by of_node_put() when device_node
is not used.

Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
Signed-off-by: Vadym Kochan 
---
 drivers/nvmem/core.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..204a515d8bc5 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -835,6 +835,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node 
*np, const char *id)
 {
 
struct device_node *nvmem_np;
+   struct nvmem_device *nvmem;
int index = 0;
 
if (id)
@@ -844,7 +845,9 @@ struct nvmem_device *of_nvmem_device_get(struct device_node 
*np, const char *id)
if (!nvmem_np)
return ERR_PTR(-ENOENT);
 
-   return __nvmem_device_get(nvmem_np, device_match_of_node);
+   nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
+   of_node_put(nvmem_np);
+   return nvmem;
 }
 EXPORT_SYMBOL_GPL(of_nvmem_device_get);
 #endif
-- 
2.17.1



[PATCH 2/3] nvmem: add ONIE nvmem cells parser

2020-09-15 Thread Vadym Kochan
ONIE is a small operating system, pre-installed on bare metal network
switches, that provides an environment for automated provisioning.

This system requires that NVMEM (EEPROM) device holds various system
information (mac address, platform name, etc) in a special TLV layout.

The driver parses ONIE TLV attributes and registers them as NVMEM cells
which can be accessed by other platform driver. Also it allows to use
of_get_mac_address() to retrieve mac address for the netdev.

Signed-off-by: Vadym Kochan 
---
 drivers/nvmem/Kconfig  |   9 +
 drivers/nvmem/Makefile |   3 +
 drivers/nvmem/onie-cells.c | 348 +
 3 files changed, 360 insertions(+)
 create mode 100644 drivers/nvmem/onie-cells.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 954d3b4a52ab..0e27caf4934e 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -270,4 +270,13 @@ config SPRD_EFUSE
  This driver can also be built as a module. If so, the module
  will be called nvmem-sprd-efuse.
 
+config NVMEM_ONIE_CELLS
+   tristate "ONIE TLV cells support"
+   help
+ This is a driver to provide cells from ONIE TLV structure stored
+ on NVMEM device.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-onie-cells.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index a7c377218341..2199784a489f 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -55,3 +55,6 @@ obj-$(CONFIG_NVMEM_ZYNQMP)+= nvmem_zynqmp_nvmem.o
 nvmem_zynqmp_nvmem-y   := zynqmp_nvmem.o
 obj-$(CONFIG_SPRD_EFUSE)   += nvmem_sprd_efuse.o
 nvmem_sprd_efuse-y := sprd-efuse.o
+
+obj-$(CONFIG_NVMEM_ONIE_CELLS) += nvmem-onie-cells.o
+nvmem-onie-cells-y := onie-cells.o
diff --git a/drivers/nvmem/onie-cells.c b/drivers/nvmem/onie-cells.c
new file mode 100644
index ..4696050e6568
--- /dev/null
+++ b/drivers/nvmem/onie-cells.c
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ONIE NVMEM cells provider
+ *
+ * Author: Vadym Kochan 
+ */
+
+#define ONIE_NVMEM_DRVNAME "onie-nvmem-cells"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ONIE_NVMEM_TLV_MAX_LEN 2048
+
+#define ONIE_NVMEM_HDR_ID  "TlvInfo"
+
+struct onie_nvmem_hdr {
+   u8 id[8];
+   u8 version;
+   __be16 data_len;
+} __packed;
+
+struct onie_nvmem_tlv {
+   u8 type;
+   u8 len;
+   u8 val[0];
+} __packed;
+
+struct onie_nvmem_attr {
+   struct list_head head;
+   const char *name;
+   unsigned int offset;
+   unsigned int len;
+};
+
+struct onie_nvmem {
+   unsigned int attr_count;
+   struct list_head attrs;
+   struct device *dev;
+
+   struct nvmem_cell_lookup *lookup;
+   struct nvmem_cell_table table;
+   struct nvmem_parser *parser;
+};
+
+static bool onie_nvmem_hdr_is_valid(struct onie_nvmem_hdr *hdr)
+{
+   if (memcmp(hdr->id, ONIE_NVMEM_HDR_ID, sizeof(hdr->id)) != 0)
+   return false;
+   if (hdr->version != 0x1)
+   return false;
+
+   return true;
+}
+
+static void onie_nvmem_attrs_free(struct onie_nvmem *onie)
+{
+   struct onie_nvmem_attr *attr, *tmp;
+
+   list_for_each_entry_safe(attr, tmp, >attrs, head) {
+   list_del(>head);
+   kfree(attr);
+   }
+}
+
+static const char *onie_nvmem_attr_name(u8 type)
+{
+   switch (type) {
+   case 0x21: return "product-name";
+   case 0x22: return "part-number";
+   case 0x23: return "serial-number";
+   case 0x24: return "mac-address";
+   case 0x25: return "manufacture-date";
+   case 0x26: return "device-version";
+   case 0x27: return "label-revision";
+   case 0x28: return "platforn-name";
+   case 0x29: return "onie-version";
+   case 0x2A: return "num-macs";
+   case 0x2B: return "manufacturer";
+   case 0x2C: return "country-code";
+   case 0x2D: return "vendor";
+   case 0x2E: return "diag-version";
+   case 0x2F: return "service-tag";
+   case 0xFD: return "vendor-extension";
+   case 0xFE: return "crc32";
+
+   default: return "unknown";
+   }
+}
+
+static int onie_nvmem_tlv_parse(struct onie_nvmem *onie, u8 *data, u16 len)
+{
+   unsigned int hlen = sizeof(struct onie_nvmem_hdr);
+   unsigned int offset = 0;
+   int err;
+
+   onie->attr_count = 0;
+
+   while (offset < len) {
+   struct onie_nvmem_attr *attr;
+   struct onie_nvmem_tlv *tlv;
+
+   tlv = (struct onie_nvmem_tlv *)(data + offset);
+
+   if (offset +

[PATCH 1/3] nvmem: core: introduce cells parser

2020-09-15 Thread Vadym Kochan
Currently NVMEM core does not allow to register cells for an already
registered nvmem device and requires that this should be done before.
But there might a driver which needs to parse the nvmem device and then
register a cells table.

Introduce nvmem_parser API which allows to register cells parser which
is called during nvmem device registration. During this stage the parser
can read the nvmem device and register the cells table.

Signed-off-by: Vadym Kochan 
---
 drivers/nvmem/core.c   | 89 ++
 include/linux/nvmem-provider.h | 27 +++
 2 files changed, 116 insertions(+)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..82a96032bc3f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -55,6 +55,14 @@ struct nvmem_cell {
struct list_headnode;
 };
 
+struct nvmem_parser {
+   struct device_node  *nvmem_of;
+   struct kref refcnt;
+   struct list_headhead;
+   nvmem_parse_t   cells_parse;
+   void *priv;
+};
+
 static DEFINE_MUTEX(nvmem_mutex);
 static DEFINE_IDA(nvmem_ida);
 
@@ -64,6 +72,9 @@ static LIST_HEAD(nvmem_cell_tables);
 static DEFINE_MUTEX(nvmem_lookup_mutex);
 static LIST_HEAD(nvmem_lookup_list);
 
+static DEFINE_MUTEX(nvmem_parser_mutex);
+static LIST_HEAD(nvmem_parser_list);
+
 static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
 
 static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
@@ -571,6 +582,30 @@ static int nvmem_add_cells_from_of(struct nvmem_device 
*nvmem)
return 0;
 }
 
+static struct nvmem_parser *
+__nvmem_parser_find_of(const struct nvmem_device *nvmem)
+{
+   struct nvmem_parser *parser;
+
+   list_for_each_entry(parser, _parser_list, head) {
+   if (dev_of_node(nvmem->base_dev) == parser->nvmem_of)
+   return parser;
+   }
+
+   return NULL;
+}
+
+static void nvmem_cells_parse(struct nvmem_device *nvmem)
+{
+   struct nvmem_parser *parser;
+
+   mutex_lock(_parser_mutex);
+   parser = __nvmem_parser_find_of(nvmem);
+   if (parser && parser->cells_parse)
+   parser->cells_parse(parser->priv, nvmem);
+   mutex_unlock(_parser_mutex);
+}
+
 /**
  * nvmem_register() - Register a nvmem device for given nvmem_config.
  * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
@@ -674,6 +709,8 @@ struct nvmem_device *nvmem_register(const struct 
nvmem_config *config)
goto err_teardown_compat;
}
 
+   nvmem_cells_parse(nvmem);
+
rval = nvmem_add_cells_from_table(nvmem);
if (rval)
goto err_remove_cells;
@@ -1630,6 +1667,58 @@ const char *nvmem_dev_name(struct nvmem_device *nvmem)
 }
 EXPORT_SYMBOL_GPL(nvmem_dev_name);
 
+struct nvmem_parser *
+nvmem_parser_register(const struct nvmem_parser_config *config)
+{
+   struct device_node *nvmem_of;
+   struct nvmem_parser *parser;
+   int err;
+
+   if (!config->cells_parse)
+   return ERR_PTR(-EINVAL);
+
+   if (!config->dev)
+   return ERR_PTR(-EINVAL);
+
+   nvmem_of = of_parse_phandle(dev_of_node(config->dev), "nvmem", 0);
+   if (!nvmem_of)
+   return ERR_PTR(-EINVAL);
+
+   parser = kzalloc(sizeof(*parser), GFP_KERNEL);
+   if (!parser) {
+   err = -ENOMEM;
+   goto err_alloc;
+   }
+
+   parser->cells_parse = config->cells_parse;
+   /* parser->cells_remove = config->cells_remove; */
+   parser->nvmem_of = nvmem_of;
+   parser->priv = config->priv;
+   kref_init(>refcnt);
+
+   mutex_lock(_parser_mutex);
+   list_add(>head, _parser_list);
+   mutex_unlock(_parser_mutex);
+
+   return parser;
+
+err_alloc:
+   of_node_put(nvmem_of);
+
+   return ERR_PTR(err);
+}
+EXPORT_SYMBOL(nvmem_parser_register);
+
+void nvmem_parser_unregister(struct nvmem_parser *parser)
+{
+   mutex_lock(_parser_mutex);
+   of_node_put(parser->nvmem_of);
+   list_del(>head);
+   kfree(parser);
+   mutex_unlock(_parser_mutex);
+}
+EXPORT_SYMBOL(nvmem_parser_unregister);
+
 static int __init nvmem_init(void)
 {
return bus_register(_bus_type);
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 06409a6c40bc..854d0cf5234f 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -15,10 +15,13 @@
 
 struct nvmem_device;
 struct nvmem_cell_info;
+struct nvmem_cell_table;
+
 typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
 typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
 void *val, size_t bytes);
+typedef void (*nvmem_parse_t)(void *priv, struct nvmem_device *nvmem);
 
 enum nvmem_type {
NVMEM_TYPE

[PATCH 0/3] nvmem: add ONIE NVMEM cells provider

2020-09-15 Thread Vadym Kochan
This series adds cells parser for the ONIE TLV attributes which are
stored on NVMEM device. It adds possibility to read the mac address (and
other info) by other drivers.

Because ONIE stores info in TLV format it should be parsed first and
then register the cells. Current NVMEM API allows to register cell
table with known cell's offset which is not guaranteed in case of TLV.

To make it properly handled the NVMEM parser object is introduced. The
parser needs to be registered before target NVMEM device is registered.
During the registration of NVMEM device the parser is called to parse
the device's cells and reister the cell table.

Vadym Kochan (3):
  nvmem: core: introduce cells parser
  nvmem: add ONIE nvmem cells parser
  dt-bindings: nvmem: add description for ONIE cells parser

 .../bindings/nvmem/onie,nvmem-cells.txt   |  11 +
 drivers/nvmem/Kconfig |   9 +
 drivers/nvmem/Makefile|   3 +
 drivers/nvmem/core.c  |  80 
 drivers/nvmem/onie-cells.c| 370 ++
 include/linux/nvmem-provider.h|  30 ++
 6 files changed, 503 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/onie,nvmem-cells.txt
 create mode 100644 drivers/nvmem/onie-cells.c

-- 
2.17.1



Re: [PATCH v3 1/3] nvmem: core: allow to register cells during nvmem registration

2020-09-11 Thread Vadym Kochan
Hi Srinivas,

On Fri, Sep 04, 2020 at 02:23:10PM +0300, Vadym Kochan wrote:
> Hi Srinivas,
> 
> On Fri, Sep 04, 2020 at 12:02:40PM +0100, Srinivas Kandagatla wrote:
> > Hi Vadym,
> > 
> > Thanks for the patch,
> > On 31/08/2020 02:55, Vadym Kochan wrote:
> > > Add NVMEM_PRE_ADD notification step which is called before any cells
> > > binding - from lookup table or config, this allows to register cells
> > > in some specific layout (tlv) which should be parsed first and then
> > > registered. So there might be a cell parser driver which can register
> > > lookup table during this notification step.
> > > 
> > This is going in right direction but totally not correct way to do it.
> > 
> > 1> this is not scalable as any consumer that will register for this even
> > will have no idea of which what kind of parsing that provider needs.
> > It can work in your case but not really useful.
> > 
> > 2> this is a consumer API, not the provider api.
> > 
> > How about adding a "parse_cells" callback in struct nvmem_config along with
> > encoding type.
> > 
> > 
> > thanks,
> > srini
> > 
> 
> Looks like I missed main point here that this cells parser should be
> registered as nvmem provider. I will think on it.
> 
> Thanks,
> 

I am trying to re-work this approach, but still I need to clarify
something.

It looks strange that this cells parser should be a nvmem provider (or I
missed something) but I remember that you suggested about introducing
something like nvmem parser. And adding nvmem parser looks more clear
for me, because what it should do is just access the nvmem device during
its registration and provide list of cells, that's all:

struct nvmem_device *nvmem_register(const struct nvmem_config *config)
{
struct nvmem_cell_table table = { };
...
parser = find_nvmem_parser();
/* I think that cell lookups may be added on the parser's probe
   statically */
parser->parse_cells(parser->priv, nvmem, );
...
}

/* here I used struct nvmem_config, not sure it is a right way to
   mix nvmem's and parser's struct fields, so may be something like
   struct nvmem_parser_config might be introduced or fill the struct
   nvmem_parser directly by the driver and pass it to the registration func */
struct nvmem_parser *nvmem_parser_register(const struct nvmem_config *config)
{
...
}

void nvmem_parser_unregister(struct nvmem_parser *parser)
{
...
}

Regards,
Vadym Kochan


Re: [net-next v8 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-11 Thread Vadym Kochan
On Thu, Sep 10, 2020 at 06:30:47PM -0700, Jakub Kicinski wrote:
> On Thu, 10 Sep 2020 18:00:50 +0300 Vadym Kochan wrote:
> > +static int prestera_sdma_tx_wait(struct prestera_sdma *sdma,
> > +struct prestera_tx_ring *tx_ring)
> > +{
> > +   int tx_wait_num = PRESTERA_SDMA_WAIT_MUL * tx_ring->max_burst;
> > +   bool is_ready;
> > +
> > +   return read_poll_timeout_atomic(prestera_sdma_is_ready, is_ready, true,
> > +   1, tx_wait_num, false, sdma);
> > +}
> 
> This is strange and generates a warning:
> 
> drivers/net/ethernet/marvell/prestera/prestera_rxtx.c: In function 
> ‘prestera_sdma_tx_wait’:
> drivers/net/ethernet/marvell/prestera/prestera_rxtx.c:695:7: warning: 
> variable ‘is_ready’ set but not used [-Wunused-but-set-variable]
>   695 |  bool is_ready;
>   |   ^~~~

Sorry about this mistake, will re-submit new version.


[net-next v8 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-10 Thread Vadym Kochan
Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
wireless SMB deployment.

The current implementation supports only boards designed for the Marvell
Switchdev solution and requires special firmware.

The core Prestera switching logic is implemented in prestera_main.c,
there is an intermediate hw layer between core logic and firmware. It is
implemented in prestera_hw.c, the purpose of it is to encapsulate hw
related logic, in future there is a plan to support more devices with
different HW related configurations.

This patch contains only basic switch initialization and RX/TX support
over SDMA mechanism.

Currently supported devices have DMA access range <= 32bit and require
ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
allocated in proper range supported by the Prestera device.

Also meanwhile there is no TX interrupt support in current firmware
version so recycling work is scheduled on each xmit.

Port's mac address is generated from the switch base mac which may be
provided via device-tree (static one or as nvme cell), or randomly
generated. This is required by the firmware.

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Co-developed-by: Volodymyr Mytnyk 
Signed-off-by: Volodymyr Mytnyk 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Put license in one line.

2) Sort includes.

3) Add missing comma for last enum member

4) Use PRESTERA_DSA_ as macro prefix in prestera_dsa.c

5) Return original error code from last called func
   in places where instead other error code was used.

6) Add comma for last member in initialized struct in prestera_hw.c

7) Split prestera_port_state_set() func body into prestera_port_open()
   and prestera_port_close().

8) Do not initialize 'int err = 0' where it is not needed.

9) Simplify device-tree "marvell,prestera" node parsing by removing not
   needed checking on 'np == NULL'.

10) Remove extra () in PRESTERA_SDMA_RX_DESC_IS_RCVD macro in 
prestera_rxtx.c

11) Use u32p_replace_bits() instead of open-coded ((word & ~mask) | val)

12) Use dev_warn_ratelimited() instead of pr_warn_ratelimited to indicate 
the device
instance in prestera_rxtx.c

13) Simplify circular buffer list creation in prestera_sdma_{rx,tx}_init() 
by using
do { } while (prev != tail) construction.

14) Use read_poll_timeout_atomic() instead of custom spinning 'while' logic 
in
prestera_rxtx.c:prestera_sdma_tx_wait()

15) Remove "prestera.h" inclusion but use force declaration for
struct prestera_port and struct prestera_switch.

PATCH v7:
1) Use ether_addr_copy() in prestera_main.c:prestera_port_set_mac_address()
   instead of memcpy().

2) Removed not needed device's DMA address range check on
   dma_pool_alloc() in prestera_rxtx.c:prestera_sdma_buf_init(),
   this should be handled by dma_xxx() API considerig device's DMA mask.

3) Removed not needed device's DMA address range check on
   dma_map_single() in prestera_rxtx.c:prestera_sdma_rx_skb_alloc(),
   this should be handled by dma_xxx() API considerig device's DMA mask.

4) Add comment about port mac address limitation in the code where
   it is used and checked - prestera_main.c:

   - prestera_is_valid_mac_addr()
   - prestera_port_create()

 drivers/net/ethernet/marvell/Kconfig  |   1 +
 drivers/net/ethernet/marvell/Makefile |   1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |  13 +
 .../net/ethernet/marvell/prestera/Makefile|   4 +
 .../net/ethernet/marvell/prestera/prestera.h  | 168 
 .../ethernet/marvell/prestera/prestera_dsa.c  | 104 +++
 .../ethernet/marvell/prestera/prestera_dsa.h  |  35 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 625 ++
 .../ethernet/marvell/prestera/prestera_hw.h   |  69 ++
 .../ethernet/marvell/prestera/prestera_main.c | 521 +++
 .../ethernet/marvell/prestera/prestera_rxtx.c | 816 ++
 .../ethernet/marvell/prestera/prestera_rxtx.h |  19 +
 12 files changed, 2376 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.h
 create mode 100644 drivers/ne

[net-next v8 2/6] net: marvell: prestera: Add PCI interface support

2020-09-10 Thread Vadym Kochan
Add PCI interface driver for Prestera Switch ASICs family devices, which
provides:

- Firmware loading mechanism
- Requests & events handling to/from the firmware
- Access to the firmware on the bus level

The firmware has to be loaded each time the device is reset. The driver
is loading it from:

/lib/firmware/mrvl/prestera/mvsw_prestera_fw-v{MAJOR}.{MINOR}.img

The full firmware image version is located within the internal header
and consists of 3 numbers - MAJOR.MINOR.PATCH. Additionally, driver has
hard-coded minimum supported firmware version which it can work with:

MAJOR - reflects the support on ABI level between driver and loaded
firmware, this number should be the same for driver and loaded
firmware.

MINOR - this is the minimum supported version between driver and the
firmware.

PATCH - indicates only fixes, firmware ABI is not changed.

Firmware image file name contains only MAJOR and MINOR numbers to make
driver be compatible with any PATCH version.

Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Sort includes.

2) Add missing comma for last enum member

3) Return original error code from last called func
   in places where instead other error code was used.

4) Use MSEC_PER_SEC instead of hard-coded 1000.

5) Remove 'if (status != PRESTERA_LDR_STATUS_START_FW)' by passing the 
'state'
   through the 'switch (state)' block.

6) Use common 'out_release' goto label for release_firmware().

PATCH v5:
1) Remove not-needed packed & aligned attributes

2) Convert 'u8 *' to 'void *' on path when handling/calling 
send_req/recv_msg
   callback. This allows to remove not-needed 'u8 *' casting.

3) Use USEC_PER_MSEC as multiplier when converting ms -> usec on calling
   readl_poll_timeout.

4) Removed pci_dev member from prestera_fw, there is already 'struct
   prestera_dev' which holds pointer to 'struct device'.

5) Replace pci_err (added in the previous patch) by dev_err.

PATCH v4:
1) Get rid of "packed" attribute for the fw image header, it is
   already aligned.

2) Cleanup not needed initialization of variables which are used in
   readl_poll_timeout() helpers.

3) Replace #define's of prestera_{fw,ldr}_{read,write} to static funcs.

4) Use pcim_ helpers for resource allocation

5) Use devm_zalloc() for struct prestera_fw instance allocation.

6) Use module_pci_driver(prestera_pci_driver) instead of module_{init,exit}.

7) Use _MS prefix for timeout #define's.

8) Use snprintf for firmware image path generation instead of using
   macrosses.

9) Use memcpy_xxxio helpers for IO memory copying.

   10) By default use same build type ('m' or 'y') for
   CONFIG_PRESTERA_PCI which is used by CONFIG_PRESTERA.

 drivers/net/ethernet/marvell/prestera/Kconfig |  11 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +
 .../ethernet/marvell/prestera/prestera_pci.c  | 769 ++
 3 files changed, 782 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_pci.c

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 76b68613ea7a..2a5945c455cc 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -11,3 +11,14 @@ config PRESTERA
 
  To compile this driver as a module, choose M here: the
  module will be called prestera.
+
+config PRESTERA_PCI
+   tristate "PCI interface driver for Marvell Prestera Switch ASICs family"
+   depends on PCI && HAS_IOMEM && PRESTERA
+   default PRESTERA
+   help
+ This is implementation of PCI interface support for Marvell Prestera
+ Switch ASICs family.
+
+ To compile this driver as a module, choose M here: the
+ module will be called prestera_pci.
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 610d75032b78..2146714eab21 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
   prestera_rxtx.o
+
+obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
new file mode 100644
index ..1b97adae542e
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -0,0 +1,769 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+#include 
+#include

[net-next v8 4/6] net: marvell: prestera: Add ethtool interface support

2020-09-10 Thread Vadym Kochan
The ethtool API provides support for the configuration of the following
features: speed and duplex, auto-negotiation, MDI-x, forward error
correction, port media type. The API also provides information about the
port status, hardware and software statistic. The following limitation
exists:

- port media type should be configured before speed setting
- ethtool -m option is not supported
- ethtool -p option is not supported
- ethtool -r option is supported for RJ45 port only
- the following combination of parameters is not supported:

  ethtool -s sw1pX port XX autoneg on

- forward error correction feature is supported only on SFP ports, 10G
  speed

- auto-negotiation and MDI-x features are not supported on
  Copper-to-Fiber SFP module

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Sorted includes.

2) Use traditional error handling pattern:

   err = F();
   if (err)
   return err;

3) Invert '!err ? speed : SPEED_UNKNOWN' into 'err ? SPEED_UNKNOWN : speed'

4) Return original error code from last called func
   in places where instead other error code was used.

5) Put license in one line.

6) Add missing comma for last enum member

7) Add comma for last member in initialized struct in prestera_hw.c

PATCH v5:

1) Convert following error check:

if (func(...))
or
if (!func(...))

to use err variable:

err = func(...)
if (err)

2) Remove "," from terminated enum entry.

PATCH v4:
1) Export only prestera_ethtool_ops instead of
   each ethtool handler.

2) Get rid of not needed cast in prestera_ethtool_get_stats(...)
   when doing memcpy.

 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   3 +
 .../marvell/prestera/prestera_ethtool.c   | 780 ++
 .../marvell/prestera/prestera_ethtool.h   |  11 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 299 +++
 .../ethernet/marvell/prestera/prestera_hw.h   |  65 ++
 .../ethernet/marvell/prestera/prestera_main.c |  28 +-
 7 files changed, 1182 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index babd71fba809..7684e7047562 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o
+  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 0a34d7ca4823..69628632e2bd 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -169,4 +169,7 @@ void prestera_device_unregister(struct prestera_device 
*dev);
 struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
 u32 dev_id, u32 hw_id);
 
+int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
+ u64 adver_link_modes, u8 adver_fec);
+
 #endif /* _PRESTERA_H_ */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c 
b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
new file mode 100644
index ..93a5e2baf808
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
@@ -0,0 +1,780 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+
+#include "prestera_ethtool.h"
+#include "prestera.h"
+#include "prestera_hw.h"
+
+#define PRESTERA_STATS_CNT \
+   (sizeof(struct prestera_port_stats) / sizeof(u64))
+#define PRESTERA_STATS_IDX(name) \
+   (offsetof(struct prestera_port_stats, name) / sizeof(u64))
+#define PRESTERA_STATS_FIELD(name) \
+   [PRESTERA_STATS_IDX(name)] = __stringify(name)
+
+static const char driver_kind[] = "prestera";
+
+static const struct prestera_link_mode {
+   enum ethtool_link_mode_bit_indices eth_mode;
+   u32 speed;
+   u64 pr_mask;
+   u8 duplex;
+   u8 port_type;
+} port_link_modes[PRESTERA_LINK_MODE_MAX] = {
+   [PRESTERA_LINK_MODE_10baseT_Half] = {
+   .eth_mode =  ETHTOOL_LINK_

[net-next v8 3/6] net: marvell: prestera: Add basic devlink support

2020-09-10 Thread Vadym Kochan
Add very basic support for devlink interface:

- driver name
- fw version
- devlink ports

Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Put license in one line.

2) Use traditional error handling pattern in 
prestera_devlink_port_register():

   err = F();
   if (err)
   return err;

3) Initialize 'sw' and 'dl' on definition.

PATCH v5:
1) Simplified some error path handling by simple return error code in:

   - prestera_dl_info_get(...)

2) Remove not-needed err assignment in:
   - prestera_dl_info_get(...)

3) Use dev_err() in prestera_devlink_register(...).

 drivers/net/ethernet/marvell/prestera/Kconfig |   1 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   4 +
 .../marvell/prestera/prestera_devlink.c   | 112 ++
 .../marvell/prestera/prestera_devlink.h   |  23 
 .../ethernet/marvell/prestera/prestera_main.c |  28 -
 6 files changed, 165 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 2a5945c455cc..b1fcc44f566a 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -6,6 +6,7 @@
 config PRESTERA
tristate "Marvell Prestera Switch ASICs support"
depends on NET_SWITCHDEV && VLAN_8021Q
+   select NET_DEVLINK
help
  This driver supports Marvell Prestera Switch ASICs family.
 
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 2146714eab21..babd71fba809 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o
+  prestera_rxtx.o prestera_devlink.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index c5bf0fe8d59e..0a34d7ca4823 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -7,8 +7,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#define PRESTERA_DRV_NAME  "prestera"
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -58,6 +61,7 @@ struct prestera_port_caps {
 struct prestera_port {
struct net_device *dev;
struct prestera_switch *sw;
+   struct devlink_port dl_port;
u32 id;
u32 hw_id;
u32 dev_id;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_devlink.c 
b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
new file mode 100644
index ..94c185a0e2b8
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+
+#include "prestera_devlink.h"
+
+static int prestera_dl_info_get(struct devlink *dl,
+   struct devlink_info_req *req,
+   struct netlink_ext_ack *extack)
+{
+   struct prestera_switch *sw = devlink_priv(dl);
+   char buf[16];
+   int err;
+
+   err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME);
+   if (err)
+   return err;
+
+   snprintf(buf, sizeof(buf), "%d.%d.%d",
+sw->dev->fw_rev.maj,
+sw->dev->fw_rev.min,
+sw->dev->fw_rev.sub);
+
+   return devlink_info_version_running_put(req,
+  DEVLINK_INFO_VERSION_GENERIC_FW,
+  buf);
+}
+
+static const struct devlink_ops prestera_dl_ops = {
+   .info_get = prestera_dl_info_get,
+};
+
+struct prestera_switch *prestera_devlink_alloc(void)
+{
+   struct devlink *dl;
+
+   dl = devlink_alloc(_dl_ops, sizeof(struct prestera_switch));
+
+   return devlink_priv(dl);
+}
+
+void prestera_devlink_free(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_free(dl);
+}
+
+int prestera_devlink_register(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+   int err;
+
+   err = devlink_register(dl, sw->dev->dev);
+   if (err)
+   dev_err(prestera_dev(sw), "devlink_register failed: %d\n", err);
+
+   return err;
+}
+
+void pre

[net-next v8 6/6] dt-bindings: marvell,prestera: Add description for device-tree bindings

2020-09-10 Thread Vadym Kochan
Add brief description how to configure base mac address binding in
device-tree.

Describe requirement for the PCI port which is connected to the ASIC, to
allow access to the firmware related registers.

Signed-off-by: Vadym Kochan 
---
 .../bindings/net/marvell,prestera.txt | 34 +++
 1 file changed, 34 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/marvell,prestera.txt 
b/Documentation/devicetree/bindings/net/marvell,prestera.txt
index 83370ebf5b89..e28938ddfdf5 100644
--- a/Documentation/devicetree/bindings/net/marvell,prestera.txt
+++ b/Documentation/devicetree/bindings/net/marvell,prestera.txt
@@ -45,3 +45,37 @@ dfx-server {
ranges = <0 MBUS_ID(0x08, 0x00) 0 0x10>;
reg = ;
 };
+
+Marvell Prestera SwitchDev bindings
+---
+Optional properties:
+- compatible: must be "marvell,prestera"
+- base-mac-provider: describes handle to node which provides base mac address,
+   might be a static base mac address or nvme cell provider.
+
+Example:
+
+eeprom_mac_addr: eeprom-mac-addr {
+   compatible = "eeprom,mac-addr-cell";
+   status = "okay";
+
+   nvmem = <_at24>;
+};
+
+prestera {
+   compatible = "marvell,prestera";
+   status = "okay";
+
+   base-mac-provider = <_mac_addr>;
+};
+
+The current implementation of Prestera Switchdev PCI interface driver requires
+that BAR2 is assigned to 0xf600 as base address from the PCI IO range:
+
+_pcie0 {
+   ranges = <0x8100 0x0 0xfb00 0x0 0xfb00 0x0 0xf
+   0x8200 0x0 0xf600 0x0 0xf600 0x0 0x200
+   0x8200 0x0 0xf900 0x0 0xf900 0x0 0x10>;
+   phys = <_comphy0 0>;
+   status = "okay";
+};
-- 
2.17.1



[net-next v8 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-09-10 Thread Vadym Kochan
The following features are supported:

- VLAN-aware bridge offloading
- VLAN-unaware bridge offloading
- FDB offloading (learning, ageing)
- Switchport configuration

Currently there are some limitations like:

- Only 1 VLAN-aware bridge instance supported
- FDB ageing timeout parameter is set globally per device

Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Signed-off-by: Vadym Kochan 
---
PATCH v8:
1) Add missing comma for last enum member.

2) Add _ms suffix for ageing variable and struct member.

3) Add comma for last member in initialized struct in prestera_hw.c

4) Use ether_addr_copy() instead of memcpy() for mac FDB copying in 
prestera_hw.c

5) Sorted includes.

6) Fix ageing macro to be in ms instead of seconds.

7) Do not intialize 'err' where it is not needed.

8) Drop swdev->ageing_time member which is not used.

9) Simplify prestera_port_attr_br_ageing_set() by simply
   return prestera_hw_switch_ageing_set(sw, ageing_time_ms), and remove err 
handling.

10) Put license in one line.

PATCH v7:
1) Add missing destroy_workqueue(swdev_wq) in 
prestera_switchdev.c:prestera_switchdev_init()
   on error path handling.

PATCH v5:
0) Add Co-developed tag.

1) Remove "," from terminated enum entry.

2) Replace 'u8 *' -> 'void *' in prestera_fw_parse_fdb_evt(...)

3) Use ether_addr_copy() in prestera_fw_parse_fdb_evt(...)

PATCH v4:
1) Check for the prestera dev interface in switchdev event handler
   to ignore unsupported topology.

 .../net/ethernet/marvell/prestera/Makefile|3 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   31 +
 .../ethernet/marvell/prestera/prestera_hw.c   |  329 +
 .../ethernet/marvell/prestera/prestera_hw.h   |   48 +
 .../ethernet/marvell/prestera/prestera_main.c |  110 +-
 .../marvell/prestera/prestera_switchdev.c | 1277 +
 .../marvell/prestera/prestera_switchdev.h |   13 +
 7 files changed, 1807 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 7684e7047562..93129e32ebc5 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
+  prestera_rxtx.o prestera_devlink.o 
prestera_ethtool.o \
+  prestera_switchdev.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 69628632e2bd..55aa4bf8a27c 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -12,6 +12,8 @@
 
 #define PRESTERA_DRV_NAME  "prestera"
 
+#define PRESTERA_DEFAULT_VID1
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -66,11 +68,13 @@ struct prestera_port {
u32 hw_id;
u32 dev_id;
u16 fp_id;
+   u16 pvid;
bool autoneg;
u64 adver_link_modes;
u8 adver_fec;
struct prestera_port_caps caps;
struct list_head list;
+   struct list_head vlans_list;
struct {
struct prestera_port_stats stats;
struct delayed_work caching_dw;
@@ -100,6 +104,7 @@ enum prestera_event_type {
PRESTERA_EVENT_TYPE_UNSPEC,
 
PRESTERA_EVENT_TYPE_PORT,
+   PRESTERA_EVENT_TYPE_FDB,
PRESTERA_EVENT_TYPE_RXTX,
 
PRESTERA_EVENT_TYPE_MAX
@@ -122,19 +127,37 @@ struct prestera_port_event {
} data;
 };
 
+enum prestera_fdb_event_id {
+   PRESTERA_FDB_EVENT_UNSPEC,
+   PRESTERA_FDB_EVENT_LEARNED,
+   PRESTERA_FDB_EVENT_AGED,
+};
+
+struct prestera_fdb_event {
+   u32 port_id;
+   u32 vid;
+   union {
+   u8 mac[ETH_ALEN];
+   } data;
+};
+
 struct prestera_event {
u16 id;
union {
struct prestera_port_event port_evt;
+   struct prestera_fdb_event fdb_evt;
};
 };
 
+struct prestera_switchdev;
 struct prestera_rxtx;
 
 struct prestera_switch {
struct prestera_device *dev;
+   struct prestera_switchdev *swdev;
struct prestera_rxtx *rxtx;
struct list_head event_handlers;
+   struct notifier_block netdev_nb;
char base_mac[ETH_ALEN];
struct list_head port_list;
rwlock_t port_li

[PATCH net] net: ipa: fix u32_replace_bits by u32p_xxx version

2020-09-10 Thread Vadym Kochan
Looks like u32p_replace_bits() should be used instead of
u32_replace_bits() which does not modifies the value but returns the
modified version.

Fixes: 2b9feef2b6c2 ("soc: qcom: ipa: filter and routing tables")
Signed-off-by: Vadym Kochan 
Reviewed-by: Alex Elder 
---
Found it while grepping of u32_replace_bits() usage and
replaced it w/o testing.

 drivers/net/ipa/ipa_table.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
index 2098ca2f2c90..b3790aa952a1 100644
--- a/drivers/net/ipa/ipa_table.c
+++ b/drivers/net/ipa/ipa_table.c
@@ -521,7 +521,7 @@ static void ipa_filter_tuple_zero(struct ipa_endpoint 
*endpoint)
val = ioread32(endpoint->ipa->reg_virt + offset);
 
/* Zero all filter-related fields, preserving the rest */
-   u32_replace_bits(val, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
+   u32p_replace_bits(, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
 
iowrite32(val, endpoint->ipa->reg_virt + offset);
 }
@@ -573,7 +573,7 @@ static void ipa_route_tuple_zero(struct ipa *ipa, u32 
route_id)
val = ioread32(ipa->reg_virt + offset);
 
/* Zero all route-related fields, preserving the rest */
-   u32_replace_bits(val, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
+   u32p_replace_bits(, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
 
iowrite32(val, ipa->reg_virt + offset);
 }
-- 
2.17.1



[net-next v8 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX3255 (AC3x)

2020-09-10 Thread Vadym Kochan
) {
...
} else {
...
}

  which makes logic more understandable.

10) Simplify sdma tx wait logic when checking/updating tx_ring->burst.

11) Remove not-needed packed & aligned attributes

12) Use USEC_PER_MSEC as multiplier when converting ms -> usec on calling
readl_poll_timeout.

13) Simplified some error path handling by simple return error code in.

14) Remove not-needed err assignment in.

15) Use dev_err() in prestera_devlink_register(...).

Patches updated:
[1] net: marvell: prestera: Add driver for Prestera family ASIC devices
[2] net: marvell: prestera: Add PCI interface support
[3] net: marvell: prestera: Add basic devlink support
[4] net: marvell: prestera: Add ethtool interface support
[5] net: marvell: prestera: Add Switchdev driver implementation

PATCH v4:
1) Use prestera_ prefix in netdev_ops variable.

2) Kconfig: use 'default PRESTERA' build type for CONFIG_PRESTERA_PCI to be
   synced by default with prestera core module.

3) Use memcpy_xxio helpers in prestera_pci.c for IO buffer copying.

4) Generate fw image path via snprintf() instead of macroses.

5) Use pcim_ helpers in prestera_pci.c which simplified the
   probe/remove logic.

6) Removed not needed initializations of variables which are used in
   readl_poll_xxx() helpers.

7) Fixed few grammar mistakes in patch[2] description.

8) Export only prestera_ethtool_ops struct instead of each
   ethtool handler.

9) Add check for prestera_dev_check() in switchdev event handling to
   make sure there is no wrong topology.

Patches updated:
[1] net: marvell: prestera: Add driver for Prestera family ASIC devices
[2] net: marvell: prestera: Add PCI interface support
[4] net: marvell: prestera: Add ethtool interface support
[5] net: marvell: prestera: Add Switchdev driver implementation

PATCH v3:
1) Simplify __be32 type casting in prestera_dsa.c

2) Added per-patch changelog under "---" line.

PATCH v2:
1) Use devlink_port_type_clear()

2) Add _MS prefix to timeout defines.

3) Remove not-needed packed attribute from the firmware ipc structs,
   also the firmware image needs to be uploaded too (will do it soon).

4) Introduce prestera_hw_switch_fini(), to be mirrored with init and
   do simple validation if the event handlers are unregistered.

5) Use kfree_rcu() for event handler unregistering.

6) Get rid of rcu-list usage when dealing with ports, not needed for
   now.

7) Little spelling corrections in the error/info messages.

8) Make pci probe & remove logic mirrored.

9) Get rid of ETH_FCS_LEN in headroom setting, not needed.

PATCH:
1) Fixed W=1 warnings

2) Renamed PCI driver name to be more generic "Prestera DX" because
   there will be more devices supported.

3) Changed firmware image dir path: marvell/ -> mrvl/prestera/
   to be aligned with location in linux-firmware.git (if such
   will be accepted).

RFC v3:
1) Fix prestera prefix in prestera_rxtx.c

2) Protect concurrent access from multiple ports on multiple CPU system
   on tx path by spinlock in prestera_rxtx.c

3) Try to get base mac address from device-tree, otherwise use a random 
generated one.

4) Move ethtool interface support into separate prestera_ethtool.c file.

5) Add basic devlink support and get rid of physical port naming ops.

6) Add STP support in Switchdev driver.

7) Removed MODULE_AUTHOR

8) Renamed prestera.c -> prestera_main.c, and kernel module to
   prestera.ko

RFC v2:
1) Use "pestera_" prefix in struct's and functions instead of mvsw_pr_

2) Original series split into additional patches for Switchdev ethtool 
support.

3) Use major and minor firmware version numbers in the firmware image 
filename.

4) Removed not needed prints.

5) Use iopoll API for waiting on register's value in prestera_pci.c

6) Use standart approach for describing PCI ID matching section instead of 
using
   custom wrappers in prestera_pci.c

7) Add RX/TX support in prestera_rxtx.c.

8) Rewritten prestera_switchdev.c with following changes:
   - handle netdev events from prestera.c

   - use struct prestera_bridge for bridge objects, and get rid of
 struct prestera_bridge_device which may confuse.

   - use refcount_t

9) Get rid of macro usage for sending fw requests in prestera_hw.c

10) Add base_mac setting as module parameter. base_mac is required for
generation default port's mac.

Vadym Kochan (6):
  net: marvell: prestera: Add driver for Prestera family ASIC devices
  net: marvell: prestera: Add PCI interface support
  net: marvell: prestera: Add basic devlink support
  net: marvell: prestera: Add ethtool interface support
  net: marvell: prestera: Add 

Re: [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-10 Thread Vadym Kochan
On Fri, Sep 04, 2020 at 10:12:07PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan  wrote:
> >
> > Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
> > ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> > wireless SMB deployment.
> >
> > The current implementation supports only boards designed for the Marvell
> > Switchdev solution and requires special firmware.
> >
> > The core Prestera switching logic is implemented in prestera_main.c,
> > there is an intermediate hw layer between core logic and firmware. It is
> > implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> > related logic, in future there is a plan to support more devices with
> > different HW related configurations.
> >
> > This patch contains only basic switch initialization and RX/TX support
> > over SDMA mechanism.
> >
> > Currently supported devices have DMA access range <= 32bit and require
> > ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
> > allocated in proper range supported by the Prestera device.
> >
> > Also meanwhile there is no TX interrupt support in current firmware
> > version so recycling work is scheduled on each xmit.
> >
> > Port's mac address is generated from the switch base mac which may be
> > provided via device-tree (static one or as nvme cell), or randomly
> > generated. This is required by the firmware.
> 
> ...
> 
[SNIP]
> ...
> 
> > +   .param = {.admin_state = admin_state}
> 
> + white spaces? Whatever you choose, just be consistent among all
> similar definitions.
> 

Can I use following format for one-liner embedded struct ?

.param = {
.admin_state = admin_state,
}
> ...
> 

I think it looks better when all of the members filled looks similar
(even if it requires 2 additional lines) instead of having:

.member = { E } ?

[SNIP]


Re: [PATCH net-next v7 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-09-10 Thread Vadym Kochan
Hi Andy,

On Fri, Sep 04, 2020 at 10:41:17PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan  wrote:
> >
> > The following features are supported:
> >
> > - VLAN-aware bridge offloading
> > - VLAN-unaware bridge offloading
> > - FDB offloading (learning, ageing)
> > - Switchport configuration
> >
> > Currently there are some limitations like:
> >
> > - Only 1 VLAN-aware bridge instance supported
> > - FDB ageing timeout parameter is set globally per device
> 
> Similar comments as per previous patches.
> 
> > +   struct list_head vlans_list;
> 
> How this container is being protected against races?
> 

It should be protected by rtnl lock from the Switchdev core:

net/switchdev/switchdev.c:int switchdev_port_obj_add(...)

which is called by:

net/bridge/br_switchdev.c:int br_switchdev_port_vlan_add(...)

> -- 
> With Best Regards,
> Andy Shevchenko


Re: [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-09 Thread Vadym Kochan
On Mon, Sep 07, 2020 at 10:55:49AM +0300, Andy Shevchenko wrote:
> On Mon, Sep 7, 2020 at 10:30 AM Vadym Kochan  wrote:
> > On Fri, Sep 04, 2020 at 10:12:07PM +0300, Andy Shevchenko wrote:
> > > On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan  
> > > wrote:
> 
> I'm assuming that you agree on all non-commented.
> 
> ...
> 
> > > > +#define prestera_dev(sw)   ((sw)->dev->dev)
> > >
> > > The point of this is...? (What I see it's 2 characters longer)
> > >
> > > ...
> > It is not about the length but rather about easier semantics, so
> > the prestera_dev() is more easier to remember than sw->dev->dev.
> 
> It actually makes it opposite, now I have to go somewhere in the file,
> quite far from the place where it is used, and check what it is. Then
> I return to the code I'm reading and after a few more lines of code I
> will forget what that macro means.
> 
> ...

Here are my points why I'd like to keep this macro:

1) It hides accessing of the 'struct device * dev' which may help in
   the future if the 'dev' will move to other place or if there will
   some additional logic to get this.
   
   This is the main point.

2) I think that even by reading sw->dev->dev the developer will jump to the
   place where it is defined.
   
   This is not strong point and really by seen just sw->dev->dev at
   it is more understandable to see where 'dev' sits.

3) From the code-writing perspective it was easier for developer
   prestera_dev() instead of sw->dev->dev.

   This is how I felt during the writing the code.

> 
> > > > +   /* firmware requires that port's mac address consist of the 
> > > > first
> > > > +* 5 bytes of base mac address
> > > > +*/
> > >
> > >
> > > > +   memcpy(dev->dev_addr, sw->base_mac, dev->addr_len - 1);
> > >
> > > Can't you call above helper for that?
> >
> > Not sure if I got this right, but I assume that may be just use
> > ether_addr_copy() and then just perform the below assignment on the
> > last byte ?
> 
> No, I mean the function where you have the same comment and something
> else. I'm wondering if you may call it from here. Or refactor code to
> make it possible to call from here.
> 
> -- 
> With Best Regards,
> Andy Shevchenko


Re: [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-09 Thread Vadym Kochan
Hi Andy,

On Tue, Sep 08, 2020 at 12:38:04PM +0300, Andy Shevchenko wrote:
> On Tue, Sep 8, 2020 at 11:35 AM Vadym Kochan  wrote:
> > On Fri, Sep 04, 2020 at 10:12:07PM +0300, Andy Shevchenko wrote:
> > > On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan  
> > > wrote:
> 
> ...
> 
> > > > +   words[3] |= FIELD_PREP(PRESTERA_W3_HW_DEV_NUM, (dsa->hw_dev_num 
> > > > >> 5));
> > >
> > > Ditto.
> > >
> > I am not sure 5 needs to be defined as macro as it just moves
> > hw_dev_num's higher bits into the last word.
> 
> And why 5? I want 6, for example!
> 
> ...

Actually this shifting is conceptually not right and should be mirrored
with PRESTERA_DSA_DEV_NUM genmask from prestera_dsa_parse(), so instead I
did this:

...
u32 dev_num = dsa->hw_dev_num;
...
dev_num = FIELD_GET(PRESTERA_DSA_DEV_NUM, dev_num);
words[3] |= FIELD_PREP(PRESTERA_DSA_W3_DEV_NUM, dev_num);
...

> 
> > > > +   err = prestera_switch_init(sw);
> > > > +   if (err) {
> > > > +   kfree(sw);
> > >
> > > > +   return err;
> > > > +   }
> > > > +
> > > > +   return 0;
> > >
> > > return err;
> > >
> > why not keep 'return 0' as indication of success point ?
> 
> Simple longer, but I'm not insisting. Your choice.
> 
> ...
> 
> > > > +   if (b == 0)
> > > > +   continue;
> > > > +
> > > > +   prestera_sdma_rx_desc_set_next(sdma,
> > > > +  ring->bufs[b - 
> > > > 1].desc,
> > > > +  buf->desc_dma);
> > > > +
> > > > +   if (b == PRESTERA_SDMA_RX_DESC_PER_Q - 1)
> > > > +   prestera_sdma_rx_desc_set_next(sdma, 
> > > > buf->desc,
> > > > +  
> > > > head->desc_dma);
> > >
> > > I guess knowing what the allowed range of bnum the above can be optimized.
> > >
> > You mean to replace PRESTERA_SDMA_RX_DESC_PER_Q by bnum ?
> 
> I don't know what you meant in above. It might be a bug, it might be
> that bnum is redundant and this definition may be used everywhere...
> But I believe there is room for improvement when I see pattern like
> 
>   for (i < X) {
> ...
> if (i == 0) {
>   ...
> } else if (i == X - 1) {
>   ...
> }
>   }
> 
> Either it can be while-loop (or do-while) with better semantics for
> the first and last item to handle or something else.
> Example from another review [1] in case you wonder how changes can be
> made. Just think about it.
> 
> [1]: https://www.spinics.net/lists/linux-pci/msg60826.html (before)
> https://www.spinics.net/lists/linux-pci/msg62043.html (after)
> 

I came up with the following approach which works:

-->8
tail = >bufs[bnum - 1];
head = >bufs[0];
next = head;
prev = next;
ring->next_rx = 0;

do {
err = prestera_sdma_buf_init(sdma, next);
if (err)
return err;

err = prestera_sdma_rx_skb_alloc(sdma, next);
if (err)
return err;

prestera_sdma_rx_desc_init(sdma, next->desc, next->buf_dma);

prestera_sdma_rx_desc_set_next(sdma, prev->desc, next->desc_dma);

prev = next;
next++;
} while (prev != tail);

/* make a circular list */
prestera_sdma_rx_desc_set_next(sdma, tail->desc, head->desc_dma);
--8<

Now it looks more list-oriented cyclic logic.

> -- 
> With Best Regards,
> Andy Shevchenko

Thanks!


Re: [RFT net] net: ipa: fix u32_replace_bits by u32p_xxx version

2020-09-09 Thread Vadym Kochan
Hi Alex,

On Wed, Sep 09, 2020 at 06:53:17AM -0500, Alex Elder wrote:
> On 9/8/20 9:32 AM, Vadym Kochan wrote:
> > Looks like u32p_replace_bits() should be used instead of
> > u32_replace_bits() which does not modifies the value but returns the
> > modified version.
> > 
> > Fixes: 2b9feef2b6c2 ("soc: qcom: ipa: filter and routing tables")
> > Signed-off-by: Vadym Kochan 
> 
> You are correct!  Thank you for finding this.
> 
> Your fix is good, and I have now tested it and verified it
> works as desired.
> 
> FYI, this is currently used only for the SDM845 platform.  It turns
> out the register values (route and filter hash config) that are read
> and intended to be updated always have value 0, so (fortunately) your
> change has no effect there.
> 

I had such assumption that probably it works without the fix.

> Nevertheless, you have fixed this bug and I appreciate it.
> 
> Reviewed-by: Alex Elder 
> 

My understanding is that I need to re-submit this as an official patch
without RFT/RFC prefix and with your reviewed tag ?

Regards,
Vadym Kochan

> > ---
> > Found it while grepping of u32_replace_bits() usage and
> > replaced it w/o testing.
> > 
> >  drivers/net/ipa/ipa_table.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
> > index 2098ca2f2c90..b3790aa952a1 100644
> > --- a/drivers/net/ipa/ipa_table.c
> > +++ b/drivers/net/ipa/ipa_table.c
> > @@ -521,7 +521,7 @@ static void ipa_filter_tuple_zero(struct ipa_endpoint 
> > *endpoint)
> > val = ioread32(endpoint->ipa->reg_virt + offset);
> >  
> > /* Zero all filter-related fields, preserving the rest */
> > -   u32_replace_bits(val, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
> > +   u32p_replace_bits(, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
> >  
> > iowrite32(val, endpoint->ipa->reg_virt + offset);
> >  }
> > @@ -573,7 +573,7 @@ static void ipa_route_tuple_zero(struct ipa *ipa, u32 
> > route_id)
> > val = ioread32(ipa->reg_virt + offset);
> >  
> > /* Zero all route-related fields, preserving the rest */
> > -   u32_replace_bits(val, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
> > +   u32p_replace_bits(, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
> >  
> > iowrite32(val, ipa->reg_virt + offset);
> >  }
> > 
> 


[RFT net] net: ipa: fix u32_replace_bits by u32p_xxx version

2020-09-08 Thread Vadym Kochan
Looks like u32p_replace_bits() should be used instead of
u32_replace_bits() which does not modifies the value but returns the
modified version.

Fixes: 2b9feef2b6c2 ("soc: qcom: ipa: filter and routing tables")
Signed-off-by: Vadym Kochan 
---
Found it while grepping of u32_replace_bits() usage and
replaced it w/o testing.

 drivers/net/ipa/ipa_table.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
index 2098ca2f2c90..b3790aa952a1 100644
--- a/drivers/net/ipa/ipa_table.c
+++ b/drivers/net/ipa/ipa_table.c
@@ -521,7 +521,7 @@ static void ipa_filter_tuple_zero(struct ipa_endpoint 
*endpoint)
val = ioread32(endpoint->ipa->reg_virt + offset);
 
/* Zero all filter-related fields, preserving the rest */
-   u32_replace_bits(val, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
+   u32p_replace_bits(, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
 
iowrite32(val, endpoint->ipa->reg_virt + offset);
 }
@@ -573,7 +573,7 @@ static void ipa_route_tuple_zero(struct ipa *ipa, u32 
route_id)
val = ioread32(ipa->reg_virt + offset);
 
/* Zero all route-related fields, preserving the rest */
-   u32_replace_bits(val, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
+   u32p_replace_bits(, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
 
iowrite32(val, ipa->reg_virt + offset);
 }
-- 
2.17.1



Re: [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-08 Thread Vadym Kochan
On Fri, Sep 04, 2020 at 10:12:07PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan  wrote:
> >
> > Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
> > ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> > wireless SMB deployment.
> >
> > The current implementation supports only boards designed for the Marvell
> > Switchdev solution and requires special firmware.
> >
> > The core Prestera switching logic is implemented in prestera_main.c,
> > there is an intermediate hw layer between core logic and firmware. It is
> > implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> > related logic, in future there is a plan to support more devices with
> > different HW related configurations.
> >
> > This patch contains only basic switch initialization and RX/TX support
> > over SDMA mechanism.
> >
> > Currently supported devices have DMA access range <= 32bit and require
> > ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
> > allocated in proper range supported by the Prestera device.
> >
> > Also meanwhile there is no TX interrupt support in current firmware
> > version so recycling work is scheduled on each xmit.
> >
> > Port's mac address is generated from the switch base mac which may be
> > provided via device-tree (static one or as nvme cell), or randomly
> > generated. This is required by the firmware.
> 
> ...
> 
> > +#define prestera_dev(sw)   ((sw)->dev->dev)
> 
> The point of this is...? (What I see it's 2 characters longer)
> 
> ...
> 
> > +   words[0] = ntohl(dsa_words[0]);
> > +   words[1] = ntohl(dsa_words[1]);
> > +   words[2] = ntohl(dsa_words[2]);
> > +   words[3] = ntohl(dsa_words[3]);
> 
> This is (semi-)NIH of be32_to_cpu_array()
> 
> You may add an additional patch to provide ntohl_array() as an alias
> how it's done for the rest:
> https://elixir.bootlin.com/linux/v5.9-rc3/source/include/linux/byteorder/generic.h#L123
> 
> ...
> 
> > +   dsa->vlan.vid &= ~PRESTERA_VID_MASK;
> > +   dsa->vlan.vid |= FIELD_PREP(PRESTERA_VID_MASK, field);
> 
> Consider to use uXX_replace_bits() (XX for size of the variable).
> Look at bitfield.h closer.
> 
> ...
> 
> > +   dsa->hw_dev_num &= PRESTERA_W3_HW_DEV_NUM;
> > +   dsa->hw_dev_num |= FIELD_PREP(PRESTERA_DEV_NUM_MASK, field);
> 
> Ditto? (Not sure why first line w/o _MASK)
> 
> ...
> 
> > +   if (dsa->hw_dev_num >= BIT(12))
> > +   return -EINVAL;
> > +   if (dsa->port_num >= BIT(17))
> > +   return -EINVAL;
> 
> Magic numbers!
> 
> ...
> 
> > +   words[3] |= FIELD_PREP(PRESTERA_W3_HW_DEV_NUM, (dsa->hw_dev_num >> 
> > 5));
> 
> Ditto.
> 
I am not sure 5 needs to be defined as macro as it just moves
hw_dev_num's higher bits into the last word.

> ...
> 
> > +   dsa_words[0] = htonl(words[0]);
> > +   dsa_words[1] = htonl(words[1]);
> > +   dsa_words[2] = htonl(words[2]);
> > +   dsa_words[3] = htonl(words[3]);
> 
> NIH of cpu_to_be32_array().
> 
> ...
> 
> > +/*
> > + * Copyright (c) 2020 Marvell International Ltd. All rights reserved.
> > + *
> > + */
> 
> One line.
> 
> ...
> 
> > +   err = prestera_find_event_handler(sw, msg->type, );
> 
> > +   if (err || !fw_event_parsers[msg->type].func)
> > +   return -EEXIST;
> 
> Why shadowing error code?
> 
> ...
> 
> > +   struct prestera_msg_port_info_req req = {
> > +   .port = port->id
> 
> Leave comma here.
> Another possibility, if you not expect this to grow, move to one line.
> 
> > +   };
> 
> ...
> 
> > +   .param = {.admin_state = admin_state}
> 
> + white spaces? Whatever you choose, just be consistent among all
> similar definitions.
> 
> ...
> 
> > +   .port = port->hw_id,
> > +   .dev = port->dev_id
> 
> Leave comma.
> 
> ...
> 
> > +   struct prestera_msg_port_attr_req req = {
> > +   .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
> > +   .port = port->hw_id,
> > +   .dev = port->dev_id
> 
> Ditto. I have a deja vu that I already pointed out to these.
> 
> > +   };
> 
> ...
> 
> > +   err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
> > +  , size

Re: [PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-07 Thread Vadym Kochan
Hi Andy,

On Fri, Sep 04, 2020 at 10:12:07PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 4, 2020 at 7:52 PM Vadym Kochan  wrote:
> >
> > Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
> > ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> > wireless SMB deployment.
> >
> > The current implementation supports only boards designed for the Marvell
> > Switchdev solution and requires special firmware.
> >
> > The core Prestera switching logic is implemented in prestera_main.c,
> > there is an intermediate hw layer between core logic and firmware. It is
> > implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> > related logic, in future there is a plan to support more devices with
> > different HW related configurations.
> >
> > This patch contains only basic switch initialization and RX/TX support
> > over SDMA mechanism.
> >
> > Currently supported devices have DMA access range <= 32bit and require
> > ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
> > allocated in proper range supported by the Prestera device.
> >
> > Also meanwhile there is no TX interrupt support in current firmware
> > version so recycling work is scheduled on each xmit.
> >
> > Port's mac address is generated from the switch base mac which may be
> > provided via device-tree (static one or as nvme cell), or randomly
> > generated. This is required by the firmware.
> 
> ...
> 
> > +#define prestera_dev(sw)   ((sw)->dev->dev)
> 
> The point of this is...? (What I see it's 2 characters longer)
> 
> ...
It is not about the length but rather about easier semantics, so
the prestera_dev() is more easier to remember than sw->dev->dev.

> 
> > +   words[0] = ntohl(dsa_words[0]);
> > +   words[1] = ntohl(dsa_words[1]);
> > +   words[2] = ntohl(dsa_words[2]);
> > +   words[3] = ntohl(dsa_words[3]);
> 
> This is (semi-)NIH of be32_to_cpu_array()
> 
> You may add an additional patch to provide ntohl_array() as an alias
> how it's done for the rest:
> https://elixir.bootlin.com/linux/v5.9-rc3/source/include/linux/byteorder/generic.h#L123
> 
> ...
> 
> > +   dsa->vlan.vid &= ~PRESTERA_VID_MASK;
> > +   dsa->vlan.vid |= FIELD_PREP(PRESTERA_VID_MASK, field);
> 
> Consider to use uXX_replace_bits() (XX for size of the variable).
> Look at bitfield.h closer.
> 
> ...
> 
> > +   dsa->hw_dev_num &= PRESTERA_W3_HW_DEV_NUM;
> > +   dsa->hw_dev_num |= FIELD_PREP(PRESTERA_DEV_NUM_MASK, field);
> 
> Ditto? (Not sure why first line w/o _MASK)
> 
> ...
> 
> > +   if (dsa->hw_dev_num >= BIT(12))
> > +   return -EINVAL;
> > +   if (dsa->port_num >= BIT(17))
> > +   return -EINVAL;
> 
> Magic numbers!
> 
> ...
> 
> > +   words[3] |= FIELD_PREP(PRESTERA_W3_HW_DEV_NUM, (dsa->hw_dev_num >> 
> > 5));
> 
> Ditto.
> 
> ...
> 
> > +   dsa_words[0] = htonl(words[0]);
> > +   dsa_words[1] = htonl(words[1]);
> > +   dsa_words[2] = htonl(words[2]);
> > +   dsa_words[3] = htonl(words[3]);
> 
> NIH of cpu_to_be32_array().
> 
> ...
> 
> > +/*
> > + * Copyright (c) 2020 Marvell International Ltd. All rights reserved.
> > + *
> > + */
> 
> One line.
> 
> ...
> 
> > +   err = prestera_find_event_handler(sw, msg->type, );
> 
> > +   if (err || !fw_event_parsers[msg->type].func)
> > +   return -EEXIST;
> 
> Why shadowing error code?
> 
> ...
> 
> > +   struct prestera_msg_port_info_req req = {
> > +   .port = port->id
> 
> Leave comma here.
> Another possibility, if you not expect this to grow, move to one line.
> 
> > +   };
> 
> ...
> 
> > +   .param = {.admin_state = admin_state}
> 
> + white spaces? Whatever you choose, just be consistent among all
> similar definitions.
> 
> ...
> 
> > +   .port = port->hw_id,
> > +   .dev = port->dev_id
> 
> Leave comma.
> 
> ...
> 
> > +   struct prestera_msg_port_attr_req req = {
> > +   .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
> > +   .port = port->hw_id,
> > +   .dev = port->dev_id
> 
> Ditto. I have a deja vu that I already pointed out to these.
> 
> > +   };
> 
> ...
> 
> > +   err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
> > +

[PATCH net-next v7 2/6] net: marvell: prestera: Add PCI interface support

2020-09-04 Thread Vadym Kochan
Add PCI interface driver for Prestera Switch ASICs family devices, which
provides:

- Firmware loading mechanism
- Requests & events handling to/from the firmware
- Access to the firmware on the bus level

The firmware has to be loaded each time the device is reset. The driver
is loading it from:

/lib/firmware/mrvl/prestera/mvsw_prestera_fw-v{MAJOR}.{MINOR}.img

The full firmware image version is located within the internal header
and consists of 3 numbers - MAJOR.MINOR.PATCH. Additionally, driver has
hard-coded minimum supported firmware version which it can work with:

MAJOR - reflects the support on ABI level between driver and loaded
firmware, this number should be the same for driver and loaded
firmware.

MINOR - this is the minimum supported version between driver and the
firmware.

PATCH - indicates only fixes, firmware ABI is not changed.

Firmware image file name contains only MAJOR and MINOR numbers to make
driver be compatible with any PATCH version.

Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Signed-off-by: Vadym Kochan 
---
PATCH v5:
1) Remove not-needed packed & aligned attributes

2) Convert 'u8 *' to 'void *' on path when handling/calling 
send_req/recv_msg
   callback. This allows to remove not-needed 'u8 *' casting.

3) Use USEC_PER_MSEC as multiplier when converting ms -> usec on calling
   readl_poll_timeout.

4) Removed pci_dev member from prestera_fw, there is already 'struct
   prestera_dev' which holds pointer to 'struct device'.

5) Replace pci_err (added in the previous patch) by dev_err.

PATCH v4:
1) Get rid of "packed" attribute for the fw image header, it is
   already aligned.

2) Cleanup not needed initialization of variables which are used in
   readl_poll_timeout() helpers.

3) Replace #define's of prestera_{fw,ldr}_{read,write} to static funcs.

4) Use pcim_ helpers for resource allocation

5) Use devm_zalloc() for struct prestera_fw instance allocation.

6) Use module_pci_driver(prestera_pci_driver) instead of module_{init,exit}.

7) Use _MS prefix for timeout #define's.

8) Use snprintf for firmware image path generation instead of using
   macrosses.

9) Use memcpy_xxxio helpers for IO memory copying.

   10) By default use same build type ('m' or 'y') for
   CONFIG_PRESTERA_PCI which is used by CONFIG_PRESTERA.

 drivers/net/ethernet/marvell/prestera/Kconfig |  11 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +
 .../ethernet/marvell/prestera/prestera_pci.c  | 778 ++
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_pci.c

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 76b68613ea7a..2a5945c455cc 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -11,3 +11,14 @@ config PRESTERA
 
  To compile this driver as a module, choose M here: the
  module will be called prestera.
+
+config PRESTERA_PCI
+   tristate "PCI interface driver for Marvell Prestera Switch ASICs family"
+   depends on PCI && HAS_IOMEM && PRESTERA
+   default PRESTERA
+   help
+ This is implementation of PCI interface support for Marvell Prestera
+ Switch ASICs family.
+
+ To compile this driver as a module, choose M here: the
+ module will be called prestera_pci.
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 610d75032b78..2146714eab21 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
   prestera_rxtx.o
+
+obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
new file mode 100644
index ..898e0a52d78c
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "prestera.h"
+
+#define PRESTERA_MSG_MAX_SIZE 1500
+
+#define PRESTERA_SUPP_FW_MAJ_VER   2
+#define PRESTERA_SUPP_FW_MIN_VER   0
+
+#define PRESTERA_FW_PATH_FMT   "mrvl/prestera/mvsw_prestera_fw-v%u.%u.img"
+
+#define PRESTERA_FW_HDR_MAGIC  0x351D9D06
+#define PRESTERA_FW_DL_TIMEOUT_MS  5
+#define PRESTERA_FW_BLK_SZ 1024
+
+#define PRESTERA_FW_V

[PATCH net-next v7 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX3255 (AC3x)

2020-09-04 Thread Vadym Kochan
 for prestera_dev_check() in switchdev event handling to
   make sure there is no wrong topology.

Patches updated:
[1] net: marvell: prestera: Add driver for Prestera family ASIC devices
[2] net: marvell: prestera: Add PCI interface support
[4] net: marvell: prestera: Add ethtool interface support
[5] net: marvell: prestera: Add Switchdev driver implementation

PATCH v3:
1) Simplify __be32 type casting in prestera_dsa.c

2) Added per-patch changelog under "---" line.

PATCH v2:
1) Use devlink_port_type_clear()

2) Add _MS prefix to timeout defines.

3) Remove not-needed packed attribute from the firmware ipc structs,
   also the firmware image needs to be uploaded too (will do it soon).

4) Introduce prestera_hw_switch_fini(), to be mirrored with init and
   do simple validation if the event handlers are unregistered.

5) Use kfree_rcu() for event handler unregistering.

6) Get rid of rcu-list usage when dealing with ports, not needed for
   now.

7) Little spelling corrections in the error/info messages.

8) Make pci probe & remove logic mirrored.

9) Get rid of ETH_FCS_LEN in headroom setting, not needed.

PATCH:
1) Fixed W=1 warnings

2) Renamed PCI driver name to be more generic "Prestera DX" because
   there will be more devices supported.

3) Changed firmware image dir path: marvell/ -> mrvl/prestera/
   to be aligned with location in linux-firmware.git (if such
   will be accepted).

RFC v3:
1) Fix prestera prefix in prestera_rxtx.c

2) Protect concurrent access from multiple ports on multiple CPU system
   on tx path by spinlock in prestera_rxtx.c

3) Try to get base mac address from device-tree, otherwise use a random 
generated one.

4) Move ethtool interface support into separate prestera_ethtool.c file.

5) Add basic devlink support and get rid of physical port naming ops.

6) Add STP support in Switchdev driver.

7) Removed MODULE_AUTHOR

8) Renamed prestera.c -> prestera_main.c, and kernel module to
   prestera.ko

RFC v2:
1) Use "pestera_" prefix in struct's and functions instead of mvsw_pr_

2) Original series split into additional patches for Switchdev ethtool 
support.

3) Use major and minor firmware version numbers in the firmware image 
filename.

4) Removed not needed prints.

5) Use iopoll API for waiting on register's value in prestera_pci.c

6) Use standart approach for describing PCI ID matching section instead of 
using
   custom wrappers in prestera_pci.c

7) Add RX/TX support in prestera_rxtx.c.

8) Rewritten prestera_switchdev.c with following changes:
   - handle netdev events from prestera.c

   - use struct prestera_bridge for bridge objects, and get rid of
 struct prestera_bridge_device which may confuse.

   - use refcount_t

9) Get rid of macro usage for sending fw requests in prestera_hw.c

10) Add base_mac setting as module parameter. base_mac is required for
generation default port's mac.

Vadym Kochan (6):
  net: marvell: prestera: Add driver for Prestera family ASIC devices
  net: marvell: prestera: Add PCI interface support
  net: marvell: prestera: Add basic devlink support
  net: marvell: prestera: Add ethtool interface support
  net: marvell: prestera: Add Switchdev driver implementation
  dt-bindings: marvell,prestera: Add description for device-tree
bindings

 .../bindings/net/marvell,prestera.txt |   34 +
 drivers/net/ethernet/marvell/Kconfig  |1 +
 drivers/net/ethernet/marvell/Makefile |1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |   25 +
 .../net/ethernet/marvell/prestera/Makefile|7 +
 .../net/ethernet/marvell/prestera/prestera.h  |  209 +++
 .../marvell/prestera/prestera_devlink.c   |  114 ++
 .../marvell/prestera/prestera_devlink.h   |   26 +
 .../ethernet/marvell/prestera/prestera_dsa.c  |  106 ++
 .../ethernet/marvell/prestera/prestera_dsa.h  |   37 +
 .../marvell/prestera/prestera_ethtool.c   |  759 ++
 .../marvell/prestera/prestera_ethtool.h   |   14 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 1227 
 .../ethernet/marvell/prestera/prestera_hw.h   |  185 +++
 .../ethernet/marvell/prestera/prestera_main.c |  671 +
 .../ethernet/marvell/prestera/prestera_pci.c  |  778 ++
 .../ethernet/marvell/prestera/prestera_rxtx.c |  823 +++
 .../ethernet/marvell/prestera/prestera_rxtx.h |   21 +
 .../marvell/prestera/prestera_switchdev.c | 1290 +
 .../marvell/prestera/prestera_switchdev.h |   16 +
 20 files changed, 6344 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera.h
 create mode 100644 drivers/net/e

[PATCH net-next v7 3/6] net: marvell: prestera: Add basic devlink support

2020-09-04 Thread Vadym Kochan
Add very basic support for devlink interface:

- driver name
- fw version
- devlink ports

Signed-off-by: Vadym Kochan 
---
PATCH v5:
1) Simplified some error path handling by simple return error code in:

   - prestera_dl_info_get(...)

2) Remove not-needed err assignment in:
   - prestera_dl_info_get(...)

3) Use dev_err() in prestera_devlink_register(...).

 drivers/net/ethernet/marvell/prestera/Kconfig |   1 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   4 +
 .../marvell/prestera/prestera_devlink.c   | 114 ++
 .../marvell/prestera/prestera_devlink.h   |  26 
 .../ethernet/marvell/prestera/prestera_main.c |  28 -
 6 files changed, 170 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 2a5945c455cc..b1fcc44f566a 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -6,6 +6,7 @@
 config PRESTERA
tristate "Marvell Prestera Switch ASICs support"
depends on NET_SWITCHDEV && VLAN_8021Q
+   select NET_DEVLINK
help
  This driver supports Marvell Prestera Switch ASICs family.
 
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 2146714eab21..babd71fba809 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o
+  prestera_rxtx.o prestera_devlink.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 2efaa5abc3be..5e890897356e 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -11,6 +11,9 @@
 #include 
 #include 
 #include 
+#include 
+
+#define PRESTERA_DRV_NAME  "prestera"
 
 struct prestera_fw_rev {
u16 maj;
@@ -63,6 +66,7 @@ struct prestera_port_caps {
 struct prestera_port {
struct net_device *dev;
struct prestera_switch *sw;
+   struct devlink_port dl_port;
u32 id;
u32 hw_id;
u32 dev_id;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_devlink.c 
b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
new file mode 100644
index ..abbd08dad6ab
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+
+#include "prestera.h"
+#include "prestera_devlink.h"
+
+static int prestera_dl_info_get(struct devlink *dl,
+   struct devlink_info_req *req,
+   struct netlink_ext_ack *extack)
+{
+   struct prestera_switch *sw = devlink_priv(dl);
+   char buf[16];
+   int err;
+
+   err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME);
+   if (err)
+   return err;
+
+   snprintf(buf, sizeof(buf), "%d.%d.%d",
+sw->dev->fw_rev.maj,
+sw->dev->fw_rev.min,
+sw->dev->fw_rev.sub);
+
+   return devlink_info_version_running_put(req,
+  DEVLINK_INFO_VERSION_GENERIC_FW,
+  buf);
+}
+
+static const struct devlink_ops prestera_dl_ops = {
+   .info_get = prestera_dl_info_get,
+};
+
+struct prestera_switch *prestera_devlink_alloc(void)
+{
+   struct devlink *dl;
+
+   dl = devlink_alloc(_dl_ops, sizeof(struct prestera_switch));
+
+   return devlink_priv(dl);
+}
+
+void prestera_devlink_free(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_free(dl);
+}
+
+int prestera_devlink_register(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+   int err;
+
+   err = devlink_register(dl, sw->dev->dev);
+   if (err)
+   dev_err(sw->dev->dev, "devlink_register failed: %d\n", err);
+
+   return err;
+}
+
+void prestera_devlink_unregister(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_unregister(dl);
+}
+
+int prestera_devlink_port_register(struct prestera_port *port)
+{
+   struct dev

[PATCH net-next v7 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-09-04 Thread Vadym Kochan
The following features are supported:

- VLAN-aware bridge offloading
- VLAN-unaware bridge offloading
- FDB offloading (learning, ageing)
- Switchport configuration

Currently there are some limitations like:

- Only 1 VLAN-aware bridge instance supported
- FDB ageing timeout parameter is set globally per device

Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Signed-off-by: Vadym Kochan 
---
PATCH v7:
1) Add missing destroy_workqueue(swdev_wq) in 
prestera_switchdev.c:prestera_switchdev_init()
   on error path handling.

PATCH v5:
0) Add Co-developed tag.

1) Remove "," from terminated enum entry.

2) Replace 'u8 *' -> 'void *' in prestera_fw_parse_fdb_evt(...)

3) Use ether_addr_copy() in prestera_fw_parse_fdb_evt(...)

PATCH v4:
1) Check for the prestera dev interface in switchdev event handler
   to ignore unsupported topology.

 .../net/ethernet/marvell/prestera/Makefile|3 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   33 +-
 .../ethernet/marvell/prestera/prestera_hw.c   |  322 +++-
 .../ethernet/marvell/prestera/prestera_hw.h   |   48 +
 .../ethernet/marvell/prestera/prestera_main.c |  111 +-
 .../marvell/prestera/prestera_switchdev.c | 1290 +
 .../marvell/prestera/prestera_switchdev.h |   16 +
 7 files changed, 1816 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 7684e7047562..93129e32ebc5 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
+  prestera_rxtx.o prestera_devlink.o 
prestera_ethtool.o \
+  prestera_switchdev.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 9a5a0deb909b..83df4695dc12 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -15,6 +15,8 @@
 
 #define PRESTERA_DRV_NAME  "prestera"
 
+#define PRESTERA_DEFAULT_VID1
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -51,8 +53,6 @@ struct prestera_port_stats {
u64 unicast_frames_sent;
u64 sent_multiple;
u64 sent_deferred;
-   u64 frames_1024_to_1518_octets;
-   u64 frames_1519_to_max_octets;
u64 good_octets_sent;
 };
 
@@ -71,11 +71,13 @@ struct prestera_port {
u32 hw_id;
u32 dev_id;
u16 fp_id;
+   u16 pvid;
bool autoneg;
u64 adver_link_modes;
u8 adver_fec;
struct prestera_port_caps caps;
struct list_head list;
+   struct list_head vlans_list;
struct {
struct prestera_port_stats stats;
struct delayed_work caching_dw;
@@ -105,6 +107,7 @@ enum prestera_event_type {
PRESTERA_EVENT_TYPE_UNSPEC,
 
PRESTERA_EVENT_TYPE_PORT,
+   PRESTERA_EVENT_TYPE_FDB,
PRESTERA_EVENT_TYPE_RXTX,
 
PRESTERA_EVENT_TYPE_MAX
@@ -127,19 +130,37 @@ struct prestera_port_event {
} data;
 };
 
+enum prestera_fdb_event_id {
+   PRESTERA_FDB_EVENT_UNSPEC,
+   PRESTERA_FDB_EVENT_LEARNED,
+   PRESTERA_FDB_EVENT_AGED,
+};
+
+struct prestera_fdb_event {
+   u32 port_id;
+   u32 vid;
+   union {
+   u8 mac[ETH_ALEN];
+   } data;
+};
+
 struct prestera_event {
u16 id;
union {
struct prestera_port_event port_evt;
+   struct prestera_fdb_event fdb_evt;
};
 };
 
+struct prestera_switchdev;
 struct prestera_rxtx;
 
 struct prestera_switch {
struct prestera_device *dev;
+   struct prestera_switchdev *swdev;
struct prestera_rxtx *rxtx;
struct list_head event_handlers;
+   struct notifier_block netdev_nb;
char base_mac[ETH_ALEN];
struct list_head port_list;
rwlock_t port_list_lock;
@@ -177,4 +198,12 @@ struct prestera_port *prestera_port_find_by_hwid(struct 
prestera_switch *sw,
 int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
  u64 adver_link_modes, u8 adver_fec);
 
+struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id);
+
+struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
+
+int

[PATCH net-next v7 4/6] net: marvell: prestera: Add ethtool interface support

2020-09-04 Thread Vadym Kochan
The ethtool API provides support for the configuration of the following
features: speed and duplex, auto-negotiation, MDI-x, forward error
correction, port media type. The API also provides information about the
port status, hardware and software statistic. The following limitation
exists:

- port media type should be configured before speed setting
- ethtool -m option is not supported
- ethtool -p option is not supported
- ethtool -r option is supported for RJ45 port only
- the following combination of parameters is not supported:

  ethtool -s sw1pX port XX autoneg on

- forward error correction feature is supported only on SFP ports, 10G
  speed

- auto-negotiation and MDI-x features are not supported on
  Copper-to-Fiber SFP module

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Signed-off-by: Vadym Kochan 
---
PATCH v5:

1) Convert following error check:

if (func(...))
or
if (!func(...))

to use err variable:

err = func(...)
if (err)

2) Remove "," from terminated enum entry.

PATCH v4:
1) Export only prestera_ethtool_ops instead of
   each ethtool handler.

2) Get rid of not needed cast in prestera_ethtool_get_stats(...)
   when doing memcpy.

 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   3 +
 .../marvell/prestera/prestera_ethtool.c   | 759 ++
 .../marvell/prestera/prestera_ethtool.h   |  14 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 295 ++-
 .../ethernet/marvell/prestera/prestera_hw.h   |  65 ++
 .../ethernet/marvell/prestera/prestera_main.c |  28 +-
 7 files changed, 1159 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index babd71fba809..7684e7047562 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o
+  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 5e890897356e..9a5a0deb909b 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -174,4 +174,7 @@ void prestera_device_unregister(struct prestera_device 
*dev);
 struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
 u32 dev_id, u32 hw_id);
 
+int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
+ u64 adver_link_modes, u8 adver_fec);
+
 #endif /* _PRESTERA_H_ */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c 
b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
new file mode 100644
index ..d947c09ce134
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
@@ -0,0 +1,759 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+
+#include "prestera.h"
+#include "prestera_hw.h"
+#include "prestera_ethtool.h"
+
+#define PRESTERA_STATS_CNT \
+   (sizeof(struct prestera_port_stats) / sizeof(u64))
+#define PRESTERA_STATS_IDX(name) \
+   (offsetof(struct prestera_port_stats, name) / sizeof(u64))
+#define PRESTERA_STATS_FIELD(name) \
+   [PRESTERA_STATS_IDX(name)] = __stringify(name)
+
+static const char driver_kind[] = "prestera";
+
+static const struct prestera_link_mode {
+   enum ethtool_link_mode_bit_indices eth_mode;
+   u32 speed;
+   u64 pr_mask;
+   u8 duplex;
+   u8 port_type;
+} port_link_modes[PRESTERA_LINK_MODE_MAX] = {
+   [PRESTERA_LINK_MODE_10baseT_Half] = {
+   .eth_mode =  ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+   .speed = 10,
+   .pr_mask = 1 << PRESTERA_LINK_MODE_10baseT_Half,
+   .duplex = PRESTERA_PORT_DUPLEX_HALF,
+   .port_type = PRESTERA_PORT_TYPE_TP,
+   },
+   [PRESTERA_LINK_MODE_10baseT_Full] = {
+   .eth_mode =  ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+   .speed = 10,
+   .pr_mask = 1 << PRESTERA_LINK_MODE_10baseT_Full,
+   .duplex = PRESTERA_PORT_D

[PATCH net-next v7 6/6] dt-bindings: marvell,prestera: Add description for device-tree bindings

2020-09-04 Thread Vadym Kochan
Add brief description how to configure base mac address binding in
device-tree.

Describe requirement for the PCI port which is connected to the ASIC, to
allow access to the firmware related registers.

Signed-off-by: Vadym Kochan 
---
 .../bindings/net/marvell,prestera.txt | 34 +++
 1 file changed, 34 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/marvell,prestera.txt 
b/Documentation/devicetree/bindings/net/marvell,prestera.txt
index 83370ebf5b89..e28938ddfdf5 100644
--- a/Documentation/devicetree/bindings/net/marvell,prestera.txt
+++ b/Documentation/devicetree/bindings/net/marvell,prestera.txt
@@ -45,3 +45,37 @@ dfx-server {
ranges = <0 MBUS_ID(0x08, 0x00) 0 0x10>;
reg = ;
 };
+
+Marvell Prestera SwitchDev bindings
+---
+Optional properties:
+- compatible: must be "marvell,prestera"
+- base-mac-provider: describes handle to node which provides base mac address,
+   might be a static base mac address or nvme cell provider.
+
+Example:
+
+eeprom_mac_addr: eeprom-mac-addr {
+   compatible = "eeprom,mac-addr-cell";
+   status = "okay";
+
+   nvmem = <_at24>;
+};
+
+prestera {
+   compatible = "marvell,prestera";
+   status = "okay";
+
+   base-mac-provider = <_mac_addr>;
+};
+
+The current implementation of Prestera Switchdev PCI interface driver requires
+that BAR2 is assigned to 0xf600 as base address from the PCI IO range:
+
+_pcie0 {
+   ranges = <0x8100 0x0 0xfb00 0x0 0xfb00 0x0 0xf
+   0x8200 0x0 0xf600 0x0 0xf600 0x0 0x200
+   0x8200 0x0 0xf900 0x0 0xf900 0x0 0x10>;
+   phys = <_comphy0 0>;
+   status = "okay";
+};
-- 
2.17.1



[PATCH net-next v7 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-04 Thread Vadym Kochan
Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
wireless SMB deployment.

The current implementation supports only boards designed for the Marvell
Switchdev solution and requires special firmware.

The core Prestera switching logic is implemented in prestera_main.c,
there is an intermediate hw layer between core logic and firmware. It is
implemented in prestera_hw.c, the purpose of it is to encapsulate hw
related logic, in future there is a plan to support more devices with
different HW related configurations.

This patch contains only basic switch initialization and RX/TX support
over SDMA mechanism.

Currently supported devices have DMA access range <= 32bit and require
ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
allocated in proper range supported by the Prestera device.

Also meanwhile there is no TX interrupt support in current firmware
version so recycling work is scheduled on each xmit.

Port's mac address is generated from the switch base mac which may be
provided via device-tree (static one or as nvme cell), or randomly
generated. This is required by the firmware.

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Co-developed-by: Volodymyr Mytnyk 
Signed-off-by: Volodymyr Mytnyk 
Signed-off-by: Vadym Kochan 
---
PATCH v7:
1) Use ether_addr_copy() in prestera_main.c:prestera_port_set_mac_address()
   instead of memcpy().

2) Removed not needed device's DMA address range check on
   dma_pool_alloc() in prestera_rxtx.c:prestera_sdma_buf_init(),
   this should be handled by dma_xxx() API considerig device's DMA mask.

3) Removed not needed device's DMA address range check on
   dma_map_single() in prestera_rxtx.c:prestera_sdma_rx_skb_alloc(),
   this should be handled by dma_xxx() API considerig device's DMA mask.

4) Add comment about port mac address limitation in the code where
   it is used and checked - prestera_main.c:

   - prestera_is_valid_mac_addr()
   - prestera_port_create()

 drivers/net/ethernet/marvell/Kconfig  |   1 +
 drivers/net/ethernet/marvell/Makefile |   1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |  13 +
 .../net/ethernet/marvell/prestera/Makefile|   4 +
 .../net/ethernet/marvell/prestera/prestera.h  | 173 
 .../ethernet/marvell/prestera/prestera_dsa.c  | 106 +++
 .../ethernet/marvell/prestera/prestera_dsa.h  |  37 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 614 +
 .../ethernet/marvell/prestera/prestera_hw.h   |  72 ++
 .../ethernet/marvell/prestera/prestera_main.c | 528 +++
 .../ethernet/marvell/prestera/prestera_rxtx.c | 823 ++
 .../ethernet/marvell/prestera/prestera_rxtx.h |  21 +
 12 files changed, 2393 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_main.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.h

diff --git a/drivers/net/ethernet/marvell/Kconfig 
b/drivers/net/ethernet/marvell/Kconfig
index ef4f35ba077d..892e5c8ff096 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -172,5 +172,6 @@ config SKY2_DEBUG
 
 
 source "drivers/net/ethernet/marvell/octeontx2/Kconfig"
+source "drivers/net/ethernet/marvell/prestera/Kconfig"
 
 endif # NET_VENDOR_MARVELL
diff --git a/drivers/net/ethernet/marvell/Makefile 
b/drivers/net/ethernet/marvell/Makefile
index 89dea7284d5b..9f88fe822555 100644
--- a/drivers/net/ethernet/marvell/Makefile
+++ b/drivers/net/ethernet/marvell/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
 obj-y  += octeontx2/
+obj-y  += prestera/
diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
new file mode 100644
index ..76b68613ea7a
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Marvell Prestera drivers configuration
+#
+
+config PRESTERA
+   tri

Re: [PATCH net v6 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-04 Thread Vadym Kochan
Hi Andrew,

On Fri, Sep 04, 2020 at 03:32:17PM +0200, Andrew Lunn wrote:
> > > > +static int prestera_is_valid_mac_addr(struct prestera_port *port, u8 
> > > > *addr)
> > > > +{
> > > > +   if (!is_valid_ether_addr(addr))
> > > > +   return -EADDRNOTAVAIL;
> > > > +
> > > > +   if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))
> > > 
> > > Why ETH_ALEN - 1?
> > > 
> > This is the restriction of the port mac address, it must have base mac
> > address part at first 5 bytes.
> 
> You probably want to put a comment here about that.
> 
> And this is particularly user unfriendly. Is this a hardware issue? Or
> firmware? Is this likely to change in the future?
> 
> Andrew

It is required by the firmware, partially it may have relation to the
hardware.

I am not sure if it will be changed in the future. But I will add
a comment as you suggested.

Thanks,


Re: [PATCH v3 1/3] nvmem: core: allow to register cells during nvmem registration

2020-09-04 Thread Vadym Kochan
Hi Srinivas,

On Fri, Sep 04, 2020 at 12:02:40PM +0100, Srinivas Kandagatla wrote:
> Hi Vadym,
> 
> Thanks for the patch,
> On 31/08/2020 02:55, Vadym Kochan wrote:
> > Add NVMEM_PRE_ADD notification step which is called before any cells
> > binding - from lookup table or config, this allows to register cells
> > in some specific layout (tlv) which should be parsed first and then
> > registered. So there might be a cell parser driver which can register
> > lookup table during this notification step.
> > 
> This is going in right direction but totally not correct way to do it.
> 
> 1> this is not scalable as any consumer that will register for this even
> will have no idea of which what kind of parsing that provider needs.
> It can work in your case but not really useful.
> 
> 2> this is a consumer API, not the provider api.
> 
> How about adding a "parse_cells" callback in struct nvmem_config along with
> encoding type.
> 
> 
> thanks,
> srini
> 

Looks like I missed main point here that this cells parser should be
registered as nvmem provider. I will think on it.

Thanks,

> > Signed-off-by: Vadym Kochan 
> > ---
> > v3:
> >  1) Update core.c changes by extending notification mechanism
> > by adding new NVMEM_PRE_ADD event id which is called before lookup
> > table cells binding, this allows for notification handler to
> > register cells which require nvmem parsing.
> > 
> >   drivers/nvmem/core.c   | 2 ++
> >   include/linux/nvmem-consumer.h | 1 +
> >   2 files changed, 3 insertions(+)
> > 
> > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > index 6cd3edb2eaf6..c48a69e0ebbe 100644
> > --- a/drivers/nvmem/core.c
> > +++ b/drivers/nvmem/core.c
> > @@ -668,6 +668,8 @@ struct nvmem_device *nvmem_register(const struct 
> > nvmem_config *config)
> > goto err_device_del;
> > }
> > +   blocking_notifier_call_chain(_notifier, NVMEM_PRE_ADD, nvmem);
> > +
> > if (config->cells) {
> > rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
> > if (rval)
> > diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> > index 052293f4cbdb..0f7107276756 100644
> > --- a/include/linux/nvmem-consumer.h
> > +++ b/include/linux/nvmem-consumer.h
> > @@ -50,6 +50,7 @@ enum {
> > NVMEM_REMOVE,
> > NVMEM_CELL_ADD,
> > NVMEM_CELL_REMOVE,
> > +   NVMEM_PRE_ADD,
> >   };
> >   #if IS_ENABLED(CONFIG_NVMEM)
> > 


Re: [PATCH net v6 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-09-04 Thread Vadym Kochan
On Thu, Sep 03, 2020 at 07:18:59PM +0200, Willem de Bruijn wrote:
> On Wed, Sep 2, 2020 at 5:07 PM Vadym Kochan  wrote:
> >
> > The following features are supported:
> >
> > - VLAN-aware bridge offloading
> > - VLAN-unaware bridge offloading
> > - FDB offloading (learning, ageing)
> > - Switchport configuration
> >
> > Currently there are some limitations like:
> >
> > - Only 1 VLAN-aware bridge instance supported
> > - FDB ageing timeout parameter is set globally per device
> >
> > Co-developed-by: Serhiy Boiko 
> > Signed-off-by: Serhiy Boiko 
> > Co-developed-by: Serhiy Pshyk 
> > Signed-off-by: Serhiy Pshyk 
> > Co-developed-by: Taras Chornyi 
> > Signed-off-by: Taras Chornyi 
> > Signed-off-by: Vadym Kochan 
> 
> 
> > +int prestera_switchdev_init(struct prestera_switch *sw)
> > +{
> > +   struct prestera_switchdev *swdev;
> > +   int err;
> > +
> > +   swdev = kzalloc(sizeof(*swdev), GFP_KERNEL);
> > +   if (!swdev)
> > +   return -ENOMEM;
> > +
> > +   sw->swdev = swdev;
> > +   swdev->sw = sw;
> > +
> > +   INIT_LIST_HEAD(>bridge_list);
> > +
> > +   swdev_wq = alloc_ordered_workqueue("%s_ordered", 0, "prestera_br");
> > +   if (!swdev_wq) {
> > +   err = -ENOMEM;
> > +   goto err_alloc_wq;
> > +   }
> > +
> > +   err = prestera_switchdev_handler_init(swdev);
> > +   if (err)
> > +   goto err_swdev_init;
> > +
> > +   err = prestera_fdb_init(sw);
> > +   if (err)
> > +   goto err_fdb_init;
> > +
> > +   return 0;
> > +
> > +err_fdb_init:
> > +err_swdev_init:
> > +err_alloc_wq:
> > +   kfree(swdev);
> > +
> > +   return err;
> > +}
> > +
> > +void prestera_switchdev_fini(struct prestera_switch *sw)
> > +{
> > +   struct prestera_switchdev *swdev = sw->swdev;
> > +
> > +   prestera_fdb_fini(sw);
> > +   prestera_switchdev_handler_fini(swdev);
> > +   destroy_workqueue(swdev_wq);
> 
> this cleanup is also needed on the error path of prestera_switchdev_init
> 

Thanks! I will fix it.

> > +   kfree(swdev);
> > +}


Re: [PATCH net v6 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-04 Thread Vadym Kochan
On Thu, Sep 03, 2020 at 06:35:34PM +0300, Andy Shevchenko wrote:
> On Thu, Sep 3, 2020 at 6:23 PM Willem de Bruijn
>  wrote:
> > On Wed, Sep 2, 2020 at 5:37 PM Vadym Kochan  
> > wrote:
> 
> ...
> 
> > > +static int prestera_is_valid_mac_addr(struct prestera_port *port, u8 
> > > *addr)
> > > +{
> > > +   if (!is_valid_ether_addr(addr))
> > > +   return -EADDRNOTAVAIL;
> > > +
> > > +   if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))
> >
> > Why ETH_ALEN - 1?
> 
> We even have a lot of helpers specifically for ethernet MACs.
> Starting from [1] till almost the end of the file. Here [2] can be
> used (or its unaligned counterpart).
> 
> [1]: 
> https://elixir.bootlin.com/linux/latest/source/include/linux/etherdevice.h#L67
> [2]: 
> https://elixir.bootlin.com/linux/latest/source/include/linux/etherdevice.h#L67
> 
> > > +   return -EINVAL;
> > > +
> > > +   return 0;
> > > +}
> 
> > > +   memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
> >
> > Is addr_len ever not ETH_ALEN for this device?
> 
> And if it is ETH_ALEN, here is [3].
> [3]: 
> https://elixir.bootlin.com/linux/latest/source/include/linux/etherdevice.h#L287

Thanks Andy, I missed this one to replace with ether_addr_copy().

> 
> -- 
> With Best Regards,
> Andy Shevchenko


Re: [PATCH net v6 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-04 Thread Vadym Kochan
Hi Willem,

On Thu, Sep 03, 2020 at 05:22:24PM +0200, Willem de Bruijn wrote:
> On Wed, Sep 2, 2020 at 5:37 PM Vadym Kochan  wrote:
> >
> > Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
> > ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> > wireless SMB deployment.
> >
> > The current implementation supports only boards designed for the Marvell
> > Switchdev solution and requires special firmware.
> >
> > The core Prestera switching logic is implemented in prestera_main.c,
> > there is an intermediate hw layer between core logic and firmware. It is
> > implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> > related logic, in future there is a plan to support more devices with
> > different HW related configurations.
> >
> > This patch contains only basic switch initialization and RX/TX support
> > over SDMA mechanism.
> >
> > Currently supported devices have DMA access range <= 32bit and require
> > ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
> > allocated in proper range supported by the Prestera device.
> >
> > Also meanwhile there is no TX interrupt support in current firmware
> > version so recycling work is scheduled on each xmit.
> >
> > Port's mac address is generated from the switch base mac which may be
> > provided via device-tree (static one or as nvme cell), or randomly
> > generated.
> >
> > Co-developed-by: Andrii Savka 
> > Signed-off-by: Andrii Savka 
> > Co-developed-by: Oleksandr Mazur 
> > Signed-off-by: Oleksandr Mazur 
> > Co-developed-by: Serhiy Boiko 
> > Signed-off-by: Serhiy Boiko 
> > Co-developed-by: Serhiy Pshyk 
> > Signed-off-by: Serhiy Pshyk 
> > Co-developed-by: Taras Chornyi 
> > Signed-off-by: Taras Chornyi 
> > Co-developed-by: Volodymyr Mytnyk 
> > Signed-off-by: Volodymyr Mytnyk 
> > Signed-off-by: Vadym Kochan 
> 
> > +int prestera_hw_port_cap_get(const struct prestera_port *port,
> > +struct prestera_port_caps *caps)
> > +{
> > +   struct prestera_msg_port_attr_resp resp;
> > +   struct prestera_msg_port_attr_req req = {
> > +   .attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
> > +   .port = port->hw_id,
> > +   .dev = port->dev_id
> > +   };
> > +   int err;
> > +
> > +   err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
> > +  , sizeof(req), , 
> > sizeof(resp));
> 
> Here and elsewhere, why use a pointer to the first field in the struct
> vs the struct itself?
> 
> They are the same address, so it's fine, just a bit confusing as the
> size argument makes clear that the entire struct is to be copied.
> 
Well, initially it was a macro to simplify passing the different kind of
request structure. But after review I changed it to a function. The
struct prestera_msg_cmd is a common for all of the fw requests which
have to include it at the beginning. Eventually __prestera_cmd_ret() is
called to pass request buffer to the fw and struct prestera_msg_cmd is
used to check the response from fw. I can use 'void *' and typecast it
to struct prestera_msg_cmd but I'd like to keep type safety. 

> > +static int prestera_is_valid_mac_addr(struct prestera_port *port, u8 *addr)
> > +{
> > +   if (!is_valid_ether_addr(addr))
> > +   return -EADDRNOTAVAIL;
> > +
> > +   if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))
> 
> Why ETH_ALEN - 1?
> 
This is the restriction of the port mac address, it must have base mac
address part at first 5 bytes.

> > +   return -EINVAL;
> > +
> > +   return 0;
> > +}
> > +
> > +static int prestera_port_set_mac_address(struct net_device *dev, void *p)
> > +{
> > +   struct prestera_port *port = netdev_priv(dev);
> > +   struct sockaddr *addr = p;
> > +   int err;
> > +
> > +   err = prestera_is_valid_mac_addr(port, addr->sa_data);
> > +   if (err)
> > +   return err;
> > +
> > +   err = prestera_hw_port_mac_set(port, addr->sa_data);
> > +   if (err)
> > +   return err;
> > +
> > +   memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
> 
> Is addr_len ever not ETH_ALEN for this device?

I will fix it to use ether_addr_copy.

> 
> > +static int prestera_sdma_buf_init(struct prestera_sdma *sdma,
> > + struct prestera_sdma_buf *buf)
> > +{
&g

Re: [PATCH net v6 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX3255 (AC3x)

2020-09-02 Thread Vadym Kochan
Sorry, I mistakenly used "net" instead of "net-next" as label.

On Wed, Sep 02, 2020 at 06:04:36PM +0300, Vadym Kochan wrote:
> Marvell Prestera 98DX3255 integrates up to 24 ports of 1GbE with 8
> ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> wireless SMB deployment.
> 
> Prestera Switchdev is a firmware based driver that operates via PCI bus.  The
> current implementation supports only boards designed for the Marvell Switchdev
> solution and requires special firmware.
> 
> This driver implementation includes only L1, basic L2 support, and RX/TX.
> 
> The core Prestera switching logic is implemented in prestera_main.c, there is
> an intermediate hw layer between core logic and firmware. It is
> implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> related logic, in future there is a plan to support more devices with
> different HW related configurations.
> 
> The following Switchdev features are supported:
> 
> - VLAN-aware bridge offloading
> - VLAN-unaware bridge offloading
> - FDB offloading (learning, ageing)
> - Switchport configuration
> 
> The original firmware image is uploaded to the linux-firmware repository.
> 
> PATCH v6:
> 1) Use rwlock to protect port list on create/delete stages. The list
>is mostly readable by fw event handler or packets receiver, but
>updated only on create/delete port which are performed on switch 
> init/fini
>stages.
> 
> 2) Remove not needed variable initialization in 
> prestera_dsa.c:prestera_dsa_parse()
> 
> 3) Get rid of bounce buffer used by tx handler in prestera_rxtx.c,
>the bounce buffer should be handled by dma_xxx API via swiotlb.
> 
> 4) Fix PRESTERA_SDMA_RX_DESC_PKT_LEN macro by using correct GENMASK(13, 
> 0) in prestera_rxtx.c
> 
> Patches updated:
> [1] net: marvell: prestera: Add driver for Prestera family ASIC 
> devices
> 
> PATCH v5:
> 0) add Co-developed tags for people who was involved in development.
> 
> 1) Make SPDX license as separate comment
> 
> 2) Change 'u8 *' -> 'void *', It allows to avoid not-needed u8* casting.
> 
> 3) Remove "," in terminated enum's.
> 
> 4) Use GENMASK(end, start) where it is applicable in.
> 
> 5) Remove not-needed 'u8 *' casting.
> 
> 6) Apply common error-check pattern
> 
> 7) Use ether_addr_copy instead of memcpy
> 
> 8) Use define for maximum MAC address range (255)
> 
> 9) Simplify prestera_port_state_set() in prestera_main.c by
>using separate if-blocks for state setting:
> 
> if (is_up) {
> ...
> } else {
> ...
> }
> 
>   which makes logic more understandable.
> 
> 10) Simplify sdma tx wait logic when checking/updating tx_ring->burst.
> 
> 11) Remove not-needed packed & aligned attributes
> 
> 12) Use USEC_PER_MSEC as multiplier when converting ms -> usec on calling
> readl_poll_timeout.
> 
> 13) Simplified some error path handling by simple return error code in.
> 
> 14) Remove not-needed err assignment in.
> 
> 15) Use dev_err() in prestera_devlink_register(...).
> 
> Patches updated:
> [1] net: marvell: prestera: Add driver for Prestera family ASIC 
> devices
>   [2] net: marvell: prestera: Add PCI interface support
> [3] net: marvell: prestera: Add basic devlink support
>   [4] net: marvell: prestera: Add ethtool interface support
>   [5] net: marvell: prestera: Add Switchdev driver implementation
> 
> PATCH v4:
> 1) Use prestera_ prefix in netdev_ops variable.
> 
> 2) Kconfig: use 'default PRESTERA' build type for CONFIG_PRESTERA_PCI to 
> be
>synced by default with prestera core module.
> 
> 3) Use memcpy_xxio helpers in prestera_pci.c for IO buffer copying.
> 
> 4) Generate fw image path via snprintf() instead of macroses.
> 
> 5) Use pcim_ helpers in prestera_pci.c which simplified the
>probe/remove logic.
> 
> 6) Removed not needed initializations of variables which are used in
>readl_poll_xxx() helpers.
> 
> 7) Fixed few grammar mistakes in patch[2] description.
> 
> 8) Export only prestera_ethtool_ops struct instead of each
>ethtool handler.
> 
> 9) Add check for prestera_dev_check() in switchdev event handling to
>make sure there is no wrong topology.
> 
> Patches updated:
> [1] net: marvell: prestera: Add driver for Prestera family ASIC 
> devices
>   [2] net: marvell: prestera: Add PCI interface support
>   [4] n

[PATCH net v6 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-09-02 Thread Vadym Kochan
Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
wireless SMB deployment.

The current implementation supports only boards designed for the Marvell
Switchdev solution and requires special firmware.

The core Prestera switching logic is implemented in prestera_main.c,
there is an intermediate hw layer between core logic and firmware. It is
implemented in prestera_hw.c, the purpose of it is to encapsulate hw
related logic, in future there is a plan to support more devices with
different HW related configurations.

This patch contains only basic switch initialization and RX/TX support
over SDMA mechanism.

Currently supported devices have DMA access range <= 32bit and require
ZONE_DMA to be enabled, for such cases SDMA driver checks if the skb
allocated in proper range supported by the Prestera device.

Also meanwhile there is no TX interrupt support in current firmware
version so recycling work is scheduled on each xmit.

Port's mac address is generated from the switch base mac which may be
provided via device-tree (static one or as nvme cell), or randomly
generated.

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Co-developed-by: Volodymyr Mytnyk 
Signed-off-by: Volodymyr Mytnyk 
Signed-off-by: Vadym Kochan 
---
PATCH v6:
1) Use rwlock to protect port list on create/delete stages. The list
   is mostly readable by fw event handler or packets receiver.

2) Remove not needed variable initialization in 
prestera_dsa.c:prestera_dsa_parse()

3) Get rid of bounce buffer allocation used by tx handler in 
prestera_rxtx.c,
   the bounce buffer should be handled by dma_xxx API via swiotlb.
   Changed only prestera_sdma_tx_buf_map() func.

4) Fix PRESTERA_SDMA_RX_DESC_PKT_LEN macro by using correct GENMASK(13, 0) 
in prestera_rxtx.c

PATCH v5:
1) Make SPDX license as separate comment

2) Change 'u8 *' -> 'void *' in prestera.h: struct 
prestera_device->{send_req,recv_msg} callbacks.
   It allows to avoid not-needed u8* casting.

3) Remove "," in terminated enum's.

4) Use GENMASK(end, start) where it is applicable in:
- prestera_dsa
- prestera_rxtx.c

5) Remove not-needed casting on FIELD_GET() macro usage in prestera_dsa.c

6) Simplify evt->id checking by using single if in prestera_hw.c: 
prestera_fw_parse_port_evt

7) Apply common error-check pattern

8) Use ether_addr_copy instead of memcpy

9) Use define for maximum MAC address range (255)

10) Simplify prestera_port_state_set() in prestera_main.c by
using separate if-blocks for state setting:

if (is_up) {
...
} else {
...
}

  which makes logic more understandable.

11) Use ms value for PRESTERA_STATS_DELAY_MS instead of jiffy

12) Remove empty lines in prestera_rxtx.c

13) Simplify sdma tx wait logic when checking/updating tx_ring->burst.

PATCH v4:
1) Use prestera_ prefix for netdev_ops struct var.

PATCH v3:
1) Simplify __be32 type casting in prestera_dsa.c: prestera_dsa_parse(...)

 drivers/net/ethernet/marvell/Kconfig  |   1 +
 drivers/net/ethernet/marvell/Makefile |   1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |  13 +
 .../net/ethernet/marvell/prestera/Makefile|   4 +
 .../net/ethernet/marvell/prestera/prestera.h  | 173 
 .../ethernet/marvell/prestera/prestera_dsa.c  | 106 +++
 .../ethernet/marvell/prestera/prestera_dsa.h  |  37 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 614 +
 .../ethernet/marvell/prestera/prestera_hw.h   |  72 ++
 .../ethernet/marvell/prestera/prestera_main.c | 522 +++
 .../ethernet/marvell/prestera/prestera_rxtx.c | 834 ++
 .../ethernet/marvell/prestera/prestera_rxtx.h |  21 +
 12 files changed, 2398 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_main.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.h

diff --git a/drivers/net/ethernet/marvell/Kconfig 
b/drivers/net/ethernet/marvell/Kconfig
index ef4f35ba077d..892e5c8ff096

[PATCH net v6 2/6] net: marvell: prestera: Add PCI interface support

2020-09-02 Thread Vadym Kochan
Add PCI interface driver for Prestera Switch ASICs family devices, which
provides:

- Firmware loading mechanism
- Requests & events handling to/from the firmware
- Access to the firmware on the bus level

The firmware has to be loaded each time the device is reset. The driver
is loading it from:

/lib/firmware/marvell/prestera_fw-v{MAJOR}.{MINOR}.img

The full firmware image version is located within the internal header
and consists of 3 numbers - MAJOR.MINOR.PATCH. Additionally, driver has
hard-coded minimum supported firmware version which it can work with:

MAJOR - reflects the support on ABI level between driver and loaded
firmware, this number should be the same for driver and loaded
firmware.

MINOR - this is the minimum supported version between driver and the
firmware.

PATCH - indicates only fixes, firmware ABI is not changed.

Firmware image file name contains only MAJOR and MINOR numbers to make
driver be compatible with any PATCH version.

Co-developed-by: Oleksandr Mazur 
Signed-off-by: Oleksandr Mazur 
Signed-off-by: Vadym Kochan 
---
PATCH v5:
1) Remove not-needed packed & aligned attributes

2) Convert 'u8 *' to 'void *' on path when handling/calling 
send_req/recv_msg
   callback. This allows to remove not-needed 'u8 *' casting.

3) Use USEC_PER_MSEC as multiplier when converting ms -> usec on calling
   readl_poll_timeout.

4) Removed pci_dev member from prestera_fw, there is already 'struct
   prestera_dev' which holds pointer to 'struct device'.

5) Replace pci_err (added in the previous patch) by dev_err.

PATCH v4:
1) Get rid of "packed" attribute for the fw image header, it is
   already aligned.

2) Cleanup not needed initialization of variables which are used in
   readl_poll_timeout() helpers.

3) Replace #define's of prestera_{fw,ldr}_{read,write} to static funcs.

4) Use pcim_ helpers for resource allocation

5) Use devm_zalloc() for struct prestera_fw instance allocation.

6) Use module_pci_driver(prestera_pci_driver) instead of module_{init,exit}.

7) Use _MS prefix for timeout #define's.

8) Use snprintf for firmware image path generation instead of using
   macrosses.

9) Use memcpy_xxxio helpers for IO memory copying.

   10) By default use same build type ('m' or 'y') for
   CONFIG_PRESTERA_PCI which is used by CONFIG_PRESTERA.

 drivers/net/ethernet/marvell/prestera/Kconfig |  11 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +
 .../ethernet/marvell/prestera/prestera_pci.c  | 778 ++
 3 files changed, 791 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_pci.c

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 76b68613ea7a..2a5945c455cc 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -11,3 +11,14 @@ config PRESTERA
 
  To compile this driver as a module, choose M here: the
  module will be called prestera.
+
+config PRESTERA_PCI
+   tristate "PCI interface driver for Marvell Prestera Switch ASICs family"
+   depends on PCI && HAS_IOMEM && PRESTERA
+   default PRESTERA
+   help
+ This is implementation of PCI interface support for Marvell Prestera
+ Switch ASICs family.
+
+ To compile this driver as a module, choose M here: the
+ module will be called prestera_pci.
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 610d75032b78..2146714eab21 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
   prestera_rxtx.o
+
+obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c 
b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
new file mode 100644
index ..898e0a52d78c
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "prestera.h"
+
+#define PRESTERA_MSG_MAX_SIZE 1500
+
+#define PRESTERA_SUPP_FW_MAJ_VER   2
+#define PRESTERA_SUPP_FW_MIN_VER   0
+
+#define PRESTERA_FW_PATH_FMT   "mrvl/prestera/mvsw_prestera_fw-v%u.%u.img"
+
+#define PRESTERA_FW_HDR_MAGIC  0x351D9D06
+#define PRESTERA_FW_DL_TIMEOUT_MS  5
+#define PRESTERA_FW_BLK_SZ 1024
+
+#define PRESTERA_FW_VER_MAJ_MUL 100
+#define

[PATCH net v6 3/6] net: marvell: prestera: Add basic devlink support

2020-09-02 Thread Vadym Kochan
Add very basic support for devlink interface:

- driver name
- fw version
- devlink ports

Signed-off-by: Vadym Kochan 
---
PATCH v5:
1) Simplified some error path handling by simple return error code in:

   - prestera_dl_info_get(...)

2) Remove not-needed err assignment in:
   - prestera_dl_info_get(...)

3) Use dev_err() in prestera_devlink_register(...).

 drivers/net/ethernet/marvell/prestera/Kconfig |   1 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   4 +
 .../marvell/prestera/prestera_devlink.c   | 114 ++
 .../marvell/prestera/prestera_devlink.h   |  26 
 .../ethernet/marvell/prestera/prestera_main.c |  28 -
 6 files changed, 170 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 2a5945c455cc..b1fcc44f566a 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -6,6 +6,7 @@
 config PRESTERA
tristate "Marvell Prestera Switch ASICs support"
depends on NET_SWITCHDEV && VLAN_8021Q
+   select NET_DEVLINK
help
  This driver supports Marvell Prestera Switch ASICs family.
 
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 2146714eab21..babd71fba809 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o
+  prestera_rxtx.o prestera_devlink.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 2efaa5abc3be..5e890897356e 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -11,6 +11,9 @@
 #include 
 #include 
 #include 
+#include 
+
+#define PRESTERA_DRV_NAME  "prestera"
 
 struct prestera_fw_rev {
u16 maj;
@@ -63,6 +66,7 @@ struct prestera_port_caps {
 struct prestera_port {
struct net_device *dev;
struct prestera_switch *sw;
+   struct devlink_port dl_port;
u32 id;
u32 hw_id;
u32 dev_id;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_devlink.c 
b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
new file mode 100644
index ..abbd08dad6ab
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+
+#include "prestera.h"
+#include "prestera_devlink.h"
+
+static int prestera_dl_info_get(struct devlink *dl,
+   struct devlink_info_req *req,
+   struct netlink_ext_ack *extack)
+{
+   struct prestera_switch *sw = devlink_priv(dl);
+   char buf[16];
+   int err;
+
+   err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME);
+   if (err)
+   return err;
+
+   snprintf(buf, sizeof(buf), "%d.%d.%d",
+sw->dev->fw_rev.maj,
+sw->dev->fw_rev.min,
+sw->dev->fw_rev.sub);
+
+   return devlink_info_version_running_put(req,
+  DEVLINK_INFO_VERSION_GENERIC_FW,
+  buf);
+}
+
+static const struct devlink_ops prestera_dl_ops = {
+   .info_get = prestera_dl_info_get,
+};
+
+struct prestera_switch *prestera_devlink_alloc(void)
+{
+   struct devlink *dl;
+
+   dl = devlink_alloc(_dl_ops, sizeof(struct prestera_switch));
+
+   return devlink_priv(dl);
+}
+
+void prestera_devlink_free(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_free(dl);
+}
+
+int prestera_devlink_register(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+   int err;
+
+   err = devlink_register(dl, sw->dev->dev);
+   if (err)
+   dev_err(sw->dev->dev, "devlink_register failed: %d\n", err);
+
+   return err;
+}
+
+void prestera_devlink_unregister(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_unregister(dl);
+}
+
+int prestera_devlink_port_register(struct prestera_port *port)
+{
+   struct dev

[PATCH net v6 6/6] dt-bindings: marvell,prestera: Add description for device-tree bindings

2020-09-02 Thread Vadym Kochan
Add brief description how to configure base mac address binding in
device-tree.

Describe requirement for the PCI port which is connected to the ASIC, to
allow access to the firmware related registers.

Signed-off-by: Vadym Kochan 
---
 .../bindings/net/marvell,prestera.txt | 34 +++
 1 file changed, 34 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/marvell,prestera.txt 
b/Documentation/devicetree/bindings/net/marvell,prestera.txt
index 83370ebf5b89..e28938ddfdf5 100644
--- a/Documentation/devicetree/bindings/net/marvell,prestera.txt
+++ b/Documentation/devicetree/bindings/net/marvell,prestera.txt
@@ -45,3 +45,37 @@ dfx-server {
ranges = <0 MBUS_ID(0x08, 0x00) 0 0x10>;
reg = ;
 };
+
+Marvell Prestera SwitchDev bindings
+---
+Optional properties:
+- compatible: must be "marvell,prestera"
+- base-mac-provider: describes handle to node which provides base mac address,
+   might be a static base mac address or nvme cell provider.
+
+Example:
+
+eeprom_mac_addr: eeprom-mac-addr {
+   compatible = "eeprom,mac-addr-cell";
+   status = "okay";
+
+   nvmem = <_at24>;
+};
+
+prestera {
+   compatible = "marvell,prestera";
+   status = "okay";
+
+   base-mac-provider = <_mac_addr>;
+};
+
+The current implementation of Prestera Switchdev PCI interface driver requires
+that BAR2 is assigned to 0xf600 as base address from the PCI IO range:
+
+_pcie0 {
+   ranges = <0x8100 0x0 0xfb00 0x0 0xfb00 0x0 0xf
+   0x8200 0x0 0xf600 0x0 0xf600 0x0 0x200
+   0x8200 0x0 0xf900 0x0 0xf900 0x0 0x10>;
+   phys = <_comphy0 0>;
+   status = "okay";
+};
-- 
2.17.1



[PATCH net v6 4/6] net: marvell: prestera: Add ethtool interface support

2020-09-02 Thread Vadym Kochan
The ethtool API provides support for the configuration of the following
features: speed and duplex, auto-negotiation, MDI-x, forward error
correction, port media type. The API also provides information about the
port status, hardware and software statistic. The following limitation
exists:

- port media type should be configured before speed setting
- ethtool -m option is not supported
- ethtool -p option is not supported
- ethtool -r option is supported for RJ45 port only
- the following combination of parameters is not supported:

  ethtool -s sw1pX port XX autoneg on

- forward error correction feature is supported only on SFP ports, 10G
  speed

- auto-negotiation and MDI-x features are not supported on
  Copper-to-Fiber SFP module

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Signed-off-by: Vadym Kochan 
---
PATCH v5:

1) Convert following error check:

if (func(...))
or
if (!func(...))

to use err variable:

err = func(...)
if (err)

2) Remove "," from terminated enum entry.

PATCH v4:
1) Export only prestera_ethtool_ops instead of
   each ethtool handler.

2) Get rid of not needed cast in prestera_ethtool_get_stats(...)
   when doing memcpy.

 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   3 +
 .../marvell/prestera/prestera_ethtool.c   | 759 ++
 .../marvell/prestera/prestera_ethtool.h   |  14 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 295 ++-
 .../ethernet/marvell/prestera/prestera_hw.h   |  65 ++
 .../ethernet/marvell/prestera/prestera_main.c |  28 +-
 7 files changed, 1159 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index babd71fba809..7684e7047562 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o
+  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 5e890897356e..9a5a0deb909b 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -174,4 +174,7 @@ void prestera_device_unregister(struct prestera_device 
*dev);
 struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
 u32 dev_id, u32 hw_id);
 
+int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
+ u64 adver_link_modes, u8 adver_fec);
+
 #endif /* _PRESTERA_H_ */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c 
b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
new file mode 100644
index ..d947c09ce134
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
@@ -0,0 +1,759 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+
+#include "prestera.h"
+#include "prestera_hw.h"
+#include "prestera_ethtool.h"
+
+#define PRESTERA_STATS_CNT \
+   (sizeof(struct prestera_port_stats) / sizeof(u64))
+#define PRESTERA_STATS_IDX(name) \
+   (offsetof(struct prestera_port_stats, name) / sizeof(u64))
+#define PRESTERA_STATS_FIELD(name) \
+   [PRESTERA_STATS_IDX(name)] = __stringify(name)
+
+static const char driver_kind[] = "prestera";
+
+static const struct prestera_link_mode {
+   enum ethtool_link_mode_bit_indices eth_mode;
+   u32 speed;
+   u64 pr_mask;
+   u8 duplex;
+   u8 port_type;
+} port_link_modes[PRESTERA_LINK_MODE_MAX] = {
+   [PRESTERA_LINK_MODE_10baseT_Half] = {
+   .eth_mode =  ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+   .speed = 10,
+   .pr_mask = 1 << PRESTERA_LINK_MODE_10baseT_Half,
+   .duplex = PRESTERA_PORT_DUPLEX_HALF,
+   .port_type = PRESTERA_PORT_TYPE_TP,
+   },
+   [PRESTERA_LINK_MODE_10baseT_Full] = {
+   .eth_mode =  ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+   .speed = 10,
+   .pr_mask = 1 << PRESTERA_LINK_MODE_10baseT_Full,
+   .duplex = PRESTERA_PORT_D

[PATCH net v6 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-09-02 Thread Vadym Kochan
The following features are supported:

- VLAN-aware bridge offloading
- VLAN-unaware bridge offloading
- FDB offloading (learning, ageing)
- Switchport configuration

Currently there are some limitations like:

- Only 1 VLAN-aware bridge instance supported
- FDB ageing timeout parameter is set globally per device

Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Signed-off-by: Vadym Kochan 
---
PATCH v5:
0) Add Co-developed tag.

1) Remove "," from terminated enum entry.

2) Replace 'u8 *' -> 'void *' in prestera_fw_parse_fdb_evt(...)

3) Use ether_addr_copy() in prestera_fw_parse_fdb_evt(...)

PATCH v4:
1) Check for the prestera dev interface in switchdev event handler
   to ignore unsupported topology.

 .../net/ethernet/marvell/prestera/Makefile|3 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   33 +-
 .../ethernet/marvell/prestera/prestera_hw.c   |  322 +++-
 .../ethernet/marvell/prestera/prestera_hw.h   |   48 +
 .../ethernet/marvell/prestera/prestera_main.c |  111 +-
 .../marvell/prestera/prestera_switchdev.c | 1289 +
 .../marvell/prestera/prestera_switchdev.h |   16 +
 7 files changed, 1815 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 7684e7047562..93129e32ebc5 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
+  prestera_rxtx.o prestera_devlink.o 
prestera_ethtool.o \
+  prestera_switchdev.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 9a5a0deb909b..83df4695dc12 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -15,6 +15,8 @@
 
 #define PRESTERA_DRV_NAME  "prestera"
 
+#define PRESTERA_DEFAULT_VID1
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -51,8 +53,6 @@ struct prestera_port_stats {
u64 unicast_frames_sent;
u64 sent_multiple;
u64 sent_deferred;
-   u64 frames_1024_to_1518_octets;
-   u64 frames_1519_to_max_octets;
u64 good_octets_sent;
 };
 
@@ -71,11 +71,13 @@ struct prestera_port {
u32 hw_id;
u32 dev_id;
u16 fp_id;
+   u16 pvid;
bool autoneg;
u64 adver_link_modes;
u8 adver_fec;
struct prestera_port_caps caps;
struct list_head list;
+   struct list_head vlans_list;
struct {
struct prestera_port_stats stats;
struct delayed_work caching_dw;
@@ -105,6 +107,7 @@ enum prestera_event_type {
PRESTERA_EVENT_TYPE_UNSPEC,
 
PRESTERA_EVENT_TYPE_PORT,
+   PRESTERA_EVENT_TYPE_FDB,
PRESTERA_EVENT_TYPE_RXTX,
 
PRESTERA_EVENT_TYPE_MAX
@@ -127,19 +130,37 @@ struct prestera_port_event {
} data;
 };
 
+enum prestera_fdb_event_id {
+   PRESTERA_FDB_EVENT_UNSPEC,
+   PRESTERA_FDB_EVENT_LEARNED,
+   PRESTERA_FDB_EVENT_AGED,
+};
+
+struct prestera_fdb_event {
+   u32 port_id;
+   u32 vid;
+   union {
+   u8 mac[ETH_ALEN];
+   } data;
+};
+
 struct prestera_event {
u16 id;
union {
struct prestera_port_event port_evt;
+   struct prestera_fdb_event fdb_evt;
};
 };
 
+struct prestera_switchdev;
 struct prestera_rxtx;
 
 struct prestera_switch {
struct prestera_device *dev;
+   struct prestera_switchdev *swdev;
struct prestera_rxtx *rxtx;
struct list_head event_handlers;
+   struct notifier_block netdev_nb;
char base_mac[ETH_ALEN];
struct list_head port_list;
rwlock_t port_list_lock;
@@ -177,4 +198,12 @@ struct prestera_port *prestera_port_find_by_hwid(struct 
prestera_switch *sw,
 int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
  u64 adver_link_modes, u8 adver_fec);
 
+struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id);
+
+struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
+
+int prestera_port_pvid_set(struct prestera_port *port, u16 vid);
+
+bool prestera_netdev_check(const struct net_device *dev);
+
 #endif /* _PR

[PATCH net v6 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX3255 (AC3x)

2020-09-02 Thread Vadym Kochan
 now.

7) Little spelling corrections in the error/info messages.

8) Make pci probe & remove logic mirrored.

9) Get rid of ETH_FCS_LEN in headroom setting, not needed.

PATCH:
1) Fixed W=1 warnings

2) Renamed PCI driver name to be more generic "Prestera DX" because
   there will be more devices supported.

3) Changed firmware image dir path: marvell/ -> mrvl/prestera/
   to be aligned with location in linux-firmware.git (if such
   will be accepted).

RFC v3:
1) Fix prestera prefix in prestera_rxtx.c

2) Protect concurrent access from multiple ports on multiple CPU system
   on tx path by spinlock in prestera_rxtx.c

3) Try to get base mac address from device-tree, otherwise use a random 
generated one.

4) Move ethtool interface support into separate prestera_ethtool.c file.

5) Add basic devlink support and get rid of physical port naming ops.

6) Add STP support in Switchdev driver.

7) Removed MODULE_AUTHOR

8) Renamed prestera.c -> prestera_main.c, and kernel module to
   prestera.ko

RFC v2:
1) Use "pestera_" prefix in struct's and functions instead of mvsw_pr_

2) Original series split into additional patches for Switchdev ethtool 
support.

3) Use major and minor firmware version numbers in the firmware image 
filename.

4) Removed not needed prints.

5) Use iopoll API for waiting on register's value in prestera_pci.c

6) Use standart approach for describing PCI ID matching section instead of 
using
   custom wrappers in prestera_pci.c

7) Add RX/TX support in prestera_rxtx.c.

8) Rewritten prestera_switchdev.c with following changes:
   - handle netdev events from prestera.c

   - use struct prestera_bridge for bridge objects, and get rid of
 struct prestera_bridge_device which may confuse.

   - use refcount_t

9) Get rid of macro usage for sending fw requests in prestera_hw.c

10) Add base_mac setting as module parameter. base_mac is required for
generation default port's mac.

Vadym Kochan (6):
  net: marvell: prestera: Add driver for Prestera family ASIC devices
  net: marvell: prestera: Add PCI interface support
  net: marvell: prestera: Add basic devlink support
  net: marvell: prestera: Add ethtool interface support
  net: marvell: prestera: Add Switchdev driver implementation
  dt-bindings: marvell,prestera: Add description for device-tree
bindings

 .../bindings/net/marvell,prestera.txt |   34 +
 drivers/net/ethernet/marvell/Kconfig  |1 +
 drivers/net/ethernet/marvell/Makefile |1 +
 drivers/net/ethernet/marvell/prestera/Kconfig |   25 +
 .../net/ethernet/marvell/prestera/Makefile|7 +
 .../net/ethernet/marvell/prestera/prestera.h  |  209 +++
 .../marvell/prestera/prestera_devlink.c   |  114 ++
 .../marvell/prestera/prestera_devlink.h   |   26 +
 .../ethernet/marvell/prestera/prestera_dsa.c  |  106 ++
 .../ethernet/marvell/prestera/prestera_dsa.h  |   37 +
 .../marvell/prestera/prestera_ethtool.c   |  759 ++
 .../marvell/prestera/prestera_ethtool.h   |   14 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 1227 
 .../ethernet/marvell/prestera/prestera_hw.h   |  185 +++
 .../ethernet/marvell/prestera/prestera_main.c |  665 +
 .../ethernet/marvell/prestera/prestera_pci.c  |  778 ++
 .../ethernet/marvell/prestera/prestera_rxtx.c |  834 +++
 .../ethernet/marvell/prestera/prestera_rxtx.h |   21 +
 .../marvell/prestera/prestera_switchdev.c | 1289 +
 .../marvell/prestera/prestera_switchdev.h |   16 +
 20 files changed, 6348 insertions(+)
 create mode 100644 drivers/net/ethernet/marvell/prestera/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/prestera/Makefile
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_dsa.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_hw.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_main.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_pci.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_rxtx.h
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

-- 
2.17.1



Re: [PATCH v3 3/3] misc: eeprom: at24: register nvmem only after eeprom is ready to use

2020-08-31 Thread Vadym Kochan
Hi Bartosz,

On Mon, Aug 31, 2020 at 07:21:39PM +0200, Bartosz Golaszewski wrote:
> On Mon, Aug 31, 2020 at 3:56 AM Vadym Kochan  wrote:
> >
> > During nvmem_register() the nvmem core sends notifications when:
> >
> > - cell added
> > - nvmem added
> >
> > and during these notifications some callback func may access the nvmem
> > device, which will fail in case of at24 eeprom because regulator and pm
> > are enabled after nvmem_register().
> >
> > Signed-off-by: Vadym Kochan 
> > ---
> > v3:
> > 1) at24 driver enables regulator and pm state machine after nvmem
> >registration which does not allow to use it on handing NVMEM_PRE_ADD 
> > event.
> >
> >  drivers/misc/eeprom/at24.c | 11 +++
> >  1 file changed, 7 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
> > index 2591c21b2b5d..26a23abc053d 100644
> > --- a/drivers/misc/eeprom/at24.c
> > +++ b/drivers/misc/eeprom/at24.c
> > @@ -692,10 +692,6 @@ static int at24_probe(struct i2c_client *client)
> > nvmem_config.word_size = 1;
> > nvmem_config.size = byte_len;
> >
> > -   at24->nvmem = devm_nvmem_register(dev, _config);
> > -   if (IS_ERR(at24->nvmem))
> > -   return PTR_ERR(at24->nvmem);
> > -
> > i2c_set_clientdata(client, at24);
> >
> > err = regulator_enable(at24->vcc_reg);
> > @@ -708,6 +704,13 @@ static int at24_probe(struct i2c_client *client)
> > pm_runtime_set_active(dev);
> > pm_runtime_enable(dev);
> >
> > +   at24->nvmem = devm_nvmem_register(dev, _config);
> > +   if (IS_ERR(at24->nvmem)) {
> > +   pm_runtime_disable(dev);
> > +   regulator_disable(at24->vcc_reg);
> > +   return PTR_ERR(at24->nvmem);
> > +   }
> > +
> > /*
> >  * Perform a one-byte test read to verify that the
> >  * chip is functional.
> > --
> > 2.17.1
> >
> 
> Good catch! Thanks for the patch. Can I queue it for fixes
> independently from the earlier patches in this series?
> 
> Bart

Sure.

Regards,
Vadym Kochan


[PATCH v3 3/3] misc: eeprom: at24: register nvmem only after eeprom is ready to use

2020-08-30 Thread Vadym Kochan
During nvmem_register() the nvmem core sends notifications when:

- cell added
- nvmem added

and during these notifications some callback func may access the nvmem
device, which will fail in case of at24 eeprom because regulator and pm
are enabled after nvmem_register().

Signed-off-by: Vadym Kochan 
---
v3:
1) at24 driver enables regulator and pm state machine after nvmem
   registration which does not allow to use it on handing NVMEM_PRE_ADD 
event.

 drivers/misc/eeprom/at24.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 2591c21b2b5d..26a23abc053d 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -692,10 +692,6 @@ static int at24_probe(struct i2c_client *client)
nvmem_config.word_size = 1;
nvmem_config.size = byte_len;
 
-   at24->nvmem = devm_nvmem_register(dev, _config);
-   if (IS_ERR(at24->nvmem))
-   return PTR_ERR(at24->nvmem);
-
i2c_set_clientdata(client, at24);
 
err = regulator_enable(at24->vcc_reg);
@@ -708,6 +704,13 @@ static int at24_probe(struct i2c_client *client)
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
 
+   at24->nvmem = devm_nvmem_register(dev, _config);
+   if (IS_ERR(at24->nvmem)) {
+   pm_runtime_disable(dev);
+   regulator_disable(at24->vcc_reg);
+   return PTR_ERR(at24->nvmem);
+   }
+
/*
 * Perform a one-byte test read to verify that the
 * chip is functional.
-- 
2.17.1



[PATCH v3 2/3] nvmem: add ONIE NVMEM cells support

2020-08-30 Thread Vadym Kochan
ONIE is a small operating system, pre-installed on bare metal network
switches, that provides an environment for automated provisioning.

This system requires that NVMEM (EEPROM) device holds various system
information (mac address, platform name, etc) in a special TLV layout.

The driver registers ONIE TLV attributes as NVMEM cells which can be
accessed by other platform driver. Also it allows to use
of_get_mac_address() to retrieve mac address for the netdev.

Signed-off-by: Vadym Kochan 
---
v3:
1) Update onie-cells.c by using nvmem notification to parse and
   register cells before device and cells are finally registered.

2) Use subsys_init() macro which allows to probe before nvmem drivers.

 drivers/nvmem/Kconfig  |   9 +
 drivers/nvmem/Makefile |   3 +
 drivers/nvmem/onie-cells.c | 410 +
 3 files changed, 422 insertions(+)
 create mode 100644 drivers/nvmem/onie-cells.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 954d3b4a52ab..922d753519f7 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -270,4 +270,13 @@ config SPRD_EFUSE
  This driver can also be built as a module. If so, the module
  will be called nvmem-sprd-efuse.
 
+config NVMEM_ONIE_CELLS
+   bool "ONIE TLV cells support"
+   help
+ This is a driver to provide cells from ONIE TLV structure stored
+ on NVME device.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-onie-cells.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index a7c377218341..2199784a489f 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -55,3 +55,6 @@ obj-$(CONFIG_NVMEM_ZYNQMP)+= nvmem_zynqmp_nvmem.o
 nvmem_zynqmp_nvmem-y   := zynqmp_nvmem.o
 obj-$(CONFIG_SPRD_EFUSE)   += nvmem_sprd_efuse.o
 nvmem_sprd_efuse-y := sprd-efuse.o
+
+obj-$(CONFIG_NVMEM_ONIE_CELLS) += nvmem-onie-cells.o
+nvmem-onie-cells-y := onie-cells.o
diff --git a/drivers/nvmem/onie-cells.c b/drivers/nvmem/onie-cells.c
new file mode 100644
index ..bbb1e421f67c
--- /dev/null
+++ b/drivers/nvmem/onie-cells.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ONIE NVMEM cells provider
+ *
+ * Author: Vadym Kochan 
+ */
+
+#define ONIE_NVMEM_DRVNAME "onie-nvmem-cells"
+
+#define pr_fmt(fmt) ONIE_NVMEM_DRVNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ONIE_NVMEM_TLV_MAX_LEN 2048
+
+#define ONIE_NVMEM_HDR_ID  "TlvInfo"
+
+struct onie_nvmem_hdr {
+   u8 id[8];
+   u8 version;
+   __be16 data_len;
+} __packed;
+
+struct onie_nvmem_tlv {
+   u8 type;
+   u8 len;
+   u8 val[0];
+} __packed;
+
+struct onie_nvmem_attr {
+   struct list_head head;
+   const char *name;
+   unsigned int offset;
+   unsigned int len;
+};
+
+struct onie_nvmem {
+   struct platform_device *pdev;
+   struct notifier_block nvmem_nb;
+   unsigned int attr_count;
+   struct list_head attrs;
+   struct kref refcnt;
+   const char *nvmem_match;
+
+   struct nvmem_cell_lookup *cell_lookup;
+   struct nvmem_cell_table cell_tbl;
+   struct nvmem_device *nvmem;
+};
+
+static bool onie_nvmem_hdr_is_valid(struct onie_nvmem_hdr *hdr)
+{
+   if (memcmp(hdr->id, ONIE_NVMEM_HDR_ID, sizeof(hdr->id)) != 0)
+   return false;
+   if (hdr->version != 0x1)
+   return false;
+
+   return true;
+}
+
+static void onie_nvmem_attrs_free(struct onie_nvmem *onie)
+{
+   struct onie_nvmem_attr *attr, *tmp;
+
+   list_for_each_entry_safe(attr, tmp, >attrs, head) {
+   list_del(>head);
+   kfree(attr);
+   }
+}
+
+static const char *onie_nvmem_attr_name(u8 type)
+{
+   switch (type) {
+   case 0x21: return "product-name";
+   case 0x22: return "part-number";
+   case 0x23: return "serial-number";
+   case 0x24: return "mac-address";
+   case 0x25: return "manufacture-date";
+   case 0x26: return "device-version";
+   case 0x27: return "label-revision";
+   case 0x28: return "platforn-name";
+   case 0x29: return "onie-version";
+   case 0x2A: return "num-macs";
+   case 0x2B: return "manufacturer";
+   case 0x2C: return "country-code";
+   case 0x2D: return "vendor";
+   case 0x2E: return "diag-version";
+   case 0x2F: return "service-tag";
+   case 0xFD: return "vendor-extension";
+   case 0xFE: return "crc32";
+
+   default: return "unknown";
+   }
+}
+
+static int onie_nvmem_tlv_parse(struct onie_nvmem *onie, u8 *data, u16 len

[PATCH v3 1/3] nvmem: core: allow to register cells during nvmem registration

2020-08-30 Thread Vadym Kochan
Add NVMEM_PRE_ADD notification step which is called before any cells
binding - from lookup table or config, this allows to register cells
in some specific layout (tlv) which should be parsed first and then
registered. So there might be a cell parser driver which can register
lookup table during this notification step.

Signed-off-by: Vadym Kochan 
---
v3:
1) Update core.c changes by extending notification mechanism
   by adding new NVMEM_PRE_ADD event id which is called before lookup
   table cells binding, this allows for notification handler to
   register cells which require nvmem parsing.

 drivers/nvmem/core.c   | 2 ++
 include/linux/nvmem-consumer.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..c48a69e0ebbe 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -668,6 +668,8 @@ struct nvmem_device *nvmem_register(const struct 
nvmem_config *config)
goto err_device_del;
}
 
+   blocking_notifier_call_chain(_notifier, NVMEM_PRE_ADD, nvmem);
+
if (config->cells) {
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
if (rval)
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 052293f4cbdb..0f7107276756 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -50,6 +50,7 @@ enum {
NVMEM_REMOVE,
NVMEM_CELL_ADD,
NVMEM_CELL_REMOVE,
+   NVMEM_PRE_ADD,
 };
 
 #if IS_ENABLED(CONFIG_NVMEM)
-- 
2.17.1



[PATCH v3 0/3] nvmem: add ONIE NVMEM cells provider

2020-08-30 Thread Vadym Kochan
This series adds cells provider for the ONIE TLV attributes which are
stored on NVMEM device. It adds possibility to read the mac address (and
other info) by other drivers.

There is a special case for this driver that before registering cells
the nvmem device should be first parsed to read the TLV layout which
holds the cells data.

v3:
1) Update core.c changes by extending notification mechanism
   by adding new NVMEM_PRE_ADD event id which is called before lookup
   table cells binding, this allows for notification handler to
   register cells which require nvmem parsing.

2) Update onie-cells.c to use nvmem notification to parse and
   register cells before device and cells are finally registered.

   Use subsys_init() macro which allows to probe before nvmem drivers.

3) at24 driver enables regulator and pm state machine after nvmem
   registration which does not allow to use it on handing NVMEM_PRE_ADD 
event.

v2:
1) Fixed wrong memcmp comparison

Vadym Kochan (3):
  nvmem: core: allow to register cells during nvmem registration
  nvmem: add ONIE NVMEM cells support
  misc: eeprom: at24: register nvmem only after eeprom is ready to use

 drivers/misc/eeprom/at24.c |  11 +-
 drivers/nvmem/Kconfig  |   9 +
 drivers/nvmem/Makefile |   3 +
 drivers/nvmem/core.c   |   2 +
 drivers/nvmem/onie-cells.c | 410 +
 include/linux/nvmem-consumer.h |   1 +
 6 files changed, 432 insertions(+), 4 deletions(-)
 create mode 100644 drivers/nvmem/onie-cells.c

-- 
2.17.1



Re: [net-next v5 0/6] net: marvell: prestera: Add Switchdev driver for Prestera family ASIC device 98DX326x (AC3x)

2020-08-30 Thread Vadym Kochan
Hi Chris,

On Wed, Aug 26, 2020 at 04:30:35AM +, Chris Packham wrote:
> Hi Vadym,
> 
> On 26/08/20 12:20 am, Vadym Kochan wrote:
> > Marvell Prestera 98DX326x integrates up to 24 ports of 1GbE with 8
> > ports of 10GbE uplinks or 2 ports of 40Gbps stacking for a largely
> > wireless SMB deployment.
> I think there's a typo here or possibly in patch 1. The AC3x family has 
> model numbers 98DX3255, 98DX3256, 98DX3257, 98DX3258, 98DX3259, 
> 98DX3265, 98DX3268. I'm not sure which variant you're specifically 
> targeting but in patch 1 you add the PCI device 0xC804 which corresponds 
> to the 98DX3255.

Looks like I need fix the commit message to refer to hw id which is used
in PCI match table.

> > Prestera Switchdev is a firmware based driver that operates via PCI bus.  
> > The
> > current implementation supports only boards designed for the Marvell 
> > Switchdev
> > solution and requires special firmware.
> >
> > This driver implementation includes only L1, basic L2 support, and RX/TX.
> >
> > The core Prestera switching logic is implemented in prestera_main.c, there 
> > is
> > an intermediate hw layer between core logic and firmware. It is
> > implemented in prestera_hw.c, the purpose of it is to encapsulate hw
> > related logic, in future there is a plan to support more devices with
> > different HW related configurations.
> >
> > The following Switchdev features are supported:
> >
> >  - VLAN-aware bridge offloading
> >  - VLAN-unaware bridge offloading
> >  - FDB offloading (learning, ageing)
> >  - Switchport configuration
> >
> > The original firmware image is uploaded to the linux-firmware repository.
> >
> > PATCH v5:
> >  0) add Co-developed tags for people who was involved in development.
> >
> >  1) Make SPDX license as separate comment
> >
> >  2) Change 'u8 *' -> 'void *', It allows to avoid not-needed u8* 
> > casting.
> >
> >  3) Remove "," in terminated enum's.
> >
> >  4) Use GENMASK(end, start) where it is applicable in.
> >
> >  5) Remove not-needed 'u8 *' casting.
> >
> >  6) Apply common error-check pattern
> >
> >  7) Use ether_addr_copy instead of memcpy
> >
> >  8) Use define for maximum MAC address range (255)
> >
> >  9) Simplify prestera_port_state_set() in prestera_main.c by
> > using separate if-blocks for state setting:
> >  
> >  if (is_up) {
> >  ...
> >  } else {
> >  ...
> >  }
> >
> >which makes logic more understandable.
> >
> >  10) Simplify sdma tx wait logic when checking/updating tx_ring->burst.
> >
> >  11) Remove not-needed packed & aligned attributes
> >
> >  12) Use USEC_PER_MSEC as multiplier when converting ms -> usec on 
> > calling
> >  readl_poll_timeout.
> >
> >  13) Simplified some error path handling by simple return error code in.
> >
> >  14) Remove not-needed err assignment in.
> >
> >  15) Use dev_err() in prestera_devlink_register(...).
> >
> >  Patches updated:
> >  [1] net: marvell: prestera: Add driver for Prestera family ASIC 
> > devices
> > [2] net: marvell: prestera: Add PCI interface support
> >  [3] net: marvell: prestera: Add basic devlink support
> > [4] net: marvell: prestera: Add ethtool interface support
> > [5] net: marvell: prestera: Add Switchdev driver implementation
> >
> > PATCH v4:
> >  1) Use prestera_ prefix in netdev_ops variable.
> >
> >  2) Kconfig: use 'default PRESTERA' build type for CONFIG_PRESTERA_PCI 
> > to be
> > synced by default with prestera core module.
> >
> >  3) Use memcpy_xxio helpers in prestera_pci.c for IO buffer copying.
> >
> >  4) Generate fw image path via snprintf() instead of macroses.
> >
> >  5) Use pcim_ helpers in prestera_pci.c which simplified the
> > probe/remove logic.
> >
> >  6) Removed not needed initializations of variables which are used in
> > readl_poll_xxx() helpers.
> >
> >  7) Fixed few grammar mistakes in patch[2] description.
> >
> >  8) Export only prestera_ethtool_ops struct instead of each
> > ethtool handler.
> >
> >  9) Add check for prestera_dev_check() in switchdev event handling to
> > make sure there is no wrong topology.
> >
> > 

Re: [net-next v5 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-08-30 Thread Vadym Kochan
Hi David,

On Wed, Aug 26, 2020 at 07:34:46AM -0700, David Miller wrote:
> From: Vadym Kochan 
> Date: Wed, 26 Aug 2020 11:17:44 +0300
> 
> > Initially there was (in RFC patch set), not locking, but _rcu list API
> > used, because the port list is modified only by 1 writer when creating
> > the port or deleting it on switch uninit (the really theoretical case
> > which might happen is that event might be received at that time which
> > causes to loop over this list to find the port), as I understand
> > correctly list_add_rcu is safe to use with no additional locking if there 
> > is 1
> > writer and many readers ? So can I use back this approach ?
> 
> Are you really certain only one writer can exist at one time?

Yes, list_add() is called on:

prestera_pci_probe() -> prestera_device_register() -> 
prestera_switch_init() -> prestera_create_ports()

and list_del() is called on:

prestera_pci_remove() -> prestera_device_unregister() -> 
prestera_switch_fini() -> prestera_destroy_ports()

in all other cases the port_list is used for port lookup on rx or when
event is received from the fw. So I really think that at least RCU list
API might be used or rw lock. In early version the ports were creating
before fw event handlers registration, but in this version the ports are
creating after event handlers are registered so it really needs locking.

Regarding DMA comments, looks like I can get rid of those bounce buffer
handling because swiotlb can handle this ? In that case looks like just
DMA map/unmap and sync should be enough.

Regards,
Vadym Kochan


Re: [net-next v5 1/6] net: marvell: prestera: Add driver for Prestera family ASIC devices

2020-08-26 Thread Vadym Kochan
On Tue, Aug 25, 2020 at 05:20:03PM -0700, David Miller wrote:
> From: Vadym Kochan 
> Date: Tue, 25 Aug 2020 15:20:08 +0300
> 
> > +int prestera_dsa_parse(struct prestera_dsa *dsa, const u8 *dsa_buf)
> > +{
> > +   __be32 *dsa_words = (__be32 *)dsa_buf;
> > +   enum prestera_dsa_cmd cmd;
> > +   u32 words[4] = { 0 };
> > +   u32 field;
> > +
> > +   words[0] = ntohl(dsa_words[0]);
> > +   words[1] = ntohl(dsa_words[1]);
> > +   words[2] = ntohl(dsa_words[2]);
> > +   words[3] = ntohl(dsa_words[3]);
> 
> All 4 elements of words[] are explicitly and unconditionally set to something,
> so you don't need the "= { 0 }" initializer.

Right, will fix it.

> 
> > +   INIT_LIST_HEAD(>port_list);
> 
> What locking protects this list?
> 

Initially there was (in RFC patch set), not locking, but _rcu list API
used, because the port list is modified only by 1 writer when creating
the port or deleting it on switch uninit (the really theoretical case
which might happen is that event might be received at that time which
causes to loop over this list to find the port), as I understand
correctly list_add_rcu is safe to use with no additional locking if there is 1
writer and many readers ? So can I use back this approach ?

> > +   new_skb = alloc_skb(len, GFP_ATOMIC | GFP_DMA);
> > +   if (!new_skb)
> > +   goto err_alloc_skb;
> 
> This seems very costly to do copies on every packet.  There should be
> something in the dma_*() API that would allow you to avoid this.

There is a limitation on the DMA range. Current device can't handle
whole ZONE_DMA range, so there is a "backup" mechanism which copies the
entire packet if the mapping was failed or if the packet's mapped
address is out of this range, this is done on both rx and tx directions.

> 
> And since you just need the buffer to DMA map it into the device,
> allocating an entire SKB object is overkill.  You can instead just
> allocate a ring of TX bounce buffers once, and then you just copy
> each packet there.  No allocations per packet.

Yes, this makes sense, thanks.


[net-next v5 5/6] net: marvell: prestera: Add Switchdev driver implementation

2020-08-25 Thread Vadym Kochan
The following features are supported:

- VLAN-aware bridge offloading
- VLAN-unaware bridge offloading
- FDB offloading (learning, ageing)
- Switchport configuration

Currently there are some limitations like:

- Only 1 VLAN-aware bridge instance supported
- FDB ageing timeout parameter is set globally per device

Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Serhiy Pshyk 
Signed-off-by: Serhiy Pshyk 
Co-developed-by: Taras Chornyi 
Signed-off-by: Taras Chornyi 
Co-developed-by: Vadym Kochan 
Signed-off-by: Vadym Kochan 
---
PATCH v5:
0) Add Co-developed tag.

1) Remove "," from terminated enum entry.

2) Replace 'u8 *' -> 'void *' in prestera_fw_parse_fdb_evt(...)

3) Use ether_addr_copy() in prestera_fw_parse_fdb_evt(...)

PATCH v4:
1) Check for the prestera dev interface in switchdev event handler
   to ignore unsupported topology.

 .../net/ethernet/marvell/prestera/Makefile|3 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   33 +-
 .../ethernet/marvell/prestera/prestera_hw.c   |  322 +++-
 .../ethernet/marvell/prestera/prestera_hw.h   |   48 +
 .../ethernet/marvell/prestera/prestera_main.c |  111 +-
 .../marvell/prestera/prestera_switchdev.c | 1289 +
 .../marvell/prestera/prestera_switchdev.h |   16 +
 7 files changed, 1815 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_switchdev.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 7684e7047562..93129e32ebc5 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
+  prestera_rxtx.o prestera_devlink.o 
prestera_ethtool.o \
+  prestera_switchdev.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index b1fd0a1edad1..968ae36eac01 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -15,6 +15,8 @@
 
 #define PRESTERA_DRV_NAME  "prestera"
 
+#define PRESTERA_DEFAULT_VID1
+
 struct prestera_fw_rev {
u16 maj;
u16 min;
@@ -51,8 +53,6 @@ struct prestera_port_stats {
u64 unicast_frames_sent;
u64 sent_multiple;
u64 sent_deferred;
-   u64 frames_1024_to_1518_octets;
-   u64 frames_1519_to_max_octets;
u64 good_octets_sent;
 };
 
@@ -71,11 +71,13 @@ struct prestera_port {
u32 hw_id;
u32 dev_id;
u16 fp_id;
+   u16 pvid;
bool autoneg;
u64 adver_link_modes;
u8 adver_fec;
struct prestera_port_caps caps;
struct list_head list;
+   struct list_head vlans_list;
struct {
struct prestera_port_stats stats;
struct delayed_work caching_dw;
@@ -105,6 +107,7 @@ enum prestera_event_type {
PRESTERA_EVENT_TYPE_UNSPEC,
 
PRESTERA_EVENT_TYPE_PORT,
+   PRESTERA_EVENT_TYPE_FDB,
PRESTERA_EVENT_TYPE_RXTX,
 
PRESTERA_EVENT_TYPE_MAX
@@ -127,19 +130,37 @@ struct prestera_port_event {
} data;
 };
 
+enum prestera_fdb_event_id {
+   PRESTERA_FDB_EVENT_UNSPEC,
+   PRESTERA_FDB_EVENT_LEARNED,
+   PRESTERA_FDB_EVENT_AGED,
+};
+
+struct prestera_fdb_event {
+   u32 port_id;
+   u32 vid;
+   union {
+   u8 mac[ETH_ALEN];
+   } data;
+};
+
 struct prestera_event {
u16 id;
union {
struct prestera_port_event port_evt;
+   struct prestera_fdb_event fdb_evt;
};
 };
 
+struct prestera_switchdev;
 struct prestera_rxtx;
 
 struct prestera_switch {
struct prestera_device *dev;
+   struct prestera_switchdev *swdev;
struct prestera_rxtx *rxtx;
struct list_head event_handlers;
+   struct notifier_block netdev_nb;
char base_mac[ETH_ALEN];
struct list_head port_list;
u32 port_count;
@@ -176,4 +197,12 @@ struct prestera_port *prestera_port_find_by_hwid(struct 
prestera_switch *sw,
 int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
  u64 adver_link_modes, u8 adver_fec);
 
+struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id);
+
+struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);
+
+int prestera_port_pvid_set(struct prestera_port *port, u16 vid);
+
+bool prestera_netdev_check(const struct net_

[net-next v5 3/6] net: marvell: prestera: Add basic devlink support

2020-08-25 Thread Vadym Kochan
Add very basic support for devlink interface:

- driver name
- fw version
- devlink ports

Signed-off-by: Vadym Kochan 
---
PATCH v5:
1) Simplified some error path handling by simple return error code in:

   - prestera_dl_info_get(...)

2) Remove not-needed err assignment in:
   - prestera_dl_info_get(...)

3) Use dev_err() in prestera_devlink_register(...).

 drivers/net/ethernet/marvell/prestera/Kconfig |   1 +
 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   4 +
 .../marvell/prestera/prestera_devlink.c   | 114 ++
 .../marvell/prestera/prestera_devlink.h   |  26 
 .../ethernet/marvell/prestera/prestera_main.c |  28 -
 6 files changed, 170 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_devlink.h

diff --git a/drivers/net/ethernet/marvell/prestera/Kconfig 
b/drivers/net/ethernet/marvell/prestera/Kconfig
index 2a5945c455cc..b1fcc44f566a 100644
--- a/drivers/net/ethernet/marvell/prestera/Kconfig
+++ b/drivers/net/ethernet/marvell/prestera/Kconfig
@@ -6,6 +6,7 @@
 config PRESTERA
tristate "Marvell Prestera Switch ASICs support"
depends on NET_SWITCHDEV && VLAN_8021Q
+   select NET_DEVLINK
help
  This driver supports Marvell Prestera Switch ASICs family.
 
diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index 2146714eab21..babd71fba809 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o
+  prestera_rxtx.o prestera_devlink.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 14eb8228c149..886b12f656d4 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -11,6 +11,9 @@
 #include 
 #include 
 #include 
+#include 
+
+#define PRESTERA_DRV_NAME  "prestera"
 
 struct prestera_fw_rev {
u16 maj;
@@ -63,6 +66,7 @@ struct prestera_port_caps {
 struct prestera_port {
struct net_device *dev;
struct prestera_switch *sw;
+   struct devlink_port dl_port;
u32 id;
u32 hw_id;
u32 dev_id;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_devlink.c 
b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
new file mode 100644
index ..abbd08dad6ab
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+
+#include "prestera.h"
+#include "prestera_devlink.h"
+
+static int prestera_dl_info_get(struct devlink *dl,
+   struct devlink_info_req *req,
+   struct netlink_ext_ack *extack)
+{
+   struct prestera_switch *sw = devlink_priv(dl);
+   char buf[16];
+   int err;
+
+   err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME);
+   if (err)
+   return err;
+
+   snprintf(buf, sizeof(buf), "%d.%d.%d",
+sw->dev->fw_rev.maj,
+sw->dev->fw_rev.min,
+sw->dev->fw_rev.sub);
+
+   return devlink_info_version_running_put(req,
+  DEVLINK_INFO_VERSION_GENERIC_FW,
+  buf);
+}
+
+static const struct devlink_ops prestera_dl_ops = {
+   .info_get = prestera_dl_info_get,
+};
+
+struct prestera_switch *prestera_devlink_alloc(void)
+{
+   struct devlink *dl;
+
+   dl = devlink_alloc(_dl_ops, sizeof(struct prestera_switch));
+
+   return devlink_priv(dl);
+}
+
+void prestera_devlink_free(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_free(dl);
+}
+
+int prestera_devlink_register(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+   int err;
+
+   err = devlink_register(dl, sw->dev->dev);
+   if (err)
+   dev_err(sw->dev->dev, "devlink_register failed: %d\n", err);
+
+   return err;
+}
+
+void prestera_devlink_unregister(struct prestera_switch *sw)
+{
+   struct devlink *dl = priv_to_devlink(sw);
+
+   devlink_unregister(dl);
+}
+
+int prestera_devlink_port_register(struct prestera_port *port)
+{
+   struct dev

[net-next v5 4/6] net: marvell: prestera: Add ethtool interface support

2020-08-25 Thread Vadym Kochan
The ethtool API provides support for the configuration of the following
features: speed and duplex, auto-negotiation, MDI-x, forward error
correction, port media type. The API also provides information about the
port status, hardware and software statistic. The following limitation
exists:

- port media type should be configured before speed setting
- ethtool -m option is not supported
- ethtool -p option is not supported
- ethtool -r option is supported for RJ45 port only
- the following combination of parameters is not supported:

  ethtool -s sw1pX port XX autoneg on

- forward error correction feature is supported only on SFP ports, 10G
  speed

- auto-negotiation and MDI-x features are not supported on
  Copper-to-Fiber SFP module

Co-developed-by: Andrii Savka 
Signed-off-by: Andrii Savka 
Co-developed-by: Serhiy Boiko 
Signed-off-by: Serhiy Boiko 
Co-developed-by: Vadym Kochan 
Signed-off-by: Vadym Kochan 
---
PATCH v5:

1) Convert following error check:

if (func(...))
or
if (!func(...))

to use err variable:

err = func(...)
if (err)

2) Remove "," from terminated enum entry.

PATCH v4:
1) Export only prestera_ethtool_ops instead of
   each ethtool handler.

2) Get rid of not needed cast in prestera_ethtool_get_stats(...)
   when doing memcpy.

 .../net/ethernet/marvell/prestera/Makefile|   2 +-
 .../net/ethernet/marvell/prestera/prestera.h  |   3 +
 .../marvell/prestera/prestera_ethtool.c   | 759 ++
 .../marvell/prestera/prestera_ethtool.h   |  14 +
 .../ethernet/marvell/prestera/prestera_hw.c   | 295 ++-
 .../ethernet/marvell/prestera/prestera_hw.h   |  65 ++
 .../ethernet/marvell/prestera/prestera_main.c |  28 +-
 7 files changed, 1159 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/prestera/prestera_ethtool.h

diff --git a/drivers/net/ethernet/marvell/prestera/Makefile 
b/drivers/net/ethernet/marvell/prestera/Makefile
index babd71fba809..7684e7047562 100644
--- a/drivers/net/ethernet/marvell/prestera/Makefile
+++ b/drivers/net/ethernet/marvell/prestera/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PRESTERA) += prestera.o
 prestera-objs  := prestera_main.o prestera_hw.o prestera_dsa.o \
-  prestera_rxtx.o prestera_devlink.o
+  prestera_rxtx.o prestera_devlink.o prestera_ethtool.o
 
 obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
diff --git a/drivers/net/ethernet/marvell/prestera/prestera.h 
b/drivers/net/ethernet/marvell/prestera/prestera.h
index 886b12f656d4..b1fd0a1edad1 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera.h
+++ b/drivers/net/ethernet/marvell/prestera/prestera.h
@@ -173,4 +173,7 @@ void prestera_device_unregister(struct prestera_device 
*dev);
 struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
 u32 dev_id, u32 hw_id);
 
+int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
+ u64 adver_link_modes, u8 adver_fec);
+
 #endif /* _PRESTERA_H_ */
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c 
b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
new file mode 100644
index ..d947c09ce134
--- /dev/null
+++ b/drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
@@ -0,0 +1,759 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
+
+#include 
+#include 
+#include 
+
+#include "prestera.h"
+#include "prestera_hw.h"
+#include "prestera_ethtool.h"
+
+#define PRESTERA_STATS_CNT \
+   (sizeof(struct prestera_port_stats) / sizeof(u64))
+#define PRESTERA_STATS_IDX(name) \
+   (offsetof(struct prestera_port_stats, name) / sizeof(u64))
+#define PRESTERA_STATS_FIELD(name) \
+   [PRESTERA_STATS_IDX(name)] = __stringify(name)
+
+static const char driver_kind[] = "prestera";
+
+static const struct prestera_link_mode {
+   enum ethtool_link_mode_bit_indices eth_mode;
+   u32 speed;
+   u64 pr_mask;
+   u8 duplex;
+   u8 port_type;
+} port_link_modes[PRESTERA_LINK_MODE_MAX] = {
+   [PRESTERA_LINK_MODE_10baseT_Half] = {
+   .eth_mode =  ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+   .speed = 10,
+   .pr_mask = 1 << PRESTERA_LINK_MODE_10baseT_Half,
+   .duplex = PRESTERA_PORT_DUPLEX_HALF,
+   .port_type = PRESTERA_PORT_TYPE_TP,
+   },
+   [PRESTERA_LINK_MODE_10baseT_Full] = {
+   .eth_mode =  ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+   .speed = 10,
+   .pr_mask = 1 << PRESTERA_LINK_MODE_10baseT_Full,
+   .

  1   2   >