Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -816,6 +816,7 @@ struct qlcnic_mac_list_s {

#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK		0x8f
#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_ACCEPT_ALL	1 /* accept all packets */
@@ -961,6 +962,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_MBX_POLL_ENABLE	12
#define __QLCNIC_DIAG_MODE		13
#define __QLCNIC_DCB_STATE		14
#define __QLCNIC_DCB_IN_AEN		15

#define QLCNIC_INTERRUPT_TEST		1
#define QLCNIC_LOOPBACK_TEST		2
@@ -2163,4 +2165,22 @@ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)

	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_ */
+3 −0
Original line number Diff line number Diff line
@@ -897,6 +897,9 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
		dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
			 QLCNIC_MBX_RSP(event[0]));
		break;
	case QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT:
		qlcnic_dcb_handle_aen(adapter, (void *)&event[1]);
		break;
	default:
		dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
			QLCNIC_MBX_RSP(event[0]));
+103 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#define QLC_DCB_NUM_PARAM		3

#define QLC_DCB_AEN_BIT			0x2
#define QLC_DCB_FW_VER			0x2
#define QLC_DCB_MAX_TC			0x8
#define QLC_DCB_MAX_APP			0x8
@@ -44,6 +45,8 @@
#define QLC_82XX_DCB_GET_PRIOMAP_APP(X)	(1 << X)
#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 int __qlcnic_dcb_attach(struct qlcnic_adapter *);
static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *);
@@ -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_query_cee_param(struct qlcnic_adapter *, char *, u8);
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_query_cee_param(struct qlcnic_adapter *, char *, u8);
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 {
	bool	tsa_capability;
@@ -102,6 +108,8 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
	.get_hw_capability	= qlcnic_83xx_dcb_get_hw_capability,
	.query_cee_param	= qlcnic_83xx_dcb_query_cee_param,
	.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 = {
@@ -113,6 +121,7 @@ static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
	.get_hw_capability	= qlcnic_82xx_dcb_get_hw_capability,
	.query_cee_param	= qlcnic_82xx_dcb_query_cee_param,
	.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)
@@ -140,6 +149,7 @@ int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
		return -ENOMEM;

	adapter->dcb = dcb;
	dcb->adapter = adapter;
	qlcnic_set_dcb_ops(adapter);

	return 0;
@@ -152,6 +162,18 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
	if (!dcb)
		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);
	dcb->cfg = NULL;
	kfree(dcb->param);
@@ -164,6 +186,7 @@ static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
{
	qlcnic_dcb_get_hw_capability(adapter);
	qlcnic_dcb_get_cee_cfg(adapter);
	qlcnic_dcb_register_aen(adapter, 1);
}

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;
	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);
	if (!dcb->cfg)
		return -ENOMEM;
	if (!dcb->cfg) {
		err = -ENOMEM;
		goto out_free_wq;
	}

	dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
	if (!dcb->param) {
@@ -188,6 +222,10 @@ out_free_cfg:
	kfree(dcb->cfg);
	dcb->cfg = NULL;

out_free_wq:
	destroy_workqueue(dcb->wq);
	dcb->wq = NULL;

	return err;
}

@@ -368,6 +406,29 @@ static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
	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)
{
	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)

	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);
}
+5 −0
Original line number Diff line number Diff line
@@ -25,10 +25,15 @@ struct qlcnic_dcb_ops {
	void (*get_info) (struct qlcnic_adapter *);
	int (*query_cee_param) (struct qlcnic_adapter *, char *, u8);
	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_mbx_params	*param;
	struct qlcnic_adapter		*adapter;
	struct delayed_work		aen_work;
	struct workqueue_struct		*wq;
	struct qlcnic_dcb_ops		*ops;
	struct qlcnic_dcb_cfg		*cfg;
};
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ enum qlcnic_regs {
#define QLCNIC_MBX_COMP_EVENT		0x8100
#define QLCNIC_MBX_REQUEST_EVENT	0x8101
#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_REMOVE_EVENT	0x8131

Loading