]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/open-fcoe-fnic-patches
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / open-fcoe-fnic-patches
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