Commit 2d8ebcab authored by Sucheta Chakraborty's avatar Sucheta Chakraborty Committed by David S. Miller

qlcnic: dcb: Register DCB AEN handler.

o Adapter sends Asynchronous Event Notifications to the driver when
  there are changes in the switch or adapter DCBX configuration.
  AEN handler updates the driver DCBX parameters.
Signed-off-by: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fb859ed6
...@@ -816,6 +816,7 @@ struct qlcnic_mac_list_s { ...@@ -816,6 +816,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f
#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D
#define QLCNIC_C2H_OPCODE_GET_DCB_AEN 0x90
#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */
#define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */
...@@ -961,6 +962,7 @@ struct qlcnic_ipaddr { ...@@ -961,6 +962,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_MBX_POLL_ENABLE 12 #define __QLCNIC_MBX_POLL_ENABLE 12
#define __QLCNIC_DIAG_MODE 13 #define __QLCNIC_DIAG_MODE 13
#define __QLCNIC_DCB_STATE 14 #define __QLCNIC_DCB_STATE 14
#define __QLCNIC_DCB_IN_AEN 15
#define QLCNIC_INTERRUPT_TEST 1 #define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2 #define QLCNIC_LOOPBACK_TEST 2
...@@ -2163,4 +2165,22 @@ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) ...@@ -2163,4 +2165,22 @@ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
return 0; return 0;
} }
static inline void
qlcnic_dcb_register_aen(struct qlcnic_adapter *adapter, u8 flag)
{
struct qlcnic_dcb *dcb = adapter->dcb;
if (dcb && dcb->ops->register_aen)
dcb->ops->register_aen(adapter, flag);
}
static inline void qlcnic_dcb_handle_aen(struct qlcnic_adapter *adapter,
void *msg)
{
struct qlcnic_dcb *dcb = adapter->dcb;
if (dcb && dcb->ops->handle_aen)
dcb->ops->handle_aen(adapter, msg);
}
#endif /* __QLCNIC_H_ */ #endif /* __QLCNIC_H_ */
...@@ -897,6 +897,9 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) ...@@ -897,6 +897,9 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n", dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
QLCNIC_MBX_RSP(event[0])); QLCNIC_MBX_RSP(event[0]));
break; break;
case QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT:
qlcnic_dcb_handle_aen(adapter, (void *)&event[1]);
break;
default: default:
dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n", dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
QLCNIC_MBX_RSP(event[0])); QLCNIC_MBX_RSP(event[0]));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define QLC_DCB_NUM_PARAM 3 #define QLC_DCB_NUM_PARAM 3
#define QLC_DCB_AEN_BIT 0x2
#define QLC_DCB_FW_VER 0x2 #define QLC_DCB_FW_VER 0x2
#define QLC_DCB_MAX_TC 0x8 #define QLC_DCB_MAX_TC 0x8
#define QLC_DCB_MAX_APP 0x8 #define QLC_DCB_MAX_APP 0x8
...@@ -44,6 +45,8 @@ ...@@ -44,6 +45,8 @@
#define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X) #define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X)
#define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210) #define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210)
static void qlcnic_dcb_aen_work(struct work_struct *);
static void __qlcnic_dcb_free(struct qlcnic_adapter *); static void __qlcnic_dcb_free(struct qlcnic_adapter *);
static int __qlcnic_dcb_attach(struct qlcnic_adapter *); static int __qlcnic_dcb_attach(struct qlcnic_adapter *);
static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *); static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *);
...@@ -52,10 +55,13 @@ static void __qlcnic_dcb_get_info(struct qlcnic_adapter *); ...@@ -52,10 +55,13 @@ static void __qlcnic_dcb_get_info(struct qlcnic_adapter *);
static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *); static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *);
static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8); static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *); static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *, void *);
static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *); static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *);
static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8); static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *); static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *, bool);
static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *, void *);
struct qlcnic_dcb_capability { struct qlcnic_dcb_capability {
bool tsa_capability; bool tsa_capability;
...@@ -102,6 +108,8 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = { ...@@ -102,6 +108,8 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
.get_hw_capability = qlcnic_83xx_dcb_get_hw_capability, .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability,
.query_cee_param = qlcnic_83xx_dcb_query_cee_param, .query_cee_param = qlcnic_83xx_dcb_query_cee_param,
.get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg, .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg,
.register_aen = qlcnic_83xx_dcb_register_aen,
.handle_aen = qlcnic_83xx_dcb_handle_aen,
}; };
static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
...@@ -113,6 +121,7 @@ static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { ...@@ -113,6 +121,7 @@ static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
.get_hw_capability = qlcnic_82xx_dcb_get_hw_capability, .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability,
.query_cee_param = qlcnic_82xx_dcb_query_cee_param, .query_cee_param = qlcnic_82xx_dcb_query_cee_param,
.get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg, .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg,
.handle_aen = qlcnic_82xx_dcb_handle_aen,
}; };
static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val) static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
...@@ -140,6 +149,7 @@ int __qlcnic_register_dcb(struct qlcnic_adapter *adapter) ...@@ -140,6 +149,7 @@ int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
return -ENOMEM; return -ENOMEM;
adapter->dcb = dcb; adapter->dcb = dcb;
dcb->adapter = adapter;
qlcnic_set_dcb_ops(adapter); qlcnic_set_dcb_ops(adapter);
return 0; return 0;
...@@ -152,6 +162,18 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter) ...@@ -152,6 +162,18 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
if (!dcb) if (!dcb)
return; return;
qlcnic_dcb_register_aen(adapter, 0);
while (test_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
usleep_range(10000, 11000);
cancel_delayed_work_sync(&dcb->aen_work);
if (dcb->wq) {
destroy_workqueue(dcb->wq);
dcb->wq = NULL;
}
kfree(dcb->cfg); kfree(dcb->cfg);
dcb->cfg = NULL; dcb->cfg = NULL;
kfree(dcb->param); kfree(dcb->param);
...@@ -164,6 +186,7 @@ static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter) ...@@ -164,6 +186,7 @@ static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
{ {
qlcnic_dcb_get_hw_capability(adapter); qlcnic_dcb_get_hw_capability(adapter);
qlcnic_dcb_get_cee_cfg(adapter); qlcnic_dcb_get_cee_cfg(adapter);
qlcnic_dcb_register_aen(adapter, 1);
} }
static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter) static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
...@@ -171,9 +194,20 @@ static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter) ...@@ -171,9 +194,20 @@ static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
struct qlcnic_dcb *dcb = adapter->dcb; struct qlcnic_dcb *dcb = adapter->dcb;
int err = 0; int err = 0;
INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work);
dcb->wq = create_singlethread_workqueue("qlcnic-dcb");
if (!dcb->wq) {
dev_err(&adapter->pdev->dev,
"DCB workqueue allocation failed. DCB will be disabled\n");
return -1;
}
dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC); dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
if (!dcb->cfg) if (!dcb->cfg) {
return -ENOMEM; err = -ENOMEM;
goto out_free_wq;
}
dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC); dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
if (!dcb->param) { if (!dcb->param) {
...@@ -188,6 +222,10 @@ static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter) ...@@ -188,6 +222,10 @@ static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
kfree(dcb->cfg); kfree(dcb->cfg);
dcb->cfg = NULL; dcb->cfg = NULL;
out_free_wq:
destroy_workqueue(dcb->wq);
dcb->wq = NULL;
return err; return err;
} }
...@@ -368,6 +406,29 @@ static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) ...@@ -368,6 +406,29 @@ static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
return err; return err;
} }
static void qlcnic_dcb_aen_work(struct work_struct *work)
{
struct qlcnic_adapter *adapter;
struct qlcnic_dcb *dcb;
dcb = container_of(work, struct qlcnic_dcb, aen_work.work);
adapter = dcb->adapter;
qlcnic_dcb_get_cee_cfg(adapter);
clear_bit(__QLCNIC_DCB_IN_AEN, &adapter->state);
}
static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *adapter,
void *data)
{
struct qlcnic_dcb *dcb = adapter->dcb;
if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
return;
queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
}
static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability; struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
...@@ -459,3 +520,43 @@ static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) ...@@ -459,3 +520,43 @@ static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
return qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0); return qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0);
} }
static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *adapter,
bool flag)
{
u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC);
struct qlcnic_cmd_args cmd;
int err;
err = qlcnic_alloc_mbx_args(&cmd, adapter, val);
if (err)
return err;
cmd.req.arg[1] = QLC_DCB_AEN_BIT;
err = qlcnic_issue_cmd(adapter, &cmd);
if (err)
dev_err(&adapter->pdev->dev, "Failed to %s DCBX AEN, err %d\n",
(flag ? "register" : "unregister"), err);
qlcnic_free_mbx_args(&cmd);
return err;
}
static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *adapter,
void *data)
{
struct qlcnic_dcb *dcb = adapter->dcb;
u32 *val = data;
if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
return;
if (*val & BIT_8)
set_bit(__QLCNIC_DCB_STATE, &adapter->state);
else
clear_bit(__QLCNIC_DCB_STATE, &adapter->state);
queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
}
...@@ -25,10 +25,15 @@ struct qlcnic_dcb_ops { ...@@ -25,10 +25,15 @@ struct qlcnic_dcb_ops {
void (*get_info) (struct qlcnic_adapter *); void (*get_info) (struct qlcnic_adapter *);
int (*query_cee_param) (struct qlcnic_adapter *, char *, u8); int (*query_cee_param) (struct qlcnic_adapter *, char *, u8);
int (*get_cee_cfg) (struct qlcnic_adapter *); int (*get_cee_cfg) (struct qlcnic_adapter *);
int (*register_aen) (struct qlcnic_adapter *, bool);
void (*handle_aen) (struct qlcnic_adapter *, void *);
}; };
struct qlcnic_dcb { struct qlcnic_dcb {
struct qlcnic_dcb_mbx_params *param; struct qlcnic_dcb_mbx_params *param;
struct qlcnic_adapter *adapter;
struct delayed_work aen_work;
struct workqueue_struct *wq;
struct qlcnic_dcb_ops *ops; struct qlcnic_dcb_ops *ops;
struct qlcnic_dcb_cfg *cfg; struct qlcnic_dcb_cfg *cfg;
}; };
......
...@@ -125,6 +125,7 @@ enum qlcnic_regs { ...@@ -125,6 +125,7 @@ enum qlcnic_regs {
#define QLCNIC_MBX_COMP_EVENT 0x8100 #define QLCNIC_MBX_COMP_EVENT 0x8100
#define QLCNIC_MBX_REQUEST_EVENT 0x8101 #define QLCNIC_MBX_REQUEST_EVENT 0x8101
#define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102 #define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102
#define QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT 0x8110
#define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130 #define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130
#define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131 #define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131
......
...@@ -1010,6 +1010,9 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index, ...@@ -1010,6 +1010,9 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index,
break; break;
} }
break; break;
case QLCNIC_C2H_OPCODE_GET_DCB_AEN:
qlcnic_dcb_handle_aen(adapter, (void *)&msg);
break;
default: default:
break; break;
} }
......
...@@ -1286,6 +1286,8 @@ static const int qlcnic_pf_passthru_supp_cmds[] = { ...@@ -1286,6 +1286,8 @@ static const int qlcnic_pf_passthru_supp_cmds[] = {
QLCNIC_CMD_GET_LINK_STATUS, QLCNIC_CMD_GET_LINK_STATUS,
QLCNIC_CMD_DCB_QUERY_CAP, QLCNIC_CMD_DCB_QUERY_CAP,
QLCNIC_CMD_DCB_QUERY_PARAM, QLCNIC_CMD_DCB_QUERY_PARAM,
QLCNIC_CMD_INIT_NIC_FUNC,
QLCNIC_CMD_STOP_NIC_FUNC,
}; };
static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = { static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = {
......
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