Skip to content

Commit 30d5f85

Browse files
Michal Kalderondavem330
authored andcommitted
qed: FW 8.42.2.0 Add fw overlay feature
This feature enables the FW to page out FW code when required Signed-off-by: Ariel Elior <[email protected]> Signed-off-by: Michal Kalderon <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0500a70 commit 30d5f85

File tree

5 files changed

+224
-1
lines changed

5 files changed

+224
-1
lines changed

drivers/net/ethernet/qlogic/qed/qed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ struct qed_fw_data {
462462
const u8 *modes_tree_buf;
463463
union init_op *init_ops;
464464
const u32 *arr_data;
465+
const u32 *fw_overlays;
466+
u32 fw_overlays_len;
465467
u32 init_ops_size;
466468
};
467469

@@ -686,6 +688,7 @@ struct qed_hwfn {
686688
/* Nvm images number and attributes */
687689
struct qed_nvm_image_info nvm_info;
688690

691+
struct phys_mem_desc *fw_overlay_mem;
689692
struct qed_ptt *p_arfs_ptt;
690693

691694
struct qed_simd_fp_handler simd_proto_handler[64];

drivers/net/ethernet/qlogic/qed/qed_dev.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,7 @@ void qed_resc_free(struct qed_dev *cdev)
14121412
qed_dmae_info_free(p_hwfn);
14131413
qed_dcbx_info_free(p_hwfn);
14141414
qed_dbg_user_data_free(p_hwfn);
1415+
qed_fw_overlay_mem_free(p_hwfn, p_hwfn->fw_overlay_mem);
14151416

14161417
/* Destroy doorbell recovery mechanism */
14171418
qed_db_recovery_teardown(p_hwfn);
@@ -2893,6 +2894,8 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
28932894
if (rc)
28942895
return rc;
28952896

2897+
qed_fw_overlay_init_ram(p_hwfn, p_ptt, p_hwfn->fw_overlay_mem);
2898+
28962899
/* Pure runtime initializations - directly to the HW */
28972900
qed_int_igu_init_pure_rt(p_hwfn, p_ptt, true, true);
28982901

@@ -3002,8 +3005,10 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
30023005
u32 load_code, resp, param, drv_mb_param;
30033006
bool b_default_mtu = true;
30043007
struct qed_hwfn *p_hwfn;
3005-
int rc = 0, i;
3008+
const u32 *fw_overlays;
3009+
u32 fw_overlays_len;
30063010
u16 ether_type;
3011+
int rc = 0, i;
30073012

30083013
if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
30093014
DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n");
@@ -3104,6 +3109,17 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
31043109
*/
31053110
qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt);
31063111

