[PATCH] PCI:tegra:Correct typo for PCIe endpoint mode in Tegra194

2020-12-30 Thread Wesley Sheng
In config PCIE_TEGRA194_EP the mode incorrectly referred to
host mode.

Signed-off-by: Wesley Sheng 
---
 drivers/pci/controller/dwc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/Kconfig 
b/drivers/pci/controller/dwc/Kconfig
index 044a3761c44f..6960babe6161 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -273,7 +273,7 @@ config PCIE_TEGRA194_EP
select PCIE_TEGRA194
help
  Enables support for the PCIe controller in the NVIDIA Tegra194 SoC to
- work in host mode. There are two instances of PCIe controllers in
+ work in endpoint mode. There are two instances of PCIe controllers in
  Tegra194. This controller can work either as EP or RC. In order to
  enable host-specific features PCIE_TEGRA194_HOST must be selected and
  in order to enable device-specific features PCIE_TEGRA194_EP must be
-- 
2.16.2



[PATCH] iommu/amd: Add prefetch iommu pages command build function

2020-09-05 Thread Wesley Sheng
Add function to build prefetch iommu pages command

Signed-off-by: Wesley Sheng 
---
 drivers/iommu/amd/amd_iommu_types.h |  2 ++
 drivers/iommu/amd/iommu.c   | 19 +++
 2 files changed, 21 insertions(+)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index baa31cd2411c..73734a0c4679 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -173,6 +173,7 @@
 #define CMD_INV_IOMMU_PAGES0x03
 #define CMD_INV_IOTLB_PAGES0x04
 #define CMD_INV_IRT0x05
+#define CMD_PF_IOMMU_PAGES 0x06
 #define CMD_COMPLETE_PPR   0x07
 #define CMD_INV_ALL0x08
 
@@ -181,6 +182,7 @@
 #define CMD_INV_IOMMU_PAGES_SIZE_MASK  0x01
 #define CMD_INV_IOMMU_PAGES_PDE_MASK   0x02
 #define CMD_INV_IOMMU_PAGES_GN_MASK0x04
+#define CMD_PF_IOMMU_PAGES_INV_MASK0x10
 
 #define PPR_STATUS_MASK0xf
 #define PPR_STATUS_SHIFT   12
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index ba9f3dbc5b94..b3971595b0e9 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -976,6 +976,25 @@ static void build_inv_irt(struct iommu_cmd *cmd, u16 devid)
CMD_SET_TYPE(cmd, CMD_INV_IRT);
 }
 
+static void build_pf_iommu_pages(struct iommu_cmd *cmd, u64 address,
+   u16 devid, int pfcnt, bool size,
+   bool inv)
+{
+   memset(cmd, 0, sizeof(*cmd));
+
+   address &= PAGE_MASK;
+
+   cmd->data[0]  = devid;
+   cmd->data[0] |= (pfcnt & 0xff) << 24;
+   cmd->data[2]  = lower_32_bits(address);
+   cmd->data[3]  = upper_32_bits(address);
+   if (size)
+   cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+   if (inv)
+   cmd->data[2] |= CMD_PF_IOMMU_PAGES_INV_MASK;
+   CMD_SET_TYPE(cmd, CMD_PF_IOMMU_PAGES);
+}
+
 /*
  * Writes the command to the IOMMUs command buffer and informs the
  * hardware about the new command.
-- 
2.16.2



[PATCH] iommu/amd: Add prefetch iommu pages command build function

2020-09-05 Thread Wesley Sheng
Add function to build prefetch iommu pages command

Signed-off-by: Wesley Sheng 
---
 drivers/iommu/amd/amd_iommu_types.h |  2 ++
 drivers/iommu/amd/iommu.c   | 19 +++
 2 files changed, 21 insertions(+)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index baa31cd2411c..73734a0c4679 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -173,6 +173,7 @@
 #define CMD_INV_IOMMU_PAGES0x03
 #define CMD_INV_IOTLB_PAGES0x04
 #define CMD_INV_IRT0x05
+#define CMD_PF_IOMMU_PAGES 0x06
 #define CMD_COMPLETE_PPR   0x07
 #define CMD_INV_ALL0x08
 
@@ -181,6 +182,7 @@
 #define CMD_INV_IOMMU_PAGES_SIZE_MASK  0x01
 #define CMD_INV_IOMMU_PAGES_PDE_MASK   0x02
 #define CMD_INV_IOMMU_PAGES_GN_MASK0x04
+#define CMD_PF_IOMMU_PAGES_INV_MASK0x10
 
 #define PPR_STATUS_MASK0xf
 #define PPR_STATUS_SHIFT   12
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index ba9f3dbc5b94..b3971595b0e9 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -976,6 +976,25 @@ static void build_inv_irt(struct iommu_cmd *cmd, u16 devid)
CMD_SET_TYPE(cmd, CMD_INV_IRT);
 }
 
+static void build_pf_iommu_pages(struct iommu_cmd *cmd, u64 address,
+   u16 devid, int pfcnt, bool size,
+   bool inv)
+{
+   memset(cmd, 0, sizeof(*cmd));
+
+   address &= PAGE_MASK;
+
+   cmd->data[0]  = devid;
+   cmd->data[0] |= (pfcnt & 0xff) << 24;
+   cmd->data[2]  = lower_32_bits(address);
+   cmd->data[3]  = upper_32_bits(address;
+   if (size)
+   cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+   if (inv)
+   cmd->data[2] |= CMD_PF_IOMMU_PAGES_INV_MASK;
+   CMD_SET_TYPE(cmd, CMD_PF_IOMMU_PAGES);
+}
+
 /*
  * Writes the command to the IOMMUs command buffer and informs the
  * hardware about the new command.
-- 
2.16.2



[PATCH 1/2] iommu/amd: Unify reserved member naming convention in struct

2020-09-04 Thread Wesley Sheng
Unify reserved member naming convention to rsvd_x in struct

Signed-off-by: Wesley Sheng 
---
 drivers/iommu/amd/amd_iommu_types.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 30a5d412255a..e5b05a97eb46 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -841,7 +841,7 @@ union irte_ga_lo {
no_fault: 1,
/* -- */
ga_log_intr : 1,
-   rsvd1   : 3,
+   rsvd_1  : 3,
is_run  : 1,
/* -- */
guest_mode  : 1,
-- 
2.16.2



[PATCH 2/2] iommu/amd: Revise ga_tag member in struct of fields_remap

2020-09-04 Thread Wesley Sheng
Per <>
ga_tag member is only available when IRTE[GuestMode]=1, this field
should be reserved when IRTE[GuestMode]=0. So change the ga_tag
to rsvd_1 in struct of fields_remap.

Signed-off-by: Wesley Sheng 
---
 drivers/iommu/amd/amd_iommu_types.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index e5b05a97eb46..baa31cd2411c 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -832,7 +832,7 @@ union irte_ga_lo {
/* -- */
guest_mode  : 1,
destination : 24,
-   ga_tag  : 32;
+   rsvd_1  : 32;
} fields_remap;
 
/* For guest vAPIC */
-- 
2.16.2



[PATCH] NTB: correct ntb_peer_spad_addr and ntb_peer_spad_read comment typos

2020-05-26 Thread Wesley Sheng
The comment for ntb_peer_spad_addr and ntb_peer_spad_read
incorrectly referred to peer doorbell register and local
scratchpad register.

Signed-off-by: Wesley Sheng 
---
 include/linux/ntb.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/ntb.h b/include/linux/ntb.h
index 8c13538aeffe..b9b0d805d0f9 100644
--- a/include/linux/ntb.h
+++ b/include/linux/ntb.h
@@ -1351,7 +1351,7 @@ static inline int ntb_spad_write(struct ntb_dev *ntb, int 
sidx, u32 val)
  * @sidx:  Scratchpad index.
  * @spad_addr: OUT - The address of the peer scratchpad register.
  *
- * Return the address of the peer doorbell register.  This may be used, for
+ * Return the address of the peer scratchpad register.  This may be used, for
  * example, by drivers that offload memory copy operations to a dma engine.
  *
  * Return: Zero on success, otherwise an error number.
