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: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Dmitry Kravkov
2011-03-31 17:04:22 -07:00
committed by David S. Miller
parent 3b7f817e47
commit fab0dc89f0
6 changed files with 84 additions and 24 deletions

View File

@@ -2966,31 +2966,36 @@ static int cnic_service_bnx2x(void *data, void *status_blk)
return 0;
}
static void cnic_ulp_stop_one(struct cnic_local *cp, int if_type)
{
struct cnic_ulp_ops *ulp_ops;
if (if_type == CNIC_ULP_ISCSI)
cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
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);
return;
}
set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
mutex_unlock(&cnic_lock);
if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type]))
ulp_ops->cnic_stop(cp->ulp_handle[if_type]);
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;
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;
}
set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
mutex_unlock(&cnic_lock);
if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type]))
ulp_ops->cnic_stop(cp->ulp_handle[if_type]);
clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[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];