diff mbox

[Utopic] bnx2x: Configure device endianity on driver load and reset endianity on removal.

Message ID 1409700784-24654-1-git-send-email-cascardo@linux.vnet.ibm.com
State New
Headers show

Commit Message

Thadeu Lima de Souza Cascardo Sept. 2, 2014, 11:33 p.m. UTC
From: Manish Chopra <manish.chopra@qlogic.com>

Some hosts can be both little and big endian.
In certain scenarios a big endian kernel can kexec a little endian kernel.

This patch fixes this case from both ends:
1) Return endianity to original values on shutdown (in case little endian kernel boots after we shutdown).
2) Do not rely on HW reset values when loading driver in little endian kernel
   but configure them explicitly (in case previous kernel was big endian and did not reset the HW).

Signed-off-by: Manish Chopra <manish.chopra@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 04860eb7d911bbd958463416cc045b69ffdf73b3)
Bug-Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1356948
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |   57 +++++++++++++++-------
 1 files changed, 39 insertions(+), 18 deletions(-)

Comments

Tim Gardner Sept. 3, 2014, 3:30 p.m. UTC | #1
On 09/02/2014 04:33 PM, Thadeu Lima de Souza Cascardo wrote:
> From: Manish Chopra <manish.chopra@qlogic.com>
>
> Some hosts can be both little and big endian.
> In certain scenarios a big endian kernel can kexec a little endian kernel.
>
> This patch fixes this case from both ends:
> 1) Return endianity to original values on shutdown (in case little endian kernel boots after we shutdown).
> 2) Do not rely on HW reset values when loading driver in little endian kernel
>     but configure them explicitly (in case previous kernel was big endian and did not reset the HW).
>
> Signed-off-by: Manish Chopra <manish.chopra@qlogic.com>
> Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> (cherry picked from commit 04860eb7d911bbd958463416cc045b69ffdf73b3)
> Bug-Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1356948
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
> ---
>   drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c |   57 +++++++++++++++-------
>   1 files changed, 39 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> index 6a8b145..9d1333f 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> @@ -6841,6 +6841,37 @@ static void bnx2x__common_init_phy(struct bnx2x *bp)
>   	bnx2x_release_phy_lock(bp);
>   }
>
> +static void bnx2x_config_endianity(struct bnx2x *bp, u32 val)
> +{
> +	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, val);
> +	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, val);
> +	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, val);
> +	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, val);
> +	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, val);
> +
> +	/* make sure this value is 0 */
> +	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
> +
> +	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, val);
> +	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, val);
> +	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, val);
> +	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, val);
> +}
> +
> +static void bnx2x_set_endianity(struct bnx2x *bp)
> +{
> +#ifdef __BIG_ENDIAN
> +	bnx2x_config_endianity(bp, 1);
> +#else
> +	bnx2x_config_endianity(bp, 0);
> +#endif
> +}
> +
> +static void bnx2x_reset_endianity(struct bnx2x *bp)
> +{
> +	bnx2x_config_endianity(bp, 0);
> +}
> +
>   /**
>    * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
>    *
> @@ -6907,23 +6938,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
>
>   	bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
>   	bnx2x_init_pxp(bp);
> -
> -#ifdef __BIG_ENDIAN
> -	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
> -	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
> -	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
> -	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
> -	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
> -	/* make sure this value is 0 */
> -	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
> -
> -/*	REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
> -	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
> -	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
> -	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
> -	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
> -#endif
> -
> +	bnx2x_set_endianity(bp);
>   	bnx2x_ilt_init_page_size(bp, INITOP_SET);
>
>   	if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
> @@ -13218,9 +13233,15 @@ static void __bnx2x_remove(struct pci_dev *pdev,
>   	bnx2x_iov_remove_one(bp);
>
>   	/* Power on: we can't let PCI layer write to us while we are in D3 */
> -	if (IS_PF(bp))
> +	if (IS_PF(bp)) {
>   		bnx2x_set_power_state(bp, PCI_D0);
>
> +		/* Set endianity registers to reset values in case next driver
> +		 * boots in different endianty environment.
> +		 */
> +		bnx2x_reset_endianity(bp);
> +	}
> +
>   	/* Disable MSI/MSI-X */
>   	bnx2x_disable_msi(bp);
>
>

This patch has yet to be merged in Linus' repo. Please remind me when 
that happens (which should be soon given that it's already in Dave 
Miller's repo)

rtg
Tim Gardner Sept. 5, 2014, 9:32 p.m. UTC | #2
Cherry-picked from linux-next
diff mbox

Patch

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 6a8b145..9d1333f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -6841,6 +6841,37 @@  static void bnx2x__common_init_phy(struct bnx2x *bp)
 	bnx2x_release_phy_lock(bp);
 }
 
+static void bnx2x_config_endianity(struct bnx2x *bp, u32 val)
+{
+	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, val);
+	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, val);
+
+	/* make sure this value is 0 */
+	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
+
+	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, val);
+	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, val);
+	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, val);
+	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, val);
+}
+
+static void bnx2x_set_endianity(struct bnx2x *bp)
+{
+#ifdef __BIG_ENDIAN
+	bnx2x_config_endianity(bp, 1);
+#else
+	bnx2x_config_endianity(bp, 0);
+#endif
+}
+
+static void bnx2x_reset_endianity(struct bnx2x *bp)
+{
+	bnx2x_config_endianity(bp, 0);
+}
+
 /**
  * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
  *
@@ -6907,23 +6938,7 @@  static int bnx2x_init_hw_common(struct bnx2x *bp)
 
 	bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
 	bnx2x_init_pxp(bp);
-
-#ifdef __BIG_ENDIAN
-	REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
-	REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
-	/* make sure this value is 0 */
-	REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
-
-/*	REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
-	REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
-	REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
-#endif
-
+	bnx2x_set_endianity(bp);
 	bnx2x_ilt_init_page_size(bp, INITOP_SET);
 
 	if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
@@ -13218,9 +13233,15 @@  static void __bnx2x_remove(struct pci_dev *pdev,
 	bnx2x_iov_remove_one(bp);
 
 	/* Power on: we can't let PCI layer write to us while we are in D3 */
-	if (IS_PF(bp))
+	if (IS_PF(bp)) {
 		bnx2x_set_power_state(bp, PCI_D0);
 
+		/* Set endianity registers to reset values in case next driver
+		 * boots in different endianty environment.
+		 */
+		bnx2x_reset_endianity(bp);
+	}
+
 	/* Disable MSI/MSI-X */
 	bnx2x_disable_msi(bp);