Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.33 373 lines 9.8 kB view raw
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 * rport_ftrs.c Remote port features (RPF) implementation. 20 */ 21 22#include <bfa.h> 23#include <bfa_svc.h> 24#include "fcbuild.h" 25#include "fcs_rport.h" 26#include "fcs_lport.h" 27#include "fcs_trcmod.h" 28#include "fcs_fcxp.h" 29#include "fcs.h" 30 31BFA_TRC_FILE(FCS, RPORT_FTRS); 32 33#define BFA_FCS_RPF_RETRIES (3) 34#define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */ 35 36static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg, 37 struct bfa_fcxp_s *fcxp_alloced); 38static void bfa_fcs_rpf_rpsc2_response(void *fcsarg, 39 struct bfa_fcxp_s *fcxp, void *cbarg, 40 bfa_status_t req_status, u32 rsp_len, 41 u32 resid_len, 42 struct fchs_s *rsp_fchs); 43static void bfa_fcs_rpf_timeout(void *arg); 44 45/** 46 * fcs_rport_ftrs_sm FCS rport state machine events 47 */ 48 49enum rpf_event { 50 RPFSM_EVENT_RPORT_OFFLINE = 1, /* Rport offline */ 51 RPFSM_EVENT_RPORT_ONLINE = 2, /* Rport online */ 52 RPFSM_EVENT_FCXP_SENT = 3, /* Frame from has been sent */ 53 RPFSM_EVENT_TIMEOUT = 4, /* Rport SM timeout event */ 54 RPFSM_EVENT_RPSC_COMP = 5, 55 RPFSM_EVENT_RPSC_FAIL = 6, 56 RPFSM_EVENT_RPSC_ERROR = 7, 57}; 58 59static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, 60 enum rpf_event event); 61static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, 62 enum rpf_event event); 63static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, 64 enum rpf_event event); 65static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, 66 enum rpf_event event); 67static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, 68 enum rpf_event event); 69static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, 70 enum rpf_event event); 71 72static void 73bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) 74{ 75 struct bfa_fcs_rport_s *rport = rpf->rport; 76 77 bfa_trc(rport->fcs, rport->pwwn); 78 bfa_trc(rport->fcs, rport->pid); 79 bfa_trc(rport->fcs, event); 80 81 switch (event) { 82 case RPFSM_EVENT_RPORT_ONLINE: 83 if (!BFA_FCS_PID_IS_WKA(rport->pid)) { 84 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); 85 rpf->rpsc_retries = 0; 86 bfa_fcs_rpf_send_rpsc2(rpf, NULL); 87 break; 88 }; 89 90 case RPFSM_EVENT_RPORT_OFFLINE: 91 break; 92 93 default: 94 bfa_assert(0); 95 } 96} 97 98static void 99bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) 100{ 101 struct bfa_fcs_rport_s *rport = rpf->rport; 102 103 bfa_trc(rport->fcs, event); 104 105 switch (event) { 106 case RPFSM_EVENT_FCXP_SENT: 107 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc); 108 break; 109 110 case RPFSM_EVENT_RPORT_OFFLINE: 111 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); 112 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe); 113 rpf->rpsc_retries = 0; 114 break; 115 116 default: 117 bfa_assert(0); 118 } 119} 120 121static void 122bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) 123{ 124 struct bfa_fcs_rport_s *rport = rpf->rport; 125 126 bfa_trc(rport->fcs, rport->pid); 127 bfa_trc(rport->fcs, event); 128 129 switch (event) { 130 case RPFSM_EVENT_RPSC_COMP: 131 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); 132 /* Update speed info in f/w via BFA */ 133 if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) 134 bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed); 135 else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) 136 bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed); 137 break; 138 139 case RPFSM_EVENT_RPSC_FAIL: 140 /* RPSC not supported by rport */ 141 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); 142 break; 143 144 case RPFSM_EVENT_RPSC_ERROR: 145 /* need to retry...delayed a bit. */ 146 if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) { 147 bfa_timer_start(rport->fcs->bfa, &rpf->timer, 148 bfa_fcs_rpf_timeout, rpf, 149 BFA_FCS_RPF_RETRY_TIMEOUT); 150 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry); 151 } else { 152 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); 153 } 154 break; 155 156 case RPFSM_EVENT_RPORT_OFFLINE: 157 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); 158 bfa_fcxp_discard(rpf->fcxp); 159 rpf->rpsc_retries = 0; 160 break; 161 162 default: 163 bfa_assert(0); 164 } 165} 166 167static void 168bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) 169{ 170 struct bfa_fcs_rport_s *rport = rpf->rport; 171 172 bfa_trc(rport->fcs, rport->pid); 173 bfa_trc(rport->fcs, event); 174 175 switch (event) { 176 case RPFSM_EVENT_TIMEOUT: 177 /* re-send the RPSC */ 178 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); 179 bfa_fcs_rpf_send_rpsc2(rpf, NULL); 180 break; 181 182 case RPFSM_EVENT_RPORT_OFFLINE: 183 bfa_timer_stop(&rpf->timer); 184 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); 185 rpf->rpsc_retries = 0; 186 break; 187 188 default: 189 bfa_assert(0); 190 } 191} 192 193static void 194bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) 195{ 196 struct bfa_fcs_rport_s *rport = rpf->rport; 197 198 bfa_trc(rport->fcs, rport->pwwn); 199 bfa_trc(rport->fcs, rport->pid); 200 bfa_trc(rport->fcs, event); 201 202 switch (event) { 203 case RPFSM_EVENT_RPORT_OFFLINE: 204 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); 205 rpf->rpsc_retries = 0; 206 break; 207 208 default: 209 bfa_assert(0); 210 } 211} 212 213static void 214bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) 215{ 216 struct bfa_fcs_rport_s *rport = rpf->rport; 217 218 bfa_trc(rport->fcs, rport->pwwn); 219 bfa_trc(rport->fcs, rport->pid); 220 bfa_trc(rport->fcs, event); 221 222 switch (event) { 223 case RPFSM_EVENT_RPORT_ONLINE: 224 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); 225 bfa_fcs_rpf_send_rpsc2(rpf, NULL); 226 break; 227 228 case RPFSM_EVENT_RPORT_OFFLINE: 229 break; 230 231 default: 232 bfa_assert(0); 233 } 234} 235/** 236 * Called when Rport is created. 237 */ 238void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport) 239{ 240 struct bfa_fcs_rpf_s *rpf = &rport->rpf; 241 242 bfa_trc(rport->fcs, rport->pid); 243 rpf->rport = rport; 244 245 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit); 246} 247 248/** 249 * Called when Rport becomes online 250 */ 251void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport) 252{ 253 bfa_trc(rport->fcs, rport->pid); 254 255 if (__fcs_min_cfg(rport->port->fcs)) 256 return; 257 258 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) 259 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE); 260} 261 262/** 263 * Called when Rport becomes offline 264 */ 265void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport) 266{ 267 bfa_trc(rport->fcs, rport->pid); 268 269 if (__fcs_min_cfg(rport->port->fcs)) 270 return; 271 272 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE); 273} 274 275static void 276bfa_fcs_rpf_timeout(void *arg) 277{ 278 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg; 279 struct bfa_fcs_rport_s *rport = rpf->rport; 280 281 bfa_trc(rport->fcs, rport->pid); 282 bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT); 283} 284 285static void 286bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced) 287{ 288 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg; 289 struct bfa_fcs_rport_s *rport = rpf->rport; 290 struct bfa_fcs_port_s *port = rport->port; 291 struct fchs_s fchs; 292 int len; 293 struct bfa_fcxp_s *fcxp; 294 295 bfa_trc(rport->fcs, rport->pwwn); 296 297 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); 298 if (!fcxp) { 299 bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe, 300 bfa_fcs_rpf_send_rpsc2, rpf); 301 return; 302 } 303 rpf->fcxp = fcxp; 304 305 len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, 306 bfa_fcs_port_get_fcid(port), &rport->pid, 1); 307 308 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, 309 FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response, 310 rpf, FC_MAX_PDUSZ, FC_RA_TOV); 311 rport->stats.rpsc_sent++; 312 bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT); 313 314} 315 316static void 317bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, 318 bfa_status_t req_status, u32 rsp_len, 319 u32 resid_len, struct fchs_s *rsp_fchs) 320{ 321 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg; 322 struct bfa_fcs_rport_s *rport = rpf->rport; 323 struct fc_ls_rjt_s *ls_rjt; 324 struct fc_rpsc2_acc_s *rpsc2_acc; 325 u16 num_ents; 326 327 bfa_trc(rport->fcs, req_status); 328 329 if (req_status != BFA_STATUS_OK) { 330 bfa_trc(rport->fcs, req_status); 331 if (req_status == BFA_STATUS_ETIMER) 332 rport->stats.rpsc_failed++; 333 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR); 334 return; 335 } 336 337 rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp); 338 if (rpsc2_acc->els_cmd == FC_ELS_ACC) { 339 rport->stats.rpsc_accs++; 340 num_ents = bfa_os_ntohs(rpsc2_acc->num_pids); 341 bfa_trc(rport->fcs, num_ents); 342 if (num_ents > 0) { 343 bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid); 344 bfa_trc(rport->fcs, 345 bfa_os_ntohs(rpsc2_acc->port_info[0].pid)); 346 bfa_trc(rport->fcs, 347 bfa_os_ntohs(rpsc2_acc->port_info[0].speed)); 348 bfa_trc(rport->fcs, 349 bfa_os_ntohs(rpsc2_acc->port_info[0].index)); 350 bfa_trc(rport->fcs, 351 rpsc2_acc->port_info[0].type); 352 353 if (rpsc2_acc->port_info[0].speed == 0) { 354 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR); 355 return; 356 } 357 358 rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed( 359 bfa_os_ntohs(rpsc2_acc->port_info[0].speed)); 360 361 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP); 362 } 363 } else { 364 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); 365 bfa_trc(rport->fcs, ls_rjt->reason_code); 366 bfa_trc(rport->fcs, ls_rjt->reason_code_expl); 367 rport->stats.rpsc_rejects++; 368 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) 369 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL); 370 else 371 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR); 372 } 373}