@@ -1373,7 +1373,7 @@ static inline int ntb_peer_spad_addr(struct ntb_dev *ntb, 
int pidx, int sidx,
  *
  * Read the peer scratchpad register, and return the value.
  *
- * Return: The value of the local scratchpad register.
+ * Return: The value of the peer scratchpad register.
  */
 static inline u32 ntb_peer_spad_read(struct ntb_dev *ntb, int pidx, int sidx)
 {
-- 
2.16.2



[PATCH] NTB: correct ntb_dev_ops and ntb_dev comment typos

2019-04-29 Thread Wesley Sheng
The comment for ntb_dev_ops and ntb_dev incorrectly referred to
ntb_ctx_ops and ntb_device.

Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 include/linux/ntb.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/ntb.h b/include/linux/ntb.h
index 56a92e3..604abc8 100644
--- a/include/linux/ntb.h
+++ b/include/linux/ntb.h
@@ -205,7 +205,7 @@ static inline int ntb_ctx_ops_is_valid(const struct 
ntb_ctx_ops *ops)
 }
 
 /**
- * struct ntb_ctx_ops - ntb device operations
+ * struct ntb_dev_ops - ntb device operations
  * @port_number:   See ntb_port_number().
  * @peer_port_count:   See ntb_peer_port_count().
  * @peer_port_number:  See ntb_peer_port_number().
@@ -404,7 +404,7 @@ struct ntb_client {
 #define drv_ntb_client(__drv) container_of((__drv), struct ntb_client, drv)
 
 /**
- * struct ntb_device - ntb device
+ * struct ntb_dev - ntb device
  * @dev:   Linux device object.
  * @pdev:  PCI device entry of the ntb.
  * @topo:  Detected topology of the ntb.
-- 
2.7.4



[PATCH 1/3] ntb_hw_switchtec: Remove redundant steps of switchtec_ntb_reinit_peer() function

2019-04-22 Thread Wesley Sheng
From: Joey Zhang 

When a re-initialization is caused by a link event, the driver will
re-setup the shared memory window. But at that time, the shared memory
is still valid, and it's unnecessary to free, reallocate and then
initialize it again. We only need to reconfigure the hardware
registers. Remove the redundant steps from
switchtec_ntb_reinit_peer() function.

Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index d905d36..947ed0b 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1457,10 +1457,13 @@ static void switchtec_ntb_deinit_db_msg_irq(struct 
switchtec_ntb *sndev)
 
 static int switchtec_ntb_reinit_peer(struct switchtec_ntb *sndev)
 {
-   dev_info(>stdev->dev, "peer reinitialized\n");
-   switchtec_ntb_deinit_shared_mw(sndev);
-   switchtec_ntb_init_mw(sndev);
-   return switchtec_ntb_init_shared_mw(sndev);
+   int rc;
+
+   dev_info(>stdev->dev, "reinitialize shared memory window\n");
+   rc = config_rsvd_lut_win(sndev, sndev->mmio_peer_ctrl, 0,
+sndev->self_partition,
+sndev->self_shared_dma);
+   return rc;
 }
 
 static int switchtec_ntb_add(struct device *dev,
-- 
2.7.4



[PATCH 2/3] ntb_hw_switchtec: Skip unnecessary re-setup of shared memory window for crosslink case

2019-04-22 Thread Wesley Sheng
In case of NTB crosslink topology, the setting of shared memory window in
the virtual partition doesn't reset on peer's reboot. So skip the
unnecessary re-setup of shared memory window for that case.

Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 947ed0b..6cf15c18 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1459,6 +1459,9 @@ static int switchtec_ntb_reinit_peer(struct switchtec_ntb 
*sndev)
 {
int rc;
 
+   if (crosslink_is_enabled(sndev))
+   return 0;
+
dev_info(>stdev->dev, "reinitialize shared memory window\n");
rc = config_rsvd_lut_win(sndev, sndev->mmio_peer_ctrl, 0,
 sndev->self_partition,
-- 
2.7.4



[PATCH 3/3] ntb_hw_switchtec: Fix setup MW with failure bug

2019-04-22 Thread Wesley Sheng
From: Joey Zhang 

Switchtec does not support setting multiple MWs simultaneously. The 
driver takes a hardware lock to ensure that two peers are not doing this
simultaneously and it fails if someone else takes the lock. In most
cases, this is fine as clients only setup the MWs once on one side of
the link.

However, there's a race condition when a re-initialization is caused by
a link event. The driver will re-setup the shared memory window
asynchronously and this races with the client setting up it's memory
windows on the link up event.

To fix this we ensure do the entire initialization in a work queue and
signal the client once it's done.

Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 66 --
 1 file changed, 39 insertions(+), 27 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 6cf15c18..f9a 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -95,7 +95,8 @@ struct switchtec_ntb {
bool link_is_up;
enum ntb_speed link_speed;
enum ntb_width link_width;
-   struct work_struct link_reinit_work;
+   struct work_struct check_link_status_work;
+   bool link_force_down;
 };
 
 static struct switchtec_ntb *ntb_sndev(struct ntb_dev *ntb)
@@ -494,33 +495,11 @@ enum switchtec_msg {
 
 static int switchtec_ntb_reinit_peer(struct switchtec_ntb *sndev);
 
-static void link_reinit_work(struct work_struct *work)
-{
-   struct switchtec_ntb *sndev;
-
-   sndev = container_of(work, struct switchtec_ntb, link_reinit_work);
-
-   switchtec_ntb_reinit_peer(sndev);
-}
-
-static void switchtec_ntb_check_link(struct switchtec_ntb *sndev,
-enum switchtec_msg msg)
+static void switchtec_ntb_link_status_update(struct switchtec_ntb *sndev)
 {
int link_sta;
int old = sndev->link_is_up;
 
-   if (msg == MSG_LINK_FORCE_DOWN) {
-   schedule_work(>link_reinit_work);
-
-   if (sndev->link_is_up) {
-   sndev->link_is_up = 0;
-   ntb_link_event(>ntb);
-   dev_info(>stdev->dev, "ntb link forced down\n");
-   }
-
-   return;
-   }
-
link_sta = sndev->self_shared->link_sta;
if (link_sta) {
u64 peer = ioread64(>peer_shared->magic);
@@ -545,6 +524,38 @@ static void switchtec_ntb_check_link(struct switchtec_ntb 
*sndev,
}
 }
 
+static void check_link_status_work(struct work_struct *work)
+{
+   struct switchtec_ntb *sndev;
+
+   sndev = container_of(work, struct switchtec_ntb,
+check_link_status_work);
+
+   if (sndev->link_force_down) {
+   sndev->link_force_down = false;
+   switchtec_ntb_reinit_peer(sndev);
+
+   if (sndev->link_is_up) {
+   sndev->link_is_up = 0;
+   ntb_link_event(>ntb);
+   dev_info(>stdev->dev, "ntb link forced down\n");
+   }
+
+   return;
+   }
+
+   switchtec_ntb_link_status_update(sndev);
+}
+
+static void switchtec_ntb_check_link(struct switchtec_ntb *sndev,
+ enum switchtec_msg msg)
+{
+   if (msg == MSG_LINK_FORCE_DOWN)
+   sndev->link_force_down = true;
+
+   schedule_work(>check_link_status_work);
+}
+
 static void switchtec_ntb_link_notification(struct switchtec_dev *stdev)
 {
struct switchtec_ntb *sndev = stdev->sndev;
@@ -577,7 +588,7 @@ static int switchtec_ntb_link_enable(struct ntb_dev *ntb,
sndev->self_shared->link_sta = 1;
switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_UP);
 
-   switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
+   switchtec_ntb_link_status_update(sndev);
 
return 0;
 }
@@ -591,7 +602,7 @@ static int switchtec_ntb_link_disable(struct ntb_dev *ntb)
sndev->self_shared->link_sta = 0;
switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_DOWN);
 
-   switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
+   switchtec_ntb_link_status_update(sndev);
 
return 0;
 }
@@ -844,7 +855,8 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb 
*sndev)
sndev->ntb.topo = NTB_TOPO_SWITCH;
sndev->ntb.ops = _ntb_ops;
 
-   INIT_WORK(>link_reinit_work, link_reinit_work);
+   INIT_WORK(>check_link_status_work, check_link_status_work);
+   sndev->link_force_down = false;
 
sndev->self_partition = sndev->stdev->partition;
 
-- 
2.7.4



[PATCH 0/3] Redundant steps removal and bug fix of ntb_hw_switchtec

2019-04-22 Thread Wesley Sheng
Hi, Everyone,

This patch series remove redundant steps and fix one bug of the 
ntb_hw_switchtec module.

When a re-initialization is caused by a link event, the driver will
re-setup the shared memory windows. But at that time, the shared memory
is still valid, and it's unnecessary to free, reallocate and then
initialize it again. Remove these redundant steps.

In case of NTB crosslink topology, the setting of shared memory window
in the virtual partition doesn't reset on peer's reboot. So skip the
re-setup of shared memory window for that case.

Switchtec does not support setting multiple MWs simultaneously. However,
there's a race condition when a re-initialization is caused by a link 
event, the driver will re-setup the shared memory window asynchronously
and this races with the client setting up its memory windows on the 
link up event. Fix this by ensure do the entire initialization in a work
queue and signal the client once it's done. 

Regard,
Wesley

--

Changed since v1:
  - It's a resend of v1

--


Joey Zhang (2):
  ntb_hw_switchtec: Remove redundant steps of
switchtec_ntb_reinit_peer() function
  ntb_hw_switchtec: Fix setup MW with failure bug

Wesley Sheng (1):
  ntb_hw_switchtec: Skip unnecessary re-setup of shared memory window
for crosslink case

 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 80 +-
 1 file changed, 49 insertions(+), 31 deletions(-)

-- 
2.7.4



[PATCH v2 1/2] switchtec: Fix false maximum supported PCIe function number issue

2019-04-15 Thread Wesley Sheng
The hardware supports up to 255 PFFs and the driver only supports 48, so
this patch updates the driver to support them all. To be backward
compatible, a new ioctl and corresponding data structure are created,
while keep the deprecated one.

Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c   | 39 +---
 include/linux/switchtec.h|  2 +-
 include/uapi/linux/switchtec_ioctl.h | 13 +++-
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index e22766c..7df9a69 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -658,19 +658,25 @@ static int ioctl_flash_part_info(struct switchtec_dev 
*stdev,
 
 static int ioctl_event_summary(struct switchtec_dev *stdev,
struct switchtec_user *stuser,
-   struct switchtec_ioctl_event_summary __user *usum)
+   struct switchtec_ioctl_event_summary __user *usum,
+   size_t size)
 {
-   struct switchtec_ioctl_event_summary s = {0};
+   struct switchtec_ioctl_event_summary *s;
int i;
u32 reg;
+   int ret = 0;
 
-   s.global = ioread32(>mmio_sw_event->global_summary);
-   s.part_bitmap = ioread32(>mmio_sw_event->part_event_bitmap);
-   s.local_part = ioread32(>mmio_part_cfg->part_event_summary);
+   s = kzalloc(sizeof(*s), GFP_KERNEL);
+   if (!s)
+   return -ENOMEM;
+
+   s->global = ioread32(>mmio_sw_event->global_summary);
+   s->part_bitmap = ioread32(>mmio_sw_event->part_event_bitmap);
+   s->local_part = ioread32(>mmio_part_cfg->part_event_summary);
 
for (i = 0; i < stdev->partition_count; i++) {
reg = ioread32(>mmio_part_cfg_all[i].part_event_summary);
-   s.part[i] = reg;
+   s->part[i] = reg;
}
 
for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
@@ -679,15 +685,19 @@ static int ioctl_event_summary(struct switchtec_dev 
*stdev,
break;
 
reg = ioread32(>mmio_pff_csr[i].pff_event_summary);
-   s.pff[i] = reg;
+   s->pff[i] = reg;
}
 
-   if (copy_to_user(usum, , sizeof(s)))
-   return -EFAULT;
+   if (copy_to_user(usum, s, size)) {
+   ret = -EFAULT;
+   goto error_case;
+   }
 
stuser->event_cnt = atomic_read(>event_cnt);
 
-   return 0;
+error_case:
+   kfree(s);
+   return ret;
 }
 
 static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev,
@@ -977,8 +987,9 @@ static long switchtec_dev_ioctl(struct file *filp, unsigned 
int cmd,
case SWITCHTEC_IOCTL_FLASH_PART_INFO:
rc = ioctl_flash_part_info(stdev, argp);
break;
-   case SWITCHTEC_IOCTL_EVENT_SUMMARY:
-   rc = ioctl_event_summary(stdev, stuser, argp);
+   case SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY:
+   rc = ioctl_event_summary(stdev, stuser, argp,
+sizeof(struct 
switchtec_ioctl_event_summary_legacy));
break;
case SWITCHTEC_IOCTL_EVENT_CTL:
rc = ioctl_event_ctl(stdev, argp);
@@ -989,6 +1000,10 @@ static long switchtec_dev_ioctl(struct file *filp, 
unsigned int cmd,
case SWITCHTEC_IOCTL_PORT_TO_PFF:
rc = ioctl_port_to_pff(stdev, argp);
break;
+   case SWITCHTEC_IOCTL_EVENT_SUMMARY:
+   rc = ioctl_event_summary(stdev, stuser, argp,
+sizeof(struct 
switchtec_ioctl_event_summary));
+   break;
default:
rc = -ENOTTY;
break;
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index 52a079b..0cfc34a 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -20,7 +20,7 @@
 #include 
 
 #define SWITCHTEC_MRPC_PAYLOAD_SIZE 1024
-#define SWITCHTEC_MAX_PFF_CSR 48
+#define SWITCHTEC_MAX_PFF_CSR 255
 
 #define SWITCHTEC_EVENT_OCCURRED BIT(0)
 #define SWITCHTEC_EVENT_CLEARBIT(0)
diff --git a/include/uapi/linux/switchtec_ioctl.h 
b/include/uapi/linux/switchtec_ioctl.h
index 4f4daf8..c912b5a 100644
--- a/include/uapi/linux/switchtec_ioctl.h
+++ b/include/uapi/linux/switchtec_ioctl.h
@@ -50,7 +50,7 @@ struct switchtec_ioctl_flash_part_info {
__u32 active;
 };
 
-struct switchtec_ioctl_event_summary {
+struct switchtec_ioctl_event_summary_legacy {
__u64 global;
__u64 part_bitmap;
__u32 local_part;
@@ -59,6 +59,15 @@ struct switchtec_ioctl_event_summary {
__u32 pff[48];
 };
 
+struct switchtec_ioctl_event_summary {
+   __u64 global;
+   __u64 part_bitmap;
+   __u32 local_part;
+   __u32 padding;
+   __u32 part[48];
+   __u32 pff[255];
+};
+
 #define SWITCHTEC_IOCTL_EVENT_STACK_ERROR  0
 #

[PATCH v2 0/2] Fix two bugs of switchtec module

2019-04-15 Thread Wesley Sheng
Hi, Everyone,

This patch series fix two bugs of switchtec module.

The first is introduced by device spec definition issue: the maximum
supported PCIe function number by hardware should be 255 instead of 
the false number of 48. Rectify it in driver and for backward 
compatible, a new ioctl and corresponding data structure are created,
while keep the deprecated one.

The second is MRPC event unintentionally masked at corner case.
Fix this bug by skipping the mask operation for MRPC event in event ISR
like what we already do for LINK event.

Regard,
Wesley

--

Changed since v1:
  - rewrapped the commit message of [PATCH 1/2] into one paragraph

--

Wesley Sheng (2):
  switchtec: Fix false maximum supported PCIe function number issue
  switchtec: Fix unintended mask of MRPC event

 drivers/pci/switch/switchtec.c   | 42 +---
 include/linux/switchtec.h|  2 +-
 include/uapi/linux/switchtec_ioctl.h | 13 ++-
 3 files changed, 42 insertions(+), 15 deletions(-)

-- 
2.7.4



[PATCH v2 2/2] switchtec: Fix unintended mask of MRPC event

2019-04-15 Thread Wesley Sheng
When running application tool switchtec-user's `firmware update` and
`event wait` commands concurrently, sometimes the firmware update
speed reduced evidently.

It is because when the MRPC event happened right after MRPC event
occurrence check but before event mask loop reach to its header
register in event ISR, the MRPC event would be masked unintentionally.
Since there's no chance to enable it again except for a module reload,
all the following MRPC execution completion check will be deferred to
timeout.

Fix this bug by skipping the mask operation for MRPC event in event
ISR, same as what we already do for LINK event.

Fixes: 52eabba5bcdb ("switchtec: Add IOCTLs to the Switchtec driver")
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 7df9a69..30f6e08 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1177,7 +1177,8 @@ static int mask_event(struct switchtec_dev *stdev, int 
eid, int idx)
if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ))
return 0;
 
-   if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE)
+   if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE ||
+   eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP)
return 0;
 
dev_dbg(>dev, "%s: %d %d %x\n", __func__, eid, idx, hdr);
-- 
2.7.4



[PATCH 1/3] ntb_hw_switchtec: Remove redundant steps of switchtec_ntb_reinit_peer() function

2019-04-08 Thread Wesley Sheng
From: Joey Zhang 

When a re-initialization is caused by a link event, the driver will
re-setup the shared memory window. But at that time, the shared memory
is still valid, and it's unnecessary to free, reallocate and then
initialize it again. We only need to reconfigure the hardware
registers. Remove the redundant steps from
switchtec_ntb_reinit_peer() function.

Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index d905d36..947ed0b 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1457,10 +1457,13 @@ static void switchtec_ntb_deinit_db_msg_irq(struct 
switchtec_ntb *sndev)
 
 static int switchtec_ntb_reinit_peer(struct switchtec_ntb *sndev)
 {
-   dev_info(>stdev->dev, "peer reinitialized\n");
-   switchtec_ntb_deinit_shared_mw(sndev);
-   switchtec_ntb_init_mw(sndev);
-   return switchtec_ntb_init_shared_mw(sndev);
+   int rc;
+
+   dev_info(>stdev->dev, "reinitialize shared memory window\n");
+   rc = config_rsvd_lut_win(sndev, sndev->mmio_peer_ctrl, 0,
+sndev->self_partition,
+sndev->self_shared_dma);
+   return rc;
 }
 
 static int switchtec_ntb_add(struct device *dev,
-- 
2.7.4



[PATCH 2/3] ntb_hw_switchtec: Skip unnecessary re-setup of shared memory window for crosslink case

2019-04-08 Thread Wesley Sheng
In case of NTB crosslink topology, the setting of shared memory window in
the virtual partition doesn't reset on peer's reboot. So skip the
unnecessary re-setup of shared memory window for that case.

Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 947ed0b..6cf15c18 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1459,6 +1459,9 @@ static int switchtec_ntb_reinit_peer(struct switchtec_ntb 
*sndev)
 {
int rc;
 
+   if (crosslink_is_enabled(sndev))
+   return 0;
+
dev_info(>stdev->dev, "reinitialize shared memory window\n");
rc = config_rsvd_lut_win(sndev, sndev->mmio_peer_ctrl, 0,
 sndev->self_partition,
-- 
2.7.4



[PATCH 3/3] ntb_hw_switchtec: Fix setup MW with failure bug

2019-04-08 Thread Wesley Sheng
From: Joey Zhang 

Switchtec does not support setting multiple MWs simultaneously. The 
driver takes a hardware lock to ensure that two peers are not doing this
simultaneously and it fails if someone else takes the lock. In most
cases, this is fine as clients only setup the MWs once on one side of
the link.

However, there's a race condition when a re-initialization is caused by
a link event. The driver will re-setup the shared memory window
asynchronously and this races with the client setting up it's memory
windows on the link up event.

To fix this we ensure do the entire initialization in a work queue and
signal the client once it's done.

Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 66 --
 1 file changed, 39 insertions(+), 27 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 6cf15c18..f9a 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -95,7 +95,8 @@ struct switchtec_ntb {
bool link_is_up;
enum ntb_speed link_speed;
enum ntb_width link_width;
-   struct work_struct link_reinit_work;
+   struct work_struct check_link_status_work;
+   bool link_force_down;
 };
 
 static struct switchtec_ntb *ntb_sndev(struct ntb_dev *ntb)
@@ -494,33 +495,11 @@ enum switchtec_msg {
 
 static int switchtec_ntb_reinit_peer(struct switchtec_ntb *sndev);
 
-static void link_reinit_work(struct work_struct *work)
-{
-   struct switchtec_ntb *sndev;
-
-   sndev = container_of(work, struct switchtec_ntb, link_reinit_work);
-
-   switchtec_ntb_reinit_peer(sndev);
-}
-
-static void switchtec_ntb_check_link(struct switchtec_ntb *sndev,
-enum switchtec_msg msg)
+static void switchtec_ntb_link_status_update(struct switchtec_ntb *sndev)
 {
int link_sta;
int old = sndev->link_is_up;
 
-   if (msg == MSG_LINK_FORCE_DOWN) {
-   schedule_work(>link_reinit_work);
-
-   if (sndev->link_is_up) {
-   sndev->link_is_up = 0;
-   ntb_link_event(>ntb);
-   dev_info(>stdev->dev, "ntb link forced down\n");
-   }
-
-   return;
-   }
-
link_sta = sndev->self_shared->link_sta;
if (link_sta) {
u64 peer = ioread64(>peer_shared->magic);
@@ -545,6 +524,38 @@ static void switchtec_ntb_check_link(struct switchtec_ntb 
*sndev,
}
 }
 
+static void check_link_status_work(struct work_struct *work)
+{
+   struct switchtec_ntb *sndev;
+
+   sndev = container_of(work, struct switchtec_ntb,
+check_link_status_work);
+
+   if (sndev->link_force_down) {
+   sndev->link_force_down = false;
+   switchtec_ntb_reinit_peer(sndev);
+
+   if (sndev->link_is_up) {
+   sndev->link_is_up = 0;
+   ntb_link_event(>ntb);
+   dev_info(>stdev->dev, "ntb link forced down\n");
+   }
+
+   return;
+   }
+
+   switchtec_ntb_link_status_update(sndev);
+}
+
+static void switchtec_ntb_check_link(struct switchtec_ntb *sndev,
+ enum switchtec_msg msg)
+{
+   if (msg == MSG_LINK_FORCE_DOWN)
+   sndev->link_force_down = true;
+
+   schedule_work(>check_link_status_work);
+}
+
 static void switchtec_ntb_link_notification(struct switchtec_dev *stdev)
 {
struct switchtec_ntb *sndev = stdev->sndev;
@@ -577,7 +588,7 @@ static int switchtec_ntb_link_enable(struct ntb_dev *ntb,
sndev->self_shared->link_sta = 1;
switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_UP);
 
-   switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
+   switchtec_ntb_link_status_update(sndev);
 
return 0;
 }
@@ -591,7 +602,7 @@ static int switchtec_ntb_link_disable(struct ntb_dev *ntb)
sndev->self_shared->link_sta = 0;
switchtec_ntb_send_msg(sndev, LINK_MESSAGE, MSG_LINK_DOWN);
 
-   switchtec_ntb_check_link(sndev, MSG_CHECK_LINK);
+   switchtec_ntb_link_status_update(sndev);
 
return 0;
 }
@@ -844,7 +855,8 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb 
*sndev)
sndev->ntb.topo = NTB_TOPO_SWITCH;
sndev->ntb.ops = _ntb_ops;
 
-   INIT_WORK(>link_reinit_work, link_reinit_work);
+   INIT_WORK(>check_link_status_work, check_link_status_work);
+   sndev->link_force_down = false;
 
sndev->self_partition = sndev->stdev->partition;
 
-- 
2.7.4



[PATCH 0/3] Redundant steps removal and bug fix of ntb_hw_switchtec

2019-04-08 Thread Wesley Sheng
Hi, Everyone,

This patch series remove redundant steps and fix one bug of the 
ntb_hw_switchtec module.

When a re-initialization is caused by a link event, the driver will
re-setup the shared memory windows. But at that time, the shared memory
is still valid, and it's unnecessary to free, reallocate and then
initialize it again. Remove these redundant steps.

In case of NTB crosslink topology, the setting of shared memory window
in the virtual partition doesn't reset on peer's reboot. So skip the
re-setup of shared memory window for that case.

Switchtec does not support setting multiple MWs simultaneously. However,
there's a race condition when a re-initialization is caused by a link 
event, the driver will re-setup the shared memory window asynchronously
and this races with the client setting up its memory windows on the 
link up event. Fix this by ensure do the entire initialization in a work
queue and signal the client once it's done. 

Regard,
Wesley

Joey Zhang (2):
  ntb_hw_switchtec: Remove redundant steps of
switchtec_ntb_reinit_peer() function
  ntb_hw_switchtec: Fix setup MW with failure bug

Wesley Sheng (1):
  ntb_hw_switchtec: Skip unnecessary re-setup of shared memory window
for crosslink case

 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 80 +-
 1 file changed, 49 insertions(+), 31 deletions(-)

-- 
2.7.4



[PATCH 0/2] Fix two bugs of switchtec module

2019-04-08 Thread Wesley Sheng
Hi, Everyone,

This patch series fix two bugs of switchtec module.

The first is introduced by device spec definition issue: the maximum
supported PCIe function number by hardware should be 255 instead of 
the false number of 48. Rectify it in driver and for backward 
compatible, a new ioctl and corresponding data structure are created,
while keep the deprecated one.

The second is MRPC event unintentionally masked at corner case.
Fix this bug by skipping the mask operation for MRPC event in event ISR
like what we already do for LINK event.

Regard,
Wesley


Wesley Sheng (2):
  switchtec: Fix false maximum supported PCIe function number issue
  switchtec: Fix unintended mask of MRPC event

 drivers/pci/switch/switchtec.c   | 42 +---
 include/linux/switchtec.h|  2 +-
 include/uapi/linux/switchtec_ioctl.h | 13 ++-
 3 files changed, 42 insertions(+), 15 deletions(-)

-- 
2.7.4



[PATCH 2/2] switchtec: Fix unintended mask of MRPC event

2019-04-08 Thread Wesley Sheng
When running application tool switchtec-user's `firmware update` and
`event wait` commands concurrently, sometimes the firmware update
speed reduced evidently.

It is because when the MRPC event happened right after MRPC event
occurrence check but before event mask loop reach to its header
register in event ISR, the MRPC event would be masked unintentionally.
Since there's no chance to enable it again except for a module reload,
all the following MRPC execution completion check will be deferred to
timeout.

Fix this bug by skipping the mask operation for MRPC event in event
ISR, same as what we already do for LINK event.

Fixes: 52eabba5bcdb ("switchtec: Add IOCTLs to the Switchtec driver")
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 7df9a69..30f6e08 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1177,7 +1177,8 @@ static int mask_event(struct switchtec_dev *stdev, int 
eid, int idx)
if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ))
return 0;
 
-   if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE)
+   if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE ||
+   eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP)
return 0;
 
dev_dbg(>dev, "%s: %d %d %x\n", __func__, eid, idx, hdr);
-- 
2.7.4



[PATCH 1/2] switchtec: Fix false maximum supported PCIe function number issue

2019-04-08 Thread Wesley Sheng
The hardware supports up to 255 PFFs and the driver only supports 48, so
this patch updates the driver to support them all.
To be backward compatible, a new ioctl and corresponding data
structure are created, while keep the deprecated one.

Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c   | 39 +---
 include/linux/switchtec.h|  2 +-
 include/uapi/linux/switchtec_ioctl.h | 13 +++-
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index e22766c..7df9a69 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -658,19 +658,25 @@ static int ioctl_flash_part_info(struct switchtec_dev 
*stdev,
 
 static int ioctl_event_summary(struct switchtec_dev *stdev,
struct switchtec_user *stuser,
-   struct switchtec_ioctl_event_summary __user *usum)
+   struct switchtec_ioctl_event_summary __user *usum,
+   size_t size)
 {
-   struct switchtec_ioctl_event_summary s = {0};
+   struct switchtec_ioctl_event_summary *s;
int i;
u32 reg;
+   int ret = 0;
 
-   s.global = ioread32(>mmio_sw_event->global_summary);
-   s.part_bitmap = ioread32(>mmio_sw_event->part_event_bitmap);
-   s.local_part = ioread32(>mmio_part_cfg->part_event_summary);
+   s = kzalloc(sizeof(*s), GFP_KERNEL);
+   if (!s)
+   return -ENOMEM;
+
+   s->global = ioread32(>mmio_sw_event->global_summary);
+   s->part_bitmap = ioread32(>mmio_sw_event->part_event_bitmap);
+   s->local_part = ioread32(>mmio_part_cfg->part_event_summary);
 
for (i = 0; i < stdev->partition_count; i++) {
reg = ioread32(>mmio_part_cfg_all[i].part_event_summary);
-   s.part[i] = reg;
+   s->part[i] = reg;
}
 
for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
@@ -679,15 +685,19 @@ static int ioctl_event_summary(struct switchtec_dev 
*stdev,
break;
 
reg = ioread32(>mmio_pff_csr[i].pff_event_summary);
-   s.pff[i] = reg;
+   s->pff[i] = reg;
}
 
-   if (copy_to_user(usum, , sizeof(s)))
-   return -EFAULT;
+   if (copy_to_user(usum, s, size)) {
+   ret = -EFAULT;
+   goto error_case;
+   }
 
stuser->event_cnt = atomic_read(>event_cnt);
 
-   return 0;
+error_case:
+   kfree(s);
+   return ret;
 }
 
 static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev,
@@ -977,8 +987,9 @@ static long switchtec_dev_ioctl(struct file *filp, unsigned 
int cmd,
case SWITCHTEC_IOCTL_FLASH_PART_INFO:
rc = ioctl_flash_part_info(stdev, argp);
break;
-   case SWITCHTEC_IOCTL_EVENT_SUMMARY:
-   rc = ioctl_event_summary(stdev, stuser, argp);
+   case SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY:
+   rc = ioctl_event_summary(stdev, stuser, argp,
+sizeof(struct 
switchtec_ioctl_event_summary_legacy));
break;
case SWITCHTEC_IOCTL_EVENT_CTL:
rc = ioctl_event_ctl(stdev, argp);
@@ -989,6 +1000,10 @@ static long switchtec_dev_ioctl(struct file *filp, 
unsigned int cmd,
case SWITCHTEC_IOCTL_PORT_TO_PFF:
rc = ioctl_port_to_pff(stdev, argp);
break;
+   case SWITCHTEC_IOCTL_EVENT_SUMMARY:
+   rc = ioctl_event_summary(stdev, stuser, argp,
+sizeof(struct 
switchtec_ioctl_event_summary));
+   break;
default:
rc = -ENOTTY;
break;
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index 52a079b..0cfc34a 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -20,7 +20,7 @@
 #include 
 
 #define SWITCHTEC_MRPC_PAYLOAD_SIZE 1024
-#define SWITCHTEC_MAX_PFF_CSR 48
+#define SWITCHTEC_MAX_PFF_CSR 255
 
 #define SWITCHTEC_EVENT_OCCURRED BIT(0)
 #define SWITCHTEC_EVENT_CLEARBIT(0)
diff --git a/include/uapi/linux/switchtec_ioctl.h 
b/include/uapi/linux/switchtec_ioctl.h
index 4f4daf8..c912b5a 100644
--- a/include/uapi/linux/switchtec_ioctl.h
+++ b/include/uapi/linux/switchtec_ioctl.h
@@ -50,7 +50,7 @@ struct switchtec_ioctl_flash_part_info {
__u32 active;
 };
 
-struct switchtec_ioctl_event_summary {
+struct switchtec_ioctl_event_summary_legacy {
__u64 global;
__u64 part_bitmap;
__u32 local_part;
@@ -59,6 +59,15 @@ struct switchtec_ioctl_event_summary {
__u32 pff[48];
 };
 
+struct switchtec_ioctl_event_summary {
+   __u64 global;
+   __u64 part_bitmap;
+   __u32 local_part;
+   __u32 padding;
+   __u32 part[48];
+   __u32 pff[255];
+};
+
 #define SWITCHTEC_IOCTL_EVENT_STACK_ERROR  0
 #

[PATCH 1/5] switchtec: Remove immediate status check after submit a MRPC command

2018-12-09 Thread Wesley Sheng
From: Kelvin Cao 

After submitting a Firmware Download MRPC command, Switchtec firmware will
delay Management EP BAR MemRd TLP responses by more than 10ms. This is a
firmware limitation. Delayed MemRd completions are problem for systems with
a low Completion Timeout (CTO).

The current driver checks the MRPC status immediately after submitting an
MRPC command, which results in the MemRd TLP that's affected by the above
limitation.

Remove the immediate status check and rely on the check after receiving an
interrupt or timing out.

This is only a software workaround to the READ issue and a proper fix of
this should be done in firmware.

Fixes: 080b47def5e5 ("MicroSemi Switchtec management interface driver")
Signed-off-by: Kelvin Cao 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/pci/switch/switchtec.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 54a8b30..d2bca2d 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -134,10 +134,6 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stuser->data, stuser->data_len);
iowrite32(stuser->cmd, >mmio_mrpc->cmd);
 
-   stuser->status = ioread32(>mmio_mrpc->status);
-   if (stuser->status != SWITCHTEC_MRPC_STATUS_INPROGRESS)
-   mrpc_complete_cmd(stdev);
-
schedule_delayed_work(>mrpc_timeout,
  msecs_to_jiffies(500));
 }
-- 
2.7.4



[PATCH 2/5] switchtec: Set DMA coherent mask in Switchtec driver

2018-12-09 Thread Wesley Sheng
From: Boris Glimcher 

Switchtec hardware supports 64-bit DMA, set the correct DMA mask.
This allows the CMA to allocate larger buffers for memory windows.

Signed-off-by: Boris Glimcher 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/pci/switch/switchtec.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index d2bca2d..480107e 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1237,6 +1237,10 @@ static int switchtec_init_pci(struct switchtec_dev 
*stdev,
if (rc)
return rc;
 
+   rc = dma_set_coherent_mask(>dev, DMA_BIT_MASK(64));
+   if (rc)
+   return rc;
+
pci_set_master(pdev);
 
stdev->mmio = pcim_iomap_table(pdev)[0];
-- 
2.7.4



[PATCH 4/5] switchtec: Improve MRPC efficiency by leveraging write combining

2018-12-09 Thread Wesley Sheng
From: Kelvin Cao 

MRPC Input buffer is mostly memory without any side effects, thus we can
improve the access time by enabling write combining on only this region of
the BAR.

In a few places, we still need to flush the WC buffer. To do this, we
simply read from the Outbound Doorbell register seeing reads to this
register are processed by low latency hardware.

Signed-off-by: Kelvin Cao 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/pci/switch/switchtec.c | 41 +++--
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index a908670..0b8862b 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -113,6 +113,19 @@ static void stuser_set_state(struct switchtec_user *stuser,
 
 static void mrpc_complete_cmd(struct switchtec_dev *stdev);
 
+static void flush_wc_buf(struct switchtec_dev *stdev)
+{
+   struct ntb_dbmsg_regs __iomem *mmio_dbmsg;
+
+   /*
+* odb (outbound doorbell) register is processed by low latency
+* hardware and w/o side effect
+*/
+   mmio_dbmsg = (void __iomem *)stdev->mmio_ntb +
+   SWITCHTEC_NTB_REG_DBMSG_OFFSET;
+   ioread32(_dbmsg->odb);
+}
+
 static void mrpc_cmd_submit(struct switchtec_dev *stdev)
 {
/* requires the mrpc_mutex to already be held when called */
@@ -132,6 +145,7 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stdev->mrpc_busy = 1;
memcpy_toio(>mmio_mrpc->input_data,
stuser->data, stuser->data_len);
+   flush_wc_buf(stdev);
iowrite32(stuser->cmd, >mmio_mrpc->cmd);
 
schedule_delayed_work(>mrpc_timeout,
@@ -1231,23 +1245,38 @@ static int switchtec_init_pci(struct switchtec_dev 
*stdev,
  struct pci_dev *pdev)
 {
int rc;
+   void __iomem *map;
+   unsigned long res_start, res_len;
 
rc = pcim_enable_device(pdev);
if (rc)
return rc;
 
-   rc = pcim_iomap_regions(pdev, 0x1, KBUILD_MODNAME);
-   if (rc)
-   return rc;
-
rc = dma_set_coherent_mask(>dev, DMA_BIT_MASK(64));
if (rc)
return rc;
 
pci_set_master(pdev);
 
-   stdev->mmio = pcim_iomap_table(pdev)[0];
-   stdev->mmio_mrpc = stdev->mmio + SWITCHTEC_GAS_MRPC_OFFSET;
+   res_start = pci_resource_start(pdev, 0);
+   res_len = pci_resource_len(pdev, 0);
+
+   if (!devm_request_mem_region(>dev, res_start,
+res_len, KBUILD_MODNAME))
+   return -EBUSY;
+
+   stdev->mmio_mrpc = devm_ioremap_wc(>dev, res_start,
+  SWITCHTEC_GAS_TOP_CFG_OFFSET);
+   if (!stdev->mmio_mrpc)
+   return -ENOMEM;
+
+   map = devm_ioremap(>dev,
+  res_start + SWITCHTEC_GAS_TOP_CFG_OFFSET,
+  res_len - SWITCHTEC_GAS_TOP_CFG_OFFSET);
+   if (!map)
+   return -ENOMEM;
+
+   stdev->mmio = map - SWITCHTEC_GAS_TOP_CFG_OFFSET;
stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET;
stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
-- 
2.7.4



[PATCH 0/5] Switchtec MRPC DMA mode support

2018-12-09 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support for the Switchtec MRPC DMA mode.

Switchtec switches supports 2 MRPC interaction modes: MRPC normal mode and
MRPC DMA mode, a new feature in the latest firmware versions. MRPC normal 
mode requires the host to read the MRPC command status and output data. 
In MRPC DMA mode the command status and output data are pushed directly to
host memory and issues an interrupt upon completion. The advantage of MRPC
DMA mode is avoiding potential high latency response from the Memory Read
TLP. 

Additionally, we've made the following changes:

* Improve the efficiency of filling MRPC Input buffer by enabling write 
  combining on MRPC region of BAR
* Software workaround for delay responded Memory READ TLPs that access 
  the BAR
* And several bug fixes

Regards,
Wesley

--

Changed since v1:
  - It's a resend of v1

--


Boris Glimcher (1):
  switchtec: Set DMA coherent mask in Switchtec driver

Joey Zhang (1):
  switchtec: A temporary variable should be used for the flags of
switchtec_ioctl_event_ctl

Kelvin Cao (2):
  switchtec: Remove immediate status check after submit a MRPC command
  switchtec: Improve MRPC efficiency by leveraging write combining

Wesley Sheng (1):
  switchtec: MRPC DMA mode implementation

 drivers/pci/switch/switchtec.c | 154 -
 include/linux/switchtec.h  |  16 +
 2 files changed, 153 insertions(+), 17 deletions(-)

-- 
2.7.4



[PATCH 5/5] switchtec: MRPC DMA mode implementation

2018-12-09 Thread Wesley Sheng
MRPC normal mode requires the host to read the MRPC command status and
output data from BAR. This results in high latency responses from the
Memory Read TLP and potential Completion Timeout (CTO).

MRPC DMA mode implementation includes:
Macro definitions for registers and data structures corresponding to
MRPC DMA mode.

Add module parameter use_dma_mrpc to select between MRPC DMA mode and
MRPC normal mode.

Add MRPC mode functionality to:
* Retrieve MRPC DMA mode version
* Allocate DMA buffer, ISR registration, and enable DMA function during
  initialization
* Check MRPC execution status and collect execution results from DMA buffer
* Release DMA buffer and disable DMA function when unloading module

MRPC DMA mode is a new feature of firmware and the driver will fall back
to MRPC normal mode if there is no support in the legacy firmware.

Include  so that readq/writeq is replaced
by two readl/writel on systems that do not support it.

Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/pci/switch/switchtec.c | 108 +
 include/linux/switchtec.h  |  16 ++
 2 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 0b8862b..6b726cb 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -13,7 +13,7 @@
 #include 
 #include 
 #include 
-
+#include 
 #include 
 
 MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");
@@ -25,6 +25,11 @@ static int max_devices = 16;
 module_param(max_devices, int, 0644);
 MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");
 
+static bool use_dma_mrpc = 1;
+module_param(use_dma_mrpc, bool, 0644);
+MODULE_PARM_DESC(use_dma_mrpc,
+"Enable the use of the DMA MRPC feature");
+
 static dev_t switchtec_devt;
 static DEFINE_IDA(switchtec_minor_ida);
 
@@ -141,6 +146,11 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);
 
+   if (stdev->dma_mrpc) {
+   stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS;
+   memset(stdev->dma_mrpc->data, 0xFF, 
SWITCHTEC_MRPC_PAYLOAD_SIZE);
+   }
+
stuser_set_state(stuser, MRPC_RUNNING);
stdev->mrpc_busy = 1;
memcpy_toio(>mmio_mrpc->input_data,
@@ -180,7 +190,11 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);
 
-   stuser->status = ioread32(>mmio_mrpc->status);
+   if (stdev->dma_mrpc)
+   stuser->status = stdev->dma_mrpc->status;
+   else
+   stuser->status = ioread32(>mmio_mrpc->status);
+
if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)
return;
 
@@ -190,13 +204,19 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE)
goto out;
 
