From 95b5fc03c189e4ea5c63785274cc0b77fcc3a818 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:57:41 +0800 Subject: [PATCH 01/12] net: arc_emac: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/arc/emac_mdio.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/arc/emac_mdio.c b/drivers/net/ethernet/arc/emac_mdio.c index 54cdafdd067d..9acf589b1178 100644 --- a/drivers/net/ethernet/arc/emac_mdio.c +++ b/drivers/net/ethernet/arc/emac_mdio.c @@ -151,10 +151,9 @@ int arc_mdio_probe(struct arc_emac_priv *priv) data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset", GPIOD_OUT_LOW); if (IS_ERR(data->reset_gpio)) { - error = PTR_ERR(data->reset_gpio); - dev_err(priv->dev, "Failed to request gpio: %d\n", error); mdiobus_free(bus); - return error; + return dev_err_probe(priv->dev, PTR_ERR(data->reset_gpio), + "Failed to request gpio\n"); } of_property_read_u32(np, "phy-reset-duration", &data->msec); @@ -166,9 +165,9 @@ int arc_mdio_probe(struct arc_emac_priv *priv) error = of_mdiobus_register(bus, priv->dev->of_node); if (error) { - dev_err(priv->dev, "cannot register MDIO bus %s\n", bus->name); mdiobus_free(bus); - return error; + return dev_err_probe(priv->dev, error, + "cannot register MDIO bus %s\n", bus->name); } return 0; From d502933c30c6417edfc3ca2babd50343ad24b896 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:57:48 +0800 Subject: [PATCH 02/12] net: atl1c: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 3b51b172b317..20c032ab631b 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -2662,10 +2662,8 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* enable device (incl. PCI PM wakeup and hotplug setup) */ err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "cannot enable PCI device\n"); /* * The atl1c chip can DMA to 64-bit addresses, but it uses a single From b0ab7096dd9bf4d6d5c9d889ab216eb78f7e0b04 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:57:56 +0800 Subject: [PATCH 03/12] net: atl1e: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 753973ac922e..2e22483a9040 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -2297,10 +2297,8 @@ static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int err = 0; err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "cannot enable PCI device\n"); /* * The atl1e chip can DMA to 64-bit addresses, but it uses a single From 9eda994d4b57e177a1e05416458e95ae7cac6c40 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:58:11 +0800 Subject: [PATCH 04/12] net: chelsio: cxgb4vf: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 49b76fd47daa..4920a80a0460 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -2902,10 +2902,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, * Initialize generic PCI device state. */ err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "cannot enable PCI device\n"); /* * Reserve PCI resources for the device. If we can't get them some From a72691ee19ca9763fca4a841843e83e88690aa97 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:58:19 +0800 Subject: [PATCH 05/12] net: enetc: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/enetc.c | 6 ++---- drivers/net/ethernet/freescale/enetc/enetc_pf.c | 12 ++++-------- drivers/net/ethernet/freescale/enetc/enetc_ptp.c | 6 ++---- drivers/net/ethernet/freescale/enetc/enetc_vf.c | 6 ++---- 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 3ca93adb9662..0c69409fe0d0 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -2610,10 +2610,8 @@ int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv) pcie_flr(pdev); err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, "device enable failed\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "device enable failed\n"); /* set up for high or low dma */ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 60d94e0a07d6..f0ff95096846 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -804,10 +804,8 @@ static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np) snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); err = of_mdiobus_register(bus, np); - if (err) { - dev_err(dev, "cannot register MDIO bus\n"); - return err; - } + if (err) + return dev_err_probe(dev, err, "cannot register MDIO bus\n"); pf->mdio = bus; @@ -1216,10 +1214,8 @@ static int enetc_pf_probe(struct pci_dev *pdev, ERR_PTR(err)); err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf)); - if (err) { - dev_err(&pdev->dev, "PCI probing failed\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "PCI probing failed\n"); si = pci_get_drvdata(pdev); if (!si->hw.port || !si->hw.global) { diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c index bc594892507a..36b4f51dd297 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c @@ -39,10 +39,8 @@ static int enetc_ptp_probe(struct pci_dev *pdev, } err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, "device enable failed\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "device enable failed\n"); /* set up for high or low dma */ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c index 1a9d1e8b772c..0704f6bf12fd 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c @@ -143,10 +143,8 @@ static int enetc_vf_probe(struct pci_dev *pdev, int err; err = enetc_pci_probe(pdev, KBUILD_MODNAME, 0); - if (err) { - dev_err(&pdev->dev, "PCI probing failed\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "PCI probing failed\n"); si = pci_get_drvdata(pdev); From 015a22f46b25d12f28efcce28039019ec504cb13 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:58:27 +0800 Subject: [PATCH 06/12] net: ethoc: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/ethoc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index ed1ed48e7483..0064ebdaf4b4 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -707,20 +707,16 @@ static int ethoc_mdio_probe(struct net_device *dev) else phy = phy_find_first(priv->mdio); - if (!phy) { - dev_err(&dev->dev, "no PHY found\n"); - return -ENXIO; - } + if (!phy) + return dev_err_probe(&dev->dev, -ENXIO, "no PHY found\n"); priv->old_duplex = -1; priv->old_link = -1; err = phy_connect_direct(dev, phy, ethoc_mdio_poll, PHY_INTERFACE_MODE_GMII); - if (err) { - dev_err(&dev->dev, "could not attach to PHY\n"); - return err; - } + if (err) + return dev_err_probe(&dev->dev, err, "could not attach to PHY\n"); phy_set_max_speed(phy, SPEED_100); From 4fd3ff3b29aebd271db5b74275adfa5d1505883d Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:58:34 +0800 Subject: [PATCH 07/12] net: hinic: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index ae707e305684..9965e8d5d0a9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -1379,10 +1379,8 @@ static int hinic_probe(struct pci_dev *pdev, { int err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Failed to enable PCI device\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "Failed to enable PCI device\n"); err = pci_request_regions(pdev, HINIC_DRV_NAME); if (err) { From 52583c8d8b12f232bd1128de9f5895bcdad7d7a3 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 15 Sep 2021 22:58:42 +0800 Subject: [PATCH 08/12] net: thunderx: Make use of the helper function dev_err_probe() When possible use dev_err_probe help to properly deal with the PROBE_DEFER error, the benefit is that DEFER issue will be logged in the devices_deferred debugfs file. And using dev_err_probe() can reduce code size, and simplify the code. Signed-off-by: Cai Huoqing Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nic_main.c | 3 +-- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 6 ++---- drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 691e1475d55e..b3d7d1afced7 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -1311,9 +1311,8 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_enable_device(pdev); if (err) { - dev_err(dev, "Failed to enable PCI device\n"); pci_set_drvdata(pdev, NULL); - return err; + return dev_err_probe(dev, err, "Failed to enable PCI device\n"); } err = pci_request_regions(pdev, DRV_NAME); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index d1667b759522..2b87565781a0 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -2119,10 +2119,8 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } err = pci_enable_device(pdev); - if (err) { - dev_err(dev, "Failed to enable PCI device\n"); - return err; - } + if (err) + return dev_err_probe(dev, err, "Failed to enable PCI device\n"); err = pci_request_regions(pdev, DRV_NAME); if (err) { diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index c36fed9c3d73..db66d4beb28a 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -1597,9 +1597,8 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = pcim_enable_device(pdev); if (err) { - dev_err(dev, "Failed to enable PCI device\n"); pci_set_drvdata(pdev, NULL); - return err; + return dev_err_probe(dev, err, "Failed to enable PCI device\n"); } err = pci_request_regions(pdev, DRV_NAME); From 63f85c401ebaa62094c373c780d4051a84608ac3 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 15 Sep 2021 21:29:46 +0530 Subject: [PATCH 09/12] octeontx2-pf: CN10K: Hide RPM stats over ethtool CN10K MAC block (RPM) differs in number of stats compared to Octeontx2 MAC block (CGX). RPM supports stats for each class of PFC and error packets etc. It would be difficult for user to read stats from ethtool and map to their definition. New debugfs file is already added to read RPM stats along with their definition. This patch adds proper checks such that RPM stats will not be part of ethtool. Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../marvell/octeontx2/nic/otx2_common.h | 2 + .../marvell/octeontx2/nic/otx2_ethtool.c | 37 +++++++++++-------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index a51ecd771d07..8e51a1db7e29 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -223,6 +223,7 @@ struct otx2_hw { #define HW_TSO 0 #define CN10K_MBOX 1 #define CN10K_LMTST 2 +#define CN10K_RPM 3 unsigned long cap_flag; #define LMT_LINE_SIZE 128 @@ -452,6 +453,7 @@ static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf) if (!is_dev_otx2(pfvf->pdev)) { __set_bit(CN10K_MBOX, &hw->cap_flag); __set_bit(CN10K_LMTST, &hw->cap_flag); + __set_bit(CN10K_RPM, &hw->cap_flag); } } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index dbfa3bc39e34..38e5924ca8e9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -121,14 +121,16 @@ static void otx2_get_strings(struct net_device *netdev, u32 sset, u8 *data) otx2_get_qset_strings(pfvf, &data, 0); - for (stats = 0; stats < CGX_RX_STATS_COUNT; stats++) { - sprintf(data, "cgx_rxstat%d: ", stats); - data += ETH_GSTRING_LEN; - } + if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) { + for (stats = 0; stats < CGX_RX_STATS_COUNT; stats++) { + sprintf(data, "cgx_rxstat%d: ", stats); + data += ETH_GSTRING_LEN; + } - for (stats = 0; stats < CGX_TX_STATS_COUNT; stats++) { - sprintf(data, "cgx_txstat%d: ", stats); - data += ETH_GSTRING_LEN; + for (stats = 0; stats < CGX_TX_STATS_COUNT; stats++) { + sprintf(data, "cgx_txstat%d: ", stats); + data += ETH_GSTRING_LEN; + } } strcpy(data, "reset_count"); @@ -205,11 +207,15 @@ static void otx2_get_ethtool_stats(struct net_device *netdev, [otx2_drv_stats[stat].index]); otx2_get_qset_stats(pfvf, stats, &data); - otx2_update_lmac_stats(pfvf); - for (stat = 0; stat < CGX_RX_STATS_COUNT; stat++) - *(data++) = pfvf->hw.cgx_rx_stats[stat]; - for (stat = 0; stat < CGX_TX_STATS_COUNT; stat++) - *(data++) = pfvf->hw.cgx_tx_stats[stat]; + + if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) { + otx2_update_lmac_stats(pfvf); + for (stat = 0; stat < CGX_RX_STATS_COUNT; stat++) + *(data++) = pfvf->hw.cgx_rx_stats[stat]; + for (stat = 0; stat < CGX_TX_STATS_COUNT; stat++) + *(data++) = pfvf->hw.cgx_tx_stats[stat]; + } + *(data++) = pfvf->reset_count; fec_corr_blks = pfvf->hw.cgx_fec_corr_blks; @@ -242,18 +248,19 @@ static void otx2_get_ethtool_stats(struct net_device *netdev, static int otx2_get_sset_count(struct net_device *netdev, int sset) { struct otx2_nic *pfvf = netdev_priv(netdev); - int qstats_count; + int qstats_count, mac_stats = 0; if (sset != ETH_SS_STATS) return -EINVAL; qstats_count = otx2_n_queue_stats * (pfvf->hw.rx_queues + pfvf->hw.tx_queues); + if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag)) + mac_stats = CGX_RX_STATS_COUNT + CGX_TX_STATS_COUNT; otx2_update_lmac_fec_stats(pfvf); return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count + - CGX_RX_STATS_COUNT + CGX_TX_STATS_COUNT + OTX2_FEC_STATS_CNT - + 1; + mac_stats + OTX2_FEC_STATS_CNT + 1; } /* Get no of queues device supports and current queue count */ From d1ab2647de3272e878604720ac0af66442e8d1d3 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 15 Sep 2021 14:58:23 -0700 Subject: [PATCH 10/12] Revert "net: wwan: iosm: firmware flashing and coredump collection" The devlink parameters are not the right mechanism to pass extra parameters to device flashing. The params added are also undocumented. This reverts commit 13bb8429ca98 ("net: wwan: iosm: firmware flashing and coredump collection"). Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/wwan/Kconfig | 1 - drivers/net/wwan/iosm/Makefile | 5 +- drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c | 6 +- drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h | 1 - drivers/net/wwan/iosm/iosm_ipc_coredump.c | 110 ----- drivers/net/wwan/iosm/iosm_ipc_coredump.h | 75 --- drivers/net/wwan/iosm/iosm_ipc_devlink.c | 360 -------------- drivers/net/wwan/iosm/iosm_ipc_devlink.h | 207 -------- drivers/net/wwan/iosm/iosm_ipc_flash.c | 562 ---------------------- drivers/net/wwan/iosm/iosm_ipc_flash.h | 271 ----------- drivers/net/wwan/iosm/iosm_ipc_imem.c | 103 +--- drivers/net/wwan/iosm/iosm_ipc_imem.h | 18 +- drivers/net/wwan/iosm/iosm_ipc_imem_ops.c | 317 ------------ drivers/net/wwan/iosm/iosm_ipc_imem_ops.h | 49 +- 14 files changed, 31 insertions(+), 2054 deletions(-) delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_coredump.c delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_coredump.h delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_devlink.c delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_devlink.h delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_flash.c delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_flash.h diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 17543be14665..77dbfc418bce 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -71,7 +71,6 @@ config RPMSG_WWAN_CTRL config IOSM tristate "IOSM Driver for Intel M.2 WWAN Device" depends on INTEL_IOMMU - select NET_DEVLINK help This driver enables Intel M.2 WWAN Device communication. diff --git a/drivers/net/wwan/iosm/Makefile b/drivers/net/wwan/iosm/Makefile index b838034bb120..4f9f0ae398e1 100644 --- a/drivers/net/wwan/iosm/Makefile +++ b/drivers/net/wwan/iosm/Makefile @@ -18,9 +18,6 @@ iosm-y = \ iosm_ipc_protocol.o \ iosm_ipc_protocol_ops.o \ iosm_ipc_mux.o \ - iosm_ipc_mux_codec.o \ - iosm_ipc_devlink.o \ - iosm_ipc_flash.o \ - iosm_ipc_coredump.o + iosm_ipc_mux_codec.o obj-$(CONFIG_IOSM) := iosm.o diff --git a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c index 128c999e08bb..519361ec40df 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c +++ b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c @@ -8,7 +8,7 @@ #include "iosm_ipc_chnl_cfg.h" /* Max. sizes of a downlink buffers */ -#define IPC_MEM_MAX_DL_FLASH_BUF_SIZE (64 * 1024) +#define IPC_MEM_MAX_DL_FLASH_BUF_SIZE (16 * 1024) #define IPC_MEM_MAX_DL_LOOPBACK_SIZE (1 * 1024 * 1024) #define IPC_MEM_MAX_DL_AT_BUF_SIZE 2048 #define IPC_MEM_MAX_DL_RPC_BUF_SIZE (32 * 1024) @@ -60,10 +60,6 @@ static struct ipc_chnl_cfg modem_cfg[] = { { IPC_MEM_CTRL_CHL_ID_6, IPC_MEM_PIPE_12, IPC_MEM_PIPE_13, IPC_MEM_MAX_TDS_MBIM, IPC_MEM_MAX_TDS_MBIM, IPC_MEM_MAX_DL_MBIM_BUF_SIZE, WWAN_PORT_MBIM }, - /* Flash Channel/Coredump Channel */ - { IPC_MEM_CTRL_CHL_ID_7, IPC_MEM_PIPE_0, IPC_MEM_PIPE_1, - IPC_MEM_MAX_TDS_FLASH_UL, IPC_MEM_MAX_TDS_FLASH_DL, - IPC_MEM_MAX_DL_FLASH_BUF_SIZE, WWAN_PORT_UNKNOWN }, }; int ipc_chnl_cfg_get(struct ipc_chnl_cfg *chnl_cfg, int index) diff --git a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h index e77084e76718..422471367f78 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h +++ b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h @@ -23,7 +23,6 @@ enum ipc_channel_id { IPC_MEM_CTRL_CHL_ID_4, IPC_MEM_CTRL_CHL_ID_5, IPC_MEM_CTRL_CHL_ID_6, - IPC_MEM_CTRL_CHL_ID_7, }; /** diff --git a/drivers/net/wwan/iosm/iosm_ipc_coredump.c b/drivers/net/wwan/iosm/iosm_ipc_coredump.c deleted file mode 100644 index fba3c3454e80..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_coredump.c +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#include "iosm_ipc_coredump.h" - -/* Collect coredump data from modem */ -int ipc_coredump_collect(struct iosm_devlink *devlink, u8 **data, int entry, - u32 region_size) -{ - int ret, bytes_to_read, bytes_read = 0, i = 0; - s32 remaining; - u8 *data_ptr; - - data_ptr = vmalloc(region_size); - if (!data_ptr) - return -ENOMEM; - - remaining = devlink->cd_file_info[entry].actual_size; - ret = ipc_devlink_send_cmd(devlink, rpsi_cmd_coredump_get, entry); - if (ret) { - dev_err(devlink->dev, "Send coredump_get cmd failed"); - goto get_cd_fail; - } - while (remaining > 0) { - bytes_to_read = min(remaining, MAX_DATA_SIZE); - bytes_read = 0; - ret = ipc_imem_sys_devlink_read(devlink, data_ptr + i, - bytes_to_read, &bytes_read); - if (ret) { - dev_err(devlink->dev, "CD data read failed"); - goto get_cd_fail; - } - remaining -= bytes_read; - i += bytes_read; - } - - *data = data_ptr; - - return ret; -get_cd_fail: - vfree(data_ptr); - return ret; -} - -/* Get coredump list to be collected from modem */ -int ipc_coredump_get_list(struct iosm_devlink *devlink, u16 cmd) -{ - u32 byte_read, num_entries, file_size; - struct iosm_cd_table *cd_table; - u8 size[MAX_SIZE_LEN], i; - char *filename; - int ret = 0; - - cd_table = kzalloc(MAX_CD_LIST_SIZE, GFP_KERNEL); - if (!cd_table) { - ret = -ENOMEM; - goto cd_init_fail; - } - - ret = ipc_devlink_send_cmd(devlink, cmd, MAX_CD_LIST_SIZE); - if (ret) { - dev_err(devlink->dev, "rpsi_cmd_coredump_start failed"); - goto cd_init_fail; - } - - ret = ipc_imem_sys_devlink_read(devlink, (u8 *)cd_table, - MAX_CD_LIST_SIZE, &byte_read); - if (ret) { - dev_err(devlink->dev, "Coredump data is invalid"); - goto cd_init_fail; - } - - if (byte_read != MAX_CD_LIST_SIZE) - goto cd_init_fail; - - if (cmd == rpsi_cmd_coredump_start) { - num_entries = le32_to_cpu(cd_table->list.num_entries); - if (num_entries == 0 || num_entries > IOSM_NOF_CD_REGION) { - ret = -EINVAL; - goto cd_init_fail; - } - - for (i = 0; i < num_entries; i++) { - file_size = le32_to_cpu(cd_table->list.entry[i].size); - filename = cd_table->list.entry[i].filename; - - if (file_size > devlink->cd_file_info[i].default_size) { - ret = -EINVAL; - goto cd_init_fail; - } - - devlink->cd_file_info[i].actual_size = file_size; - dev_dbg(devlink->dev, "file: %s actual size %d", - filename, file_size); - devlink_flash_update_status_notify(devlink->devlink_ctx, - filename, - "FILENAME", 0, 0); - snprintf(size, sizeof(size), "%d", file_size); - devlink_flash_update_status_notify(devlink->devlink_ctx, - size, "FILE SIZE", - 0, 0); - } - } - -cd_init_fail: - kfree(cd_table); - return ret; -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_coredump.h b/drivers/net/wwan/iosm/iosm_ipc_coredump.h deleted file mode 100644 index d5028153c8d1..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_coredump.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#ifndef _IOSM_IPC_COREDUMP_H_ -#define _IOSM_IPC_COREDUMP_H_ - -#include "iosm_ipc_devlink.h" - -/* Max number of bytes to receive for Coredump list structure */ -#define MAX_CD_LIST_SIZE 0x1000 - -/* Max buffer allocated to receive coredump data */ -#define MAX_DATA_SIZE 0x00010000 - -/* Max number of file entries */ -#define MAX_NOF_ENTRY 256 - -/* Max length */ -#define MAX_SIZE_LEN 32 - -/** - * struct iosm_cd_list_entry - Structure to hold coredump file info. - * @size: Number of bytes for the entry - * @filename: Coredump filename to be generated on host - */ -struct iosm_cd_list_entry { - __le32 size; - char filename[IOSM_MAX_FILENAME_LEN]; -} __packed; - -/** - * struct iosm_cd_list - Structure to hold list of coredump files - * to be collected. - * @num_entries: Number of entries to be received - * @entry: Contains File info - */ -struct iosm_cd_list { - __le32 num_entries; - struct iosm_cd_list_entry entry[MAX_NOF_ENTRY]; -} __packed; - -/** - * struct iosm_cd_table - Common Coredump table - * @version: Version of coredump structure - * @list: Coredump list structure - */ -struct iosm_cd_table { - __le32 version; - struct iosm_cd_list list; -} __packed; - -/** - * ipc_coredump_collect - To collect coredump - * @devlink: Pointer to devlink instance. - * @data: Pointer to snapshot - * @entry: ID of requested snapshot - * @region_size: Region size - * - * Returns: 0 on success, error on failure - */ -int ipc_coredump_collect(struct iosm_devlink *devlink, u8 **data, int entry, - u32 region_size); - -/** - * ipc_coredump_get_list - Get coredump list - * @devlink: Pointer to devlink instance. - * @cmd: RPSI command to be sent - * - * Returns: 0 on success, error on failure - */ -int ipc_coredump_get_list(struct iosm_devlink *devlink, u16 cmd); - -#endif /* _IOSM_IPC_COREDUMP_H_ */ diff --git a/drivers/net/wwan/iosm/iosm_ipc_devlink.c b/drivers/net/wwan/iosm/iosm_ipc_devlink.c deleted file mode 100644 index 592792c277fe..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_devlink.c +++ /dev/null @@ -1,360 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#include "iosm_ipc_chnl_cfg.h" -#include "iosm_ipc_coredump.h" -#include "iosm_ipc_devlink.h" -#include "iosm_ipc_flash.h" - -/* Coredump list */ -static struct iosm_coredump_file_info list[IOSM_NOF_CD_REGION] = { - {"report.json", REPORT_JSON_SIZE,}, - {"coredump.fcd", COREDUMP_FCD_SIZE,}, - {"cdd.log", CDD_LOG_SIZE,}, - {"eeprom.bin", EEPROM_BIN_SIZE,}, - {"bootcore_trace.bin", BOOTCORE_TRC_BIN_SIZE,}, - {"bootcore_prev_trace.bin", BOOTCORE_PREV_TRC_BIN_SIZE,}, -}; - -/* Get the param values for the specific param ID's */ -static int ipc_devlink_get_param(struct devlink *dl, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(dl); - int rc = 0; - - switch (id) { - case IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH: - ctx->val.vu8 = ipc_devlink->param.erase_full_flash; - break; - - case IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION: - ctx->val.vu8 = ipc_devlink->param.download_region; - break; - - case IOSM_DEVLINK_PARAM_ID_ADDRESS: - ctx->val.vu32 = ipc_devlink->param.address; - break; - - case IOSM_DEVLINK_PARAM_ID_REGION_COUNT: - ctx->val.vu8 = ipc_devlink->param.region_count; - break; - - default: - rc = -EOPNOTSUPP; - break; - } - - return rc; -} - -/* Set the param values for the specific param ID's */ -static int ipc_devlink_set_param(struct devlink *dl, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(dl); - int rc = 0; - - switch (id) { - case IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH: - ipc_devlink->param.erase_full_flash = ctx->val.vu8; - break; - - case IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION: - ipc_devlink->param.download_region = ctx->val.vu8; - break; - - case IOSM_DEVLINK_PARAM_ID_ADDRESS: - ipc_devlink->param.address = ctx->val.vu32; - break; - - case IOSM_DEVLINK_PARAM_ID_REGION_COUNT: - ipc_devlink->param.region_count = ctx->val.vu8; - break; - - default: - rc = -EOPNOTSUPP; - break; - } - - return rc; -} - -/* Devlink param structure array */ -static const struct devlink_param iosm_devlink_params[] = { - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH, - "erase_full_flash", DEVLINK_PARAM_TYPE_BOOL, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION, - "download_region", DEVLINK_PARAM_TYPE_BOOL, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_ADDRESS, - "address", DEVLINK_PARAM_TYPE_U32, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_REGION_COUNT, - "region_count", DEVLINK_PARAM_TYPE_U8, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), -}; - -/* Get devlink flash component type */ -static enum iosm_flash_comp_type -ipc_devlink_get_flash_comp_type(const char comp_str[], u32 len) -{ - enum iosm_flash_comp_type fls_type; - - if (!strncmp("PSI", comp_str, len)) - fls_type = FLASH_COMP_TYPE_PSI; - else if (!strncmp("EBL", comp_str, len)) - fls_type = FLASH_COMP_TYPE_EBL; - else if (!strncmp("FLS", comp_str, len)) - fls_type = FLASH_COMP_TYPE_FLS; - else - fls_type = FLASH_COMP_TYPE_INVAL; - - return fls_type; -} - -/* Function triggered on devlink flash command - * Flash update function which calls multiple functions based on - * component type specified in the flash command - */ -static int ipc_devlink_flash_update(struct devlink *devlink, - struct devlink_flash_update_params *params, - struct netlink_ext_ack *extack) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(devlink); - enum iosm_flash_comp_type fls_type; - u32 rc = -EINVAL; - u8 *mdm_rsp; - - mdm_rsp = kzalloc(IOSM_EBL_DW_PACK_SIZE, GFP_KERNEL); - if (!mdm_rsp) - return -ENOMEM; - - fls_type = ipc_devlink_get_flash_comp_type(params->component, - strlen(params->component)); - - switch (fls_type) { - case FLASH_COMP_TYPE_PSI: - rc = ipc_flash_boot_psi(ipc_devlink, params->fw); - break; - case FLASH_COMP_TYPE_EBL: - rc = ipc_flash_boot_ebl(ipc_devlink, params->fw); - if (!rc) - rc = ipc_flash_boot_set_capabilities(ipc_devlink, - mdm_rsp); - if (!rc) - rc = ipc_flash_read_swid(ipc_devlink, mdm_rsp); - break; - case FLASH_COMP_TYPE_FLS: - rc = ipc_flash_send_fls(ipc_devlink, params->fw, mdm_rsp); - break; - default: - devlink_flash_update_status_notify(devlink, "Invalid component", - params->component, 0, 0); - break; - } - - if (!rc) - devlink_flash_update_status_notify(devlink, "Flashing success", - params->component, 0, 0); - else - devlink_flash_update_status_notify(devlink, "Flashing failed", - params->component, 0, 0); - - kfree(mdm_rsp); - return rc; -} - -/* Call back function for devlink ops */ -static const struct devlink_ops devlink_flash_ops = { - .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT, - .flash_update = ipc_devlink_flash_update, -}; - -/* Send command to modem to collect data */ -int ipc_devlink_send_cmd(struct iosm_devlink *ipc_devlink, u16 cmd, u32 entry) -{ - struct iosm_rpsi_cmd rpsi_cmd; - - rpsi_cmd.param.dword = cpu_to_le32(entry); - rpsi_cmd.cmd = cpu_to_le16(cmd); - rpsi_cmd.crc = rpsi_cmd.param.word[0] ^ rpsi_cmd.param.word[1] ^ - rpsi_cmd.cmd; - - return ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&rpsi_cmd, - sizeof(rpsi_cmd)); -} - -static int ipc_devlink_coredump_snapshot(struct devlink *dl, - const struct devlink_region_ops *ops, - struct netlink_ext_ack *extack, - u8 **data) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(dl); - struct iosm_coredump_file_info *cd_list = ops->priv; - u32 region_size; - int rc; - - dev_dbg(ipc_devlink->dev, "Region:%s, ID:%d", ops->name, - cd_list->entry); - region_size = cd_list->default_size; - rc = ipc_coredump_collect(ipc_devlink, data, cd_list->entry, - region_size); - if (rc) { - dev_err(ipc_devlink->dev, "Fail to create snapshot,err %d", rc); - goto coredump_collect_err; - } - - /* Send coredump end cmd indicating end of coredump collection */ - if (cd_list->entry == (IOSM_NOF_CD_REGION - 1)) - ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end); - - return rc; -coredump_collect_err: - ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end); - return rc; -} - -/* To create regions for coredump files */ -static int ipc_devlink_create_region(struct iosm_devlink *devlink) -{ - struct devlink_region_ops *mdm_coredump; - int rc = 0; - u8 i; - - mdm_coredump = devlink->iosm_devlink_mdm_coredump; - for (i = 0; i < IOSM_NOF_CD_REGION; i++) { - mdm_coredump[i].name = list[i].filename; - mdm_coredump[i].snapshot = ipc_devlink_coredump_snapshot; - mdm_coredump[i].destructor = vfree; - devlink->cd_regions[i] = - devlink_region_create(devlink->devlink_ctx, - &mdm_coredump[i], MAX_SNAPSHOTS, - list[i].default_size); - - if (IS_ERR(devlink->cd_regions[i])) { - rc = PTR_ERR(devlink->cd_regions[i]); - dev_err(devlink->dev, "Devlink region fail,err %d", rc); - /* Delete previously created regions */ - for ( ; i > 0; i--) - devlink_region_destroy(devlink->cd_regions[i]); - goto region_create_fail; - } - list[i].entry = i; - mdm_coredump[i].priv = list + i; - } -region_create_fail: - return rc; -} - -/* To Destroy devlink regions */ -static void ipc_devlink_destroy_region(struct iosm_devlink *ipc_devlink) -{ - u8 i; - - for (i = 0; i < IOSM_NOF_CD_REGION; i++) - devlink_region_destroy(ipc_devlink->cd_regions[i]); -} - -/* Handle registration to devlink framework */ -struct iosm_devlink *ipc_devlink_init(struct iosm_imem *ipc_imem) -{ - struct ipc_chnl_cfg chnl_cfg_flash = { 0 }; - struct iosm_devlink *ipc_devlink; - struct devlink *devlink_ctx; - int rc; - - devlink_ctx = devlink_alloc(&devlink_flash_ops, - sizeof(struct iosm_devlink), - ipc_imem->dev); - if (!devlink_ctx) { - dev_err(ipc_imem->dev, "devlink_alloc failed"); - goto devlink_alloc_fail; - } - - ipc_devlink = devlink_priv(devlink_ctx); - ipc_devlink->devlink_ctx = devlink_ctx; - ipc_devlink->pcie = ipc_imem->pcie; - ipc_devlink->dev = ipc_imem->dev; - rc = devlink_register(devlink_ctx); - if (rc) { - dev_err(ipc_devlink->dev, "devlink_register failed rc %d", rc); - goto free_dl; - } - - rc = devlink_params_register(devlink_ctx, iosm_devlink_params, - ARRAY_SIZE(iosm_devlink_params)); - if (rc) { - dev_err(ipc_devlink->dev, - "devlink_params_register failed. rc %d", rc); - goto param_reg_fail; - } - - devlink_params_publish(devlink_ctx); - ipc_devlink->cd_file_info = list; - - rc = ipc_devlink_create_region(ipc_devlink); - if (rc) { - dev_err(ipc_devlink->dev, "Devlink Region create failed, rc %d", - rc); - goto region_create_fail; - } - - if (ipc_chnl_cfg_get(&chnl_cfg_flash, IPC_MEM_CTRL_CHL_ID_7) < 0) - goto chnl_get_fail; - - ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL, - chnl_cfg_flash, IRQ_MOD_OFF); - - init_completion(&ipc_devlink->devlink_sio.read_sem); - skb_queue_head_init(&ipc_devlink->devlink_sio.rx_list); - - dev_dbg(ipc_devlink->dev, "iosm devlink register success"); - - return ipc_devlink; - -chnl_get_fail: - ipc_devlink_destroy_region(ipc_devlink); -region_create_fail: - devlink_params_unpublish(devlink_ctx); - devlink_params_unregister(devlink_ctx, iosm_devlink_params, - ARRAY_SIZE(iosm_devlink_params)); -param_reg_fail: - devlink_unregister(devlink_ctx); -free_dl: - devlink_free(devlink_ctx); -devlink_alloc_fail: - return NULL; -} - -/* Handle unregistration of devlink */ -void ipc_devlink_deinit(struct iosm_devlink *ipc_devlink) -{ - struct devlink *devlink_ctx = ipc_devlink->devlink_ctx; - - ipc_devlink_destroy_region(ipc_devlink); - devlink_params_unpublish(devlink_ctx); - devlink_params_unregister(devlink_ctx, iosm_devlink_params, - ARRAY_SIZE(iosm_devlink_params)); - if (ipc_devlink->devlink_sio.devlink_read_pend) { - complete(&ipc_devlink->devlink_sio.read_sem); - complete(&ipc_devlink->devlink_sio.channel->ul_sem); - } - if (!ipc_devlink->devlink_sio.devlink_read_pend) - skb_queue_purge(&ipc_devlink->devlink_sio.rx_list); - - ipc_imem_sys_devlink_close(ipc_devlink); - devlink_unregister(devlink_ctx); - devlink_free(devlink_ctx); -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_devlink.h b/drivers/net/wwan/iosm/iosm_ipc_devlink.h deleted file mode 100644 index 392735080cb3..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_devlink.h +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#ifndef _IOSM_IPC_DEVLINK_H_ -#define _IOSM_IPC_DEVLINK_H_ - -#include - -#include "iosm_ipc_imem.h" -#include "iosm_ipc_imem_ops.h" -#include "iosm_ipc_pcie.h" - -/* MAX file name length */ -#define IOSM_MAX_FILENAME_LEN 32 -/* EBL response size */ -#define IOSM_EBL_RSP_SIZE 76 -/* MAX number of regions supported */ -#define IOSM_NOF_CD_REGION 6 -/* MAX number of SNAPSHOTS supported */ -#define MAX_SNAPSHOTS 1 -/* Default Coredump file size */ -#define REPORT_JSON_SIZE 0x800 -#define COREDUMP_FCD_SIZE 0x10E00000 -#define CDD_LOG_SIZE 0x30000 -#define EEPROM_BIN_SIZE 0x10000 -#define BOOTCORE_TRC_BIN_SIZE 0x8000 -#define BOOTCORE_PREV_TRC_BIN_SIZE 0x20000 - -/** - * enum iosm_devlink_param_id - Enum type to different devlink params - * @IOSM_DEVLINK_PARAM_ID_BASE: Devlink param base ID - * @IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH: Set if full erase required - * @IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION: Set if fls file to be - * flashed is Loadmap/region file - * @IOSM_DEVLINK_PARAM_ID_ADDRESS: Address of the region to be - * flashed - * @IOSM_DEVLINK_PARAM_ID_REGION_COUNT: Max region count - */ - -enum iosm_devlink_param_id { - IOSM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, - IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH, - IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION, - IOSM_DEVLINK_PARAM_ID_ADDRESS, - IOSM_DEVLINK_PARAM_ID_REGION_COUNT, -}; - -/** - * enum iosm_rpsi_cmd_code - Enum type for RPSI command list - * @rpsi_cmd_code_ebl: Command to load ebl - * @rpsi_cmd_coredump_start: Command to get list of files and - * file size info from PSI - * @rpsi_cmd_coredump_get: Command to get the coredump data - * @rpsi_cmd_coredump_end: Command to stop receiving the coredump - */ -enum iosm_rpsi_cmd_code { - rpsi_cmd_code_ebl = 0x02, - rpsi_cmd_coredump_start = 0x10, - rpsi_cmd_coredump_get = 0x11, - rpsi_cmd_coredump_end = 0x12, -}; - -/** - * enum iosm_flash_comp_type - Enum for different flash component types - * @FLASH_COMP_TYPE_PSI: PSI flash comp type - * @FLASH_COMP_TYPE_EBL: EBL flash comp type - * @FLASH_COMP_TYPE_FLS: FLS flash comp type - * @FLASH_COMP_TYPE_INVAL: Invalid flash comp type - */ -enum iosm_flash_comp_type { - FLASH_COMP_TYPE_PSI, - FLASH_COMP_TYPE_EBL, - FLASH_COMP_TYPE_FLS, - FLASH_COMP_TYPE_INVAL, -}; - -/** - * struct iosm_devlink_sio - SIO instance - * @rx_list: Downlink skbuf list received from CP - * @read_sem: Needed for the blocking read or downlink transfer - * @channel_id: Reserved channel id for flashing/CD collection to RAM - * @channel: Channel instance for flashing and coredump - * @devlink_read_pend: Check if read is pending - */ -struct iosm_devlink_sio { - struct sk_buff_head rx_list; - struct completion read_sem; - int channel_id; - struct ipc_mem_channel *channel; - u32 devlink_read_pend; -}; - -/** - * struct iosm_flash_params - List of flash params required for flashing - * @address: Address of the region file to be flashed - * @region_count: Maximum no of regions for each fls file - * @download_region: To be set if region is being flashed - * @erase_full_flash: To set the flashing mode - * erase_full_flash = 1; full erase - * erase_full_flash = 0; no erase - * @erase_full_flash_done: Flag to check if it is a full erase - */ -struct iosm_flash_params { - u32 address; - u8 region_count; - u8 download_region; - u8 erase_full_flash; - u8 erase_full_flash_done; -}; - -/** - * struct iosm_ebl_ctx_data - EBL ctx data used during flashing - * @ebl_sw_info_version: SWID version info obtained from EBL - * @m_ebl_resp: Buffer used to read and write the ebl data - */ -struct iosm_ebl_ctx_data { - u8 ebl_sw_info_version; - u8 m_ebl_resp[IOSM_EBL_RSP_SIZE]; -}; - -/** - * struct iosm_coredump_file_info - Coredump file info - * @filename: Name of coredump file - * @default_size: Default size of coredump file - * @actual_size: Actual size of coredump file - * @entry: Index of the coredump file - */ -struct iosm_coredump_file_info { - char filename[IOSM_MAX_FILENAME_LEN]; - u32 default_size; - u32 actual_size; - u32 entry; -}; - -/** - * struct iosm_devlink - IOSM Devlink structure - * @devlink_sio: SIO instance for read/write functionality - * @pcie: Pointer to PCIe component - * @dev: Pointer to device struct - * @devlink_ctx: Pointer to devlink context - * @param: Params required for flashing - * @ebl_ctx: Data to be read and written to Modem - * @cd_file_info: coredump file info - * @iosm_devlink_mdm_coredump: region ops for coredump collection - * @cd_regions: coredump regions - */ -struct iosm_devlink { - struct iosm_devlink_sio devlink_sio; - struct iosm_pcie *pcie; - struct device *dev; - struct devlink *devlink_ctx; - struct iosm_flash_params param; - struct iosm_ebl_ctx_data ebl_ctx; - struct iosm_coredump_file_info *cd_file_info; - struct devlink_region_ops iosm_devlink_mdm_coredump[IOSM_NOF_CD_REGION]; - struct devlink_region *cd_regions[IOSM_NOF_CD_REGION]; -}; - -/** - * union iosm_rpsi_param_u - RPSI cmd param for CRC calculation - * @word: Words member used in CRC calculation - * @dword: Actual data - */ -union iosm_rpsi_param_u { - __le16 word[2]; - __le32 dword; -}; - -/** - * struct iosm_rpsi_cmd - Structure for RPSI Command - * @param: Used to calculate CRC - * @cmd: Stores the RPSI command - * @crc: Stores the CRC value - */ -struct iosm_rpsi_cmd { - union iosm_rpsi_param_u param; - __le16 cmd; - __le16 crc; -}; - -/** - * ipc_devlink_init - To initialize the devlink to IOSM driver - * @ipc_imem: Pointer to struct iosm_imem - * - * Returns: Pointer to iosm_devlink on success and NULL on failure - */ -struct iosm_devlink *ipc_devlink_init(struct iosm_imem *ipc_imem); - -/** - * ipc_devlink_deinit - To unintialize the devlink from IOSM driver. - * @ipc_devlink: Devlink instance - */ -void ipc_devlink_deinit(struct iosm_devlink *ipc_devlink); - -/** - * ipc_devlink_send_cmd - Send command to Modem - * @ipc_devlink: Pointer to struct iosm_devlink - * @cmd: Command to be sent to modem - * @entry: Command entry number - * - * Returns: 0 on success and failure value on error - */ -int ipc_devlink_send_cmd(struct iosm_devlink *ipc_devlink, u16 cmd, u32 entry); - -#endif /* _IOSM_IPC_DEVLINK_H */ diff --git a/drivers/net/wwan/iosm/iosm_ipc_flash.c b/drivers/net/wwan/iosm/iosm_ipc_flash.c deleted file mode 100644 index a43aafc70168..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_flash.c +++ /dev/null @@ -1,562 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#include "iosm_ipc_coredump.h" -#include "iosm_ipc_devlink.h" -#include "iosm_ipc_flash.h" - -/* This function will pack the data to be sent to the modem using the - * payload, payload length and pack id - */ -static int ipc_flash_proc_format_ebl_pack(struct iosm_flash_data *flash_req, - u32 pack_length, u16 pack_id, - u8 *payload, u32 payload_length) -{ - u16 checksum = pack_id; - u32 i; - - if (payload_length + IOSM_EBL_HEAD_SIZE > pack_length) - return -EINVAL; - - flash_req->pack_id = cpu_to_le16(pack_id); - flash_req->msg_length = cpu_to_le32(payload_length); - checksum += (payload_length >> IOSM_EBL_PAYL_SHIFT) + - (payload_length & IOSM_EBL_CKSM); - - for (i = 0; i < payload_length; i++) - checksum += payload[i]; - - flash_req->checksum = cpu_to_le16(checksum); - - return 0; -} - -/* validate the response received from modem and - * check the type of errors received - */ -static int ipc_flash_proc_check_ebl_rsp(void *hdr_rsp, void *payload_rsp) -{ - struct iosm_ebl_error *err_info = payload_rsp; - u16 *rsp_code = hdr_rsp; - int res = 0; - u32 i; - - if (*rsp_code == IOSM_EBL_RSP_BUFF) { - for (i = 0; i < IOSM_MAX_ERRORS; i++) { - if (!err_info->error[i].error_code) { - pr_err("EBL: error_class = %d, error_code = %d", - err_info->error[i].error_class, - err_info->error[i].error_code); - } - } - res = -EINVAL; - } - - return res; -} - -/* Send data to the modem */ -static int ipc_flash_send_data(struct iosm_devlink *ipc_devlink, u32 size, - u16 pack_id, u8 *payload, u32 payload_length) -{ - struct iosm_flash_data flash_req; - int ret; - - ret = ipc_flash_proc_format_ebl_pack(&flash_req, size, - pack_id, payload, payload_length); - if (ret) { - dev_err(ipc_devlink->dev, "EBL2 pack failed for pack_id:%d", - pack_id); - goto ipc_free_payload; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&flash_req, - IOSM_EBL_HEAD_SIZE); - if (ret) { - dev_err(ipc_devlink->dev, "EBL Header write failed for Id:%x", - pack_id); - goto ipc_free_payload; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, payload, payload_length); - if (ret) { - dev_err(ipc_devlink->dev, "EBL Payload write failed for Id:%x", - pack_id); - } - -ipc_free_payload: - return ret; -} - -/* Allocate flash channel and read LER data from modem */ -int ipc_flash_link_establish(struct iosm_imem *ipc_imem) -{ - u8 ler_data[IOSM_LER_RSP_SIZE]; - u32 bytes_read; - - /* Allocate channel for flashing/cd collection */ - ipc_imem->ipc_devlink->devlink_sio.channel = - ipc_imem_sys_devlink_open(ipc_imem); - - if (!ipc_imem->ipc_devlink->devlink_sio.channel) - goto chl_open_fail; - - if (ipc_imem_sys_devlink_read(ipc_imem->ipc_devlink, ler_data, - IOSM_LER_RSP_SIZE, &bytes_read)) - goto devlink_read_fail; - - if (bytes_read != IOSM_LER_RSP_SIZE) - goto devlink_read_fail; - return 0; - -devlink_read_fail: - ipc_imem_sys_devlink_close(ipc_imem->ipc_devlink); -chl_open_fail: - return -EIO; -} - -/* Receive data from the modem */ -static int ipc_flash_receive_data(struct iosm_devlink *ipc_devlink, u32 size, - u8 *mdm_rsp) -{ - u8 mdm_rsp_hdr[IOSM_EBL_HEAD_SIZE]; - u32 bytes_read; - int ret; - - ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp_hdr, - IOSM_EBL_HEAD_SIZE, &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed", - IOSM_EBL_HEAD_SIZE); - goto ipc_flash_recv_err; - } - - if (bytes_read != IOSM_EBL_HEAD_SIZE) { - ret = -EINVAL; - goto ipc_flash_recv_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp, size, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed", - size); - goto ipc_flash_recv_err; - } - - if (bytes_read != size) { - ret = -EINVAL; - goto ipc_flash_recv_err; - } - - ret = ipc_flash_proc_check_ebl_rsp(mdm_rsp_hdr + 2, mdm_rsp); - -ipc_flash_recv_err: - return ret; -} - -/* Function to send command to modem and receive response */ -static int ipc_flash_send_receive(struct iosm_devlink *ipc_devlink, u16 pack_id, - u8 *payload, u32 payload_length, u8 *mdm_rsp) -{ - size_t frame_len = IOSM_EBL_DW_PACK_SIZE; - int ret; - - if (pack_id == FLASH_SET_PROT_CONF) - frame_len = IOSM_EBL_W_PACK_SIZE; - - ret = ipc_flash_send_data(ipc_devlink, frame_len, pack_id, payload, - payload_length); - if (ret) - goto ipc_flash_send_rcv; - - ret = ipc_flash_receive_data(ipc_devlink, - frame_len - IOSM_EBL_HEAD_SIZE, mdm_rsp); - -ipc_flash_send_rcv: - return ret; -} - -/* Set the capabilities for the EBL */ -int ipc_flash_boot_set_capabilities(struct iosm_devlink *ipc_devlink, - u8 *mdm_rsp) -{ - int ret; - - ipc_devlink->ebl_ctx.ebl_sw_info_version = - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_RSP_SW_INFO_VER]; - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_ERASE] = IOSM_CAP_NOT_ENHANCED; - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_CRC] = IOSM_CAP_NOT_ENHANCED; - - if (ipc_devlink->ebl_ctx.m_ebl_resp[EBL_CAPS_FLAG] & - IOSM_CAP_USE_EXT_CAP) { - if (ipc_devlink->param.erase_full_flash) - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &= - ~((u8)IOSM_EXT_CAP_ERASE_ALL); - else - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &= - ~((u8)IOSM_EXT_CAP_COMMIT_ALL); - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_EXT_CAPS_HANDLED] = - IOSM_CAP_USE_EXT_CAP; - } - - /* Write back the EBL capability to modem - * Request Set Protcnf command - */ - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SET_PROT_CONF, - ipc_devlink->ebl_ctx.m_ebl_resp, - IOSM_EBL_RSP_SIZE, mdm_rsp); - return ret; -} - -/* Read the SWID type and SWID value from the EBL */ -int ipc_flash_read_swid(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp) -{ - struct iosm_flash_msg_control cmd_msg; - struct iosm_swid_table *swid; - char ebl_swid[IOSM_SWID_STR]; - int ret; - - if (ipc_devlink->ebl_ctx.ebl_sw_info_version != - IOSM_EXT_CAP_SWID_OOS_PACK) - return -EINVAL; - - cmd_msg.action = cpu_to_le32(FLASH_OOSC_ACTION_READ); - cmd_msg.type = cpu_to_le32(FLASH_OOSC_TYPE_SWID_TABLE); - cmd_msg.length = cpu_to_le32(IOSM_MSG_LEN_ARG); - cmd_msg.arguments = cpu_to_le32(IOSM_MSG_LEN_ARG); - - ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_CONTROL, - (u8 *)&cmd_msg, IOSM_MDM_SEND_16, mdm_rsp); - if (ret) - goto ipc_swid_err; - - cmd_msg.action = cpu_to_le32(*((u32 *)mdm_rsp)); - - ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_DATA_READ, - (u8 *)&cmd_msg, IOSM_MDM_SEND_4, mdm_rsp); - if (ret) - goto ipc_swid_err; - - swid = (struct iosm_swid_table *)mdm_rsp; - dev_dbg(ipc_devlink->dev, "SWID %x RF_ENGINE_ID %x", swid->sw_id_val, - swid->rf_engine_id_val); - - snprintf(ebl_swid, sizeof(ebl_swid), "SWID: %x, RF_ENGINE_ID: %x", - swid->sw_id_val, swid->rf_engine_id_val); - - devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, ebl_swid, - NULL, 0, 0); -ipc_swid_err: - return ret; -} - -/* Function to check if full erase or conditional erase was successful */ -static int ipc_flash_erase_check(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp) -{ - int ret, count = 0; - u16 mdm_rsp_data; - - /* Request Flash Erase Check */ - do { - mdm_rsp_data = IOSM_MDM_SEND_DATA; - ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_CHECK, - (u8 *)&mdm_rsp_data, - IOSM_MDM_SEND_2, mdm_rsp); - if (ret) - goto ipc_erase_chk_err; - - mdm_rsp_data = *((u16 *)mdm_rsp); - if (mdm_rsp_data > IOSM_MDM_ERASE_RSP) { - dev_err(ipc_devlink->dev, - "Flash Erase Check resp wrong 0x%04X", - mdm_rsp_data); - ret = -EINVAL; - goto ipc_erase_chk_err; - } - count++; - msleep(IOSM_FLASH_ERASE_CHECK_INTERVAL); - } while ((mdm_rsp_data != IOSM_MDM_ERASE_RSP) && - (count < (IOSM_FLASH_ERASE_CHECK_TIMEOUT / - IOSM_FLASH_ERASE_CHECK_INTERVAL))); - - if (mdm_rsp_data != IOSM_MDM_ERASE_RSP) { - dev_err(ipc_devlink->dev, "Modem erase check timeout failure!"); - ret = -ETIMEDOUT; - } - -ipc_erase_chk_err: - return ret; -} - -/* Full erase function which will erase the nand flash through EBL command */ -static int ipc_flash_full_erase(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp) -{ - u32 erase_address = IOSM_ERASE_START_ADDR; - struct iosm_flash_msg_control cmd_msg; - u32 erase_length = IOSM_ERASE_LEN; - int ret; - - dev_dbg(ipc_devlink->dev, "Erase full nand flash"); - cmd_msg.action = cpu_to_le32(FLASH_OOSC_ACTION_ERASE); - cmd_msg.type = cpu_to_le32(FLASH_OOSC_TYPE_ALL_FLASH); - cmd_msg.length = cpu_to_le32(erase_length); - cmd_msg.arguments = cpu_to_le32(erase_address); - - ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_CONTROL, - (unsigned char *)&cmd_msg, - IOSM_MDM_SEND_16, mdm_rsp); - if (ret) - goto ipc_flash_erase_err; - - ipc_devlink->param.erase_full_flash_done = IOSM_SET_FLAG; - ret = ipc_flash_erase_check(ipc_devlink, mdm_rsp); - -ipc_flash_erase_err: - return ret; -} - -/* Logic for flashing all the Loadmaps available for individual fls file */ -static int ipc_flash_download_region(struct iosm_devlink *ipc_devlink, - const struct firmware *fw, u8 *mdm_rsp) -{ - __le32 reg_info[2]; /* 0th position region address, 1st position size */ - char *file_ptr; - u32 rest_len; - u32 raw_len; - int ret; - - file_ptr = (char *)fw->data; - reg_info[0] = cpu_to_le32(ipc_devlink->param.address); - - if (!ipc_devlink->param.erase_full_flash_done) { - reg_info[1] = cpu_to_le32(ipc_devlink->param.address + - fw->size - 2); - ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_START, - (u8 *)reg_info, IOSM_MDM_SEND_8, - mdm_rsp); - if (ret) - goto dl_region_fail; - - ret = ipc_flash_erase_check(ipc_devlink, mdm_rsp); - if (ret) - goto dl_region_fail; - } - - /* Request Flash Set Address */ - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SET_ADDRESS, - (u8 *)reg_info, IOSM_MDM_SEND_4, mdm_rsp); - if (ret) - goto dl_region_fail; - - rest_len = fw->size; - - /* Request Flash Write Raw Image */ - ret = ipc_flash_send_data(ipc_devlink, IOSM_EBL_DW_PACK_SIZE, - FLASH_WRITE_IMAGE_RAW, (u8 *)&rest_len, - IOSM_MDM_SEND_4); - if (ret) - goto dl_region_fail; - - do { - raw_len = (rest_len > IOSM_FLS_BUF_SIZE) ? IOSM_FLS_BUF_SIZE : - rest_len; - ret = ipc_imem_sys_devlink_write(ipc_devlink, file_ptr, - raw_len); - if (ret) { - dev_err(ipc_devlink->dev, "Image write failed"); - goto dl_region_fail; - } - file_ptr += raw_len; - rest_len -= raw_len; - } while (rest_len); - - ret = ipc_flash_receive_data(ipc_devlink, IOSM_EBL_DW_PAYL_SIZE, - mdm_rsp); - -dl_region_fail: - return ret; -} - -/* Flash the individual fls files */ -int ipc_flash_send_fls(struct iosm_devlink *ipc_devlink, - const struct firmware *fw, u8 *mdm_rsp) -{ - u16 flash_cmd; - int ret; - - if (ipc_devlink->param.erase_full_flash) { - ipc_devlink->param.erase_full_flash = false; - ret = ipc_flash_full_erase(ipc_devlink, mdm_rsp); - if (ret) - goto ipc_flash_err; - } - - /* Request Sec Start */ - if (!ipc_devlink->param.download_region) { - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SEC_START, - (u8 *)fw->data, fw->size, mdm_rsp); - if (ret) - goto ipc_flash_err; - } else { - /* Download regions */ - ipc_devlink->param.region_count -= IOSM_SET_FLAG; - ret = ipc_flash_download_region(ipc_devlink, fw, mdm_rsp); - if (ret) - goto ipc_flash_err; - - if (!ipc_devlink->param.region_count) { - /* Request Sec End */ - flash_cmd = IOSM_MDM_SEND_DATA; - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SEC_END, - (u8 *)&flash_cmd, - IOSM_MDM_SEND_2, mdm_rsp); - } - } - -ipc_flash_err: - return ret; -} - -/* Inject RPSI */ -int ipc_flash_boot_psi(struct iosm_devlink *ipc_devlink, - const struct firmware *fw) -{ - u8 psi_ack_byte[IOSM_PSI_ACK], read_data[2]; - u32 bytes_read; - u8 *psi_code; - int ret; - - dev_dbg(ipc_devlink->dev, "Boot transfer PSI"); - psi_code = kzalloc(fw->size, GFP_KERNEL); - if (!psi_code) - return -ENOMEM; - - memcpy(psi_code, fw->data, fw->size); - ret = ipc_imem_sys_devlink_write(ipc_devlink, psi_code, fw->size); - if (ret) { - dev_err(ipc_devlink->dev, "RPSI Image write failed"); - goto ipc_flash_psi_free; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, - IOSM_LER_ACK_SIZE, &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "ipc_devlink_sio_read ACK failed"); - goto ipc_flash_psi_free; - } - - if (bytes_read != IOSM_LER_ACK_SIZE) { - ret = -EINVAL; - goto ipc_flash_psi_free; - } - - snprintf(psi_ack_byte, sizeof(psi_ack_byte), "%x%x", read_data[0], - read_data[1]); - devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, - psi_ack_byte, "PSI ACK", 0, 0); - - if (read_data[0] == 0x00 && read_data[1] == 0xCD) { - dev_dbg(ipc_devlink->dev, "Coredump detected"); - ret = ipc_coredump_get_list(ipc_devlink, - rpsi_cmd_coredump_start); - if (ret) - dev_err(ipc_devlink->dev, "Failed to get cd list"); - } - -ipc_flash_psi_free: - kfree(psi_code); - return ret; -} - -/* Inject EBL */ -int ipc_flash_boot_ebl(struct iosm_devlink *ipc_devlink, - const struct firmware *fw) -{ - u32 ebl_size = fw->size; - u8 read_data[2]; - u32 bytes_read; - int ret; - - if (ipc_mmio_get_exec_stage(ipc_devlink->pcie->imem->mmio) != - IPC_MEM_EXEC_STAGE_PSI) { - devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, - "Invalid execution stage", - NULL, 0, 0); - return -EINVAL; - } - - dev_dbg(ipc_devlink->dev, "Boot transfer EBL"); - ret = ipc_devlink_send_cmd(ipc_devlink, rpsi_cmd_code_ebl, - IOSM_RPSI_LOAD_SIZE); - if (ret) { - dev_err(ipc_devlink->dev, "Sending rpsi_cmd_code_ebl failed"); - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "rpsi_cmd_code_ebl read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_READ_SIZE) { - ret = -EINVAL; - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&ebl_size, - sizeof(ebl_size)); - if (ret) { - dev_err(ipc_devlink->dev, "EBL length write failed"); - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_READ_SIZE) { - ret = -EINVAL; - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, (unsigned char *)fw->data, - fw->size); - if (ret) { - dev_err(ipc_devlink->dev, "EBL data transfer failed"); - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_READ_SIZE) { - ret = -EINVAL; - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, - ipc_devlink->ebl_ctx.m_ebl_resp, - IOSM_EBL_RSP_SIZE, &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL response read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_EBL_RSP_SIZE) - ret = -EINVAL; - -ipc_flash_ebl_err: - return ret; -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_flash.h b/drivers/net/wwan/iosm/iosm_ipc_flash.h deleted file mode 100644 index aee848927228..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_flash.h +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#ifndef _IOSM_IPC_FLASH_H -#define _IOSM_IPC_FLASH_H - -/* Buffer size used to read the fls image */ -#define IOSM_FLS_BUF_SIZE 0x00100000 -/* Full erase start address */ -#define IOSM_ERASE_START_ADDR 0x00000000 -/* Erase length for NAND flash */ -#define IOSM_ERASE_LEN 0xFFFFFFFF -/* EBL response Header size */ -#define IOSM_EBL_HEAD_SIZE 8 -/* EBL payload size */ -#define IOSM_EBL_W_PAYL_SIZE 2048 -/* Total EBL pack size */ -#define IOSM_EBL_W_PACK_SIZE (IOSM_EBL_HEAD_SIZE + IOSM_EBL_W_PAYL_SIZE) -/* EBL payload size */ -#define IOSM_EBL_DW_PAYL_SIZE 16384 -/* Total EBL pack size */ -#define IOSM_EBL_DW_PACK_SIZE (IOSM_EBL_HEAD_SIZE + IOSM_EBL_DW_PAYL_SIZE) -/* EBL name size */ -#define IOSM_EBL_NAME 32 -/* Maximum supported error types */ -#define IOSM_MAX_ERRORS 8 -/* Read size for RPSI/EBL response */ -#define IOSM_READ_SIZE 2 -/* Link establishment response ack size */ -#define IOSM_LER_ACK_SIZE 2 -/* PSI ACK len */ -#define IOSM_PSI_ACK 8 -/* SWID capability for packed swid type */ -#define IOSM_EXT_CAP_SWID_OOS_PACK 0x02 -/* EBL error response buffer */ -#define IOSM_EBL_RSP_BUFF 0x0041 -/* SWID string length */ -#define IOSM_SWID_STR 64 -/* Load EBL command size */ -#define IOSM_RPSI_LOAD_SIZE 0 -/* EBL payload checksum */ -#define IOSM_EBL_CKSM 0x0000FFFF -/* SWID msg len and argument */ -#define IOSM_MSG_LEN_ARG 0 -/* Data to be sent to modem */ -#define IOSM_MDM_SEND_DATA 0x0000 -/* Data received from modem as part of erase check */ -#define IOSM_MDM_ERASE_RSP 0x0001 -/* Bit shift to calculate Checksum */ -#define IOSM_EBL_PAYL_SHIFT 16 -/* Flag To be set */ -#define IOSM_SET_FLAG 1 -/* Set flash erase check timeout to 100 msec */ -#define IOSM_FLASH_ERASE_CHECK_TIMEOUT 100 -/* Set flash erase check interval to 20 msec */ -#define IOSM_FLASH_ERASE_CHECK_INTERVAL 20 -/* Link establishment response ack size */ -#define IOSM_LER_RSP_SIZE 60 - -/** - * enum iosm_flash_package_type - Enum for the flashing operations - * @FLASH_SET_PROT_CONF: Write EBL capabilities - * @FLASH_SEC_START: Start writing the secpack - * @FLASH_SEC_END: Validate secpack end - * @FLASH_SET_ADDRESS: Set the address for flashing - * @FLASH_ERASE_START: Start erase before flashing - * @FLASH_ERASE_CHECK: Validate the erase functionality - * @FLASH_OOS_CONTROL: Retrieve data based on oos actions - * @FLASH_OOS_DATA_READ: Read data from EBL - * @FLASH_WRITE_IMAGE_RAW: Write the raw image to flash - */ -enum iosm_flash_package_type { - FLASH_SET_PROT_CONF = 0x0086, - FLASH_SEC_START = 0x0204, - FLASH_SEC_END, - FLASH_SET_ADDRESS = 0x0802, - FLASH_ERASE_START = 0x0805, - FLASH_ERASE_CHECK, - FLASH_OOS_CONTROL = 0x080C, - FLASH_OOS_DATA_READ = 0x080E, - FLASH_WRITE_IMAGE_RAW, -}; - -/** - * enum iosm_out_of_session_action - Actions possible over the - * OutOfSession command interface - * @FLASH_OOSC_ACTION_READ: Read data according to its type - * @FLASH_OOSC_ACTION_ERASE: Erase data according to its type - */ -enum iosm_out_of_session_action { - FLASH_OOSC_ACTION_READ = 2, - FLASH_OOSC_ACTION_ERASE = 3, -}; - -/** - * enum iosm_out_of_session_type - Data types that can be handled over the - * Out Of Session command Interface - * @FLASH_OOSC_TYPE_ALL_FLASH: The whole flash area - * @FLASH_OOSC_TYPE_SWID_TABLE: Read the swid table from the target - */ -enum iosm_out_of_session_type { - FLASH_OOSC_TYPE_ALL_FLASH = 8, - FLASH_OOSC_TYPE_SWID_TABLE = 16, -}; - -/** - * enum iosm_ebl_caps - EBL capability settings - * @IOSM_CAP_NOT_ENHANCED: If capability not supported - * @IOSM_CAP_USE_EXT_CAP: To be set if extended capability is set - * @IOSM_EXT_CAP_ERASE_ALL: Set Erase all capability - * @IOSM_EXT_CAP_COMMIT_ALL: Set the commit all capability - */ -enum iosm_ebl_caps { - IOSM_CAP_NOT_ENHANCED = 0x00, - IOSM_CAP_USE_EXT_CAP = 0x01, - IOSM_EXT_CAP_ERASE_ALL = 0x08, - IOSM_EXT_CAP_COMMIT_ALL = 0x20, -}; - -/** - * enum iosm_ebl_rsp - EBL response field - * @EBL_CAPS_FLAG: EBL capability flag - * @EBL_SKIP_ERASE: EBL skip erase flag - * @EBL_SKIP_CRC: EBL skip wr_pack crc - * @EBL_EXT_CAPS_HANDLED: EBL extended capability handled flag - * @EBL_OOS_CONFIG: EBL oos configuration - * @EBL_RSP_SW_INFO_VER: EBL SW info version - */ -enum iosm_ebl_rsp { - EBL_CAPS_FLAG = 50, - EBL_SKIP_ERASE = 54, - EBL_SKIP_CRC = 55, - EBL_EXT_CAPS_HANDLED = 57, - EBL_OOS_CONFIG = 64, - EBL_RSP_SW_INFO_VER = 70, -}; - -/** - * enum iosm_mdm_send_recv_data - Data to send to modem - * @IOSM_MDM_SEND_2: Send 2 bytes of payload - * @IOSM_MDM_SEND_4: Send 4 bytes of payload - * @IOSM_MDM_SEND_8: Send 8 bytes of payload - * @IOSM_MDM_SEND_16: Send 16 bytes of payload - */ -enum iosm_mdm_send_recv_data { - IOSM_MDM_SEND_2 = 2, - IOSM_MDM_SEND_4 = 4, - IOSM_MDM_SEND_8 = 8, - IOSM_MDM_SEND_16 = 16, -}; - -/** - * struct iosm_ebl_one_error - Structure containing error details - * @error_class: Error type- standard, security and text error - * @error_code: Specific error from error type - */ -struct iosm_ebl_one_error { - u16 error_class; - u16 error_code; -}; - -/** - * struct iosm_ebl_error- Structure with max error type supported - * @error: Array of one_error structure with max errors - */ -struct iosm_ebl_error { - struct iosm_ebl_one_error error[IOSM_MAX_ERRORS]; -}; - -/** - * struct iosm_swid_table - SWID table data for modem - * @number_of_data_sets: Number of swid types - * @sw_id_type: SWID type - SWID - * @sw_id_val: SWID value - * @rf_engine_id_type: RF engine ID type - RF_ENGINE_ID - * @rf_engine_id_val: RF engine ID value - */ -struct iosm_swid_table { - u32 number_of_data_sets; - char sw_id_type[IOSM_EBL_NAME]; - u32 sw_id_val; - char rf_engine_id_type[IOSM_EBL_NAME]; - u32 rf_engine_id_val; -}; - -/** - * struct iosm_flash_msg_control - Data sent to modem - * @action: Action to be performed - * @type: Type of action - * @length: Length of the action - * @arguments: Argument value sent to modem - */ -struct iosm_flash_msg_control { - __le32 action; - __le32 type; - __le32 length; - __le32 arguments; -}; - -/** - * struct iosm_flash_data - Header Data to be sent to modem - * @checksum: Checksum value calculated for the payload data - * @pack_id: Flash Action type - * @msg_length: Payload length - */ -struct iosm_flash_data { - __le16 checksum; - __le16 pack_id; - __le32 msg_length; -}; - -/** - * ipc_flash_boot_psi - Inject PSI image - * @ipc_devlink: Pointer to devlink structure - * @fw: FW image - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_boot_psi(struct iosm_devlink *ipc_devlink, - const struct firmware *fw); - -/** - * ipc_flash_boot_ebl - Inject EBL image - * @ipc_devlink: Pointer to devlink structure - * @fw: FW image - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_boot_ebl(struct iosm_devlink *ipc_devlink, - const struct firmware *fw); - -/** - * ipc_flash_boot_set_capabilities - Set modem bool capabilities in flash - * @ipc_devlink: Pointer to devlink structure - * @mdm_rsp: Pointer to modem response buffer - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_boot_set_capabilities(struct iosm_devlink *ipc_devlink, - u8 *mdm_rsp); - -/** - * ipc_flash_link_establish - Flash link establishment - * @ipc_imem: Pointer to struct iosm_imem - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_link_establish(struct iosm_imem *ipc_imem); - -/** - * ipc_flash_read_swid - Get swid during flash phase - * @ipc_devlink: Pointer to devlink structure - * @mdm_rsp: Pointer to modem response buffer - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_read_swid(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp); - -/** - * ipc_flash_send_fls - Inject Modem subsystem fls file to device - * @ipc_devlink: Pointer to devlink structure - * @fw: FW image - * @mdm_rsp: Pointer to modem response buffer - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_send_fls(struct iosm_devlink *ipc_devlink, - const struct firmware *fw, u8 *mdm_rsp); -#endif diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c index 1cf49e9959f4..9f00e36b7f79 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c @@ -6,8 +6,6 @@ #include #include "iosm_ipc_chnl_cfg.h" -#include "iosm_ipc_devlink.h" -#include "iosm_ipc_flash.h" #include "iosm_ipc_imem.h" #include "iosm_ipc_port.h" @@ -265,12 +263,9 @@ static void ipc_imem_dl_skb_process(struct iosm_imem *ipc_imem, switch (pipe->channel->ctype) { case IPC_CTYPE_CTRL: port_id = pipe->channel->channel_id; - if (port_id == IPC_MEM_CTRL_CHL_ID_7) - ipc_imem_sys_devlink_notify_rx(ipc_imem->ipc_devlink, - skb); - else - wwan_port_rx(ipc_imem->ipc_port[port_id]->iosm_port, - skb); + + /* Pass the packet to the wwan layer. */ + wwan_port_rx(ipc_imem->ipc_port[port_id]->iosm_port, skb); break; case IPC_CTYPE_WWAN: @@ -404,8 +399,19 @@ static void ipc_imem_rom_irq_exec(struct iosm_imem *ipc_imem) { struct ipc_mem_channel *channel; - channel = ipc_imem->ipc_devlink->devlink_sio.channel; + if (ipc_imem->flash_channel_id < 0) { + ipc_imem->rom_exit_code = IMEM_ROM_EXIT_FAIL; + dev_err(ipc_imem->dev, "Missing flash app:%d", + ipc_imem->flash_channel_id); + return; + } + ipc_imem->rom_exit_code = ipc_mmio_get_rom_exit_code(ipc_imem->mmio); + + /* Wake up the flash app to continue or to terminate depending + * on the CP ROM exit code. + */ + channel = &ipc_imem->channels[ipc_imem->flash_channel_id]; complete(&channel->ul_sem); } @@ -566,7 +572,7 @@ static void ipc_imem_handle_irq(struct iosm_imem *ipc_imem, int irq) enum ipc_phase old_phase, phase; bool retry_allocation = false; bool ul_pending = false; - int i; + int ch_id, i; if (irq != IMEM_IRQ_DONT_CARE) ipc_imem->ev_irq_pending[irq] = false; @@ -690,8 +696,11 @@ static void ipc_imem_handle_irq(struct iosm_imem *ipc_imem, int irq) if ((phase == IPC_P_PSI || phase == IPC_P_EBL) && ipc_imem->ipc_requested_state == IPC_MEM_DEVICE_IPC_RUNNING && ipc_mmio_get_ipc_state(ipc_imem->mmio) == - IPC_MEM_DEVICE_IPC_RUNNING) { - complete(&ipc_imem->ipc_devlink->devlink_sio.channel->ul_sem); + IPC_MEM_DEVICE_IPC_RUNNING && + ipc_imem->flash_channel_id >= 0) { + /* Wake up the flash app to open the pipes. */ + ch_id = ipc_imem->flash_channel_id; + complete(&ipc_imem->channels[ch_id].ul_sem); } /* Reset the expected CP state. */ @@ -1167,9 +1176,6 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) ipc_port_deinit(ipc_imem->ipc_port); } - if (ipc_imem->ipc_devlink) - ipc_devlink_deinit(ipc_imem->ipc_devlink); - ipc_imem_device_ipc_uninit(ipc_imem); ipc_imem_channel_reset(ipc_imem); @@ -1252,7 +1258,6 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, void __iomem *mmio, struct device *dev) { struct iosm_imem *ipc_imem = kzalloc(sizeof(*pcie->imem), GFP_KERNEL); - enum ipc_mem_exec_stage stage; if (!ipc_imem) return NULL; @@ -1267,6 +1272,9 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, ipc_imem->cp_version = 0; ipc_imem->device_sleep = IPC_HOST_SLEEP_ENTER_SLEEP; + /* Reset the flash channel id. */ + ipc_imem->flash_channel_id = -1; + /* Reset the max number of configured channels */ ipc_imem->nr_of_channels = 0; @@ -1320,21 +1328,8 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, goto imem_config_fail; } - stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - if (stage == IPC_MEM_EXEC_STAGE_BOOT) { - /* Alloc and Register devlink */ - ipc_imem->ipc_devlink = ipc_devlink_init(ipc_imem); - if (!ipc_imem->ipc_devlink) { - dev_err(ipc_imem->dev, "Devlink register failed"); - goto imem_config_fail; - } - - if (ipc_flash_link_establish(ipc_imem)) - goto devlink_channel_fail; - } return ipc_imem; -devlink_channel_fail: - ipc_devlink_deinit(ipc_imem->ipc_devlink); + imem_config_fail: hrtimer_cancel(&ipc_imem->td_alloc_timer); hrtimer_cancel(&ipc_imem->fast_update_timer); @@ -1366,51 +1361,3 @@ void ipc_imem_td_update_timer_suspend(struct iosm_imem *ipc_imem, bool suspend) { ipc_imem->td_update_timer_suspended = suspend; } - -/* Verify the CP execution state, copy the chip info, - * change the execution phase to ROM - */ -static int ipc_imem_devlink_trigger_chip_info_cb(struct iosm_imem *ipc_imem, - int arg, void *msg, - size_t msgsize) -{ - enum ipc_mem_exec_stage stage; - struct sk_buff *skb; - int rc = -EINVAL; - size_t size; - - /* Test the CP execution state. */ - stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - if (stage != IPC_MEM_EXEC_STAGE_BOOT) { - dev_err(ipc_imem->dev, - "Execution_stage: expected BOOT, received = %X", stage); - goto trigger_chip_info_fail; - } - /* Allocate a new sk buf for the chip info. */ - size = ipc_imem->mmio->chip_info_size; - if (size > IOSM_CHIP_INFO_SIZE_MAX) - goto trigger_chip_info_fail; - - skb = ipc_pcie_alloc_local_skb(ipc_imem->pcie, GFP_ATOMIC, size); - if (!skb) { - dev_err(ipc_imem->dev, "exhausted skbuf kernel DL memory"); - rc = -ENOMEM; - goto trigger_chip_info_fail; - } - /* Copy the chip info characters into the ipc_skb. */ - ipc_mmio_copy_chip_info(ipc_imem->mmio, skb_put(skb, size), size); - /* First change to the ROM boot phase. */ - dev_dbg(ipc_imem->dev, "execution_stage[%X] eq. BOOT", stage); - ipc_imem->phase = ipc_imem_phase_update(ipc_imem); - ipc_imem_sys_devlink_notify_rx(ipc_imem->ipc_devlink, skb); - rc = 0; -trigger_chip_info_fail: - return rc; -} - -int ipc_imem_devlink_trigger_chip_info(struct iosm_imem *ipc_imem) -{ - return ipc_task_queue_send_task(ipc_imem, - ipc_imem_devlink_trigger_chip_info_cb, - 0, NULL, 0, true); -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index 6be6708b4eec..dc65b0712261 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -69,7 +69,7 @@ struct ipc_chnl_cfg; #define IMEM_IRQ_DONT_CARE (-1) -#define IPC_MEM_MAX_CHANNELS 8 +#define IPC_MEM_MAX_CHANNELS 7 #define IPC_MEM_MUX_IP_SESSION_ENTRIES 8 @@ -98,7 +98,6 @@ struct ipc_chnl_cfg; #define IPC_MEM_DL_ETH_OFFSET 16 #define IPC_CB(skb) ((struct ipc_skb_cb *)((skb)->cb)) -#define IOSM_CHIP_INFO_SIZE_MAX 100 #define FULLY_FUNCTIONAL 0 @@ -305,9 +304,9 @@ enum ipc_phase { * @ipc_port: IPC PORT data structure pointer * @pcie: IPC PCIe * @dev: Pointer to device structure + * @flash_channel_id: Reserved channel id for flashing to RAM. * @ipc_requested_state: Expected IPC state on CP. * @channels: Channel list with UL/DL pipe pairs. - * @ipc_devlink: IPC Devlink data structure pointer * @ipc_status: local ipc_status * @nr_of_channels: number of configured channels * @startup_timer: startup timer for NAND support. @@ -350,9 +349,9 @@ struct iosm_imem { struct iosm_cdev *ipc_port[IPC_MEM_MAX_CHANNELS]; struct iosm_pcie *pcie; struct device *dev; + int flash_channel_id; enum ipc_mem_device_ipc_state ipc_requested_state; struct ipc_mem_channel channels[IPC_MEM_MAX_CHANNELS]; - struct iosm_devlink *ipc_devlink; u32 ipc_status; u32 nr_of_channels; struct hrtimer startup_timer; @@ -576,15 +575,4 @@ void ipc_imem_ipc_init_check(struct iosm_imem *ipc_imem); */ void ipc_imem_channel_init(struct iosm_imem *ipc_imem, enum ipc_ctype ctype, struct ipc_chnl_cfg chnl_cfg, u32 irq_moderation); - -/** - * ipc_imem_devlink_trigger_chip_info - Inform devlink that the chip - * information are available if the - * flashing to RAM interworking shall be - * executed. - * @ipc_imem: Pointer to imem structure - * - * Returns: 0 on success, -1 on failure - */ -int ipc_imem_devlink_trigger_chip_info(struct iosm_imem *ipc_imem); #endif diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c index b885a6570235..0a472ce77370 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c @@ -6,7 +6,6 @@ #include #include "iosm_ipc_chnl_cfg.h" -#include "iosm_ipc_devlink.h" #include "iosm_ipc_imem.h" #include "iosm_ipc_imem_ops.h" #include "iosm_ipc_port.h" @@ -332,319 +331,3 @@ int ipc_imem_sys_cdev_write(struct iosm_cdev *ipc_cdev, struct sk_buff *skb) out: return ret; } - -/* Open a SIO link to CP and return the channel instance */ -struct ipc_mem_channel *ipc_imem_sys_devlink_open(struct iosm_imem *ipc_imem) -{ - struct ipc_mem_channel *channel; - enum ipc_phase phase; - int channel_id; - - phase = ipc_imem_phase_update(ipc_imem); - switch (phase) { - case IPC_P_OFF: - case IPC_P_ROM: - /* Get a channel id as flash id and reserve it. */ - channel_id = ipc_imem_channel_alloc(ipc_imem, - IPC_MEM_CTRL_CHL_ID_7, - IPC_CTYPE_CTRL); - - if (channel_id < 0) { - dev_err(ipc_imem->dev, - "reservation of a flash channel id failed"); - goto error; - } - - ipc_imem->ipc_devlink->devlink_sio.channel_id = channel_id; - channel = &ipc_imem->channels[channel_id]; - - /* Enqueue chip info data to be read */ - if (ipc_imem_devlink_trigger_chip_info(ipc_imem)) { - dev_err(ipc_imem->dev, "Enqueue of chip info failed"); - channel->state = IMEM_CHANNEL_FREE; - goto error; - } - - return channel; - - case IPC_P_PSI: - case IPC_P_EBL: - ipc_imem->cp_version = ipc_mmio_get_cp_version(ipc_imem->mmio); - if (ipc_imem->cp_version == -1) { - dev_err(ipc_imem->dev, "invalid CP version"); - goto error; - } - - channel_id = ipc_imem->ipc_devlink->devlink_sio.channel_id; - return ipc_imem_channel_open(ipc_imem, channel_id, - IPC_HP_CDEV_OPEN); - - default: - /* CP is in the wrong state (e.g. CRASH or CD_READY) */ - dev_err(ipc_imem->dev, "SIO open refused, phase %d", phase); - } -error: - return NULL; -} - -/* Release a SIO channel link to CP. */ -void ipc_imem_sys_devlink_close(struct iosm_devlink *ipc_devlink) -{ - struct iosm_imem *ipc_imem = ipc_devlink->pcie->imem; - int boot_check_timeout = BOOT_CHECK_DEFAULT_TIMEOUT; - enum ipc_mem_exec_stage exec_stage; - struct ipc_mem_channel *channel; - enum ipc_phase curr_phase; - int status = 0; - u32 tail = 0; - - channel = ipc_imem->ipc_devlink->devlink_sio.channel; - curr_phase = ipc_imem->phase; - /* Increase the total wait time to boot_check_timeout */ - do { - exec_stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - if (exec_stage == IPC_MEM_EXEC_STAGE_RUN || - exec_stage == IPC_MEM_EXEC_STAGE_PSI) - break; - msleep(20); - boot_check_timeout -= 20; - } while (boot_check_timeout > 0); - - /* If there are any pending TDs then wait for Timeout/Completion before - * closing pipe. - */ - if (channel->ul_pipe.old_tail != channel->ul_pipe.old_head) { - status = wait_for_completion_interruptible_timeout - (&ipc_imem->ul_pend_sem, - msecs_to_jiffies(IPC_PEND_DATA_TIMEOUT)); - if (status == 0) { - dev_dbg(ipc_imem->dev, - "Data Timeout on UL-Pipe:%d Head:%d Tail:%d", - channel->ul_pipe.pipe_nr, - channel->ul_pipe.old_head, - channel->ul_pipe.old_tail); - } - } - - ipc_protocol_get_head_tail_index(ipc_imem->ipc_protocol, - &channel->dl_pipe, NULL, &tail); - - if (tail != channel->dl_pipe.old_tail) { - status = wait_for_completion_interruptible_timeout - (&ipc_imem->dl_pend_sem, - msecs_to_jiffies(IPC_PEND_DATA_TIMEOUT)); - if (status == 0) { - dev_dbg(ipc_imem->dev, - "Data Timeout on DL-Pipe:%d Head:%d Tail:%d", - channel->dl_pipe.pipe_nr, - channel->dl_pipe.old_head, - channel->dl_pipe.old_tail); - } - } - - /* Due to wait for completion in messages, there is a small window - * between closing the pipe and updating the channel is closed. In this - * small window there could be HP update from Host Driver. Hence update - * the channel state as CLOSING to aviod unnecessary interrupt - * towards CP. - */ - channel->state = IMEM_CHANNEL_CLOSING; - /* Release the pipe resources */ - ipc_imem_pipe_cleanup(ipc_imem, &channel->ul_pipe); - ipc_imem_pipe_cleanup(ipc_imem, &channel->dl_pipe); -} - -void ipc_imem_sys_devlink_notify_rx(struct iosm_devlink *ipc_devlink, - struct sk_buff *skb) -{ - skb_queue_tail(&ipc_devlink->devlink_sio.rx_list, skb); - complete(&ipc_devlink->devlink_sio.read_sem); -} - -/* PSI transfer */ -static int ipc_imem_sys_psi_transfer(struct iosm_imem *ipc_imem, - struct ipc_mem_channel *channel, - unsigned char *buf, int count) -{ - int psi_start_timeout = PSI_START_DEFAULT_TIMEOUT; - enum ipc_mem_exec_stage exec_stage; - - dma_addr_t mapping = 0; - int ret; - - ret = ipc_pcie_addr_map(ipc_imem->pcie, buf, count, &mapping, - DMA_TO_DEVICE); - if (ret) - goto pcie_addr_map_fail; - - /* Save the PSI information for the CP ROM driver on the doorbell - * scratchpad. - */ - ipc_mmio_set_psi_addr_and_size(ipc_imem->mmio, mapping, count); - ipc_doorbell_fire(ipc_imem->pcie, 0, IPC_MEM_EXEC_STAGE_BOOT); - - ret = wait_for_completion_interruptible_timeout - (&channel->ul_sem, - msecs_to_jiffies(IPC_PSI_TRANSFER_TIMEOUT)); - - if (ret <= 0) { - dev_err(ipc_imem->dev, "Failed PSI transfer to CP, Error-%d", - ret); - goto psi_transfer_fail; - } - /* If the PSI download fails, return the CP boot ROM exit code */ - if (ipc_imem->rom_exit_code != IMEM_ROM_EXIT_OPEN_EXT && - ipc_imem->rom_exit_code != IMEM_ROM_EXIT_CERT_EXT) { - ret = (-1) * ((int)ipc_imem->rom_exit_code); - goto psi_transfer_fail; - } - - dev_dbg(ipc_imem->dev, "PSI image successfully downloaded"); - - /* Wait psi_start_timeout milliseconds until the CP PSI image is - * running and updates the execution_stage field with - * IPC_MEM_EXEC_STAGE_PSI. Verify the execution stage. - */ - do { - exec_stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - - if (exec_stage == IPC_MEM_EXEC_STAGE_PSI) - break; - - msleep(20); - psi_start_timeout -= 20; - } while (psi_start_timeout > 0); - - if (exec_stage != IPC_MEM_EXEC_STAGE_PSI) - goto psi_transfer_fail; /* Unknown status of CP PSI process. */ - - ipc_imem->phase = IPC_P_PSI; - - /* Enter the PSI phase. */ - dev_dbg(ipc_imem->dev, "execution_stage[%X] eq. PSI", exec_stage); - - /* Request the RUNNING state from CP and wait until it was reached - * or timeout. - */ - ipc_imem_ipc_init_check(ipc_imem); - - ret = wait_for_completion_interruptible_timeout - (&channel->ul_sem, msecs_to_jiffies(IPC_PSI_TRANSFER_TIMEOUT)); - if (ret <= 0) { - dev_err(ipc_imem->dev, - "Failed PSI RUNNING state on CP, Error-%d", ret); - goto psi_transfer_fail; - } - - if (ipc_mmio_get_ipc_state(ipc_imem->mmio) != - IPC_MEM_DEVICE_IPC_RUNNING) { - dev_err(ipc_imem->dev, - "ch[%d] %s: unexpected CP IPC state %d, not RUNNING", - channel->channel_id, - ipc_imem_phase_get_string(ipc_imem->phase), - ipc_mmio_get_ipc_state(ipc_imem->mmio)); - - goto psi_transfer_fail; - } - - /* Create the flash channel for the transfer of the images. */ - if (!ipc_imem_sys_devlink_open(ipc_imem)) { - dev_err(ipc_imem->dev, "can't open flash_channel"); - goto psi_transfer_fail; - } - - ret = 0; -psi_transfer_fail: - ipc_pcie_addr_unmap(ipc_imem->pcie, count, mapping, DMA_TO_DEVICE); -pcie_addr_map_fail: - return ret; -} - -int ipc_imem_sys_devlink_write(struct iosm_devlink *ipc_devlink, - unsigned char *buf, int count) -{ - struct iosm_imem *ipc_imem = ipc_devlink->pcie->imem; - struct ipc_mem_channel *channel; - struct sk_buff *skb; - dma_addr_t mapping; - int ret; - - channel = ipc_imem->ipc_devlink->devlink_sio.channel; - - /* In the ROM phase the PSI image is passed to CP about a specific - * shared memory area and doorbell scratchpad directly. - */ - if (ipc_imem->phase == IPC_P_ROM) { - ret = ipc_imem_sys_psi_transfer(ipc_imem, channel, buf, count); - /* If the PSI transfer fails then send crash - * Signature. - */ - if (ret > 0) - ipc_imem_msg_send_feature_set(ipc_imem, - IPC_MEM_INBAND_CRASH_SIG, - false); - goto out; - } - - /* Allocate skb memory for the uplink buffer. */ - skb = ipc_pcie_alloc_skb(ipc_devlink->pcie, count, GFP_KERNEL, &mapping, - DMA_TO_DEVICE, 0); - if (!skb) { - ret = -ENOMEM; - goto out; - } - - memcpy(skb_put(skb, count), buf, count); - - IPC_CB(skb)->op_type = UL_USR_OP_BLOCKED; - - /* Add skb to the uplink skbuf accumulator. */ - skb_queue_tail(&channel->ul_list, skb); - - /* Inform the IPC tasklet to pass uplink IP packets to CP. */ - if (!ipc_imem_call_cdev_write(ipc_imem)) { - ret = wait_for_completion_interruptible(&channel->ul_sem); - - if (ret < 0) { - dev_err(ipc_imem->dev, - "ch[%d] no CP confirmation, status = %d", - channel->channel_id, ret); - ipc_pcie_kfree_skb(ipc_devlink->pcie, skb); - goto out; - } - } - ret = 0; -out: - return ret; -} - -int ipc_imem_sys_devlink_read(struct iosm_devlink *devlink, u8 *data, - u32 bytes_to_read, u32 *bytes_read) -{ - struct sk_buff *skb = NULL; - int rc = 0; - - /* check skb is available in rx_list or wait for skb */ - devlink->devlink_sio.devlink_read_pend = 1; - while (!skb && !(skb = skb_dequeue(&devlink->devlink_sio.rx_list))) { - if (!wait_for_completion_interruptible_timeout - (&devlink->devlink_sio.read_sem, - msecs_to_jiffies(IPC_READ_TIMEOUT))) { - dev_err(devlink->dev, "Read timedout"); - rc = -ETIMEDOUT; - goto devlink_read_fail; - } - } - devlink->devlink_sio.devlink_read_pend = 0; - if (bytes_to_read < skb->len) { - dev_err(devlink->dev, "Invalid size,expected len %d", skb->len); - rc = -EINVAL; - goto devlink_read_fail; - } - *bytes_read = skb->len; - memcpy(data, skb->data, skb->len); - -devlink_read_fail: - ipc_pcie_kfree_skb(devlink->pcie, skb); - return rc; -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h index f0c88ac5643c..2007fe23e9a5 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h @@ -9,7 +9,7 @@ #include "iosm_ipc_mux_codec.h" /* Maximum wait time for blocking read */ -#define IPC_READ_TIMEOUT 3000 +#define IPC_READ_TIMEOUT 500 /* The delay in ms for defering the unregister */ #define SIO_UNREGISTER_DEFER_DELAY_MS 1 @@ -98,51 +98,4 @@ int ipc_imem_sys_wwan_transmit(struct iosm_imem *ipc_imem, int if_id, */ void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem, enum ipc_mux_protocol mux_type); - -/** - * ipc_imem_sys_devlink_open - Open a Flash/CD Channel link to CP - * @ipc_imem: iosm_imem instance - * - * Return: channel instance on success, NULL for failure - */ -struct ipc_mem_channel *ipc_imem_sys_devlink_open(struct iosm_imem *ipc_imem); - -/** - * ipc_imem_sys_devlink_close - Release a Flash/CD channel link to CP - * @ipc_devlink: Pointer to ipc_devlink data-struct - * - */ -void ipc_imem_sys_devlink_close(struct iosm_devlink *ipc_devlink); - -/** - * ipc_imem_sys_devlink_notify_rx - Receive downlink characters from CP, - * the downlink skbuf is added at the end of the - * downlink or rx list - * @ipc_devlink: Pointer to ipc_devlink data-struct - * @skb: Pointer to sk buffer - */ -void ipc_imem_sys_devlink_notify_rx(struct iosm_devlink *ipc_devlink, - struct sk_buff *skb); - -/** - * ipc_imem_sys_devlink_read - Copy the rx data and free the skbuf - * @ipc_devlink: Devlink instance - * @data: Buffer to read the data from modem - * @bytes_to_read: Size of destination buffer - * @bytes_read: Number of bytes read - * - * Return: 0 on success and failure value on error - */ -int ipc_imem_sys_devlink_read(struct iosm_devlink *ipc_devlink, u8 *data, - u32 bytes_to_read, u32 *bytes_read); - -/** - * ipc_imem_sys_devlink_write - Route the uplink buffer to CP - * @ipc_devlink: Devlink_sio instance - * @buf: Pointer to buffer - * @count: Number of data bytes to write - * Return: 0 on success and failure value on error - */ -int ipc_imem_sys_devlink_write(struct iosm_devlink *ipc_devlink, - unsigned char *buf, int count); #endif From 227b9644ab16d2ecd98d593edbe15c32c0c9620a Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Thu, 16 Sep 2021 11:37:38 +0800 Subject: [PATCH 11/12] net/tls: support SM4 GCM/CCM algorithm The RFC8998 specification defines the use of the ShangMi algorithm cipher suites in TLS 1.3, and also supports the GCM/CCM mode using the SM4 algorithm. Signed-off-by: Tianjia Zhang Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/uapi/linux/tls.h | 30 ++++++++++++++++++++++++++ net/tls/tls_main.c | 46 ++++++++++++++++++++++++++++++++++++++++ net/tls/tls_sw.c | 34 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/include/uapi/linux/tls.h b/include/uapi/linux/tls.h index 0d54baea1d8d..5f38be0ec0f3 100644 --- a/include/uapi/linux/tls.h +++ b/include/uapi/linux/tls.h @@ -84,6 +84,20 @@ #define TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE 16 #define TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE 8 +#define TLS_CIPHER_SM4_GCM 55 +#define TLS_CIPHER_SM4_GCM_IV_SIZE 8 +#define TLS_CIPHER_SM4_GCM_KEY_SIZE 16 +#define TLS_CIPHER_SM4_GCM_SALT_SIZE 4 +#define TLS_CIPHER_SM4_GCM_TAG_SIZE 16 +#define TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE 8 + +#define TLS_CIPHER_SM4_CCM 56 +#define TLS_CIPHER_SM4_CCM_IV_SIZE 8 +#define TLS_CIPHER_SM4_CCM_KEY_SIZE 16 +#define TLS_CIPHER_SM4_CCM_SALT_SIZE 4 +#define TLS_CIPHER_SM4_CCM_TAG_SIZE 16 +#define TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE 8 + #define TLS_SET_RECORD_TYPE 1 #define TLS_GET_RECORD_TYPE 2 @@ -124,6 +138,22 @@ struct tls12_crypto_info_chacha20_poly1305 { unsigned char rec_seq[TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE]; }; +struct tls12_crypto_info_sm4_gcm { + struct tls_crypto_info info; + unsigned char iv[TLS_CIPHER_SM4_GCM_IV_SIZE]; + unsigned char key[TLS_CIPHER_SM4_GCM_KEY_SIZE]; + unsigned char salt[TLS_CIPHER_SM4_GCM_SALT_SIZE]; + unsigned char rec_seq[TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE]; +}; + +struct tls12_crypto_info_sm4_ccm { + struct tls_crypto_info info; + unsigned char iv[TLS_CIPHER_SM4_CCM_IV_SIZE]; + unsigned char key[TLS_CIPHER_SM4_CCM_KEY_SIZE]; + unsigned char salt[TLS_CIPHER_SM4_CCM_SALT_SIZE]; + unsigned char rec_seq[TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE]; +}; + enum { TLS_INFO_UNSPEC, TLS_INFO_VERSION, diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index fde56ff49163..d44399efeac6 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -421,6 +421,46 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval, rc = -EFAULT; break; } + case TLS_CIPHER_SM4_GCM: { + struct tls12_crypto_info_sm4_gcm *sm4_gcm_info = + container_of(crypto_info, + struct tls12_crypto_info_sm4_gcm, info); + + if (len != sizeof(*sm4_gcm_info)) { + rc = -EINVAL; + goto out; + } + lock_sock(sk); + memcpy(sm4_gcm_info->iv, + cctx->iv + TLS_CIPHER_SM4_GCM_SALT_SIZE, + TLS_CIPHER_SM4_GCM_IV_SIZE); + memcpy(sm4_gcm_info->rec_seq, cctx->rec_seq, + TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE); + release_sock(sk); + if (copy_to_user(optval, sm4_gcm_info, sizeof(*sm4_gcm_info))) + rc = -EFAULT; + break; + } + case TLS_CIPHER_SM4_CCM: { + struct tls12_crypto_info_sm4_ccm *sm4_ccm_info = + container_of(crypto_info, + struct tls12_crypto_info_sm4_ccm, info); + + if (len != sizeof(*sm4_ccm_info)) { + rc = -EINVAL; + goto out; + } + lock_sock(sk); + memcpy(sm4_ccm_info->iv, + cctx->iv + TLS_CIPHER_SM4_CCM_SALT_SIZE, + TLS_CIPHER_SM4_CCM_IV_SIZE); + memcpy(sm4_ccm_info->rec_seq, cctx->rec_seq, + TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE); + release_sock(sk); + if (copy_to_user(optval, sm4_ccm_info, sizeof(*sm4_ccm_info))) + rc = -EFAULT; + break; + } default: rc = -EINVAL; } @@ -524,6 +564,12 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, case TLS_CIPHER_CHACHA20_POLY1305: optsize = sizeof(struct tls12_crypto_info_chacha20_poly1305); break; + case TLS_CIPHER_SM4_GCM: + optsize = sizeof(struct tls12_crypto_info_sm4_gcm); + break; + case TLS_CIPHER_SM4_CCM: + optsize = sizeof(struct tls12_crypto_info_sm4_ccm); + break; default: rc = -EINVAL; goto err_crypto_info; diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 4feb95e34b64..989d1423a245 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -2424,6 +2424,40 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) cipher_name = "rfc7539(chacha20,poly1305)"; break; } + case TLS_CIPHER_SM4_GCM: { + struct tls12_crypto_info_sm4_gcm *sm4_gcm_info; + + sm4_gcm_info = (void *)crypto_info; + nonce_size = TLS_CIPHER_SM4_GCM_IV_SIZE; + tag_size = TLS_CIPHER_SM4_GCM_TAG_SIZE; + iv_size = TLS_CIPHER_SM4_GCM_IV_SIZE; + iv = sm4_gcm_info->iv; + rec_seq_size = TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE; + rec_seq = sm4_gcm_info->rec_seq; + keysize = TLS_CIPHER_SM4_GCM_KEY_SIZE; + key = sm4_gcm_info->key; + salt = sm4_gcm_info->salt; + salt_size = TLS_CIPHER_SM4_GCM_SALT_SIZE; + cipher_name = "gcm(sm4)"; + break; + } + case TLS_CIPHER_SM4_CCM: { + struct tls12_crypto_info_sm4_ccm *sm4_ccm_info; + + sm4_ccm_info = (void *)crypto_info; + nonce_size = TLS_CIPHER_SM4_CCM_IV_SIZE; + tag_size = TLS_CIPHER_SM4_CCM_TAG_SIZE; + iv_size = TLS_CIPHER_SM4_CCM_IV_SIZE; + iv = sm4_ccm_info->iv; + rec_seq_size = TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE; + rec_seq = sm4_ccm_info->rec_seq; + keysize = TLS_CIPHER_SM4_CCM_KEY_SIZE; + key = sm4_ccm_info->key; + salt = sm4_ccm_info->salt; + salt_size = TLS_CIPHER_SM4_CCM_SALT_SIZE; + cipher_name = "ccm(sm4)"; + break; + } default: rc = -EINVAL; goto free_priv; From 4b5a3ab17c6c942bd428984b6b37fe3c07f18ab3 Mon Sep 17 00:00:00 2001 From: Srujana Challa Date: Thu, 16 Sep 2021 15:11:14 +0530 Subject: [PATCH 12/12] octeontx2-af: Hardware configuration for inline IPsec On OcteonTX2/CN10K SoC, the admin function (AF) is the only one with all priviliges to configure HW and alloc resources, PFs and it's VFs have to request AF via mailbox for all their needs. This patch adds new mailbox messages for CPT PFs and VFs to configure HW resources for inline-IPsec. Signed-off-by: Subbaraya Sundeep Signed-off-by: Srujana Challa Signed-off-by: Vidya Sagar Velumuri Signed-off-by: David S. Miller --- .../ethernet/marvell/octeontx2/af/common.h | 1 + .../net/ethernet/marvell/octeontx2/af/mbox.h | 60 +++++++- .../net/ethernet/marvell/octeontx2/af/rvu.c | 54 +++++++ .../net/ethernet/marvell/octeontx2/af/rvu.h | 2 + .../ethernet/marvell/octeontx2/af/rvu_cn10k.c | 4 +- .../ethernet/marvell/octeontx2/af/rvu_cpt.c | 135 ++++++++++++++++++ .../ethernet/marvell/octeontx2/af/rvu_nix.c | 112 +++++++++++++++ .../ethernet/marvell/octeontx2/af/rvu_reg.h | 2 + 8 files changed, 367 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h index d9bea13f15b8..8931864ee110 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h @@ -191,6 +191,7 @@ enum nix_scheduler { #define NIX_CHAN_SDP_CH_START (0x700ull) #define NIX_CHAN_SDP_CHX(a) (NIX_CHAN_SDP_CH_START + (a)) #define NIX_CHAN_SDP_NUM_CHANS 256 +#define NIX_CHAN_CPT_CH_START (0x800ull) /* The mask is to extract lower 10-bits of channel number * which CPT will pass to X2P. diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index 154877706a0e..f77f745be05b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -186,6 +186,8 @@ M(CPT_LF_ALLOC, 0xA00, cpt_lf_alloc, cpt_lf_alloc_req_msg, \ M(CPT_LF_FREE, 0xA01, cpt_lf_free, msg_req, msg_rsp) \ M(CPT_RD_WR_REGISTER, 0xA02, cpt_rd_wr_register, cpt_rd_wr_reg_msg, \ cpt_rd_wr_reg_msg) \ +M(CPT_INLINE_IPSEC_CFG, 0xA04, cpt_inline_ipsec_cfg, \ + cpt_inline_ipsec_cfg_msg, msg_rsp) \ M(CPT_STATS, 0xA05, cpt_sts, cpt_sts_req, cpt_sts_rsp) \ M(CPT_RXC_TIME_CFG, 0xA06, cpt_rxc_time_cfg, cpt_rxc_time_cfg_req, \ msg_rsp) \ @@ -270,6 +272,10 @@ M(NIX_BP_ENABLE, 0x8016, nix_bp_enable, nix_bp_cfg_req, \ nix_bp_cfg_rsp) \ M(NIX_BP_DISABLE, 0x8017, nix_bp_disable, nix_bp_cfg_req, msg_rsp) \ M(NIX_GET_MAC_ADDR, 0x8018, nix_get_mac_addr, msg_req, nix_get_mac_addr_rsp) \ +M(NIX_INLINE_IPSEC_CFG, 0x8019, nix_inline_ipsec_cfg, \ + nix_inline_ipsec_cfg, msg_rsp) \ +M(NIX_INLINE_IPSEC_LF_CFG, 0x801a, nix_inline_ipsec_lf_cfg, \ + nix_inline_ipsec_lf_cfg, msg_rsp) \ M(NIX_CN10K_AQ_ENQ, 0x801b, nix_cn10k_aq_enq, nix_cn10k_aq_enq_req, \ nix_cn10k_aq_enq_rsp) \ M(NIX_GET_HW_INFO, 0x801c, nix_get_hw_info, msg_req, nix_hw_info) \ @@ -1065,6 +1071,40 @@ struct nix_bp_cfg_rsp { u8 chan_cnt; /* Number of channel for which bpids are assigned */ }; +/* Global NIX inline IPSec configuration */ +struct nix_inline_ipsec_cfg { + struct mbox_msghdr hdr; + u32 cpt_credit; + struct { + u8 egrp; + u8 opcode; + u16 param1; + u16 param2; + } gen_cfg; + struct { + u16 cpt_pf_func; + u8 cpt_slot; + } inst_qsel; + u8 enable; +}; + +/* Per NIX LF inline IPSec configuration */ +struct nix_inline_ipsec_lf_cfg { + struct mbox_msghdr hdr; + u64 sa_base_addr; + struct { + u32 tag_const; + u16 lenm1_max; + u8 sa_pow2_size; + u8 tt; + } ipsec_cfg0; + struct { + u32 sa_idx_max; + u8 sa_idx_w; + } ipsec_cfg1; + u8 enable; +}; + struct nix_hw_info { struct mbox_msghdr hdr; u16 rsvs16; @@ -1399,7 +1439,9 @@ enum cpt_af_status { CPT_AF_ERR_LF_INVALID = -903, CPT_AF_ERR_ACCESS_DENIED = -904, CPT_AF_ERR_SSO_PF_FUNC_INVALID = -905, - CPT_AF_ERR_NIX_PF_FUNC_INVALID = -906 + CPT_AF_ERR_NIX_PF_FUNC_INVALID = -906, + CPT_AF_ERR_INLINE_IPSEC_INB_ENA = -907, + CPT_AF_ERR_INLINE_IPSEC_OUT_ENA = -908 }; /* CPT mbox message formats */ @@ -1420,6 +1462,22 @@ struct cpt_lf_alloc_req_msg { int blkaddr; }; +#define CPT_INLINE_INBOUND 0 +#define CPT_INLINE_OUTBOUND 1 + +/* Mailbox message request format for CPT IPsec + * inline inbound and outbound configuration. + */ +struct cpt_inline_ipsec_cfg_msg { + struct mbox_msghdr hdr; + u8 enable; + u8 slot; + u8 dir; + u8 sso_pf_func_ovrd; + u16 sso_pf_func; /* inbound path SSO_PF_FUNC */ + u16 nix_pf_func; /* outbound path NIX_PF_FUNC */ +}; + /* Mailbox message request and response format for CPT stats. */ struct cpt_sts_req { struct mbox_msghdr hdr; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 35836903b7fb..3bba8bc91f35 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -1287,6 +1287,60 @@ static int rvu_lookup_rsrc(struct rvu *rvu, struct rvu_block *block, return (val & 0xFFF); } +int rvu_get_blkaddr_from_slot(struct rvu *rvu, int blktype, u16 pcifunc, + u16 global_slot, u16 *slot_in_block) +{ + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + int numlfs, total_lfs = 0, nr_blocks = 0; + int i, num_blkaddr[BLK_COUNT] = { 0 }; + struct rvu_block *block; + int blkaddr = -ENODEV; + u16 start_slot; + + if (!is_blktype_attached(pfvf, blktype)) + return -ENODEV; + + /* Get all the block addresses from which LFs are attached to + * the given pcifunc in num_blkaddr[]. + */ + for (blkaddr = BLKADDR_RVUM; blkaddr < BLK_COUNT; blkaddr++) { + block = &rvu->hw->block[blkaddr]; + if (block->type != blktype) + continue; + if (!is_block_implemented(rvu->hw, blkaddr)) + continue; + + numlfs = rvu_get_rsrc_mapcount(pfvf, blkaddr); + if (numlfs) { + total_lfs += numlfs; + num_blkaddr[nr_blocks] = blkaddr; + nr_blocks++; + } + } + + if (global_slot >= total_lfs) + return -ENODEV; + + /* Based on the given global slot number retrieve the + * correct block address out of all attached block + * addresses and slot number in that block. + */ + total_lfs = 0; + blkaddr = -ENODEV; + for (i = 0; i < nr_blocks; i++) { + numlfs = rvu_get_rsrc_mapcount(pfvf, num_blkaddr[i]); + total_lfs += numlfs; + if (global_slot < total_lfs) { + blkaddr = num_blkaddr[i]; + start_slot = total_lfs - numlfs; + *slot_in_block = global_slot - start_slot; + break; + } + } + + return blkaddr; +} + static void rvu_detach_block(struct rvu *rvu, int pcifunc, int blktype) { struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index 1d9411232f1d..f59169cdc0db 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -656,6 +656,8 @@ int rvu_lf_reset(struct rvu *rvu, struct rvu_block *block, int lf); int rvu_get_blkaddr(struct rvu *rvu, int blktype, u16 pcifunc); int rvu_poll_reg(struct rvu *rvu, u64 block, u64 offset, u64 mask, bool zero); int rvu_get_num_lbk_chans(void); +int rvu_get_blkaddr_from_slot(struct rvu *rvu, int blktype, u16 pcifunc, + u16 global_slot, u16 *slot_in_block); /* RVU HW reg validation */ enum regmap_block { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c index 46a41cfff575..7dbbc115cde4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c @@ -334,8 +334,8 @@ int rvu_set_channels_base(struct rvu *rvu) /* Out of 4096 channels start CPT from 2048 so * that MSB for CPT channels is always set */ - if (cpt_chan_base <= 0x800) { - hw->cpt_chan_base = 0x800; + if (cpt_chan_base <= NIX_CHAN_CPT_CH_START) { + hw->cpt_chan_base = NIX_CHAN_CPT_CH_START; } else { dev_err(rvu->dev, "CPT channels could not fit in the range 2048-4095\n"); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c index 1f90a7403392..267d092b8e97 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c @@ -197,6 +197,141 @@ int rvu_mbox_handler_cpt_lf_free(struct rvu *rvu, struct msg_req *req, return ret; } +static int cpt_inline_ipsec_cfg_inbound(struct rvu *rvu, int blkaddr, u8 cptlf, + struct cpt_inline_ipsec_cfg_msg *req) +{ + u16 sso_pf_func = req->sso_pf_func; + u8 nix_sel; + u64 val; + + val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf)); + if (req->enable && (val & BIT_ULL(16))) { + /* IPSec inline outbound path is already enabled for a given + * CPT LF, HRM states that inline inbound & outbound paths + * must not be enabled at the same time for a given CPT LF + */ + return CPT_AF_ERR_INLINE_IPSEC_INB_ENA; + } + /* Check if requested 'CPTLF <=> SSOLF' mapping is valid */ + if (sso_pf_func && !is_pffunc_map_valid(rvu, sso_pf_func, BLKTYPE_SSO)) + return CPT_AF_ERR_SSO_PF_FUNC_INVALID; + + nix_sel = (blkaddr == BLKADDR_CPT1) ? 1 : 0; + /* Enable CPT LF for IPsec inline inbound operations */ + if (req->enable) + val |= BIT_ULL(9); + else + val &= ~BIT_ULL(9); + + val |= (u64)nix_sel << 8; + rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); + + if (sso_pf_func) { + /* Set SSO_PF_FUNC */ + val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf)); + val |= (u64)sso_pf_func << 32; + val |= (u64)req->nix_pf_func << 48; + rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val); + } + if (req->sso_pf_func_ovrd) + /* Set SSO_PF_FUNC_OVRD for inline IPSec */ + rvu_write64(rvu, blkaddr, CPT_AF_ECO, 0x1); + + /* Configure the X2P Link register with the cpt base channel number and + * range of channels it should propagate to X2P + */ + if (!is_rvu_otx2(rvu)) { + val = (ilog2(NIX_CHAN_CPT_X2P_MASK + 1) << 16); + val |= rvu->hw->cpt_chan_base; + + rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0), val); + rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1), val); + } + + return 0; +} + +static int cpt_inline_ipsec_cfg_outbound(struct rvu *rvu, int blkaddr, u8 cptlf, + struct cpt_inline_ipsec_cfg_msg *req) +{ + u16 nix_pf_func = req->nix_pf_func; + int nix_blkaddr; + u8 nix_sel; + u64 val; + + val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf)); + if (req->enable && (val & BIT_ULL(9))) { + /* IPSec inline inbound path is already enabled for a given + * CPT LF, HRM states that inline inbound & outbound paths + * must not be enabled at the same time for a given CPT LF + */ + return CPT_AF_ERR_INLINE_IPSEC_OUT_ENA; + } + + /* Check if requested 'CPTLF <=> NIXLF' mapping is valid */ + if (nix_pf_func && !is_pffunc_map_valid(rvu, nix_pf_func, BLKTYPE_NIX)) + return CPT_AF_ERR_NIX_PF_FUNC_INVALID; + + /* Enable CPT LF for IPsec inline outbound operations */ + if (req->enable) + val |= BIT_ULL(16); + else + val &= ~BIT_ULL(16); + rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); + + if (nix_pf_func) { + /* Set NIX_PF_FUNC */ + val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf)); + val |= (u64)nix_pf_func << 48; + rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val); + + nix_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, nix_pf_func); + nix_sel = (nix_blkaddr == BLKADDR_NIX0) ? 0 : 1; + + val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf)); + val |= (u64)nix_sel << 8; + rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); + } + + return 0; +} + +int rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu *rvu, + struct cpt_inline_ipsec_cfg_msg *req, + struct msg_rsp *rsp) +{ + u16 pcifunc = req->hdr.pcifunc; + struct rvu_block *block; + int cptlf, blkaddr, ret; + u16 actual_slot; + + blkaddr = rvu_get_blkaddr_from_slot(rvu, BLKTYPE_CPT, pcifunc, + req->slot, &actual_slot); + if (blkaddr < 0) + return CPT_AF_ERR_LF_INVALID; + + block = &rvu->hw->block[blkaddr]; + + cptlf = rvu_get_lf(rvu, block, pcifunc, actual_slot); + if (cptlf < 0) + return CPT_AF_ERR_LF_INVALID; + + switch (req->dir) { + case CPT_INLINE_INBOUND: + ret = cpt_inline_ipsec_cfg_inbound(rvu, blkaddr, cptlf, req); + break; + + case CPT_INLINE_OUTBOUND: + ret = cpt_inline_ipsec_cfg_outbound(rvu, blkaddr, cptlf, req); + break; + + default: + return CPT_AF_ERR_PARAM; + } + + return ret; +} + static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req) { u64 offset = req->reg_offset; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 9ef4e942e31e..ea3e03fa55d4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -4579,6 +4579,118 @@ int rvu_mbox_handler_nix_lso_format_cfg(struct rvu *rvu, return 0; } +#define IPSEC_GEN_CFG_EGRP GENMASK_ULL(50, 48) +#define IPSEC_GEN_CFG_OPCODE GENMASK_ULL(47, 32) +#define IPSEC_GEN_CFG_PARAM1 GENMASK_ULL(31, 16) +#define IPSEC_GEN_CFG_PARAM2 GENMASK_ULL(15, 0) + +#define CPT_INST_QSEL_BLOCK GENMASK_ULL(28, 24) +#define CPT_INST_QSEL_PF_FUNC GENMASK_ULL(23, 8) +#define CPT_INST_QSEL_SLOT GENMASK_ULL(7, 0) + +static void nix_inline_ipsec_cfg(struct rvu *rvu, struct nix_inline_ipsec_cfg *req, + int blkaddr) +{ + u8 cpt_idx, cpt_blkaddr; + u64 val; + + cpt_idx = (blkaddr == BLKADDR_NIX0) ? 0 : 1; + if (req->enable) { + /* Enable context prefetching */ + if (!is_rvu_otx2(rvu)) + val = BIT_ULL(51); + + /* Set OPCODE and EGRP */ + val |= FIELD_PREP(IPSEC_GEN_CFG_EGRP, req->gen_cfg.egrp); + val |= FIELD_PREP(IPSEC_GEN_CFG_OPCODE, req->gen_cfg.opcode); + val |= FIELD_PREP(IPSEC_GEN_CFG_PARAM1, req->gen_cfg.param1); + val |= FIELD_PREP(IPSEC_GEN_CFG_PARAM2, req->gen_cfg.param2); + + rvu_write64(rvu, blkaddr, NIX_AF_RX_IPSEC_GEN_CFG, val); + + /* Set CPT queue for inline IPSec */ + val = FIELD_PREP(CPT_INST_QSEL_SLOT, req->inst_qsel.cpt_slot); + val |= FIELD_PREP(CPT_INST_QSEL_PF_FUNC, + req->inst_qsel.cpt_pf_func); + + if (!is_rvu_otx2(rvu)) { + cpt_blkaddr = (cpt_idx == 0) ? BLKADDR_CPT0 : + BLKADDR_CPT1; + val |= FIELD_PREP(CPT_INST_QSEL_BLOCK, cpt_blkaddr); + } + + rvu_write64(rvu, blkaddr, NIX_AF_RX_CPTX_INST_QSEL(cpt_idx), + val); + + /* Set CPT credit */ + rvu_write64(rvu, blkaddr, NIX_AF_RX_CPTX_CREDIT(cpt_idx), + req->cpt_credit); + } else { + rvu_write64(rvu, blkaddr, NIX_AF_RX_IPSEC_GEN_CFG, 0x0); + rvu_write64(rvu, blkaddr, NIX_AF_RX_CPTX_INST_QSEL(cpt_idx), + 0x0); + rvu_write64(rvu, blkaddr, NIX_AF_RX_CPTX_CREDIT(cpt_idx), + 0x3FFFFF); + } +} + +int rvu_mbox_handler_nix_inline_ipsec_cfg(struct rvu *rvu, + struct nix_inline_ipsec_cfg *req, + struct msg_rsp *rsp) +{ + if (!is_block_implemented(rvu->hw, BLKADDR_CPT0)) + return 0; + + nix_inline_ipsec_cfg(rvu, req, BLKADDR_NIX0); + if (is_block_implemented(rvu->hw, BLKADDR_CPT1)) + nix_inline_ipsec_cfg(rvu, req, BLKADDR_NIX1); + + return 0; +} + +int rvu_mbox_handler_nix_inline_ipsec_lf_cfg(struct rvu *rvu, + struct nix_inline_ipsec_lf_cfg *req, + struct msg_rsp *rsp) +{ + int lf, blkaddr, err; + u64 val; + + if (!is_block_implemented(rvu->hw, BLKADDR_CPT0)) + return 0; + + err = nix_get_nixlf(rvu, req->hdr.pcifunc, &lf, &blkaddr); + if (err) + return err; + + if (req->enable) { + /* Set TT, TAG_CONST, SA_POW2_SIZE and LENM1_MAX */ + val = (u64)req->ipsec_cfg0.tt << 44 | + (u64)req->ipsec_cfg0.tag_const << 20 | + (u64)req->ipsec_cfg0.sa_pow2_size << 16 | + req->ipsec_cfg0.lenm1_max; + + if (blkaddr == BLKADDR_NIX1) + val |= BIT_ULL(46); + + rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_CFG0(lf), val); + + /* Set SA_IDX_W and SA_IDX_MAX */ + val = (u64)req->ipsec_cfg1.sa_idx_w << 32 | + req->ipsec_cfg1.sa_idx_max; + rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_CFG1(lf), val); + + /* Set SA base address */ + rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_SA_BASE(lf), + req->sa_base_addr); + } else { + rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_CFG0(lf), 0x0); + rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_CFG1(lf), 0x0); + rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_IPSEC_SA_BASE(lf), + 0x0); + } + + return 0; +} void rvu_nix_reset_mac(struct rvu_pfvf *pfvf, int pcifunc) { bool from_vf = !!(pcifunc & RVU_PFVF_FUNC_MASK); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h index 21f1ed4e222f..dbaeb10de7c2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h @@ -236,6 +236,8 @@ #define NIX_AF_RX_DEF_OIP6_DSCP (0x02F8) #define NIX_AF_RX_IPSEC_GEN_CFG (0x0300) #define NIX_AF_RX_CPTX_INST_ADDR (0x0310) +#define NIX_AF_RX_CPTX_INST_QSEL(a) (0x0320ull | (uint64_t)(a) << 3) +#define NIX_AF_RX_CPTX_CREDIT(a) (0x0360ull | (uint64_t)(a) << 3) #define NIX_AF_NDC_TX_SYNC (0x03F0) #define NIX_AF_AQ_CFG (0x0400) #define NIX_AF_AQ_BASE (0x0410)