Merge branch 'qed-fixes'
Manish Chopra says: ==================== qed: Bug fixes Please consider applying this series to net. V2: - Use available helpers for declaring bitmap and bitmap operations. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
23bd51e0f0
|
@ -299,6 +299,7 @@ struct qed_hwfn {
|
||||||
|
|
||||||
/* Flag indicating whether interrupts are enabled or not*/
|
/* Flag indicating whether interrupts are enabled or not*/
|
||||||
bool b_int_enabled;
|
bool b_int_enabled;
|
||||||
|
bool b_int_requested;
|
||||||
|
|
||||||
struct qed_mcp_info *mcp_info;
|
struct qed_mcp_info *mcp_info;
|
||||||
|
|
||||||
|
@ -491,6 +492,8 @@ u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
|
||||||
u32 input_len, u8 *input_buf,
|
u32 input_len, u8 *input_buf,
|
||||||
u32 max_size, u8 *unzip_buf);
|
u32 max_size, u8 *unzip_buf);
|
||||||
|
|
||||||
|
int qed_slowpath_irq_req(struct qed_hwfn *hwfn);
|
||||||
|
|
||||||
#define QED_ETH_INTERFACE_VERSION 300
|
#define QED_ETH_INTERFACE_VERSION 300
|
||||||
|
|
||||||
#endif /* _QED_H */
|
#endif /* _QED_H */
|
||||||
|
|
|
@ -1385,52 +1385,63 @@ err0:
|
||||||
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;
|
||||||
|
|
||||||
p_regview = cdev->regview +
|
/* adjust bar offset for second engine */
|
||||||
i * qed_hw_bar_size(cdev, 0);
|
addr = cdev->regview + qed_hw_bar_size(p_hwfn, 0) / 2;
|
||||||
p_doorbell = cdev->doorbells +
|
p_regview = addr;
|
||||||
i * qed_hw_bar_size(cdev, 1);
|
|
||||||
rc = qed_hw_prepare_single(&cdev->hwfns[i], p_regview,
|
/* adjust doorbell bar offset for second engine */
|
||||||
|
addr = cdev->doorbells + qed_hw_bar_size(p_hwfn, 1) / 2;
|
||||||
|
p_doorbell = addr;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
|
|
@ -783,22 +783,16 @@ void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn,
|
||||||
qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf);
|
qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
|
int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
|
||||||
struct qed_ptt *p_ptt,
|
|
||||||
enum qed_int_mode int_mode)
|
enum qed_int_mode int_mode)
|
||||||
{
|
{
|
||||||
int i;
|
int rc, i;
|
||||||
|
|
||||||
p_hwfn->b_int_enabled = 1;
|
|
||||||
|
|
||||||
/* Mask non-link attentions */
|
/* Mask non-link attentions */
|
||||||
for (i = 0; i < 9; i++)
|
for (i = 0; i < 9; i++)
|
||||||
qed_wr(p_hwfn, p_ptt,
|
qed_wr(p_hwfn, p_ptt,
|
||||||
MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0);
|
MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0);
|
||||||
|
|
||||||
/* Enable interrupt Generation */
|
|
||||||
qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
|
|
||||||
|
|
||||||
/* Configure AEU signal change to produce attentions for link */
|
/* Configure AEU signal change to produce attentions for link */
|
||||||
qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff);
|
qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff);
|
||||||
qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff);
|
qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff);
|
||||||
|
@ -808,6 +802,19 @@ void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
|
||||||
|
|
||||||
/* Unmask AEU signals toward IGU */
|
/* Unmask AEU signals toward IGU */
|
||||||
qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff);
|
qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff);
|
||||||
|
if ((int_mode != QED_INT_MODE_INTA) || IS_LEAD_HWFN(p_hwfn)) {
|
||||||
|
rc = qed_slowpath_irq_req(p_hwfn);
|
||||||
|
if (rc != 0) {
|
||||||
|
DP_NOTICE(p_hwfn, "Slowpath IRQ request failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
p_hwfn->b_int_requested = true;
|
||||||
|
}
|
||||||
|
/* Enable interrupt Generation */
|
||||||
|
qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
|
||||||
|
p_hwfn->b_int_enabled = 1;
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn,
|
void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn,
|
||||||
|
@ -1127,3 +1134,11 @@ int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn,
|
||||||
|
|
||||||
return info->igu_sb_cnt;
|
return info->igu_sb_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qed_int_disable_post_isr_release(struct qed_dev *cdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_each_hwfn(cdev, i)
|
||||||
|
cdev->hwfns[i].b_int_requested = false;
|
||||||
|
}
|
||||||
|
|
|
@ -169,10 +169,14 @@ int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn,
|
||||||
int *p_iov_blks);
|
int *p_iov_blks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @brief qed_int_disable_post_isr_release - performs the cleanup post ISR
|
||||||
|
* release. The API need to be called after releasing all slowpath IRQs
|
||||||
|
* of the device.
|
||||||
|
*
|
||||||
|
* @param cdev
|
||||||
*
|
*
|
||||||
* @brief Interrupt handler
|
|
||||||
*/
|
*/
|
||||||
|
void qed_int_disable_post_isr_release(struct qed_dev *cdev);
|
||||||
|
|
||||||
#define QED_CAU_DEF_RX_TIMER_RES 0
|
#define QED_CAU_DEF_RX_TIMER_RES 0
|
||||||
#define QED_CAU_DEF_TX_TIMER_RES 0
|
#define QED_CAU_DEF_TX_TIMER_RES 0
|
||||||
|
@ -366,9 +370,10 @@ void qed_int_setup(struct qed_hwfn *p_hwfn,
|
||||||
* @param p_hwfn
|
* @param p_hwfn
|
||||||
* @param p_ptt
|
* @param p_ptt
|
||||||
* @param int_mode
|
* @param int_mode
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
*/
|
*/
|
||||||
void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
|
int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
|
||||||
struct qed_ptt *p_ptt,
|
|
||||||
enum qed_int_mode int_mode);
|
enum qed_int_mode int_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -476,41 +476,22 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qed_slowpath_irq_req(struct qed_dev *cdev)
|
int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
|
||||||
{
|
{
|
||||||
int i = 0, rc = 0;
|
struct qed_dev *cdev = hwfn->cdev;
|
||||||
|
int rc = 0;
|
||||||
|
u8 id;
|
||||||
|
|
||||||
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
|
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
|
||||||
/* Request all the slowpath MSI-X vectors */
|
id = hwfn->my_id;
|
||||||
for (i = 0; i < cdev->num_hwfns; i++) {
|
snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x",
|
||||||
snprintf(cdev->hwfns[i].name, NAME_SIZE,
|
id, cdev->pdev->bus->number,
|
||||||
"sp-%d-%02x:%02x.%02x",
|
PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
|
||||||
i, cdev->pdev->bus->number,
|
rc = request_irq(cdev->int_params.msix_table[id].vector,
|
||||||
PCI_SLOT(cdev->pdev->devfn),
|
qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc);
|
||||||
cdev->hwfns[i].abs_pf_id);
|
if (!rc)
|
||||||
|
DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP),
|
||||||
rc = request_irq(cdev->int_params.msix_table[i].vector,
|
|
||||||
qed_msix_sp_int, 0,
|
|
||||||
cdev->hwfns[i].name,
|
|
||||||
cdev->hwfns[i].sp_dpc);
|
|
||||||
if (rc)
|
|
||||||
break;
|
|
||||||
|
|
||||||
DP_VERBOSE(&cdev->hwfns[i],
|
|
||||||
(NETIF_MSG_INTR | QED_MSG_SP),
|
|
||||||
"Requested slowpath MSI-X\n");
|
"Requested slowpath MSI-X\n");
|
||||||
}
|
|
||||||
|
|
||||||
if (i != cdev->num_hwfns) {
|
|
||||||
/* Free already request MSI-X vectors */
|
|
||||||
for (i--; i >= 0; i--) {
|
|
||||||
unsigned int vec =
|
|
||||||
cdev->int_params.msix_table[i].vector;
|
|
||||||
synchronize_irq(vec);
|
|
||||||
free_irq(cdev->int_params.msix_table[i].vector,
|
|
||||||
cdev->hwfns[i].sp_dpc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
|
|
||||||
|
@ -534,13 +515,17 @@ static void qed_slowpath_irq_free(struct qed_dev *cdev)
|
||||||
|
|
||||||
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
|
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
|
||||||
for_each_hwfn(cdev, i) {
|
for_each_hwfn(cdev, i) {
|
||||||
|
if (!cdev->hwfns[i].b_int_requested)
|
||||||
|
break;
|
||||||
synchronize_irq(cdev->int_params.msix_table[i].vector);
|
synchronize_irq(cdev->int_params.msix_table[i].vector);
|
||||||
free_irq(cdev->int_params.msix_table[i].vector,
|
free_irq(cdev->int_params.msix_table[i].vector,
|
||||||
cdev->hwfns[i].sp_dpc);
|
cdev->hwfns[i].sp_dpc);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (QED_LEADING_HWFN(cdev)->b_int_requested)
|
||||||
free_irq(cdev->pdev->irq, cdev);
|
free_irq(cdev->pdev->irq, cdev);
|
||||||
}
|
}
|
||||||
|
qed_int_disable_post_isr_release(cdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qed_nic_stop(struct qed_dev *cdev)
|
static int qed_nic_stop(struct qed_dev *cdev)
|
||||||
|
@ -765,16 +750,11 @@ static int qed_slowpath_start(struct qed_dev *cdev,
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
/* Request the slowpath IRQ */
|
|
||||||
rc = qed_slowpath_irq_req(cdev);
|
|
||||||
if (rc)
|
|
||||||
goto err2;
|
|
||||||
|
|
||||||
/* Allocate stream for unzipping */
|
/* Allocate stream for unzipping */
|
||||||
rc = qed_alloc_stream_mem(cdev);
|
rc = qed_alloc_stream_mem(cdev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DP_NOTICE(cdev, "Failed to allocate stream memory\n");
|
DP_NOTICE(cdev, "Failed to allocate stream memory\n");
|
||||||
goto err3;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the slowpath */
|
/* Start the slowpath */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -124,8 +124,12 @@ struct qed_spq {
|
||||||
dma_addr_t p_phys;
|
dma_addr_t p_phys;
|
||||||
struct qed_spq_entry *p_virt;
|
struct qed_spq_entry *p_virt;
|
||||||
|
|
||||||
/* Used as index for completions (returns on EQ by FW) */
|
#define SPQ_RING_SIZE \
|
||||||
u16 echo_idx;
|
(CORE_SPQE_PAGE_SIZE_BYTES / sizeof(struct slow_path_element))
|
||||||
|
|
||||||
|
/* Bitmap for handling out-of-order completions */
|
||||||
|
DECLARE_BITMAP(p_comp_bitmap, SPQ_RING_SIZE);
|
||||||
|
u8 comp_bitmap_idx;
|
||||||
|
|
||||||
/* Statistics */
|
/* Statistics */
|
||||||
u32 unlimited_pending_count;
|
u32 unlimited_pending_count;
|
||||||
|
|
|
@ -112,8 +112,6 @@ static int
|
||||||
qed_spq_fill_entry(struct qed_hwfn *p_hwfn,
|
qed_spq_fill_entry(struct qed_hwfn *p_hwfn,
|
||||||
struct qed_spq_entry *p_ent)
|
struct qed_spq_entry *p_ent)
|
||||||
{
|
{
|
||||||
p_ent->elem.hdr.echo = 0;
|
|
||||||
p_hwfn->p_spq->echo_idx++;
|
|
||||||
p_ent->flags = 0;
|
p_ent->flags = 0;
|
||||||
|
|
||||||
switch (p_ent->comp_mode) {
|
switch (p_ent->comp_mode) {
|
||||||
|
@ -196,9 +194,11 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
|
||||||
struct qed_spq_entry *p_ent)
|
struct qed_spq_entry *p_ent)
|
||||||
{
|
{
|
||||||
struct qed_chain *p_chain = &p_hwfn->p_spq->chain;
|
struct qed_chain *p_chain = &p_hwfn->p_spq->chain;
|
||||||
|
u16 echo = qed_chain_get_prod_idx(p_chain);
|
||||||
struct slow_path_element *elem;
|
struct slow_path_element *elem;
|
||||||
struct core_db_data db;
|
struct core_db_data db;
|
||||||
|
|
||||||
|
p_ent->elem.hdr.echo = cpu_to_le16(echo);
|
||||||
elem = qed_chain_produce(p_chain);
|
elem = qed_chain_produce(p_chain);
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
DP_NOTICE(p_hwfn, "Failed to produce from SPQ chain\n");
|
DP_NOTICE(p_hwfn, "Failed to produce from SPQ chain\n");
|
||||||
|
@ -437,7 +437,9 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
|
||||||
p_spq->comp_count = 0;
|
p_spq->comp_count = 0;
|
||||||
p_spq->comp_sent_count = 0;
|
p_spq->comp_sent_count = 0;
|
||||||
p_spq->unlimited_pending_count = 0;
|
p_spq->unlimited_pending_count = 0;
|
||||||
p_spq->echo_idx = 0;
|
|
||||||
|
bitmap_zero(p_spq->p_comp_bitmap, SPQ_RING_SIZE);
|
||||||
|
p_spq->comp_bitmap_idx = 0;
|
||||||
|
|
||||||
/* SPQ cid, cannot fail */
|
/* SPQ cid, cannot fail */
|
||||||
qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid);
|
qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid);
|
||||||
|
@ -582,27 +584,33 @@ qed_spq_add_entry(struct qed_hwfn *p_hwfn,
|
||||||
struct qed_spq *p_spq = p_hwfn->p_spq;
|
struct qed_spq *p_spq = p_hwfn->p_spq;
|
||||||
|
|
||||||
if (p_ent->queue == &p_spq->unlimited_pending) {
|
if (p_ent->queue == &p_spq->unlimited_pending) {
|
||||||
struct qed_spq_entry *p_en2;
|
|
||||||
|
|
||||||
if (list_empty(&p_spq->free_pool)) {
|
if (list_empty(&p_spq->free_pool)) {
|
||||||
list_add_tail(&p_ent->list, &p_spq->unlimited_pending);
|
list_add_tail(&p_ent->list, &p_spq->unlimited_pending);
|
||||||
p_spq->unlimited_pending_count++;
|
p_spq->unlimited_pending_count++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else {
|
||||||
|
struct qed_spq_entry *p_en2;
|
||||||
|
|
||||||
p_en2 = list_first_entry(&p_spq->free_pool,
|
p_en2 = list_first_entry(&p_spq->free_pool,
|
||||||
struct qed_spq_entry,
|
struct qed_spq_entry,
|
||||||
list);
|
list);
|
||||||
list_del(&p_en2->list);
|
list_del(&p_en2->list);
|
||||||
|
|
||||||
/* Strcut assignment */
|
/* Copy the ring element physical pointer to the new
|
||||||
|
* entry, since we are about to override the entire ring
|
||||||
|
* entry and don't want to lose the pointer.
|
||||||
|
*/
|
||||||
|
p_ent->elem.data_ptr = p_en2->elem.data_ptr;
|
||||||
|
|
||||||
*p_en2 = *p_ent;
|
*p_en2 = *p_ent;
|
||||||
|
|
||||||
kfree(p_ent);
|
kfree(p_ent);
|
||||||
|
|
||||||
p_ent = p_en2;
|
p_ent = p_en2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* entry is to be placed in 'pending' queue */
|
/* entry is to be placed in 'pending' queue */
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
|
@ -777,13 +785,38 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
|
||||||
list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending,
|
list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending,
|
||||||
list) {
|
list) {
|
||||||
if (p_ent->elem.hdr.echo == echo) {
|
if (p_ent->elem.hdr.echo == echo) {
|
||||||
|
u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE;
|
||||||
|
|
||||||
list_del(&p_ent->list);
|
list_del(&p_ent->list);
|
||||||
|
|
||||||
|
/* Avoid overriding of SPQ entries when getting
|
||||||
|
* out-of-order completions, by marking the completions
|
||||||
|
* in a bitmap and increasing the chain consumer only
|
||||||
|
* for the first successive completed entries.
|
||||||
|
*/
|
||||||
|
bitmap_set(p_spq->p_comp_bitmap, pos, SPQ_RING_SIZE);
|
||||||
|
|
||||||
|
while (test_bit(p_spq->comp_bitmap_idx,
|
||||||
|
p_spq->p_comp_bitmap)) {
|
||||||
|
bitmap_clear(p_spq->p_comp_bitmap,
|
||||||
|
p_spq->comp_bitmap_idx,
|
||||||
|
SPQ_RING_SIZE);
|
||||||
|
p_spq->comp_bitmap_idx++;
|
||||||
qed_chain_return_produced(&p_spq->chain);
|
qed_chain_return_produced(&p_spq->chain);
|
||||||
|
}
|
||||||
|
|
||||||
p_spq->comp_count++;
|
p_spq->comp_count++;
|
||||||
found = p_ent;
|
found = p_ent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is relatively uncommon - depends on scenarios
|
||||||
|
* which have mutliple per-PF sent ramrods.
|
||||||
|
*/
|
||||||
|
DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
|
||||||
|
"Got completion for echo %04x - doesn't match echo %04x in completion pending list\n",
|
||||||
|
le16_to_cpu(echo),
|
||||||
|
le16_to_cpu(p_ent->elem.hdr.echo));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release lock before callback, as callback may post
|
/* Release lock before callback, as callback may post
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#ifndef __COMMON_HSI__
|
#ifndef __COMMON_HSI__
|
||||||
#define __COMMON_HSI__
|
#define __COMMON_HSI__
|
||||||
|
|
||||||
|
#define CORE_SPQE_PAGE_SIZE_BYTES 4096
|
||||||
|
|
||||||
#define FW_MAJOR_VERSION 8
|
#define FW_MAJOR_VERSION 8
|
||||||
#define FW_MINOR_VERSION 4
|
#define FW_MINOR_VERSION 4
|
||||||
#define FW_REVISION_VERSION 2
|
#define FW_REVISION_VERSION 2
|
||||||
|
|
|
@ -111,7 +111,8 @@ static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain)
|
||||||
used = ((u32)0x10000u + (u32)(p_chain->prod_idx)) -
|
used = ((u32)0x10000u + (u32)(p_chain->prod_idx)) -
|
||||||
(u32)p_chain->cons_idx;
|
(u32)p_chain->cons_idx;
|
||||||
if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
|
if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
|
||||||
used -= (used / p_chain->elem_per_page);
|
used -= p_chain->prod_idx / p_chain->elem_per_page -
|
||||||
|
p_chain->cons_idx / p_chain->elem_per_page;
|
||||||
|
|
||||||
return p_chain->capacity - used;
|
return p_chain->capacity - used;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue