summaryrefslogtreecommitdiff
path: root/drivers/net/cnic.c
diff options
context:
space:
mode:
authorDmitry Kravkov <dmitry@broadcom.com>2011-03-31 17:04:22 -0700
committerDavid S. Miller <davem@davemloft.net>2011-03-31 17:04:22 -0700
commitfab0dc89f0d98459c6ce7fa27422949ac15837fa (patch)
treecd7d169e81ff9028d746f2540302d677b17f30cf /drivers/net/cnic.c
parent3b7f817e47bb66ae4d82ed73689a521af70a5410 (diff)
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>
Diffstat (limited to 'drivers/net/cnic.c')
-rw-r--r--drivers/net/cnic.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 8cca60e43444..5dfbff06631c 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2966,31 +2966,36 @@ 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;
-
- cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+ struct cnic_ulp_ops *ulp_ops;
- for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; 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);
- continue;
- }
- set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+ 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]);
+ 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]);
- }
+ 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];