-   stuser->return_code = ioread32(>mmio_mrpc->ret_value);
+   if (stdev->dma_mrpc)
+   stuser->return_code = stdev->dma_mrpc->rtn_code;
+   else
+   stuser->return_code = ioread32(>mmio_mrpc->ret_value);
if (stuser->return_code != 0)
goto out;
 
-   memcpy_fromio(stuser->data, >mmio_mrpc->output_data,
- stuser->read_len);
-
+   if (stdev->dma_mrpc)
+   memcpy(stuser->data, >dma_mrpc->data,
+ stuser->read_len);
+   else
+   memcpy_fromio(stuser->data, >mmio_mrpc->output_data,
+ stuser->read_len);
 out:
complete_all(>comp);
list_del_init(>list);
@@ -231,7 +251,10 @@ static void mrpc_timeout_work(struct work_struct *work)
 
mutex_lock(>mrpc_mutex);
 
-   status = ioread32(>mmio_mrpc->status);
+   if (stdev->dma_mrpc)
+   status = stdev->dma_mrpc->status;
+   else
+   status = ioread32(>mmio_mrpc->status);
if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {
schedule_delayed_work(>mrpc_timeout,
  msecs_to_jiffies(500));
@@ -239,7 +262,6 @@ static void mrpc_timeout_work(struct work_struct *work)
}
 
