diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_disc.c')
-rw-r--r-- | drivers/scsi/libfc/fc_disc.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 44806307f831..4c880656990b 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c | |||
@@ -113,6 +113,11 @@ void fc_disc_stop_rports(struct fc_disc *disc) | |||
113 | lport->tt.rport_logoff(rport); | 113 | lport->tt.rport_logoff(rport); |
114 | } | 114 | } |
115 | 115 | ||
116 | list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) { | ||
117 | rport = PRIV_TO_RPORT(rdata); | ||
118 | lport->tt.rport_logoff(rport); | ||
119 | } | ||
120 | |||
116 | mutex_unlock(&disc->disc_mutex); | 121 | mutex_unlock(&disc->disc_mutex); |
117 | } | 122 | } |
118 | 123 | ||
@@ -131,23 +136,32 @@ static void fc_disc_rport_callback(struct fc_lport *lport, | |||
131 | { | 136 | { |
132 | struct fc_rport_libfc_priv *rdata = rport->dd_data; | 137 | struct fc_rport_libfc_priv *rdata = rport->dd_data; |
133 | struct fc_disc *disc = &lport->disc; | 138 | struct fc_disc *disc = &lport->disc; |
134 | int found = 0; | ||
135 | 139 | ||
136 | FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event, | 140 | FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event, |
137 | rport->port_id); | 141 | rport->port_id); |
138 | 142 | ||
139 | if (event == RPORT_EV_CREATED) { | 143 | switch (event) { |
144 | case RPORT_EV_CREATED: | ||
140 | if (disc) { | 145 | if (disc) { |
141 | found = 1; | ||
142 | mutex_lock(&disc->disc_mutex); | 146 | mutex_lock(&disc->disc_mutex); |
143 | list_add_tail(&rdata->peers, &disc->rports); | 147 | list_add_tail(&rdata->peers, &disc->rports); |
144 | mutex_unlock(&disc->disc_mutex); | 148 | mutex_unlock(&disc->disc_mutex); |
145 | } | 149 | } |
150 | break; | ||
151 | case RPORT_EV_LOGO: | ||
152 | case RPORT_EV_FAILED: | ||
153 | case RPORT_EV_STOP: | ||
154 | mutex_lock(&disc->disc_mutex); | ||
155 | mutex_lock(&rdata->rp_mutex); | ||
156 | if (rdata->trans_state == FC_PORTSTATE_ROGUE) | ||
157 | list_del(&rdata->peers); | ||
158 | mutex_unlock(&rdata->rp_mutex); | ||
159 | mutex_unlock(&disc->disc_mutex); | ||
160 | break; | ||
161 | default: | ||
162 | break; | ||
146 | } | 163 | } |
147 | 164 | ||
148 | if (!found) | ||
149 | FC_DEBUG_DISC("The rport (%6x) is not maintained " | ||
150 | "by the discovery layer\n", rport->port_id); | ||
151 | } | 165 | } |
152 | 166 | ||
153 | /** | 167 | /** |
@@ -439,6 +453,7 @@ static int fc_disc_new_target(struct fc_disc *disc, | |||
439 | rdata = rport->dd_data; | 453 | rdata = rport->dd_data; |
440 | rdata->ops = &fc_disc_rport_ops; | 454 | rdata->ops = &fc_disc_rport_ops; |
441 | rdata->rp_state = RPORT_ST_INIT; | 455 | rdata->rp_state = RPORT_ST_INIT; |
456 | list_add_tail(&rdata->peers, &disc->rogue_rports); | ||
442 | lport->tt.rport_login(rport); | 457 | lport->tt.rport_login(rport); |
443 | } | 458 | } |
444 | } | 459 | } |
@@ -630,6 +645,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) | |||
630 | rdata = rport->dd_data; | 645 | rdata = rport->dd_data; |
631 | rdata->ops = &fc_disc_rport_ops; | 646 | rdata->ops = &fc_disc_rport_ops; |
632 | rdata->local_port = lport; | 647 | rdata->local_port = lport; |
648 | list_add_tail(&rdata->peers, | ||
649 | &disc->rogue_rports); | ||
633 | lport->tt.rport_login(rport); | 650 | lport->tt.rport_login(rport); |
634 | } else | 651 | } else |
635 | FC_DBG("Failed to allocate memory for " | 652 | FC_DBG("Failed to allocate memory for " |
@@ -769,7 +786,6 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
769 | static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) | 786 | static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) |
770 | { | 787 | { |
771 | struct fc_lport *lport; | 788 | struct fc_lport *lport; |
772 | struct fc_rport *rport; | ||
773 | struct fc_rport *new_rport; | 789 | struct fc_rport *new_rport; |
774 | struct fc_rport_libfc_priv *rdata; | 790 | struct fc_rport_libfc_priv *rdata; |
775 | 791 | ||
@@ -778,15 +794,12 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) | |||
778 | if (dp->ids.port_id == fc_host_port_id(lport->host)) | 794 | if (dp->ids.port_id == fc_host_port_id(lport->host)) |
779 | goto out; | 795 | goto out; |
780 | 796 | ||
781 | rport = lport->tt.rport_lookup(lport, dp->ids.port_id); | ||
782 | if (rport) | ||
783 | fc_disc_del_target(disc, rport); | ||
784 | |||
785 | new_rport = lport->tt.rport_create(dp); | 797 | new_rport = lport->tt.rport_create(dp); |
786 | if (new_rport) { | 798 | if (new_rport) { |
787 | rdata = new_rport->dd_data; | 799 | rdata = new_rport->dd_data; |
788 | rdata->ops = &fc_disc_rport_ops; | 800 | rdata->ops = &fc_disc_rport_ops; |
789 | kfree(dp); | 801 | kfree(dp); |
802 | list_add_tail(&rdata->peers, &disc->rogue_rports); | ||
790 | lport->tt.rport_login(new_rport); | 803 | lport->tt.rport_login(new_rport); |
791 | } | 804 | } |
792 | return; | 805 | return; |
@@ -848,6 +861,7 @@ int fc_disc_init(struct fc_lport *lport) | |||
848 | INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout); | 861 | INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout); |
849 | mutex_init(&disc->disc_mutex); | 862 | mutex_init(&disc->disc_mutex); |
850 | INIT_LIST_HEAD(&disc->rports); | 863 | INIT_LIST_HEAD(&disc->rports); |
864 | INIT_LIST_HEAD(&disc->rogue_rports); | ||
851 | 865 | ||
852 | disc->lport = lport; | 866 | disc->lport = lport; |
853 | disc->delay = FC_DISC_DELAY; | 867 | disc->delay = FC_DISC_DELAY; |