Commit e5c4e6c6 authored by Manish Chopra's avatar Manish Chopra Committed by David S. Miller

qlcnic: Interrupt based driver firmware mailbox mechanism

o Driver firmware mailbox interface was operating in polling mode
  because of limitations with the earlier versions of 83xx adapter firmware.
  These issues are resolved and we are implementing interrupt based mailbox
  mechanism.

o Data structures and API's for interrupt mode mailbox mechanism.
Signed-off-by: default avatarManish Chopra <manish.chopra@qlogic.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9c11984
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -468,6 +467,7 @@ struct qlcnic_hardware_context { ...@@ -468,6 +467,7 @@ struct qlcnic_hardware_context {
u32 mbox_aen[QLC_83XX_MBX_AEN_CNT]; u32 mbox_aen[QLC_83XX_MBX_AEN_CNT];
u32 mbox_reg[4]; u32 mbox_reg[4];
spinlock_t mbx_lock; spinlock_t mbx_lock;
struct qlcnic_mailbox *mailbox;
}; };
struct qlcnic_adapter_stats { struct qlcnic_adapter_stats {
...@@ -966,6 +966,21 @@ struct qlcnic_filter_hash { ...@@ -966,6 +966,21 @@ struct qlcnic_filter_hash {
u16 fbucket_size; u16 fbucket_size;
}; };
/* Mailbox specific data structures */
struct qlcnic_mailbox {
struct workqueue_struct *work_q;
struct qlcnic_adapter *adapter;
struct qlcnic_mbx_ops *ops;
struct work_struct work;
struct completion completion;
struct list_head cmd_q;
unsigned long status;
spinlock_t queue_lock; /* Mailbox queue lock */
spinlock_t aen_lock; /* Mailbox response/AEN lock */
atomic_t rsp_status;
u32 num_cmds;
};
struct qlcnic_adapter { struct qlcnic_adapter {
struct qlcnic_hardware_context *ahw; struct qlcnic_hardware_context *ahw;
struct qlcnic_recv_context *recv_ctx; struct qlcnic_recv_context *recv_ctx;
...@@ -1379,9 +1394,20 @@ struct _cdrp_cmd { ...@@ -1379,9 +1394,20 @@ struct _cdrp_cmd {
}; };
struct qlcnic_cmd_args { struct qlcnic_cmd_args {
struct _cdrp_cmd req; struct completion completion;
struct _cdrp_cmd rsp; struct list_head list;
int op_type; struct _cdrp_cmd req;
struct _cdrp_cmd rsp;
atomic_t rsp_status;
int pay_size;
u32 rsp_opcode;
u32 total_cmds;
u32 op_type;
u32 type;
u32 cmd_op;
u32 *hdr; /* Back channel message header */
u32 *pay; /* Back channel message payload */
u8 func_num;
}; };
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
...@@ -1594,6 +1620,20 @@ struct qlcnic_nic_template { ...@@ -1594,6 +1620,20 @@ struct qlcnic_nic_template {
int (*resume)(struct qlcnic_adapter *); int (*resume)(struct qlcnic_adapter *);
}; };
struct qlcnic_mbx_ops {
int (*enqueue_cmd) (struct qlcnic_adapter *,
struct qlcnic_cmd_args *, unsigned long *);
void (*dequeue_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
void (*decode_resp) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
void (*encode_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
void (*nofity_fw) (struct qlcnic_adapter *, u8);
};
int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);
/* Adapter hardware abstraction */ /* Adapter hardware abstraction */
struct qlcnic_hardware_ops { struct qlcnic_hardware_ops {
void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t); void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
......
...@@ -89,6 +89,13 @@ ...@@ -89,6 +89,13 @@
#define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16 #define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16
#define QLC_83XX_MBX_POST_BC_OP 0x1
#define QLC_83XX_MBX_COMPLETION 0x0
#define QLC_83XX_MBX_REQUEST 0x1
#define QLC_83XX_MBX_TIMEOUT (5 * HZ)
#define QLC_83XX_MBX_CMD_LOOP 5000000
/* status descriptor mailbox data /* status descriptor mailbox data
* @phy_addr_{low|high}: physical address of buffer * @phy_addr_{low|high}: physical address of buffer
* @sds_ring_size: buffer size * @sds_ring_size: buffer size
...@@ -449,6 +456,20 @@ enum qlcnic_83xx_states { ...@@ -449,6 +456,20 @@ enum qlcnic_83xx_states {
#define QLC_83xx_FLASH_MAX_WAIT_USEC 100 #define QLC_83xx_FLASH_MAX_WAIT_USEC 100
#define QLC_83XX_FLASH_LOCK_TIMEOUT 10000 #define QLC_83XX_FLASH_LOCK_TIMEOUT 10000
enum qlc_83xx_mbx_cmd_type {
QLC_83XX_MBX_CMD_WAIT = 0,
QLC_83XX_MBX_CMD_NO_WAIT,
QLC_83XX_MBX_CMD_BUSY_WAIT,
};
enum qlc_83xx_mbx_response_states {
QLC_83XX_MBX_RESPONSE_WAIT = 0,
QLC_83XX_MBX_RESPONSE_ARRIVED,
};
#define QLC_83XX_MBX_RESPONSE_FAILED 0x2
#define QLC_83XX_MBX_RESPONSE_UNKNOWN 0x3
/* Additional registers in 83xx */ /* Additional registers in 83xx */
enum qlc_83xx_ext_regs { enum qlc_83xx_ext_regs {
QLCNIC_GLOBAL_RESET = 0, QLCNIC_GLOBAL_RESET = 0,
...@@ -498,7 +519,7 @@ enum qlc_83xx_ext_regs { ...@@ -498,7 +519,7 @@ enum qlc_83xx_ext_regs {
/* 83xx funcitons */ /* 83xx funcitons */
int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *); int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8); int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8);
void qlcnic_83xx_get_func_no(struct qlcnic_adapter *); void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
int qlcnic_83xx_cam_lock(struct qlcnic_adapter *); int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
...@@ -551,7 +572,7 @@ void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *, ...@@ -551,7 +572,7 @@ void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *); void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_handle_aen(int, void *); irqreturn_t qlcnic_83xx_handle_aen(int, void *);
int qlcnic_83xx_get_port_info(struct qlcnic_adapter *); int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *); void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *); void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *); irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_intr(int, void *); irqreturn_t qlcnic_83xx_intr(int, void *);
......
...@@ -617,7 +617,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) ...@@ -617,7 +617,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
if (err) if (err)
return err; return err;
qlcnic_83xx_enable_mbx_intrpt(adapter); qlcnic_83xx_enable_mbx_interrupt(adapter);
if (qlcnic_83xx_configure_opmode(adapter)) { if (qlcnic_83xx_configure_opmode(adapter)) {
qlcnic_83xx_idc_enter_failed_state(adapter, 1); qlcnic_83xx_idc_enter_failed_state(adapter, 1);
...@@ -2120,7 +2120,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2120,7 +2120,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
/* Initilaize 83xx mailbox spinlock */ /* Initilaize 83xx mailbox spinlock */
spin_lock_init(&ahw->mbx_lock); spin_lock_init(&ahw->mbx_lock);
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); set_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
qlcnic_83xx_clear_function_resources(adapter); qlcnic_83xx_clear_function_resources(adapter);
/* register for NIC IDC AEN Events */ /* register for NIC IDC AEN Events */
......
...@@ -33,7 +33,7 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32); ...@@ -33,7 +33,7 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32);
static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *); static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *);
static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *);
static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *);
static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *,
struct qlcnic_cmd_args *); struct qlcnic_cmd_args *);
static void qlcnic_sriov_process_bc_cmd(struct work_struct *); static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
...@@ -45,7 +45,7 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { ...@@ -45,7 +45,7 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
.get_mac_address = qlcnic_83xx_get_mac_address, .get_mac_address = qlcnic_83xx_get_mac_address,
.setup_intr = qlcnic_83xx_setup_intr, .setup_intr = qlcnic_83xx_setup_intr,
.alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args,
.mbx_cmd = qlcnic_sriov_vf_mbx_op, .mbx_cmd = qlcnic_sriov_issue_cmd,
.get_func_no = qlcnic_83xx_get_func_no, .get_func_no = qlcnic_83xx_get_func_no,
.api_lock = qlcnic_83xx_cam_lock, .api_lock = qlcnic_83xx_cam_lock,
.api_unlock = qlcnic_83xx_cam_unlock, .api_unlock = qlcnic_83xx_cam_unlock,
...@@ -295,7 +295,7 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, ...@@ -295,7 +295,7 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
opcode = ((struct qlcnic_bc_hdr *)hdr)->cmd_op; opcode = ((struct qlcnic_bc_hdr *)hdr)->cmd_op;
if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { if (!test_bit(QLC_83XX_MBX_READY, &ahw->idc.status)) {
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"Mailbox cmd attempted, 0x%x\n", opcode); "Mailbox cmd attempted, 0x%x\n", opcode);
dev_info(&adapter->pdev->dev, "Mailbox detached\n"); dev_info(&adapter->pdev->dev, "Mailbox detached\n");
...@@ -1083,6 +1083,7 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work) ...@@ -1083,6 +1083,7 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work)
if (test_bit(QLC_BC_VF_FLR, &vf->state)) if (test_bit(QLC_BC_VF_FLR, &vf->state))
return; return;
memset(&cmd, 0, sizeof(struct qlcnic_cmd_args));
trans = list_first_entry(&vf->rcv_act.wait_list, trans = list_first_entry(&vf->rcv_act.wait_list,
struct qlcnic_bc_trans, list); struct qlcnic_bc_trans, list);
adapter = vf->adapter; adapter = vf->adapter;
...@@ -1232,6 +1233,7 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov, ...@@ -1232,6 +1233,7 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov,
return; return;
} }
memset(&cmd, 0, sizeof(struct qlcnic_cmd_args));
cmd_op = hdr->cmd_op; cmd_op = hdr->cmd_op;
if (qlcnic_sriov_alloc_bc_trans(&trans)) if (qlcnic_sriov_alloc_bc_trans(&trans))
return; return;
...@@ -1357,7 +1359,7 @@ int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable) ...@@ -1357,7 +1359,7 @@ int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable)
if (enable) if (enable)
cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
err = qlcnic_83xx_mbx_op(adapter, &cmd); err = qlcnic_83xx_issue_cmd(adapter, &cmd);
if (err != QLCNIC_RCODE_SUCCESS) { if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
...@@ -1389,7 +1391,7 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter, ...@@ -1389,7 +1391,7 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter,
return -EIO; return -EIO;
} }
static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter, static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
...@@ -1409,7 +1411,7 @@ static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter, ...@@ -1409,7 +1411,7 @@ static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter,
goto cleanup_transaction; goto cleanup_transaction;
retry: retry:
if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { if (!test_bit(QLC_83XX_MBX_READY, &ahw->idc.status)) {
rsp = -EIO; rsp = -EIO;
QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n", QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n",
QLCNIC_MBX_RSP(cmd->req.arg[0]), func); QLCNIC_MBX_RSP(cmd->req.arg[0]), func);
...@@ -1612,7 +1614,7 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) ...@@ -1612,7 +1614,7 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
int err; int err;
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
qlcnic_83xx_enable_mbx_intrpt(adapter); qlcnic_83xx_enable_mbx_interrupt(adapter);
err = qlcnic_sriov_cfg_bc_intr(adapter, 1); err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
if (err) if (err)
...@@ -1988,7 +1990,7 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) ...@@ -1988,7 +1990,7 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter)
int err; int err;
set_bit(QLC_83XX_MODULE_LOADED, &idc->status); set_bit(QLC_83XX_MODULE_LOADED, &idc->status);
qlcnic_83xx_enable_mbx_intrpt(adapter); qlcnic_83xx_enable_mbx_interrupt(adapter);
err = qlcnic_sriov_cfg_bc_intr(adapter, 1); err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
if (err) if (err)
return err; return err;
......
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