3112+
fw_overlays = cdev->fw_data->fw_overlays;
3113+
fw_overlays_len = cdev->fw_data->fw_overlays_len;
3114+
p_hwfn->fw_overlay_mem =
3115+
qed_fw_overlay_mem_alloc(p_hwfn, fw_overlays,
3116+
fw_overlays_len);
3117+
if (!p_hwfn->fw_overlay_mem) {
3118+
DP_NOTICE(p_hwfn,
3119+
"Failed to allocate fw overlay memory\n");
3120+
goto load_err;
3121+
}
3122+
31073123
switch (load_code) {
31083124
case FW_MSG_CODE_DRV_LOAD_ENGINE:
31093125
rc = qed_hw_init_common(p_hwfn, p_hwfn->p_main_ptt,

drivers/net/ethernet/qlogic/qed/qed_hsi.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,19 @@ struct sdm_op_gen {
18431843
#define SDM_OP_GEN_RESERVED_SHIFT 20
18441844
};
18451845

1846+
/* Physical memory descriptor */
1847+
struct phys_mem_desc {
1848+
dma_addr_t phys_addr;
1849+
void *virt_addr;
1850+
u32 size; /* In bytes */
1851+
};
1852+
1853+
/* Virtual memory descriptor */
1854+
struct virt_mem_desc {
1855+
void *ptr;
1856+
u32 size; /* In bytes */
1857+
};
1858+
18461859
/****************************************/
18471860
/* Debug Tools HSI constants and macros */
18481861
/****************************************/
@@ -2872,6 +2885,15 @@ enum bin_init_buffer_type {
28722885
MAX_BIN_INIT_BUFFER_TYPE
28732886
};
28742887

2888+
/* FW overlay buffer header */
2889+
struct fw_overlay_buf_hdr {
2890+
u32 data;
2891+
#define FW_OVERLAY_BUF_HDR_STORM_ID_MASK 0xFF
2892+
#define FW_OVERLAY_BUF_HDR_STORM_ID_SHIFT 0
2893+
#define FW_OVERLAY_BUF_HDR_BUF_SIZE_MASK 0xFFFFFF
2894+
#define FW_OVERLAY_BUF_HDR_BUF_SIZE_SHIFT 8
2895+
};
2896+
28752897
/* init array header: raw */
28762898
struct init_array_raw_hdr {
28772899
u32 data;
@@ -4345,6 +4367,42 @@ void qed_memset_task_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type);
43454367
void qed_set_rdma_error_level(struct qed_hwfn *p_hwfn,
43464368
struct qed_ptt *p_ptt,
43474369
u8 assert_level[NUM_STORMS]);
4370+
/**
4371+
* @brief qed_fw_overlay_mem_alloc - Allocates and fills the FW overlay memory.
4372+
*
4373+
* @param p_hwfn - HW device data
4374+
* @param fw_overlay_in_buf - the input FW overlay buffer.
4375+
* @param buf_size - the size of the input FW overlay buffer in bytes.
4376+
* must be aligned to dwords.
4377+
* @param fw_overlay_out_mem - OUT: a pointer to the allocated overlays memory.
4378+
*
4379+
* @return a pointer to the allocated overlays memory,
4380+
* or NULL in case of failures.
4381+
*/
4382+
struct phys_mem_desc *
4383+
qed_fw_overlay_mem_alloc(struct qed_hwfn *p_hwfn,
4384+
const u32 * const fw_overlay_in_buf,
4385+
u32 buf_size_in_bytes);
4386+
4387+
/**
4388+
* @brief qed_fw_overlay_init_ram - Initializes the FW overlay RAM.
4389+
*
4390+
* @param p_hwfn - HW device data.
4391+
* @param p_ptt - ptt window used for writing the registers.
4392+
* @param fw_overlay_mem - the allocated FW overlay memory.
4393+
*/
4394+
void qed_fw_overlay_init_ram(struct qed_hwfn *p_hwfn,
4395+
struct qed_ptt *p_ptt,
4396+
struct phys_mem_desc *fw_overlay_mem);
4397+
4398+
/**
4399+
* @brief qed_fw_overlay_mem_free - Frees the FW overlay memory.
4400+
*
4401+
* @param p_hwfn - HW device data.
4402+
* @param fw_overlay_mem - the allocated FW overlay memory to free.
4403+
*/
4404+
void qed_fw_overlay_mem_free(struct qed_hwfn *p_hwfn,
4405+
struct phys_mem_desc *fw_overlay_mem);
43484406

43494407
/* Ystorm flow control mode. Use enum fw_flow_ctrl_mode */
43504408
#define YSTORM_FLOW_CONTROL_MODE_OFFSET (IRO[0].base)

drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,3 +1572,144 @@ void qed_set_rdma_error_level(struct qed_hwfn *p_hwfn,
15721572
qed_wr(p_hwfn, p_ptt, ram_addr, assert_level[storm_id]);
15731573
}
15741574
}
1575+
1576+
#define PHYS_ADDR_DWORDS DIV_ROUND_UP(sizeof(dma_addr_t), 4)
1577+
#define OVERLAY_HDR_SIZE_DWORDS (sizeof(struct fw_overlay_buf_hdr) / 4)
1578+
1579+
static u32 qed_get_overlay_addr_ram_addr(struct qed_hwfn *p_hwfn, u8 storm_id)
1580+
{
1581+
switch (storm_id) {
1582+
case 0:
1583+
return TSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
1584+
TSTORM_OVERLAY_BUF_ADDR_OFFSET;
1585+
case 1:
1586+
return MSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
1587+
MSTORM_OVERLAY_BUF_ADDR_OFFSET;
1588+
case 2:
1589+
return USEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
1590+
USTORM_OVERLAY_BUF_ADDR_OFFSET;
1591+
case 3:
1592+
return XSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
1593+
XSTORM_OVERLAY_BUF_ADDR_OFFSET;
1594+
case 4:
1595+
return YSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
1596+
YSTORM_OVERLAY_BUF_ADDR_OFFSET;
1597+
case 5:
1598+
return PSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
1599+
PSTORM_OVERLAY_BUF_ADDR_OFFSET;
1600+
1601+
default:
1602+
return 0;
1603+
}
1604+
}
1605+
1606+
struct phys_mem_desc *qed_fw_overlay_mem_alloc(struct qed_hwfn *p_hwfn,
1607+
const u32 * const
1608+
fw_overlay_in_buf,
1609+
u32 buf_size_in_bytes)
1610+
{
1611+
u32 buf_size = buf_size_in_bytes / sizeof(u32), buf_offset = 0;
1612+
struct phys_mem_desc *allocated_mem;
1613+
1614+
if (!buf_size)
1615+
return NULL;
1616+
1617+
allocated_mem = kcalloc(NUM_STORMS, sizeof(struct phys_mem_desc),
1618+
GFP_KERNEL);
1619+
if (!allocated_mem)
1620+
return NULL;
1621+
1622+
memset(allocated_mem, 0, NUM_STORMS * sizeof(struct phys_mem_desc));
1623+
1624+
/* For each Storm, set physical address in RAM */
1625+
while (buf_offset < buf_size) {
1626+
struct phys_mem_desc *storm_mem_desc;
1627+
struct fw_overlay_buf_hdr *hdr;
1628+
u32 storm_buf_size;
1629+
u8 storm_id;
1630+
1631+
hdr =
1632+
(struct fw_overlay_buf_hdr *)&fw_overlay_in_buf[buf_offset];
1633+
storm_buf_size = GET_FIELD(hdr->data,
1634+
FW_OVERLAY_BUF_HDR_BUF_SIZE);
1635+
storm_id = GET_FIELD(hdr->data, FW_OVERLAY_BUF_HDR_STORM_ID);
1636+
storm_mem_desc = allocated_mem + storm_id;
1637+
storm_mem_desc->size = storm_buf_size * sizeof(u32);
1638+
1639+
/* Allocate physical memory for Storm's overlays buffer */
1640+
storm_mem_desc->virt_addr =
1641+
dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
1642+
storm_mem_desc->size,
1643+
&storm_mem_desc->phys_addr, GFP_KERNEL);
1644+
if (!storm_mem_desc->virt_addr)
1645+
break;
1646+
1647+
/* Skip overlays buffer header */
1648+
buf_offset += OVERLAY_HDR_SIZE_DWORDS;
1649+
1650+
/* Copy Storm's overlays buffer to allocated memory */
1651+
memcpy(storm_mem_desc->virt_addr,
1652+
&fw_overlay_in_buf[buf_offset], storm_mem_desc->size);
1653+
1654+
/* Advance to next Storm */
1655+
buf_offset += storm_buf_size;
1656+
}
1657+
1658+
/* If memory allocation has failed, free all allocated memory */
1659+
if (buf_offset < buf_size) {
1660+
qed_fw_overlay_mem_free(p_hwfn, allocated_mem);
1661+
return NULL;
1662+
}
1663+
1664+
return allocated_mem;
1665+
}
1666+
1667+
void qed_fw_overlay_init_ram(struct qed_hwfn *p_hwfn,
1668+
struct qed_ptt *p_ptt,
1669+
struct phys_mem_desc *fw_overlay_mem)
1670+
{
1671+
u8 storm_id;
1672+
1673+
for (storm_id = 0; storm_id < NUM_STORMS; storm_id++) {
1674+
struct phys_mem_desc *storm_mem_desc =
1675+
(struct phys_mem_desc *)fw_overlay_mem + storm_id;
1676+
u32 ram_addr, i;
1677+
1678+
/* Skip Storms with no FW overlays */
1679+
if (!storm_mem_desc->virt_addr)
1680+
continue;
1681+
1682+
/* Calculate overlay RAM GRC address of current PF */
1683+
ram_addr = qed_get_overlay_addr_ram_addr(p_hwfn, storm_id) +
1684+
sizeof(dma_addr_t) * p_hwfn->rel_pf_id;
1685+
1686+
/* Write Storm's overlay physical address to RAM */
1687+
for (i = 0; i < PHYS_ADDR_DWORDS; i++, ram_addr += sizeof(u32))
1688+
qed_wr(p_hwfn, p_ptt, ram_addr,
1689+
((u32 *)&storm_mem_desc->phys_addr)[i]);
1690+
}
1691+
}
1692+
1693+
void qed_fw_overlay_mem_free(struct qed_hwfn *p_hwfn,
1694+
struct phys_mem_desc *fw_overlay_mem)
1695+
{
1696+
u8 storm_id;
1697+
1698+
if (!fw_overlay_mem)
1699+
return;
1700+
1701+
for (storm_id = 0; storm_id < NUM_STORMS; storm_id++) {
1702+
struct phys_mem_desc *storm_mem_desc =
1703+
(struct phys_mem_desc *)fw_overlay_mem + storm_id;
1704+
1705+
/* Free Storm's physical memory */
1706+
if (storm_mem_desc->virt_addr)
1707+
dma_free_coherent(&p_hwfn->cdev->pdev->dev,
1708+
storm_mem_desc->size,
1709+
storm_mem_desc->virt_addr,
1710+
storm_mem_desc->phys_addr);
1711+
}
1712+
1713+
/* Free allocated virtual memory */
1714+
kfree(fw_overlay_mem);
1715+
}

drivers/net/ethernet/qlogic/qed/qed_init_ops.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,5 +589,10 @@ int qed_init_fw_data(struct qed_dev *cdev, const u8 *data)
589589
len = buf_hdr[BIN_BUF_INIT_CMD].length;
590590
fw->init_ops_size = len / sizeof(struct init_raw_op);
591591

592+
offset = buf_hdr[BIN_BUF_INIT_OVERLAYS].offset;
593+
fw->fw_overlays = (u32 *)(data + offset);
594+
len = buf_hdr[BIN_BUF_INIT_OVERLAYS].length;
595+
fw->fw_overlays_len = len;
596+
592597
return 0;
593598
}

0 commit comments

Comments
 (0)