mrpc_complete_cmd(stdev);
-
 out:
mutex_unlock(>mrpc_mutex);
 }
@@ -1030,10 +1052,24 @@ static void enable_link_state_events(struct 
switchtec_dev *stdev)
}
 }
 
+static void enable_dma_mrpc(struct switchtec_dev *stdev)
+{
+   writeq(stdev->dma_mrpc_dma_addr, >mmio_mrpc->dma_addr);
+   flush_wc_buf(stdev);
+   iowrite32(SWITCHTEC_D

[PATCH 3/5] switchtec: A temporary variable should be used for the flags of switchtec_ioctl_event_ctl

2018-12-09 Thread Wesley Sheng
From: Joey Zhang 

For nr_idxs is larger than 1 switchtec_ioctl_event_ctl event flags will be
used by each event indexes. In current implementation the event flags are
overwritten by first call of the function event_ctl().

Preserve the event flag value with a temporary variable.

Fixes: 52eabba5bcdb ("switchtec: Add IOCTLs to the Switchtec driver")
Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/pci/switch/switchtec.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 480107e..a908670 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -796,6 +796,7 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
 {
int ret;
int nr_idxs;
+   unsigned int event_flags;
struct switchtec_ioctl_event_ctl ctl;
 
if (copy_from_user(, uctl, sizeof(ctl)))
@@ -817,7 +818,9 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
else
return -EINVAL;
 
+   event_flags = ctl.flags;
for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {
+   ctl.flags = event_flags;
ret = event_ctl(stdev, );
if (ret < 0)
return ret;
-- 
2.7.4



[PATCH v2 3/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-12-05 Thread Wesley Sheng
From: Paul Selles 

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.

Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Reported-by: Boris Glimcher 
Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 9 +++--
 include/linux/switchtec.h  | 6 +-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 9916bc5..f6f0035 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -264,6 +264,7 @@ static void switchtec_ntb_mw_clr_direct(struct 
switchtec_ntb *sndev, int idx)
ctl_val &= ~NTB_CTRL_BAR_DIR_WIN_EN;
iowrite32(ctl_val, >bar_entry[bar].ctl);
iowrite32(0, >bar_entry[bar].win_size);
+   iowrite32(0, >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition, >bar_entry[bar].xlate_addr);
 }
 
@@ -286,7 +287,9 @@ static void switchtec_ntb_mw_set_direct(struct 
switchtec_ntb *sndev, int idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (lower_32_bits(size) & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(upper_32_bits(size), >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition | addr,
  >bar_entry[bar].xlate_addr);
 }
@@ -1053,7 +1056,9 @@ static int crosslink_setup_mws(struct switchtec_ntb 
*sndev, int ntb_lut_idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (lower_32_bits(size) & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(upper_32_bits(size), 
>bar_ext_entry[bar].win_size);
iowrite64(sndev->peer_partition | addr,
  >bar_entry[bar].xlate_addr);
}
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index 623719c9..64aa25e 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -243,7 +243,11 @@ struct ntb_ctrl_regs {
u32 win_size;
u64 xlate_addr;
} bar_entry[6];
-   u32 reserved2[216];
+   struct {
+   u32 win_size;
+   u32 reserved[3];
+   } bar_ext_entry[6];
+   u32 reserved2[192];
u32 req_id_table[512];
u32 reserved3[256];
u64 lut_entry[512];
-- 
2.7.4



[PATCH v2 2/3] ntb_hw_switchtec: NT req id mapping table register entry number should be 512

2018-12-05 Thread Wesley Sheng
The number of available NT req id mapping table entries per NTB control
register is 512. The driver mistakenly limits the number to 256.

Fix the array size of NT req id mapping table.

Fixes: c082b04c9d40 ("NTB: switchtec: Add NTB hardware register definitions")
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 include/linux/switchtec.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index ab400af..623719c9 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -244,8 +244,8 @@ struct ntb_ctrl_regs {
u64 xlate_addr;
} bar_entry[6];
u32 reserved2[216];
-   u32 req_id_table[256];
-   u32 reserved3[512];
+   u32 req_id_table[512];
+   u32 reserved3[256];
u64 lut_entry[512];
 } __packed;
 
-- 
2.7.4



[PATCH v2 0/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-12-05 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support of >=4G memory windows.

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.
Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Additionally, we've made the following changes:

* debug print 64bit aligned crosslink BAR numbers
* Fix the array size of NT req id mapping table

Tested with ntb_test.sh successfully based on NTB fixes series from
Logan Gunthorpe  at 
https://github.com/sbates130272/linux-p2pmem on branch of
ntb_multiport_fixes

Regards,
Wesley

--

Changed since v1:
  - Using upper_32_bits() and lower_32_bits() marcos makes it easier
to read and avoids compiler warning on 32-bit arch
  - Reorder the patches to make the bug fixes first and add a "Fixes"
line to the commit messages

--
Paul Selles (2):
  ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers
  ntb_hw_switchtec: Added support of >=4G memory windows

Wesley Sheng (1):
  ntb_hw_switchtec: NT req id mapping table register entry number should
be 512

 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 11 ---
 include/linux/switchtec.h  | 10 +++---
 2 files changed, 15 insertions(+), 6 deletions(-)

-- 
2.7.4



[PATCH v2 3/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-12-05 Thread Wesley Sheng
From: Paul Selles 

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.

Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Reported-by: Boris Glimcher 
Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 9 +++--
 include/linux/switchtec.h  | 6 +-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 9916bc5..f6f0035 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -264,6 +264,7 @@ static void switchtec_ntb_mw_clr_direct(struct 
switchtec_ntb *sndev, int idx)
ctl_val &= ~NTB_CTRL_BAR_DIR_WIN_EN;
iowrite32(ctl_val, >bar_entry[bar].ctl);
iowrite32(0, >bar_entry[bar].win_size);
+   iowrite32(0, >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition, >bar_entry[bar].xlate_addr);
 }
 
@@ -286,7 +287,9 @@ static void switchtec_ntb_mw_set_direct(struct 
switchtec_ntb *sndev, int idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (lower_32_bits(size) & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(upper_32_bits(size), >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition | addr,
  >bar_entry[bar].xlate_addr);
 }
@@ -1053,7 +1056,9 @@ static int crosslink_setup_mws(struct switchtec_ntb 
*sndev, int ntb_lut_idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (lower_32_bits(size) & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(upper_32_bits(size), 
>bar_ext_entry[bar].win_size);
iowrite64(sndev->peer_partition | addr,
  >bar_entry[bar].xlate_addr);
}
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index 623719c9..64aa25e 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -243,7 +243,11 @@ struct ntb_ctrl_regs {
u32 win_size;
u64 xlate_addr;
} bar_entry[6];
-   u32 reserved2[216];
+   struct {
+   u32 win_size;
+   u32 reserved[3];
+   } bar_ext_entry[6];
+   u32 reserved2[192];
u32 req_id_table[512];
u32 reserved3[256];
u64 lut_entry[512];
-- 
2.7.4



[PATCH v2 2/3] ntb_hw_switchtec: NT req id mapping table register entry number should be 512

2018-12-05 Thread Wesley Sheng
The number of available NT req id mapping table entries per NTB control
register is 512. The driver mistakenly limits the number to 256.

Fix the array size of NT req id mapping table.

Fixes: c082b04c9d40 ("NTB: switchtec: Add NTB hardware register definitions")
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 include/linux/switchtec.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index ab400af..623719c9 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -244,8 +244,8 @@ struct ntb_ctrl_regs {
u64 xlate_addr;
} bar_entry[6];
u32 reserved2[216];
-   u32 req_id_table[256];
-   u32 reserved3[512];
+   u32 req_id_table[512];
+   u32 reserved3[256];
u64 lut_entry[512];
 } __packed;
 
-- 
2.7.4



[PATCH v2 0/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-12-05 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support of >=4G memory windows.

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.
Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Additionally, we've made the following changes:

* debug print 64bit aligned crosslink BAR numbers
* Fix the array size of NT req id mapping table

Tested with ntb_test.sh successfully based on NTB fixes series from
Logan Gunthorpe  at 
https://github.com/sbates130272/linux-p2pmem on branch of
ntb_multiport_fixes

Regards,
Wesley

--

Changed since v1:
  - Using upper_32_bits() and lower_32_bits() marcos makes it easier
to read and avoids compiler warning on 32-bit arch
  - Reorder the patches to make the bug fixes first and add a "Fixes"
line to the commit messages

--
Paul Selles (2):
  ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers
  ntb_hw_switchtec: Added support of >=4G memory windows

Wesley Sheng (1):
  ntb_hw_switchtec: NT req id mapping table register entry number should
be 512

 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 11 ---
 include/linux/switchtec.h  | 10 +++---
 2 files changed, 15 insertions(+), 6 deletions(-)

-- 
2.7.4



[PATCH v2 1/3] ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers

2018-12-05 Thread Wesley Sheng
From: Paul Selles 

Switchtec NTB crosslink BARs are 64bit addressed but they are printed as
32bit addressed BARs. Fix debug log to increment the BAR numbers by 2 to
reflect the 64bit address alignment.

Fixes: 017525018202 ("ntb_hw_switchtec: Add initialization code for crosslink")
Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 5ee5f40..9916bc5 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1120,7 +1120,7 @@ static int crosslink_enum_partition(struct switchtec_ntb 
*sndev,
 
dev_dbg(>stdev->dev,
"Crosslink BAR%d addr: %llx\n",
-   i, bar_addr);
+   i*2, bar_addr);
 
if (bar_addr != bar_space * i)
continue;
-- 
2.7.4



[PATCH v2 1/3] ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers

2018-12-05 Thread Wesley Sheng
From: Paul Selles 

Switchtec NTB crosslink BARs are 64bit addressed but they are printed as
32bit addressed BARs. Fix debug log to increment the BAR numbers by 2 to
reflect the 64bit address alignment.

Fixes: 017525018202 ("ntb_hw_switchtec: Add initialization code for crosslink")
Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
Reviewed-by: Logan Gunthorpe 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 5ee5f40..9916bc5 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1120,7 +1120,7 @@ static int crosslink_enum_partition(struct switchtec_ntb 
*sndev,
 
dev_dbg(>stdev->dev,
"Crosslink BAR%d addr: %llx\n",
-   i, bar_addr);
+   i*2, bar_addr);
 
if (bar_addr != bar_space * i)
continue;
-- 
2.7.4



[PATCH 2/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-11-21 Thread Wesley Sheng
From: Paul Selles 

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.

Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Reported-by: Boris Glimcher 
Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 9 +++--
 include/linux/switchtec.h  | 6 +-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 9916bc5..32850fb 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -264,6 +264,7 @@ static void switchtec_ntb_mw_clr_direct(struct 
switchtec_ntb *sndev, int idx)
ctl_val &= ~NTB_CTRL_BAR_DIR_WIN_EN;
iowrite32(ctl_val, >bar_entry[bar].ctl);
iowrite32(0, >bar_entry[bar].win_size);
+   iowrite32(0, >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition, >bar_entry[bar].xlate_addr);
 }
 
@@ -286,7 +287,9 @@ static void switchtec_ntb_mw_set_direct(struct 
switchtec_ntb *sndev, int idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (size & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(size >> 32, >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition | addr,
  >bar_entry[bar].xlate_addr);
 }
@@ -1053,7 +1056,9 @@ static int crosslink_setup_mws(struct switchtec_ntb 
*sndev, int ntb_lut_idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (size & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(size >> 32, >bar_ext_entry[bar].win_size);
iowrite64(sndev->peer_partition | addr,
  >bar_entry[bar].xlate_addr);
}
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index eee0412..1e6e333 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -248,7 +248,11 @@ struct ntb_ctrl_regs {
u32 win_size;
u64 xlate_addr;
} bar_entry[6];
-   u32 reserved2[216];
+   struct {
+   u32 win_size;
+   u32 reserved[3];
+   } bar_ext_entry[6];
+   u32 reserved2[192];
u32 req_id_table[256];
u32 reserved3[512];
u64 lut_entry[512];
-- 
2.7.4



[PATCH 1/3] ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers

2018-11-21 Thread Wesley Sheng
From: Paul Selles 

Switchtec NTB crosslink BARs are 64bit addressed but they are printed as
32bit addressed BARs. Fix debug log to increment the BAR numbers by 2 to
reflect the 64bit address alignment.

Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 5ee5f40..9916bc5 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1120,7 +1120,7 @@ static int crosslink_enum_partition(struct switchtec_ntb 
*sndev,
 
dev_dbg(>stdev->dev,
"Crosslink BAR%d addr: %llx\n",
-   i, bar_addr);
+   i*2, bar_addr);
 
if (bar_addr != bar_space * i)
continue;
-- 
2.7.4



[PATCH 0/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-11-21 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support of >=4G memory windows.

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.
Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Additionally, we've made the following changes:

* debug print 64bit aligned crosslink BAR numbers
* Fix the array size of NT req id mapping table

Tested with ntb_test.sh successfully based on NTB fixes series from
Logan Gunthorpe  at 
https://github.com/sbates130272/linux-p2pmem on branch of
ntb_multiport_fixes

Regards,
Wesley



Paul Selles (2):
  ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers
  ntb_hw_switchtec: Added support of >=4G memory windows

Wesley Sheng (1):
  ntb_hw_switchtec: NT req id mapping table register entry number should
be 512

 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 11 ---
 include/linux/switchtec.h  | 10 +++---
 2 files changed, 15 insertions(+), 6 deletions(-)

-- 
2.7.4



[PATCH 3/3] ntb_hw_switchtec: NT req id mapping table register entry number should be 512

2018-11-21 Thread Wesley Sheng
The number of available NT req id mapping table entries per NTB control
register is 512. The driver mistakenly limits the number to 256.

Fix the array size of NT req id mapping table.

Signed-off-by: Wesley Sheng 
---
 include/linux/switchtec.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index 1e6e333..52a079b 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -253,8 +253,8 @@ struct ntb_ctrl_regs {
u32 reserved[3];
} bar_ext_entry[6];
u32 reserved2[192];
-   u32 req_id_table[256];
-   u32 reserved3[512];
+   u32 req_id_table[512];
+   u32 reserved3[256];
u64 lut_entry[512];
 } __packed;
 
-- 
2.7.4



[PATCH 2/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-11-21 Thread Wesley Sheng
From: Paul Selles 

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.

Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Reported-by: Boris Glimcher 
Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 9 +++--
 include/linux/switchtec.h  | 6 +-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 9916bc5..32850fb 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -264,6 +264,7 @@ static void switchtec_ntb_mw_clr_direct(struct 
switchtec_ntb *sndev, int idx)
ctl_val &= ~NTB_CTRL_BAR_DIR_WIN_EN;
iowrite32(ctl_val, >bar_entry[bar].ctl);
iowrite32(0, >bar_entry[bar].win_size);
+   iowrite32(0, >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition, >bar_entry[bar].xlate_addr);
 }
 
@@ -286,7 +287,9 @@ static void switchtec_ntb_mw_set_direct(struct 
switchtec_ntb *sndev, int idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (size & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(size >> 32, >bar_ext_entry[bar].win_size);
iowrite64(sndev->self_partition | addr,
  >bar_entry[bar].xlate_addr);
 }
@@ -1053,7 +1056,9 @@ static int crosslink_setup_mws(struct switchtec_ntb 
*sndev, int ntb_lut_idx,
ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;
 
iowrite32(ctl_val, >bar_entry[bar].ctl);
-   iowrite32(xlate_pos | size, >bar_entry[bar].win_size);
+   iowrite32(xlate_pos | (size & 0xF000),
+ >bar_entry[bar].win_size);
+   iowrite32(size >> 32, >bar_ext_entry[bar].win_size);
iowrite64(sndev->peer_partition | addr,
  >bar_entry[bar].xlate_addr);
}
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index eee0412..1e6e333 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -248,7 +248,11 @@ struct ntb_ctrl_regs {
u32 win_size;
u64 xlate_addr;
} bar_entry[6];
-   u32 reserved2[216];
+   struct {
+   u32 win_size;
+   u32 reserved[3];
+   } bar_ext_entry[6];
+   u32 reserved2[192];
u32 req_id_table[256];
u32 reserved3[512];
u64 lut_entry[512];
-- 
2.7.4



[PATCH 1/3] ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers

2018-11-21 Thread Wesley Sheng
From: Paul Selles 

Switchtec NTB crosslink BARs are 64bit addressed but they are printed as
32bit addressed BARs. Fix debug log to increment the BAR numbers by 2 to
reflect the 64bit address alignment.

Signed-off-by: Paul Selles 
Signed-off-by: Wesley Sheng 
---
 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c 
b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 5ee5f40..9916bc5 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -1120,7 +1120,7 @@ static int crosslink_enum_partition(struct switchtec_ntb 
*sndev,
 
dev_dbg(>stdev->dev,
"Crosslink BAR%d addr: %llx\n",
-   i, bar_addr);
+   i*2, bar_addr);
 
if (bar_addr != bar_space * i)
continue;
-- 
2.7.4



[PATCH 0/3] ntb_hw_switchtec: Added support of >=4G memory windows

2018-11-21 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support of >=4G memory windows.

Current Switchtec's BAR setup registers are limited to 32bits,
corresponding to the maximum MW (memory window) size is <4G.
Increase the MW sizes with the addition of the BAR Setup Extension
Register for the upper 32bits of a 64bits MW size. This increases the MW
range to between 4K and 2^63.

Additionally, we've made the following changes:

* debug print 64bit aligned crosslink BAR numbers
* Fix the array size of NT req id mapping table

Tested with ntb_test.sh successfully based on NTB fixes series from
Logan Gunthorpe  at 
https://github.com/sbates130272/linux-p2pmem on branch of
ntb_multiport_fixes

Regards,
Wesley



Paul Selles (2):
  ntb_hw_switchtec: debug print 64bit aligned crosslink BAR Numbers
  ntb_hw_switchtec: Added support of >=4G memory windows

Wesley Sheng (1):
  ntb_hw_switchtec: NT req id mapping table register entry number should
be 512

 drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 11 ---
 include/linux/switchtec.h  | 10 +++---
 2 files changed, 15 insertions(+), 6 deletions(-)

-- 
2.7.4



[PATCH 3/3] ntb_hw_switchtec: NT req id mapping table register entry number should be 512

2018-11-21 Thread Wesley Sheng
The number of available NT req id mapping table entries per NTB control
register is 512. The driver mistakenly limits the number to 256.

Fix the array size of NT req id mapping table.

Signed-off-by: Wesley Sheng 
---
 include/linux/switchtec.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index 1e6e333..52a079b 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -253,8 +253,8 @@ struct ntb_ctrl_regs {
u32 reserved[3];
} bar_ext_entry[6];
u32 reserved2[192];
-   u32 req_id_table[256];
-   u32 reserved3[512];
+   u32 req_id_table[512];
+   u32 reserved3[256];
u64 lut_entry[512];
 } __packed;
 
-- 
2.7.4



[PATCH 4/5] switchtec: Improve MRPC efficiency by leveraging write combining

2018-11-14 Thread Wesley Sheng
From: Kelvin Cao 

MRPC Input buffer is mostly memory without any side effects, thus we can
improve the access time by enabling write combining on only this region of
the BAR.

In a few places, we still need to flush the WC buffer. To do this, we
simply read from the Outbound Doorbell register seeing reads to this
register are processed by low latency hardware.

Signed-off-by: Kelvin Cao 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 41 +++--
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index a908670..0b8862b 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -113,6 +113,19 @@ static void stuser_set_state(struct switchtec_user *stuser,
 
 static void mrpc_complete_cmd(struct switchtec_dev *stdev);
 
+static void flush_wc_buf(struct switchtec_dev *stdev)
+{
+   struct ntb_dbmsg_regs __iomem *mmio_dbmsg;
+
+   /*
+* odb (outbound doorbell) register is processed by low latency
+* hardware and w/o side effect
+*/
+   mmio_dbmsg = (void __iomem *)stdev->mmio_ntb +
+   SWITCHTEC_NTB_REG_DBMSG_OFFSET;
+   ioread32(_dbmsg->odb);
+}
+
 static void mrpc_cmd_submit(struct switchtec_dev *stdev)
 {
/* requires the mrpc_mutex to already be held when called */
@@ -132,6 +145,7 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stdev->mrpc_busy = 1;
memcpy_toio(>mmio_mrpc->input_data,
stuser->data, stuser->data_len);
+   flush_wc_buf(stdev);
iowrite32(stuser->cmd, >mmio_mrpc->cmd);
 
schedule_delayed_work(>mrpc_timeout,
@@ -1231,23 +1245,38 @@ static int switchtec_init_pci(struct switchtec_dev 
*stdev,
  struct pci_dev *pdev)
 {
int rc;
+   void __iomem *map;
+   unsigned long res_start, res_len;
 
rc = pcim_enable_device(pdev);
if (rc)
return rc;
 
-   rc = pcim_iomap_regions(pdev, 0x1, KBUILD_MODNAME);
-   if (rc)
-   return rc;
-
rc = dma_set_coherent_mask(>dev, DMA_BIT_MASK(64));
if (rc)
return rc;
 
pci_set_master(pdev);
 
-   stdev->mmio = pcim_iomap_table(pdev)[0];
-   stdev->mmio_mrpc = stdev->mmio + SWITCHTEC_GAS_MRPC_OFFSET;
+   res_start = pci_resource_start(pdev, 0);
+   res_len = pci_resource_len(pdev, 0);
+
+   if (!devm_request_mem_region(>dev, res_start,
+res_len, KBUILD_MODNAME))
+   return -EBUSY;
+
+   stdev->mmio_mrpc = devm_ioremap_wc(>dev, res_start,
+  SWITCHTEC_GAS_TOP_CFG_OFFSET);
+   if (!stdev->mmio_mrpc)
+   return -ENOMEM;
+
+   map = devm_ioremap(>dev,
+  res_start + SWITCHTEC_GAS_TOP_CFG_OFFSET,
+  res_len - SWITCHTEC_GAS_TOP_CFG_OFFSET);
+   if (!map)
+   return -ENOMEM;
+
+   stdev->mmio = map - SWITCHTEC_GAS_TOP_CFG_OFFSET;
stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET;
stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
-- 
2.7.4



[PATCH 5/5] switchtec: MRPC DMA mode implementation

2018-11-14 Thread Wesley Sheng
MRPC normal mode requires the host to read the MRPC command status and
output data from BAR. This results in high latency responses from the
Memory Read TLP and potential Completion Timeout (CTO).

MRPC DMA mode implementation includes:
Macro definitions for registers and data structures corresponding to
MRPC DMA mode.

Add module parameter use_dma_mrpc to select between MRPC DMA mode and
MRPC normal mode.

Add MRPC mode functionality to:
* Retrieve MRPC DMA mode version
* Allocate DMA buffer, ISR registration, and enable DMA function during
  initialization
* Check MRPC execution status and collect execution results from DMA buffer
* Release DMA buffer and disable DMA function when unloading module

MRPC DMA mode is a new feature of firmware and the driver will fall back
to MRPC normal mode if there is no support in the legacy firmware.

Include  so that readq/writeq is replaced
by two readl/writel on systems that do not support it.

Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 108 +
 include/linux/switchtec.h  |  16 ++
 2 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 0b8862b..6b726cb 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -13,7 +13,7 @@
 #include 
 #include 
 #include 
-
+#include 
 #include 
 
 MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");
@@ -25,6 +25,11 @@ static int max_devices = 16;
 module_param(max_devices, int, 0644);
 MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");
 
+static bool use_dma_mrpc = 1;
+module_param(use_dma_mrpc, bool, 0644);
+MODULE_PARM_DESC(use_dma_mrpc,
+"Enable the use of the DMA MRPC feature");
+
 static dev_t switchtec_devt;
 static DEFINE_IDA(switchtec_minor_ida);
 
@@ -141,6 +146,11 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);
 
+   if (stdev->dma_mrpc) {
+   stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS;
+   memset(stdev->dma_mrpc->data, 0xFF, 
SWITCHTEC_MRPC_PAYLOAD_SIZE);
+   }
+
stuser_set_state(stuser, MRPC_RUNNING);
stdev->mrpc_busy = 1;
memcpy_toio(>mmio_mrpc->input_data,
@@ -180,7 +190,11 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);
 
-   stuser->status = ioread32(>mmio_mrpc->status);
+   if (stdev->dma_mrpc)
+   stuser->status = stdev->dma_mrpc->status;
+   else
+   stuser->status = ioread32(>mmio_mrpc->status);
+
if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)
return;
 
@@ -190,13 +204,19 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE)
goto out;
 
-   stuser->return_code = ioread32(>mmio_mrpc->ret_value);
+   if (stdev->dma_mrpc)
+   stuser->return_code = stdev->dma_mrpc->rtn_code;
+   else
+   stuser->return_code = ioread32(>mmio_mrpc->ret_value);
if (stuser->return_code != 0)
goto out;
 
-   memcpy_fromio(stuser->data, >mmio_mrpc->output_data,
- stuser->read_len);
-
+   if (stdev->dma_mrpc)
+   memcpy(stuser->data, >dma_mrpc->data,
+ stuser->read_len);
+   else
+   memcpy_fromio(stuser->data, >mmio_mrpc->output_data,
+ stuser->read_len);
 out:
complete_all(>comp);
list_del_init(>list);
@@ -231,7 +251,10 @@ static void mrpc_timeout_work(struct work_struct *work)
 
mutex_lock(>mrpc_mutex);
 
-   status = ioread32(>mmio_mrpc->status);
+   if (stdev->dma_mrpc)
+   status = stdev->dma_mrpc->status;
+   else
+   status = ioread32(>mmio_mrpc->status);
if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {
schedule_delayed_work(>mrpc_timeout,
  msecs_to_jiffies(500));
@@ -239,7 +262,6 @@ static void mrpc_timeout_work(struct work_struct *work)
}
 
mrpc_complete_cmd(stdev);
-
 out:
mutex_unlock(>mrpc_mutex);
 }
@@ -1030,10 +1052,24 @@ static void enable_link_state_events(struct 
switchtec_dev *stdev)
}
 }
 
+static void enable_dma_mrpc(struct switchtec_dev *stdev)
+{
+   writeq(stdev->dma_mrpc_dma_addr, >mmio_mrpc->dma_addr);
+   flush_wc_buf(stdev);
+   iowrite32(SWITCHTEC_DMA_MRPC_

[PATCH 3/5] switchtec: A temporary variable should be used for the flags of switchtec_ioctl_event_ctl

2018-11-14 Thread Wesley Sheng
From: Joey Zhang 

For nr_idxs is larger than 1 switchtec_ioctl_event_ctl event flags will be
used by each event indexes. In current implementation the event flags are
overwritten by first call of the function event_ctl().

Preserve the event flag value with a temporary variable.

Fixes: 52eabba5bcdb ("switchtec: Add IOCTLs to the Switchtec driver")
Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 480107e..a908670 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -796,6 +796,7 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
 {
int ret;
int nr_idxs;
+   unsigned int event_flags;
struct switchtec_ioctl_event_ctl ctl;
 
if (copy_from_user(, uctl, sizeof(ctl)))
@@ -817,7 +818,9 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
else
return -EINVAL;
 
+   event_flags = ctl.flags;
for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {
+   ctl.flags = event_flags;
ret = event_ctl(stdev, );
if (ret < 0)
return ret;
-- 
2.7.4



[PATCH 5/5] switchtec: MRPC DMA mode implementation

2018-11-14 Thread Wesley Sheng
MRPC normal mode requires the host to read the MRPC command status and
output data from BAR. This results in high latency responses from the
Memory Read TLP and potential Completion Timeout (CTO).

MRPC DMA mode implementation includes:
Macro definitions for registers and data structures corresponding to
MRPC DMA mode.

Add module parameter use_dma_mrpc to select between MRPC DMA mode and
MRPC normal mode.

Add MRPC mode functionality to:
* Retrieve MRPC DMA mode version
* Allocate DMA buffer, ISR registration, and enable DMA function during
  initialization
* Check MRPC execution status and collect execution results from DMA buffer
* Release DMA buffer and disable DMA function when unloading module

MRPC DMA mode is a new feature of firmware and the driver will fall back
to MRPC normal mode if there is no support in the legacy firmware.

Include  so that readq/writeq is replaced
by two readl/writel on systems that do not support it.

Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 108 +
 include/linux/switchtec.h  |  16 ++
 2 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 0b8862b..6b726cb 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -13,7 +13,7 @@
 #include 
 #include 
 #include 
-
+#include 
 #include 
 
 MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");
@@ -25,6 +25,11 @@ static int max_devices = 16;
 module_param(max_devices, int, 0644);
 MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");
 
+static bool use_dma_mrpc = 1;
+module_param(use_dma_mrpc, bool, 0644);
+MODULE_PARM_DESC(use_dma_mrpc,
+"Enable the use of the DMA MRPC feature");
+
 static dev_t switchtec_devt;
 static DEFINE_IDA(switchtec_minor_ida);
 
@@ -141,6 +146,11 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);
 
+   if (stdev->dma_mrpc) {
+   stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS;
+   memset(stdev->dma_mrpc->data, 0xFF, 
SWITCHTEC_MRPC_PAYLOAD_SIZE);
+   }
+
stuser_set_state(stuser, MRPC_RUNNING);
stdev->mrpc_busy = 1;
memcpy_toio(>mmio_mrpc->input_data,
@@ -180,7 +190,11 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);
 
-   stuser->status = ioread32(>mmio_mrpc->status);
+   if (stdev->dma_mrpc)
+   stuser->status = stdev->dma_mrpc->status;
+   else
+   stuser->status = ioread32(>mmio_mrpc->status);
+
if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)
return;
 
@@ -190,13 +204,19 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE)
goto out;
 
-   stuser->return_code = ioread32(>mmio_mrpc->ret_value);
+   if (stdev->dma_mrpc)
+   stuser->return_code = stdev->dma_mrpc->rtn_code;
+   else
+   stuser->return_code = ioread32(>mmio_mrpc->ret_value);
if (stuser->return_code != 0)
goto out;
 
-   memcpy_fromio(stuser->data, >mmio_mrpc->output_data,
- stuser->read_len);
-
+   if (stdev->dma_mrpc)
+   memcpy(stuser->data, >dma_mrpc->data,
+ stuser->read_len);
+   else
+   memcpy_fromio(stuser->data, >mmio_mrpc->output_data,
+ stuser->read_len);
 out:
complete_all(>comp);
list_del_init(>list);
@@ -231,7 +251,10 @@ static void mrpc_timeout_work(struct work_struct *work)
 
mutex_lock(>mrpc_mutex);
 
-   status = ioread32(>mmio_mrpc->status);
+   if (stdev->dma_mrpc)
+   status = stdev->dma_mrpc->status;
+   else
+   status = ioread32(>mmio_mrpc->status);
if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {
schedule_delayed_work(>mrpc_timeout,
  msecs_to_jiffies(500));
@@ -239,7 +262,6 @@ static void mrpc_timeout_work(struct work_struct *work)
}
 
mrpc_complete_cmd(stdev);
-
 out:
mutex_unlock(>mrpc_mutex);
 }
@@ -1030,10 +1052,24 @@ static void enable_link_state_events(struct 
switchtec_dev *stdev)
}
 }
 
+static void enable_dma_mrpc(struct switchtec_dev *stdev)
+{
+   writeq(stdev->dma_mrpc_dma_addr, >mmio_mrpc->dma_addr);
+   flush_wc_buf(stdev);
+   iowrite32(SWITCHTEC_DMA_MRPC_

[PATCH 3/5] switchtec: A temporary variable should be used for the flags of switchtec_ioctl_event_ctl

2018-11-14 Thread Wesley Sheng
From: Joey Zhang 

For nr_idxs is larger than 1 switchtec_ioctl_event_ctl event flags will be
used by each event indexes. In current implementation the event flags are
overwritten by first call of the function event_ctl().

Preserve the event flag value with a temporary variable.

Fixes: 52eabba5bcdb ("switchtec: Add IOCTLs to the Switchtec driver")
Signed-off-by: Joey Zhang 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 480107e..a908670 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -796,6 +796,7 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
 {
int ret;
int nr_idxs;
+   unsigned int event_flags;
struct switchtec_ioctl_event_ctl ctl;
 
if (copy_from_user(, uctl, sizeof(ctl)))
@@ -817,7 +818,9 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
else
return -EINVAL;
 
+   event_flags = ctl.flags;
for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {
+   ctl.flags = event_flags;
ret = event_ctl(stdev, );
if (ret < 0)
return ret;
-- 
2.7.4



[PATCH 4/5] switchtec: Improve MRPC efficiency by leveraging write combining

2018-11-14 Thread Wesley Sheng
From: Kelvin Cao 

MRPC Input buffer is mostly memory without any side effects, thus we can
improve the access time by enabling write combining on only this region of
the BAR.

In a few places, we still need to flush the WC buffer. To do this, we
simply read from the Outbound Doorbell register seeing reads to this
register are processed by low latency hardware.

Signed-off-by: Kelvin Cao 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 41 +++--
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index a908670..0b8862b 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -113,6 +113,19 @@ static void stuser_set_state(struct switchtec_user *stuser,
 
 static void mrpc_complete_cmd(struct switchtec_dev *stdev);
 
+static void flush_wc_buf(struct switchtec_dev *stdev)
+{
+   struct ntb_dbmsg_regs __iomem *mmio_dbmsg;
+
+   /*
+* odb (outbound doorbell) register is processed by low latency
+* hardware and w/o side effect
+*/
+   mmio_dbmsg = (void __iomem *)stdev->mmio_ntb +
+   SWITCHTEC_NTB_REG_DBMSG_OFFSET;
+   ioread32(_dbmsg->odb);
+}
+
 static void mrpc_cmd_submit(struct switchtec_dev *stdev)
 {
/* requires the mrpc_mutex to already be held when called */
@@ -132,6 +145,7 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stdev->mrpc_busy = 1;
memcpy_toio(>mmio_mrpc->input_data,
stuser->data, stuser->data_len);
+   flush_wc_buf(stdev);
iowrite32(stuser->cmd, >mmio_mrpc->cmd);
 
schedule_delayed_work(>mrpc_timeout,
@@ -1231,23 +1245,38 @@ static int switchtec_init_pci(struct switchtec_dev 
*stdev,
  struct pci_dev *pdev)
 {
int rc;
+   void __iomem *map;
+   unsigned long res_start, res_len;
 
rc = pcim_enable_device(pdev);
if (rc)
return rc;
 
-   rc = pcim_iomap_regions(pdev, 0x1, KBUILD_MODNAME);
-   if (rc)
-   return rc;
-
rc = dma_set_coherent_mask(>dev, DMA_BIT_MASK(64));
if (rc)
return rc;
 
pci_set_master(pdev);
 
-   stdev->mmio = pcim_iomap_table(pdev)[0];
-   stdev->mmio_mrpc = stdev->mmio + SWITCHTEC_GAS_MRPC_OFFSET;
+   res_start = pci_resource_start(pdev, 0);
+   res_len = pci_resource_len(pdev, 0);
+
+   if (!devm_request_mem_region(>dev, res_start,
+res_len, KBUILD_MODNAME))
+   return -EBUSY;
+
+   stdev->mmio_mrpc = devm_ioremap_wc(>dev, res_start,
+  SWITCHTEC_GAS_TOP_CFG_OFFSET);
+   if (!stdev->mmio_mrpc)
+   return -ENOMEM;
+
+   map = devm_ioremap(>dev,
+  res_start + SWITCHTEC_GAS_TOP_CFG_OFFSET,
+  res_len - SWITCHTEC_GAS_TOP_CFG_OFFSET);
+   if (!map)
+   return -ENOMEM;
+
+   stdev->mmio = map - SWITCHTEC_GAS_TOP_CFG_OFFSET;
stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET;
stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
-- 
2.7.4



[PATCH 0/5] Switchtec MRPC DMA mode support

2018-11-14 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support for the Switchtec MRPC DMA mode.

Switchtec switches supports 2 MRPC interaction modes: MRPC normal mode and
MRPC DMA mode, a new feature in the latest firmware versions. MRPC normal 
mode requires the host to read the MRPC command status and output data. 
In MRPC DMA mode the command status and output data are pushed directly to
host memory and issues an interrupt upon completion. The advantage of MRPC
DMA mode is avoiding potential high latency response from the Memory Read
TLP. 

Additionally, we've made the following changes:

* Improve the efficiency of filling MRPC Input buffer by enabling write 
  combining on MRPC region of BAR
* Software workaround for delay responded Memory READ TLPs that access 
  the BAR
* And several bug fixes

Regards,
Wesley



Boris Glimcher (1):
  switchtec: Set DMA coherent mask in Switchtec driver

Joey Zhang (1):
  switchtec: A temporary variable should be used for the flags of
switchtec_ioctl_event_ctl

Kelvin Cao (2):
  switchtec: Remove immediate status check after submit a MRPC command
  switchtec: Improve MRPC efficiency by leveraging write combining

Wesley Sheng (1):
  switchtec: MRPC DMA mode implementation

 drivers/pci/switch/switchtec.c | 154 -
 include/linux/switchtec.h  |  16 +
 2 files changed, 153 insertions(+), 17 deletions(-)

-- 
2.7.4



[PATCH 2/5] switchtec: Set DMA coherent mask in Switchtec driver

2018-11-14 Thread Wesley Sheng
From: Boris Glimcher 

Switchtec hardware supports 64-bit DMA, set the correct DMA mask.
This allows the CMA to allocate larger buffers for memory windows.

Signed-off-by: Boris Glimcher 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index d2bca2d..480107e 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1237,6 +1237,10 @@ static int switchtec_init_pci(struct switchtec_dev 
*stdev,
if (rc)
return rc;
 
+   rc = dma_set_coherent_mask(>dev, DMA_BIT_MASK(64));
+   if (rc)
+   return rc;
+
pci_set_master(pdev);
 
stdev->mmio = pcim_iomap_table(pdev)[0];
-- 
2.7.4



[PATCH 0/5] Switchtec MRPC DMA mode support

2018-11-14 Thread Wesley Sheng
Hi, Everyone,

This patch series adds support for the Switchtec MRPC DMA mode.

Switchtec switches supports 2 MRPC interaction modes: MRPC normal mode and
MRPC DMA mode, a new feature in the latest firmware versions. MRPC normal 
mode requires the host to read the MRPC command status and output data. 
In MRPC DMA mode the command status and output data are pushed directly to
host memory and issues an interrupt upon completion. The advantage of MRPC
DMA mode is avoiding potential high latency response from the Memory Read
TLP. 

Additionally, we've made the following changes:

* Improve the efficiency of filling MRPC Input buffer by enabling write 
  combining on MRPC region of BAR
* Software workaround for delay responded Memory READ TLPs that access 
  the BAR
* And several bug fixes

Regards,
Wesley



Boris Glimcher (1):
  switchtec: Set DMA coherent mask in Switchtec driver

Joey Zhang (1):
  switchtec: A temporary variable should be used for the flags of
switchtec_ioctl_event_ctl

Kelvin Cao (2):
  switchtec: Remove immediate status check after submit a MRPC command
  switchtec: Improve MRPC efficiency by leveraging write combining

Wesley Sheng (1):
  switchtec: MRPC DMA mode implementation

 drivers/pci/switch/switchtec.c | 154 -
 include/linux/switchtec.h  |  16 +
 2 files changed, 153 insertions(+), 17 deletions(-)

-- 
2.7.4



[PATCH 2/5] switchtec: Set DMA coherent mask in Switchtec driver

2018-11-14 Thread Wesley Sheng
From: Boris Glimcher 

Switchtec hardware supports 64-bit DMA, set the correct DMA mask.
This allows the CMA to allocate larger buffers for memory windows.

Signed-off-by: Boris Glimcher 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index d2bca2d..480107e 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1237,6 +1237,10 @@ static int switchtec_init_pci(struct switchtec_dev 
*stdev,
if (rc)
return rc;
 
+   rc = dma_set_coherent_mask(>dev, DMA_BIT_MASK(64));
+   if (rc)
+   return rc;
+
pci_set_master(pdev);
 
stdev->mmio = pcim_iomap_table(pdev)[0];
-- 
2.7.4



[PATCH 1/5] switchtec: Remove immediate status check after submit a MRPC command

2018-11-14 Thread Wesley Sheng
From: Kelvin Cao 

After submitting a Firmware Download MRPC command, Switchtec firmware will
delay Management EP BAR MemRd TLP responses by more than 10ms. This is a
firmware limitation. Delayed MemRd completions are problem for systems with
a low Completion Timeout (CTO).

The current driver checks the MRPC status immediately after submitting an
MRPC command, which results in the MemRd TLP that's affected by the above
limitation.

Remove the immediate status check and rely on the check after receiving an
interrupt or timing out.

This is only a software workaround to the READ issue and a proper fix of
this should be done in firmware.

Fixes: 080b47def5e5 ("MicroSemi Switchtec management interface driver")
Signed-off-by: Kelvin Cao 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 54a8b30..d2bca2d 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -134,10 +134,6 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stuser->data, stuser->data_len);
iowrite32(stuser->cmd, >mmio_mrpc->cmd);
 
-   stuser->status = ioread32(>mmio_mrpc->status);
-   if (stuser->status != SWITCHTEC_MRPC_STATUS_INPROGRESS)
-   mrpc_complete_cmd(stdev);
-
schedule_delayed_work(>mrpc_timeout,
  msecs_to_jiffies(500));
 }
-- 
2.7.4



[PATCH 1/5] switchtec: Remove immediate status check after submit a MRPC command

2018-11-14 Thread Wesley Sheng
From: Kelvin Cao 

After submitting a Firmware Download MRPC command, Switchtec firmware will
delay Management EP BAR MemRd TLP responses by more than 10ms. This is a
firmware limitation. Delayed MemRd completions are problem for systems with
a low Completion Timeout (CTO).

The current driver checks the MRPC status immediately after submitting an
MRPC command, which results in the MemRd TLP that's affected by the above
limitation.

Remove the immediate status check and rely on the check after receiving an
interrupt or timing out.

This is only a software workaround to the READ issue and a proper fix of
this should be done in firmware.

Fixes: 080b47def5e5 ("MicroSemi Switchtec management interface driver")
Signed-off-by: Kelvin Cao 
Signed-off-by: Wesley Sheng 
---
 drivers/pci/switch/switchtec.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 54a8b30..d2bca2d 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -134,10 +134,6 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
stuser->data, stuser->data_len);
iowrite32(stuser->cmd, >mmio_mrpc->cmd);
 
-   stuser->status = ioread32(>mmio_mrpc->status);
-   if (stuser->status != SWITCHTEC_MRPC_STATUS_INPROGRESS)
-   mrpc_complete_cmd(stdev);
-
schedule_delayed_work(>mrpc_timeout,
  msecs_to_jiffies(500));
 }
-- 
2.7.4