]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Subject: Open-FCoE bugfixes for fnic |
2 | From: Hannes Reinecke <hare@suse.de> | |
3 | Date: Fri Dec 5 16:40:29 2008 +0100: | |
4 | ||
5 | The fnic driver requires some bugfixes for the open-FCoE stack. | |
6 | ||
7 | Signed-off-by: Abhijeet Joglekar <abjoglek@cisco.com> | |
8 | Acked-by: Hannes Reinecke <hare@suse.de> | |
9 | ||
10 | diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c | |
11 | index 0cd8d0c..2b13e7b 100644 | |
12 | --- a/drivers/scsi/libfc/fc_disc.c | |
13 | +++ b/drivers/scsi/libfc/fc_disc.c | |
14 | @@ -101,12 +101,8 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport, | |
15 | } | |
16 | } | |
17 | ||
18 | - if (!disc_found) { | |
19 | - FC_DEBUG_DISC("The rport (%6x) for lport (%6x) " | |
20 | - "is not maintained by the discovery layer\n", | |
21 | - port_id, fc_host_port_id(lport->host)); | |
22 | + if (!disc_found) | |
23 | found = NULL; | |
24 | - } | |
25 | ||
26 | return found; | |
27 | } | |
28 | diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c | |
29 | index 12a1196..d81ed95 100644 | |
30 | --- a/drivers/scsi/libfc/fc_exch.c | |
31 | +++ b/drivers/scsi/libfc/fc_exch.c | |
32 | @@ -378,7 +378,6 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec) | |
33 | return -ENOMEM; | |
34 | } | |
35 | ||
36 | - sp->f_ctl |= FC_FC_SEQ_INIT; | |
37 | ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL; | |
38 | if (timer_msec) | |
39 | fc_exch_timer_set_locked(ep, timer_msec); | |
40 | @@ -466,7 +465,6 @@ static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id) | |
41 | ||
42 | sp = &ep->seq; | |
43 | sp->ssb_stat = 0; | |
44 | - sp->f_ctl = 0; | |
45 | sp->cnt = 0; | |
46 | sp->id = seq_id; | |
47 | return sp; | |
48 | @@ -530,7 +528,7 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp) | |
49 | struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, | |
50 | struct fc_frame *fp, u16 xid) | |
51 | { | |
52 | - struct fc_exch *ep = NULL; | |
53 | + struct fc_exch *ep; | |
54 | ||
55 | /* allocate memory for exchange */ | |
56 | ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC); | |
57 | @@ -834,8 +832,8 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) | |
58 | struct fc_exch *ep = fc_seq_exch(sp); | |
59 | ||
60 | sp = fc_seq_alloc(ep, ep->seq_id++); | |
61 | - FC_DEBUG_EXCH("exch %4x f_ctl %6x seq %2x f_ctl %6x\n", | |
62 | - ep->xid, ep->f_ctl, sp->id, sp->f_ctl); | |
63 | + FC_DEBUG_EXCH("exch %4x f_ctl %6x seq %2x\n", | |
64 | + ep->xid, ep->f_ctl, sp->id); | |
65 | return sp; | |
66 | } | |
67 | /* | |
68 | @@ -860,12 +858,13 @@ int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, struct fc_frame *fp) | |
69 | struct fc_exch *ep; | |
70 | struct fc_frame_header *fh = fc_frame_header_get(fp); | |
71 | int error; | |
72 | + u32 f_ctl; | |
73 | ||
74 | ep = fc_seq_exch(sp); | |
75 | WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT); | |
76 | ||
77 | - sp->f_ctl = ntoh24(fh->fh_f_ctl); | |
78 | - fc_exch_setup_hdr(ep, fp, sp->f_ctl); | |
79 | + f_ctl = ntoh24(fh->fh_f_ctl); | |
80 | + fc_exch_setup_hdr(ep, fp, f_ctl); | |
81 | ||
82 | /* | |
83 | * update sequence count if this frame is carrying | |
84 | @@ -889,9 +888,8 @@ int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, struct fc_frame *fp) | |
85 | * We can only be called to send once for each sequence. | |
86 | */ | |
87 | spin_lock_bh(&ep->ex_lock); | |
88 | - ep->f_ctl &= ~FC_FC_FIRST_SEQ; /* not first seq */ | |
89 | - sp->f_ctl &= ~FC_FC_FIRST_SEQ; /* not first seq */ | |
90 | - if (sp->f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT)) | |
91 | + ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ; /* not first seq */ | |
92 | + if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT)) | |
93 | ep->esb_stat &= ~ESB_ST_SEQ_INIT; | |
94 | spin_unlock_bh(&ep->ex_lock); | |
95 | return error; | |
96 | @@ -930,8 +928,9 @@ static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp, | |
97 | struct fc_exch *ep = fc_seq_exch(sp); | |
98 | ||
99 | f_ctl = FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; | |
100 | + f_ctl |= ep->f_ctl; | |
101 | fc_fill_fc_hdr(fp, rctl, ep->did, ep->sid, fh_type, f_ctl, 0); | |
102 | - fc_seq_send(fc_seq_exch(sp)->lp, sp, fp); | |
103 | + fc_seq_send(ep->lp, sp, fp); | |
104 | } | |
105 | ||
106 | /* | |
107 | @@ -952,7 +951,6 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) | |
108 | */ | |
109 | if (fc_sof_needs_ack(fr_sof(rx_fp))) { | |
110 | fp = fc_frame_alloc(lp, 0); | |
111 | - BUG_ON(!fp); | |
112 | if (!fp) | |
113 | return; | |
114 | ||
115 | @@ -1848,7 +1846,6 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, | |
116 | ep->r_a_tov = FC_DEF_R_A_TOV; | |
117 | ep->lp = lp; | |
118 | sp = &ep->seq; | |
119 | - WARN_ON((sp->f_ctl & FC_FC_END_SEQ) != 0); | |
120 | ||
121 | ep->fh_type = fh->fh_type; /* save for possbile timeout handling */ | |
122 | ep->f_ctl = ntoh24(fh->fh_f_ctl); | |
123 | @@ -1861,7 +1858,6 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, | |
124 | if (timer_msec) | |
125 | fc_exch_timer_set_locked(ep, timer_msec); | |
126 | ep->f_ctl &= ~FC_FC_FIRST_SEQ; /* not first seq */ | |
127 | - sp->f_ctl = ep->f_ctl; /* save for possible abort */ | |
128 | ||
129 | if (ep->f_ctl & FC_FC_SEQ_INIT) | |
130 | ep->esb_stat &= ~ESB_ST_SEQ_INIT; | |
131 | diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c | |
132 | index de16203..591d160 100644 | |
133 | --- a/drivers/scsi/libfc/fc_lport.c | |
134 | +++ b/drivers/scsi/libfc/fc_lport.c | |
135 | @@ -465,6 +465,56 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |
136 | } | |
137 | ||
138 | /** | |
139 | + * fc_lport_recv_adisc_req - Handle received Address Discovery Request | |
140 | + * @lport: Fibre Channel local port recieving the ADISC | |
141 | + * @sp: current sequence in the ADISC exchange | |
142 | + * @fp: ADISC request frame | |
143 | + * | |
144 | + * Locking Note: The lport lock is exected to be held before calling | |
145 | + * this function. | |
146 | + */ | |
147 | +static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, | |
148 | + struct fc_lport *lport) | |
149 | +{ | |
150 | + struct fc_frame *fp; | |
151 | + struct fc_exch *ep = fc_seq_exch(sp); | |
152 | + struct fc_els_adisc *req, *rp; | |
153 | + struct fc_seq_els_data rjt_data; | |
154 | + size_t len; | |
155 | + u32 f_ctl; | |
156 | + | |
157 | + FC_DEBUG_LPORT("Received ADISC request while in state %s\n", | |
158 | + fc_lport_state(lport)); | |
159 | + | |
160 | + req = fc_frame_payload_get(in_fp, sizeof(*req)); | |
161 | + if (!req) { | |
162 | + rjt_data.fp = NULL; | |
163 | + rjt_data.reason = ELS_RJT_LOGIC; | |
164 | + rjt_data.explan = ELS_EXPL_NONE; | |
165 | + lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | |
166 | + } else { | |
167 | + len = sizeof(*rp); | |
168 | + fp = fc_frame_alloc(lport, len); | |
169 | + if (fp) { | |
170 | + rp = fc_frame_payload_get(fp, len); | |
171 | + memset(rp, 0, len); | |
172 | + rp->adisc_cmd = ELS_LS_ACC; | |
173 | + rp->adisc_wwpn = htonll(lport->wwpn); | |
174 | + rp->adisc_wwnn = htonll(lport->wwnn); | |
175 | + hton24(rp->adisc_port_id, | |
176 | + fc_host_port_id(lport->host)); | |
177 | + sp = lport->tt.seq_start_next(sp); | |
178 | + f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; | |
179 | + f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; | |
180 | + fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | |
181 | + FC_TYPE_ELS, f_ctl, 0); | |
182 | + lport->tt.seq_send(lport, sp, fp); | |
183 | + } | |
184 | + } | |
185 | + fc_frame_free(in_fp); | |
186 | +} | |
187 | + | |
188 | +/** | |
189 | * fc_lport_recv_logo_req - Handle received fabric LOGO request | |
190 | * @lport: Fibre Channel local port recieving the LOGO | |
191 | * @sp: current sequence in the LOGO exchange | |
192 | @@ -821,6 +871,9 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | |
193 | case ELS_RNID: | |
194 | recv = fc_lport_recv_rnid_req; | |
195 | break; | |
196 | + case ELS_ADISC: | |
197 | + recv = fc_lport_recv_adisc_req; | |
198 | + break; | |
199 | } | |
200 | ||
201 | if (recv) | |
202 | diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c | |
203 | index d081af5..3ea7fc9 100644 | |
204 | --- a/drivers/scsi/libfc/fc_rport.c | |
205 | +++ b/drivers/scsi/libfc/fc_rport.c | |
206 | @@ -333,8 +333,12 @@ int fc_rport_logoff(struct fc_rport *rport) | |
207 | */ | |
208 | fc_rport_state_enter(rport, RPORT_ST_NONE); | |
209 | ||
210 | + mutex_unlock(&rdata->rp_mutex); | |
211 | + | |
212 | cancel_delayed_work_sync(&rdata->retry_work); | |
213 | ||
214 | + mutex_lock(&rdata->rp_mutex); | |
215 | + | |
216 | rdata->event = RPORT_EV_STOP; | |
217 | queue_work(rport_event_queue, &rdata->event_work); | |
218 | ||
219 | diff --git a/include/scsi/fc/fc_els.h b/include/scsi/fc/fc_els.h | |
220 | index af4bf0c..195ca01 100644 | |
221 | --- a/include/scsi/fc/fc_els.h | |
222 | +++ b/include/scsi/fc/fc_els.h | |
223 | @@ -401,6 +401,20 @@ struct fc_els_prli { | |
224 | }; | |
225 | ||
226 | /* | |
227 | + * ELS_ADISC payload | |
228 | + */ | |
229 | +struct fc_els_adisc { | |
230 | + __u8 adisc_cmd; | |
231 | + __u8 adisc_resv[3]; | |
232 | + __u8 adisc_resv1; | |
233 | + __u8 adisc_hard_addr[3]; | |
234 | + __be64 adisc_wwpn; | |
235 | + __be64 adisc_wwnn; | |
236 | + __u8 adisc_resv2; | |
237 | + __u8 adisc_port_id[3]; | |
238 | +} __attribute__((__packed__)); | |
239 | + | |
240 | +/* | |
241 | * ELS_LOGO - process or fabric logout. | |
242 | */ | |
243 | struct fc_els_logo { | |
244 | diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h | |
245 | index 587be50..a7095cb 100644 | |
246 | --- a/include/scsi/libfc.h | |
247 | +++ b/include/scsi/libfc.h | |
248 | @@ -287,7 +287,6 @@ struct fc_seq { | |
249 | u8 id; /* seq ID */ | |
250 | u16 ssb_stat; /* status flags for sequence status block */ | |
251 | u16 cnt; /* frames sent so far on sequence */ | |
252 | - u32 f_ctl; /* F_CTL flags for frames */ | |
253 | u32 rec_data; /* FC-4 value for REC */ | |
254 | }; | |
255 |