mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 16:07:39 +00:00
Merge branch 'qlcnic'
Himanshu Madhani says: ==================== qlcnic: Bug fixes. This series contains bug fixes for mailbox handling and multi Tx queue support for all supported adapters. changes from v1 -> v2 o updated patch to fix usage of netif_tx_{wake,stop} api during link change as per David Miller's suggestion. o Dropped patch to use spinklock per tx queue for more work. o Added reworked patch for memory allocation failures. o Added patch to allow capturing of dump, when auto recovery is disabled in firmware. o Added patches for mailbox interrupt handling and debugging data for mailbox failure. Please apply to net. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a7c12639bd
6 changed files with 74 additions and 72 deletions
|
@ -447,8 +447,9 @@ irqreturn_t qlcnic_83xx_intr(int irq, void *data)
|
|||
|
||||
qlcnic_83xx_poll_process_aen(adapter);
|
||||
|
||||
if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||
ahw->diag_cnt++;
|
||||
if (ahw->diag_test) {
|
||||
if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
|
||||
ahw->diag_cnt++;
|
||||
qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -1345,11 +1346,6 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
|
|||
}
|
||||
|
||||
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
|
||||
/* disable and free mailbox interrupt */
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
||||
qlcnic_83xx_enable_mbx_poll(adapter);
|
||||
qlcnic_83xx_free_mbx_intr(adapter);
|
||||
}
|
||||
adapter->ahw->loopback_state = 0;
|
||||
adapter->ahw->hw_ops->setup_link_event(adapter, 1);
|
||||
}
|
||||
|
@ -1363,33 +1359,20 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
|||
{
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
struct qlcnic_host_sds_ring *sds_ring;
|
||||
int ring, err;
|
||||
int ring;
|
||||
|
||||
clear_bit(__QLCNIC_DEV_UP, &adapter->state);
|
||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
|
||||
for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
|
||||
sds_ring = &adapter->recv_ctx->sds_rings[ring];
|
||||
qlcnic_83xx_disable_intr(adapter, sds_ring);
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
|
||||
qlcnic_83xx_enable_mbx_poll(adapter);
|
||||
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
||||
qlcnic_83xx_disable_intr(adapter, sds_ring);
|
||||
}
|
||||
}
|
||||
|
||||
qlcnic_fw_destroy_ctx(adapter);
|
||||
qlcnic_detach(adapter);
|
||||
|
||||
if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
||||
err = qlcnic_83xx_setup_mbx_intr(adapter);
|
||||
qlcnic_83xx_disable_mbx_poll(adapter);
|
||||
if (err) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"%s: failed to setup mbx interrupt\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
adapter->ahw->diag_test = 0;
|
||||
adapter->drv_sds_rings = drv_sds_rings;
|
||||
|
||||
|
@ -1399,9 +1382,6 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
|
|||
if (netif_running(netdev))
|
||||
__qlcnic_up(adapter, netdev);
|
||||
|
||||
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
|
||||
!(adapter->flags & QLCNIC_MSIX_ENABLED))
|
||||
qlcnic_83xx_disable_mbx_poll(adapter);
|
||||
out:
|
||||
netif_device_attach(netdev);
|
||||
}
|
||||
|
@ -3754,6 +3734,19 @@ static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
|
|||
return;
|
||||
}
|
||||
|
||||
static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
u32 offset;
|
||||
|
||||
offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
|
||||
dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
|
||||
readl(ahw->pci_base0 + offset),
|
||||
QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
|
||||
QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
|
||||
QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
|
||||
}
|
||||
|
||||
static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
|
||||
{
|
||||
struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
|
||||
|
@ -3798,6 +3791,8 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
|
|||
__func__, cmd->cmd_op, cmd->type, ahw->pci_func,
|
||||
ahw->op_mode);
|
||||
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
||||
qlcnic_dump_mailbox_registers(adapter);
|
||||
qlcnic_83xx_get_mbx_data(adapter, cmd);
|
||||
qlcnic_dump_mbx(adapter, cmd);
|
||||
qlcnic_83xx_idc_request_reset(adapter,
|
||||
QLCNIC_FORCE_FW_DUMP_KEY);
|
||||
|
|
|
@ -662,4 +662,5 @@ pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
|
|||
pci_channel_state_t);
|
||||
pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
|
||||
void qlcnic_83xx_io_resume(struct pci_dev *);
|
||||
void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
|
||||
#endif
|
||||
|
|
|
@ -740,6 +740,7 @@ static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)
|
|||
adapter->ahw->idc.err_code = -EIO;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"%s: Device in unknown state\n", __func__);
|
||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -818,7 +819,6 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
|
|||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
struct qlcnic_mailbox *mbx = ahw->mailbox;
|
||||
int ret = 0;
|
||||
u32 owner;
|
||||
u32 val;
|
||||
|
||||
/* Perform NIC configuration based ready state entry actions */
|
||||
|
@ -848,9 +848,9 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
|
|||
set_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
|
||||
} else {
|
||||
owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
|
||||
if (ahw->pci_func == owner)
|
||||
qlcnic_dump_fw(adapter);
|
||||
netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
|
||||
__func__);
|
||||
qlcnic_83xx_idc_enter_failed_state(adapter, 1);
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -948,13 +948,26 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
|
||||
static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
|
||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
adapter->ahw->idc.err_code = -EIO;
|
||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
u32 val, owner;
|
||||
|
||||
return 0;
|
||||
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
|
||||
if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
|
||||
owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
|
||||
if (ahw->pci_func == owner) {
|
||||
qlcnic_83xx_stop_hw(adapter);
|
||||
qlcnic_dump_fw(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
|
||||
__func__);
|
||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
ahw->idc.err_code = -EIO;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
|
||||
|
@ -1063,12 +1076,6 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
|
|||
adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
|
||||
qlcnic_83xx_periodic_tasks(adapter);
|
||||
|
||||
/* Do not reschedule if firmaware is in hanged state and auto
|
||||
* recovery is disabled
|
||||
*/
|
||||
if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
|
||||
return;
|
||||
|
||||
/* Re-schedule the function */
|
||||
if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
|
||||
qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
|
||||
|
@ -1219,10 +1226,10 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
|
|||
}
|
||||
|
||||
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
|
||||
if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) ||
|
||||
!qlcnic_auto_fw_reset) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"%s:failed, device in non reset mode\n", __func__);
|
||||
if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
|
||||
netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
|
||||
__func__);
|
||||
qlcnic_83xx_idc_enter_failed_state(adapter, 0);
|
||||
qlcnic_83xx_unlock_driver(adapter);
|
||||
return;
|
||||
}
|
||||
|
@ -1254,24 +1261,24 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
|
|||
if (size & 0xF)
|
||||
size = (size + 16) & ~0xF;
|
||||
|
||||
p_cache = kzalloc(size, GFP_KERNEL);
|
||||
p_cache = vzalloc(size);
|
||||
if (p_cache == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
|
||||
size / sizeof(u32));
|
||||
if (ret) {
|
||||
kfree(p_cache);
|
||||
vfree(p_cache);
|
||||
return ret;
|
||||
}
|
||||
/* 16 byte write to MS memory */
|
||||
ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache,
|
||||
size / 16);
|
||||
if (ret) {
|
||||
kfree(p_cache);
|
||||
vfree(p_cache);
|
||||
return ret;
|
||||
}
|
||||
kfree(p_cache);
|
||||
vfree(p_cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1939,7 +1946,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,
|
|||
p_dev->ahw->reset.seq_index = index;
|
||||
}
|
||||
|
||||
static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
|
||||
void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
|
||||
{
|
||||
p_dev->ahw->reset.seq_index = 0;
|
||||
|
||||
|
@ -1994,6 +2001,14 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
|
|||
val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
|
||||
if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
|
||||
qlcnic_dump_fw(adapter);
|
||||
|
||||
if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
|
||||
netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
|
||||
__func__);
|
||||
qlcnic_83xx_idc_enter_failed_state(adapter, 1);
|
||||
return err;
|
||||
}
|
||||
|
||||
qlcnic_83xx_init_hw(adapter);
|
||||
|
||||
if (qlcnic_83xx_copy_bootloader(adapter))
|
||||
|
@ -2073,8 +2088,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
|
|||
ahw->nic_mode = QLCNIC_DEFAULT_MODE;
|
||||
adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
|
||||
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
|
||||
adapter->max_sds_rings = ahw->max_rx_ques;
|
||||
adapter->max_tx_rings = ahw->max_tx_ques;
|
||||
adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
|
||||
adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
|
||||
} else {
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
@ -667,30 +667,25 @@ qlcnic_set_ringparam(struct net_device *dev,
|
|||
static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
|
||||
u8 rx_ring, u8 tx_ring)
|
||||
{
|
||||
if (rx_ring == 0 || tx_ring == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (rx_ring != 0) {
|
||||
if (rx_ring > adapter->max_sds_rings) {
|
||||
netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
|
||||
netdev_err(adapter->netdev,
|
||||
"Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
|
||||
rx_ring, adapter->max_sds_rings);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_ring != 0) {
|
||||
if (qlcnic_82xx_check(adapter) &&
|
||||
(tx_ring > adapter->max_tx_rings)) {
|
||||
if (tx_ring > adapter->max_tx_rings) {
|
||||
netdev_err(adapter->netdev,
|
||||
"Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
|
||||
tx_ring, adapter->max_tx_rings);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (qlcnic_83xx_check(adapter) &&
|
||||
(tx_ring > QLCNIC_SINGLE_RING)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
|
||||
tx_ring, QLCNIC_SINGLE_RING);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -948,6 +943,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
|
|||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
struct qlcnic_cmd_args cmd;
|
||||
int ret, drv_sds_rings = adapter->drv_sds_rings;
|
||||
int drv_tx_rings = adapter->drv_tx_rings;
|
||||
|
||||
if (qlcnic_83xx_check(adapter))
|
||||
return qlcnic_83xx_interrupt_test(netdev);
|
||||
|
@ -980,6 +976,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
|
|||
|
||||
clear_diag_irq:
|
||||
adapter->drv_sds_rings = drv_sds_rings;
|
||||
adapter->drv_tx_rings = drv_tx_rings;
|
||||
clear_bit(__QLCNIC_RESETTING, &adapter->state);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -687,17 +687,11 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
|
|||
if (adapter->ahw->linkup && !linkup) {
|
||||
netdev_info(netdev, "NIC Link is down\n");
|
||||
adapter->ahw->linkup = 0;
|
||||
if (netif_running(netdev)) {
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
}
|
||||
netif_carrier_off(netdev);
|
||||
} else if (!adapter->ahw->linkup && linkup) {
|
||||
netdev_info(netdev, "NIC Link is up\n");
|
||||
adapter->ahw->linkup = 1;
|
||||
if (netif_running(netdev)) {
|
||||
netif_carrier_on(netdev);
|
||||
netif_wake_queue(netdev);
|
||||
}
|
||||
netif_carrier_on(netdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1178,6 +1178,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
|
|||
} else {
|
||||
adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
|
||||
adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
|
||||
adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
|
||||
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
|
||||
}
|
||||
|
||||
|
@ -1940,7 +1941,6 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
|
|||
qlcnic_detach(adapter);
|
||||
|
||||
adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
|
||||
adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
|
||||
adapter->ahw->diag_test = test;
|
||||
adapter->ahw->linkup = 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue