Commit c78df14e authored by Ariel Elior's avatar Ariel Elior Committed by David S. Miller

qed: Fix BAR size split for some servers

Can't rely on pci config space to discover bar size,
as in some environments this returns a wrong, too large value.
Instead, rely on device register, which contains the value
provided by MFW at preboot.
Signed-off-by: default avatarAriel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: default avatarManish Chopra <manish.chopra@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 76a9a364
...@@ -1385,52 +1385,63 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn, ...@@ -1385,52 +1385,63 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
return rc; return rc;
} }
static u32 qed_hw_bar_size(struct qed_dev *cdev, static u32 qed_hw_bar_size(struct qed_hwfn *p_hwfn,
u8 bar_id) u8 bar_id)
{ {
u32 size = pci_resource_len(cdev->pdev, (bar_id > 0) ? 2 : 0); u32 bar_reg = (bar_id == 0 ? PGLUE_B_REG_PF_BAR0_SIZE
: PGLUE_B_REG_PF_BAR1_SIZE);
u32 val = qed_rd(p_hwfn, p_hwfn->p_main_ptt, bar_reg);
return size / cdev->num_hwfns; /* Get the BAR size(in KB) from hardware given val */
return 1 << (val + 15);
} }
int qed_hw_prepare(struct qed_dev *cdev, int qed_hw_prepare(struct qed_dev *cdev,
int personality) int personality)
{ {
int rc, i; struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
int rc;
/* Store the precompiled init data ptrs */ /* Store the precompiled init data ptrs */
qed_init_iro_array(cdev); qed_init_iro_array(cdev);
/* Initialize the first hwfn - will learn number of hwfns */ /* Initialize the first hwfn - will learn number of hwfns */
rc = qed_hw_prepare_single(&cdev->hwfns[0], cdev->regview, rc = qed_hw_prepare_single(p_hwfn,
cdev->regview,
cdev->doorbells, personality); cdev->doorbells, personality);
if (rc) if (rc)
return rc; return rc;
personality = cdev->hwfns[0].hw_info.personality; personality = p_hwfn->hw_info.personality;
/* Initialize the rest of the hwfns */ /* Initialize the rest of the hwfns */
for (i = 1; i < cdev->num_hwfns; i++) { if (cdev->num_hwfns > 1) {
void __iomem *p_regview, *p_doorbell; void __iomem *p_regview, *p_doorbell;
u8 __iomem *addr;
/* adjust bar offset for second engine */
addr = cdev->regview + qed_hw_bar_size(p_hwfn, 0) / 2;
p_regview = addr;
p_regview = cdev->regview + /* adjust doorbell bar offset for second engine */
i * qed_hw_bar_size(cdev, 0); addr = cdev->doorbells + qed_hw_bar_size(p_hwfn, 1) / 2;
p_doorbell = cdev->doorbells + p_doorbell = addr;
i * qed_hw_bar_size(cdev, 1);
rc = qed_hw_prepare_single(&cdev->hwfns[i], p_regview, /* prepare second hw function */
rc = qed_hw_prepare_single(&cdev->hwfns[1], p_regview,
p_doorbell, personality); p_doorbell, personality);
/* in case of error, need to free the previously
* initiliazed hwfn 0.
*/
if (rc) { if (rc) {
/* Cleanup previously initialized hwfns */ qed_init_free(p_hwfn);
while (--i >= 0) { qed_mcp_free(p_hwfn);
qed_init_free(&cdev->hwfns[i]); qed_hw_hwfn_free(p_hwfn);
qed_mcp_free(&cdev->hwfns[i]);
qed_hw_hwfn_free(&cdev->hwfns[i]);
}
return rc;
} }
} }
return 0; return rc;
} }
void qed_hw_remove(struct qed_dev *cdev) void qed_hw_remove(struct qed_dev *cdev)
......
...@@ -363,4 +363,8 @@ ...@@ -363,4 +363,8 @@
0x7 << 0) 0x7 << 0)
#define MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT \ #define MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT \
0 0
#define PGLUE_B_REG_PF_BAR0_SIZE \
0x2aae60UL
#define PGLUE_B_REG_PF_BAR1_SIZE \
0x2aae64UL
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment