diff options
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 24 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 17 |
4 files changed, 29 insertions, 23 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index be7d6824581a..3ca4b6a5eddd 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -261,9 +261,9 @@ | |||
261 | struct name_list_extended { | 261 | struct name_list_extended { |
262 | struct get_name_list_extended *l; | 262 | struct get_name_list_extended *l; |
263 | dma_addr_t ldma; | 263 | dma_addr_t ldma; |
264 | struct list_head fcports; /* protect by sess_list */ | 264 | struct list_head fcports; |
265 | spinlock_t fcports_lock; | ||
265 | u32 size; | 266 | u32 size; |
266 | u8 sent; | ||
267 | }; | 267 | }; |
268 | /* | 268 | /* |
269 | * Timeout timer counts in seconds | 269 | * Timeout timer counts in seconds |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 04870621e712..cacf2ccc081b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -643,8 +643,7 @@ qla24xx_async_gnl_sp_done(void *s, int res) | |||
643 | (loop_id & 0x7fff)); | 643 | (loop_id & 0x7fff)); |
644 | } | 644 | } |
645 | 645 | ||
646 | spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); | 646 | spin_lock_irqsave(&vha->gnl.fcports_lock, flags); |
647 | vha->gnl.sent = 0; | ||
648 | 647 | ||
649 | INIT_LIST_HEAD(&h); | 648 | INIT_LIST_HEAD(&h); |
650 | fcport = tf = NULL; | 649 | fcport = tf = NULL; |
@@ -653,12 +652,16 @@ qla24xx_async_gnl_sp_done(void *s, int res) | |||
653 | 652 | ||
654 | list_for_each_entry_safe(fcport, tf, &h, gnl_entry) { | 653 | list_for_each_entry_safe(fcport, tf, &h, gnl_entry) { |
655 | list_del_init(&fcport->gnl_entry); | 654 | list_del_init(&fcport->gnl_entry); |
655 | spin_lock(&vha->hw->tgt.sess_lock); | ||
656 | fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); | 656 | fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); |
657 | spin_unlock(&vha->hw->tgt.sess_lock); | ||
657 | ea.fcport = fcport; | 658 | ea.fcport = fcport; |
658 | 659 | ||
659 | qla2x00_fcport_event_handler(vha, &ea); | 660 | qla2x00_fcport_event_handler(vha, &ea); |
660 | } | 661 | } |
662 | spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags); | ||
661 | 663 | ||
664 | spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); | ||
662 | /* create new fcport if fw has knowledge of new sessions */ | 665 | /* create new fcport if fw has knowledge of new sessions */ |
663 | for (i = 0; i < n; i++) { | 666 | for (i = 0; i < n; i++) { |
664 | port_id_t id; | 667 | port_id_t id; |
@@ -710,18 +713,21 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
710 | ql_dbg(ql_dbg_disc, vha, 0x20d9, | 713 | ql_dbg(ql_dbg_disc, vha, 0x20d9, |
711 | "Async-gnlist WWPN %8phC \n", fcport->port_name); | 714 | "Async-gnlist WWPN %8phC \n", fcport->port_name); |
712 | 715 | ||
713 | spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); | 716 | spin_lock_irqsave(&vha->gnl.fcports_lock, flags); |
717 | if (!list_empty(&fcport->gnl_entry)) { | ||
718 | spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags); | ||
719 | rval = QLA_SUCCESS; | ||
720 | goto done; | ||
721 | } | ||
722 | |||
723 | spin_lock(&vha->hw->tgt.sess_lock); | ||
714 | fcport->disc_state = DSC_GNL; | 724 | fcport->disc_state = DSC_GNL; |
715 | fcport->last_rscn_gen = fcport->rscn_gen; | 725 | fcport->last_rscn_gen = fcport->rscn_gen; |
716 | fcport->last_login_gen = fcport->login_gen; | 726 | fcport->last_login_gen = fcport->login_gen; |
727 | spin_unlock(&vha->hw->tgt.sess_lock); | ||
717 | 728 | ||
718 | list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports); | 729 | list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports); |
719 | if (vha->gnl.sent) { | 730 | spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags); |
720 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); | ||
721 | return QLA_SUCCESS; | ||
722 | } | ||
723 | vha->gnl.sent = 1; | ||
724 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); | ||
725 | 731 | ||
726 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | 732 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); |
727 | if (!sp) | 733 | if (!sp) |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index afcb5567998a..585f37155f29 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -4577,6 +4577,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, | |||
4577 | 4577 | ||
4578 | spin_lock_init(&vha->work_lock); | 4578 | spin_lock_init(&vha->work_lock); |
4579 | spin_lock_init(&vha->cmd_list_lock); | 4579 | spin_lock_init(&vha->cmd_list_lock); |
4580 | spin_lock_init(&vha->gnl.fcports_lock); | ||
4580 | init_waitqueue_head(&vha->fcport_waitQ); | 4581 | init_waitqueue_head(&vha->fcport_waitQ); |
4581 | init_waitqueue_head(&vha->vref_waitq); | 4582 | init_waitqueue_head(&vha->vref_waitq); |
4582 | 4583 | ||
@@ -4877,6 +4878,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) | |||
4877 | } | 4878 | } |
4878 | qlt_plogi_ack_unref(vha, pla); | 4879 | qlt_plogi_ack_unref(vha, pla); |
4879 | } else { | 4880 | } else { |
4881 | fc_port_t *dfcp = NULL; | ||
4882 | |||
4880 | spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); | 4883 | spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); |
4881 | tfcp = qla2x00_find_fcport_by_nportid(vha, | 4884 | tfcp = qla2x00_find_fcport_by_nportid(vha, |
4882 | &e->u.new_sess.id, 1); | 4885 | &e->u.new_sess.id, 1); |
@@ -4899,11 +4902,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) | |||
4899 | default: | 4902 | default: |
4900 | fcport->login_pause = 1; | 4903 | fcport->login_pause = 1; |
4901 | tfcp->conflict = fcport; | 4904 | tfcp->conflict = fcport; |
4902 | qlt_schedule_sess_for_deletion(tfcp); | 4905 | dfcp = tfcp; |
4903 | break; | 4906 | break; |
4904 | } | 4907 | } |
4905 | } | 4908 | } |
4906 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); | 4909 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); |
4910 | if (dfcp) | ||
4911 | qlt_schedule_sess_for_deletion(tfcp); | ||
4907 | 4912 | ||
4908 | wwn = wwn_to_u64(fcport->node_name); | 4913 | wwn = wwn_to_u64(fcport->node_name); |
4909 | 4914 | ||
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 896b2d8bd803..b49ac85f3de2 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
@@ -1224,10 +1224,10 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess) | |||
1224 | } | 1224 | } |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | /* ha->tgt.sess_lock supposed to be held on entry */ | ||
1228 | void qlt_schedule_sess_for_deletion(struct fc_port *sess) | 1227 | void qlt_schedule_sess_for_deletion(struct fc_port *sess) |
1229 | { | 1228 | { |
1230 | struct qla_tgt *tgt = sess->tgt; | 1229 | struct qla_tgt *tgt = sess->tgt; |
1230 | struct qla_hw_data *ha = sess->vha->hw; | ||
1231 | unsigned long flags; | 1231 | unsigned long flags; |
1232 | 1232 | ||
1233 | if (sess->disc_state == DSC_DELETE_PEND) | 1233 | if (sess->disc_state == DSC_DELETE_PEND) |
@@ -1244,16 +1244,16 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess) | |||
1244 | return; | 1244 | return; |
1245 | } | 1245 | } |
1246 | 1246 | ||
1247 | spin_lock_irqsave(&ha->tgt.sess_lock, flags); | ||
1247 | if (sess->deleted == QLA_SESS_DELETED) | 1248 | if (sess->deleted == QLA_SESS_DELETED) |
1248 | sess->logout_on_delete = 0; | 1249 | sess->logout_on_delete = 0; |
1249 | 1250 | ||
1250 | spin_lock_irqsave(&sess->vha->work_lock, flags); | ||
1251 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | 1251 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { |
1252 | spin_unlock_irqrestore(&sess->vha->work_lock, flags); | 1252 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); |
1253 | return; | 1253 | return; |
1254 | } | 1254 | } |
1255 | sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; | 1255 | sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; |
1256 | spin_unlock_irqrestore(&sess->vha->work_lock, flags); | 1256 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); |
1257 | 1257 | ||
1258 | sess->disc_state = DSC_DELETE_PEND; | 1258 | sess->disc_state = DSC_DELETE_PEND; |
1259 | 1259 | ||
@@ -1262,13 +1262,10 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess) | |||
1262 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, | 1262 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, |
1263 | "Scheduling sess %p for deletion\n", sess); | 1263 | "Scheduling sess %p for deletion\n", sess); |
1264 | 1264 | ||
1265 | /* use cancel to push work element through before re-queue */ | ||
1266 | cancel_work_sync(&sess->del_work); | ||
1267 | INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn); | 1265 | INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn); |
1268 | queue_work(sess->vha->hw->wq, &sess->del_work); | 1266 | WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work)); |
1269 | } | 1267 | } |
1270 | 1268 | ||
1271 | /* ha->tgt.sess_lock supposed to be held on entry */ | ||
1272 | static void qlt_clear_tgt_db(struct qla_tgt *tgt) | 1269 | static void qlt_clear_tgt_db(struct qla_tgt *tgt) |
1273 | { | 1270 | { |
1274 | struct fc_port *sess; | 1271 | struct fc_port *sess; |
@@ -1451,8 +1448,8 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) | |||
1451 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess); | 1448 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess); |
1452 | 1449 | ||
1453 | sess->local = 1; | 1450 | sess->local = 1; |
1454 | qlt_schedule_sess_for_deletion(sess); | ||
1455 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); | 1451 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); |
1452 | qlt_schedule_sess_for_deletion(sess); | ||
1456 | } | 1453 | } |
1457 | 1454 | ||
1458 | static inline int test_tgt_sess_count(struct qla_tgt *tgt) | 1455 | static inline int test_tgt_sess_count(struct qla_tgt *tgt) |
@@ -1512,10 +1509,8 @@ int qlt_stop_phase1(struct qla_tgt *tgt) | |||
1512 | * Lock is needed, because we still can get an incoming packet. | 1509 | * Lock is needed, because we still can get an incoming packet. |
1513 | */ | 1510 | */ |
1514 | mutex_lock(&vha->vha_tgt.tgt_mutex); | 1511 | mutex_lock(&vha->vha_tgt.tgt_mutex); |
1515 | spin_lock_irqsave(&ha->tgt.sess_lock, flags); | ||
1516 | tgt->tgt_stop = 1; | 1512 | tgt->tgt_stop = 1; |
1517 | qlt_clear_tgt_db(tgt); | 1513 | qlt_clear_tgt_db(tgt); |
1518 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); | ||
1519 | mutex_unlock(&vha->vha_tgt.tgt_mutex); | 1514 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
1520 | mutex_unlock(&qla_tgt_mutex); | 1515 | mutex_unlock(&qla_tgt_mutex); |
1521 | 1516 | ||