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

Commit fab0dc89 authored by Dmitry Kravkov's avatar Dmitry Kravkov Committed by David S. Miller
Browse files

bnx2x, cnic: Disable iSCSI if DCBX negotiation is successful



With current bnx2x firmware 6.2.9, iSCSI is not supported in DCB
network, so we need to disable it.  Add cnic command to disconnect
iSCSI connections and prevent future connections when DCBX negotiation
succeeds.

Signed-off-by: default avatarDmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3b7f817e
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -571,6 +571,28 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
{
	switch (state) {
	case BNX2X_DCBX_STATE_NEG_RECEIVED:
#ifdef BCM_CNIC
		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
			struct cnic_ops *c_ops;
			struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
			bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
			cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
			cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;

			rcu_read_lock();
			c_ops = rcu_dereference(bp->cnic_ops);
			if (c_ops) {
				bnx2x_cnic_notify(bp, CNIC_CTL_STOP_ISCSI_CMD);
				rcu_read_unlock();
				return;
			}
			rcu_read_unlock();
		}

		/* fall through if no CNIC initialized  */
	case BNX2X_DCBX_STATE_ISCSI_STOPPED:
#endif

		{
			DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
#ifdef BCM_DCBNL
+6 −2
Original line number Diff line number Diff line
@@ -183,9 +183,13 @@ void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);

enum {
	BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
	BNX2X_DCBX_STATE_TX_PAUSED = 0x2,
	BNX2X_DCBX_STATE_TX_RELEASED = 0x4
#ifdef BCM_CNIC
	BNX2X_DCBX_STATE_ISCSI_STOPPED,
#endif
	BNX2X_DCBX_STATE_TX_PAUSED,
	BNX2X_DCBX_STATE_TX_RELEASED
};

void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);

/* DCB netlink */
+5 −0
Original line number Diff line number Diff line
@@ -10342,6 +10342,11 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
		break;
	}

	case DRV_CTL_ISCSI_STOPPED_CMD: {
		bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED);
		break;
	}

	default:
		BNX2X_ERR("unknown command %x\n", ctl->cmd);
		rc = -EINVAL;
+45 −19
Original line number Diff line number Diff line
@@ -2966,22 +2966,19 @@ static int cnic_service_bnx2x(void *data, void *status_blk)
	return 0;
}

static void cnic_ulp_stop(struct cnic_dev *dev)
static void cnic_ulp_stop_one(struct cnic_local *cp, int if_type)
{
	struct cnic_local *cp = dev->cnic_priv;
	int if_type;
	struct cnic_ulp_ops *ulp_ops;

	if (if_type == CNIC_ULP_ISCSI)
		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);

	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
		struct cnic_ulp_ops *ulp_ops;

	mutex_lock(&cnic_lock);
	ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
					    lockdep_is_held(&cnic_lock));
	if (!ulp_ops) {
		mutex_unlock(&cnic_lock);
			continue;
		return;
	}
	set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
	mutex_unlock(&cnic_lock);
@@ -2991,6 +2988,14 @@ static void cnic_ulp_stop(struct cnic_dev *dev)

	clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
}

static void cnic_ulp_stop(struct cnic_dev *dev)
{
	struct cnic_local *cp = dev->cnic_priv;
	int if_type;

	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++)
		cnic_ulp_stop_one(cp, if_type);
}

static void cnic_ulp_start(struct cnic_dev *dev)
@@ -3039,6 +3044,12 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info)

		cnic_put(dev);
		break;
	case CNIC_CTL_STOP_ISCSI_CMD: {
		struct cnic_local *cp = dev->cnic_priv;
		set_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags);
		queue_delayed_work(cnic_wq, &cp->delete_task, 0);
		break;
	}
	case CNIC_CTL_COMPLETION_CMD: {
		u32 cid = BNX2X_SW_CID(info->data.comp.cid);
		u32 l5_cid;
@@ -3562,8 +3573,12 @@ static void cnic_init_csk_state(struct cnic_sock *csk)

static int cnic_cm_connect(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
{
	struct cnic_local *cp = csk->dev->cnic_priv;
	int err = 0;

	if (cp->ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)
		return -EOPNOTSUPP;

	if (!cnic_in_use(csk))
		return -EINVAL;

@@ -3965,6 +3980,17 @@ static void cnic_delete_task(struct work_struct *work)
	cp = container_of(work, struct cnic_local, delete_task.work);
	dev = cp->dev;

	if (test_and_clear_bit(CNIC_LCL_FL_STOP_ISCSI, &cp->cnic_local_flags)) {
		struct drv_ctl_info info;

		rtnl_lock();
		cnic_ulp_stop_one(cp, CNIC_ULP_ISCSI);
		rtnl_unlock();

		info.cmd = DRV_CTL_ISCSI_STOPPED_CMD;
		cp->ethdev->drv_ctl(dev->netdev, &info);
	}

	for (i = 0; i < cp->max_cid_space; i++) {
		struct cnic_context *ctx = &cp->ctx_tbl[i];

+1 −0
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ struct cnic_local {
#define	CNIC_LCL_FL_KWQ_INIT		0x0
#define	CNIC_LCL_FL_L2_WAIT		0x1
#define	CNIC_LCL_FL_RINGS_INITED	0x2
#define	CNIC_LCL_FL_STOP_ISCSI		0x4

	struct cnic_dev *dev;

Loading