]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/scsi/bfa/loop.c
Merge branch 'twl4030-mfd' into for-2.6.33
[mv-sheeva.git] / drivers / scsi / bfa / loop.c
1 /*
2  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 /**
19  *  port_loop.c vport private loop implementation.
20  */
21 #include <bfa.h>
22 #include <bfa_svc.h>
23 #include "fcs_lport.h"
24 #include "fcs_rport.h"
25 #include "fcs_trcmod.h"
26 #include "lport_priv.h"
27
28 BFA_TRC_FILE(FCS, LOOP);
29
30 /**
31  *   ALPA to LIXA bitmap mapping
32  *
33  *   ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
34  * is for L_bit (login required) and is filled as ALPA 0x00 here.
35  */
36 static const u8   port_loop_alpa_map[] = {
37         0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, /* Word 3 Bits 0..7 */
38         0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, /* Word 3 Bits 8..15 */
39         0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5, /* Word 3 Bits 16..23 */
40         0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3, /* Word 3 Bits 24..31 */
41
42         0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, /* Word 2 Bits 0..7 */
43         0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, /* Word 2 Bits 8..15 */
44         0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, /* Word 2 Bits 16..23 */
45         0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73, /* Word 2 Bits 24..31 */
46
47         0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, /* Word 1 Bits 0..7 */
48         0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, /* Word 1 Bits 8..15 */
49         0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, /* Word 1 Bits 16..23 */
50         0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, /* Word 1 Bits 24..31 */
51
52         0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, /* Word 0 Bits 0..7 */
53         0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26, /* Word 0 Bits 8..15 */
54         0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, /* Word 0 Bits 16..23 */
55         0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, /* Word 0 Bits 24..31 */
56 };
57
58 /*
59  * Local Functions
60  */
61 bfa_status_t    bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
62                                              u8 alpa);
63
64 void            bfa_fcs_port_loop_plogi_response(void *fcsarg,
65                                                  struct bfa_fcxp_s *fcxp,
66                                                  void *cbarg,
67                                                  bfa_status_t req_status,
68                                                  u32 rsp_len,
69                                                  u32 resid_len,
70                                                  struct fchs_s *rsp_fchs);
71
72 bfa_status_t    bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port,
73                                              u8 alpa);
74
75 void            bfa_fcs_port_loop_adisc_response(void *fcsarg,
76                                                  struct bfa_fcxp_s *fcxp,
77                                                  void *cbarg,
78                                                  bfa_status_t req_status,
79                                                  u32 rsp_len,
80                                                  u32 resid_len,
81                                                  struct fchs_s *rsp_fchs);
82
83 bfa_status_t    bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port,
84                                                  u8 alpa);
85
86 void            bfa_fcs_port_loop_plogi_acc_response(void *fcsarg,
87                                                      struct bfa_fcxp_s *fcxp,
88                                                      void *cbarg,
89                                                      bfa_status_t req_status,
90                                                      u32 rsp_len,
91                                                      u32 resid_len,
92                                                      struct fchs_s *rsp_fchs);
93
94 bfa_status_t    bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port,
95                                                  u8 alpa);
96
97 void            bfa_fcs_port_loop_adisc_acc_response(void *fcsarg,
98                                                      struct bfa_fcxp_s *fcxp,
99                                                      void *cbarg,
100                                                      bfa_status_t req_status,
101                                                      u32 rsp_len,
102                                                      u32 resid_len,
103                                                      struct fchs_s *rsp_fchs);
104 /**
105  *   Called by port to initializar in provate LOOP topology.
106  */
107 void
108 bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port)
109 {
110 }
111
112 /**
113  *   Called by port to notify transition to online state.
114  */
115 void
116 bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port)
117 {
118
119         u8         num_alpa = port->port_topo.ploop.num_alpa;
120         u8        *alpa_pos_map = port->port_topo.ploop.alpa_pos_map;
121         struct bfa_fcs_rport_s *r_port;
122         int             ii = 0;
123
124         /*
125          * If the port role is Initiator Mode, create Rports.
126          */
127         if (port->port_cfg.roles == BFA_PORT_ROLE_FCP_IM) {
128                 /*
129                  * Check if the ALPA positional bitmap is available.
130                  * if not, we send PLOGI to all possible ALPAs.
131                  */
132                 if (num_alpa > 0) {
133                         for (ii = 0; ii < num_alpa; ii++) {
134                                 /*
135                                  * ignore ALPA of bfa port
136                                  */
137                                 if (alpa_pos_map[ii] != port->pid) {
138                                         r_port = bfa_fcs_rport_create(port,
139                                                 alpa_pos_map[ii]);
140                                 }
141                         }
142                 } else {
143                         for (ii = 0; ii < MAX_ALPA_COUNT; ii++) {
144                                 /*
145                                  * ignore ALPA of bfa port
146                                  */
147                                 if ((port_loop_alpa_map[ii] > 0)
148                                     && (port_loop_alpa_map[ii] != port->pid))
149                                         bfa_fcs_port_loop_send_plogi(port,
150                                                 port_loop_alpa_map[ii]);
151                                 /**TBD */
152                         }
153                 }
154         } else {
155                 /*
156                  * TBD Target Mode ??
157                  */
158         }
159
160 }
161
162 /**
163  *   Called by port to notify transition to offline state.
164  */
165 void
166 bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port)
167 {
168
169 }
170
171 /**
172  *   Called by port to notify a LIP on the loop.
173  */
174 void
175 bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port)
176 {
177 }
178
179 /**
180  * Local Functions.
181  */
182 bfa_status_t
183 bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
184 {
185         struct fchs_s          fchs;
186         struct bfa_fcxp_s *fcxp = NULL;
187         int             len;
188
189         bfa_trc(port->fcs, alpa);
190
191         fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
192                                   NULL);
193         bfa_assert(fcxp);
194
195         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
196                              bfa_fcs_port_get_fcid(port), 0,
197                              port->port_cfg.pwwn, port->port_cfg.nwwn,
198                                  bfa_pport_get_maxfrsize(port->fcs->bfa));
199
200         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
201                           FC_CLASS_3, len, &fchs,
202                           bfa_fcs_port_loop_plogi_response, (void *)port,
203                           FC_MAX_PDUSZ, FC_RA_TOV);
204
205         return BFA_STATUS_OK;
206 }
207
208 /**
209  *   Called by fcxp to notify the Plogi response
210  */
211 void
212 bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
213                                  void *cbarg, bfa_status_t req_status,
214                                  u32 rsp_len, u32 resid_len,
215                                  struct fchs_s *rsp_fchs)
216 {
217         struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
218         struct fc_logi_s     *plogi_resp;
219         struct fc_els_cmd_s   *els_cmd;
220
221         bfa_trc(port->fcs, req_status);
222
223         /*
224          * Sanity Checks
225          */
226         if (req_status != BFA_STATUS_OK) {
227                 bfa_trc(port->fcs, req_status);
228                 /*
229                  * @todo
230                  * This could mean that the device with this APLA does not
231                  * exist on the loop.
232                  */
233
234                 return;
235         }
236
237         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
238         plogi_resp = (struct fc_logi_s *) els_cmd;
239
240         if (els_cmd->els_code == FC_ELS_ACC) {
241                 bfa_fcs_rport_start(port, rsp_fchs, plogi_resp);
242         } else {
243                 bfa_trc(port->fcs, plogi_resp->els_cmd.els_code);
244                 bfa_assert(0);
245         }
246 }
247
248 bfa_status_t
249 bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port, u8 alpa)
250 {
251         struct fchs_s          fchs;
252         struct bfa_fcxp_s *fcxp;
253         int             len;
254
255         bfa_trc(port->fcs, alpa);
256
257         fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
258                                   NULL);
259         bfa_assert(fcxp);
260
261         len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
262                                  bfa_fcs_port_get_fcid(port), 0,
263                                  port->port_cfg.pwwn, port->port_cfg.nwwn,
264                                  bfa_pport_get_maxfrsize(port->fcs->bfa));
265
266         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
267                                  FC_CLASS_3, len, &fchs,
268                                  bfa_fcs_port_loop_plogi_acc_response,
269                                  (void *)port, FC_MAX_PDUSZ, 0); /* No response
270                                                                   * expected
271                                                                   */
272
273         return BFA_STATUS_OK;
274 }
275
276 /*
277  *  Plogi Acc Response
278  * We donot do any processing here.
279  */
280 void
281 bfa_fcs_port_loop_plogi_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
282                                      void *cbarg, bfa_status_t req_status,
283                                      u32 rsp_len, u32 resid_len,
284                                      struct fchs_s *rsp_fchs)
285 {
286
287         struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
288
289         bfa_trc(port->fcs, port->pid);
290
291         /*
292          * Sanity Checks
293          */
294         if (req_status != BFA_STATUS_OK) {
295                 bfa_trc(port->fcs, req_status);
296                 return;
297         }
298 }
299
300 bfa_status_t
301 bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port, u8 alpa)
302 {
303         struct fchs_s          fchs;
304         struct bfa_fcxp_s *fcxp;
305         int             len;
306
307         bfa_trc(port->fcs, alpa);
308
309         fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
310                                   NULL);
311         bfa_assert(fcxp);
312
313         len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
314                              bfa_fcs_port_get_fcid(port), 0,
315                              port->port_cfg.pwwn, port->port_cfg.nwwn);
316
317         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
318                           FC_CLASS_3, len, &fchs,
319                           bfa_fcs_port_loop_adisc_response, (void *)port,
320                           FC_MAX_PDUSZ, FC_RA_TOV);
321
322         return BFA_STATUS_OK;
323 }
324
325 /**
326  *   Called by fcxp to notify the ADISC response
327  */
328 void
329 bfa_fcs_port_loop_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
330                                  void *cbarg, bfa_status_t req_status,
331                                  u32 rsp_len, u32 resid_len,
332                                  struct fchs_s *rsp_fchs)
333 {
334         struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
335         struct bfa_fcs_rport_s *rport;
336         struct fc_adisc_s     *adisc_resp;
337         struct fc_els_cmd_s   *els_cmd;
338         u32        pid = rsp_fchs->s_id;
339
340         bfa_trc(port->fcs, req_status);
341
342         /*
343          * Sanity Checks
344          */
345         if (req_status != BFA_STATUS_OK) {
346                 /*
347                  * TBD : we may need to retry certain requests
348                  */
349                 bfa_fcxp_free(fcxp);
350                 return;
351         }
352
353         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
354         adisc_resp = (struct fc_adisc_s *) els_cmd;
355
356         if (els_cmd->els_code == FC_ELS_ACC) {
357         } else {
358                 bfa_trc(port->fcs, adisc_resp->els_cmd.els_code);
359
360                 /*
361                  * TBD: we may need to check for reject codes and retry
362                  */
363                 rport = bfa_fcs_port_get_rport_by_pid(port, pid);
364                 if (rport) {
365                         list_del(&rport->qe);
366                         bfa_fcs_rport_delete(rport);
367                 }
368
369         }
370         return;
371 }
372
373 bfa_status_t
374 bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port, u8 alpa)
375 {
376         struct fchs_s          fchs;
377         struct bfa_fcxp_s *fcxp;
378         int             len;
379
380         bfa_trc(port->fcs, alpa);
381
382         fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
383                                   NULL);
384         bfa_assert(fcxp);
385
386         len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
387                                  bfa_fcs_port_get_fcid(port), 0,
388                                  port->port_cfg.pwwn, port->port_cfg.nwwn);
389
390         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
391                                 FC_CLASS_3, len, &fchs,
392                                 bfa_fcs_port_loop_adisc_acc_response,
393                                 (void *)port, FC_MAX_PDUSZ, 0); /* no reponse
394                                                                  * expected
395                                                                  */
396
397         return BFA_STATUS_OK;
398 }
399
400 /*
401  *  Adisc Acc Response
402  * We donot do any processing here.
403  */
404 void
405 bfa_fcs_port_loop_adisc_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
406                                      void *cbarg, bfa_status_t req_status,
407                                      u32 rsp_len, u32 resid_len,
408                                      struct fchs_s *rsp_fchs)
409 {
410
411         struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
412
413         bfa_trc(port->fcs, port->pid);
414
415         /*
416          * Sanity Checks
417          */
418         if (req_status != BFA_STATUS_OK) {
419                 bfa_trc(port->fcs, req_status);
420                 return;
421         }
422 }