root/drivers/scsi/bfa/bfa_fcs_fcpim.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bfa_fcs_itnim_sm_offline
  2. bfa_fcs_itnim_sm_prli_send
  3. bfa_fcs_itnim_sm_prli
  4. bfa_fcs_itnim_sm_hal_rport_online
  5. bfa_fcs_itnim_sm_prli_retry
  6. bfa_fcs_itnim_sm_hcb_online
  7. bfa_fcs_itnim_sm_online
  8. bfa_fcs_itnim_sm_hcb_offline
  9. bfa_fcs_itnim_sm_initiator
  10. bfa_fcs_itnim_aen_post
  11. bfa_fcs_itnim_send_prli
  12. bfa_fcs_itnim_prli_response
  13. bfa_fcs_itnim_timeout
  14. bfa_fcs_itnim_free
  15. bfa_fcs_itnim_create
  16. bfa_fcs_itnim_delete
  17. bfa_fcs_itnim_brp_online
  18. bfa_fcs_itnim_rport_offline
  19. bfa_fcs_itnim_is_initiator
  20. bfa_fcs_itnim_get_online_state
  21. bfa_cb_itnim_online
  22. bfa_cb_itnim_offline
  23. bfa_cb_itnim_tov_begin
  24. bfa_cb_itnim_tov
  25. bfa_cb_itnim_sler
  26. bfa_fcs_itnim_lookup
  27. bfa_fcs_itnim_attr_get
  28. bfa_fcs_itnim_stats_get
  29. bfa_fcs_itnim_stats_clear
  30. bfa_fcs_fcpim_uf_recv

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
   4  * Copyright (c) 2014- QLogic Corporation.
   5  * All rights reserved
   6  * www.qlogic.com
   7  *
   8  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
   9  */
  10 
  11 /*
  12  *  fcpim.c - FCP initiator mode i-t nexus state machine
  13  */
  14 
  15 #include "bfad_drv.h"
  16 #include "bfa_fcs.h"
  17 #include "bfa_fcbuild.h"
  18 #include "bfad_im.h"
  19 
  20 BFA_TRC_FILE(FCS, FCPIM);
  21 
  22 /*
  23  * forward declarations
  24  */
  25 static void     bfa_fcs_itnim_timeout(void *arg);
  26 static void     bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
  27 static void     bfa_fcs_itnim_send_prli(void *itnim_cbarg,
  28                                         struct bfa_fcxp_s *fcxp_alloced);
  29 static void     bfa_fcs_itnim_prli_response(void *fcsarg,
  30                          struct bfa_fcxp_s *fcxp, void *cbarg,
  31                             bfa_status_t req_status, u32 rsp_len,
  32                             u32 resid_len, struct fchs_s *rsp_fchs);
  33 static void     bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
  34                         enum bfa_itnim_aen_event event);
  35 
  36 static void     bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
  37                                          enum bfa_fcs_itnim_event event);
  38 static void     bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
  39                                            enum bfa_fcs_itnim_event event);
  40 static void     bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
  41                                       enum bfa_fcs_itnim_event event);
  42 static void     bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
  43                                             enum bfa_fcs_itnim_event event);
  44 static void     bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
  45                                             enum bfa_fcs_itnim_event event);
  46 static void     bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
  47                                         enum bfa_fcs_itnim_event event);
  48 static void     bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
  49                                         enum bfa_fcs_itnim_event event);
  50 static void     bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
  51                                              enum bfa_fcs_itnim_event event);
  52 static void     bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
  53                                            enum bfa_fcs_itnim_event event);
  54 
  55 static struct bfa_sm_table_s itnim_sm_table[] = {
  56         {BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
  57         {BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
  58         {BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
  59         {BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
  60         {BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
  61         {BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
  62         {BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
  63         {BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
  64 };
  65 
  66 /*
  67  *  fcs_itnim_sm FCS itnim state machine
  68  */
  69 
  70 static void
  71 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
  72                  enum bfa_fcs_itnim_event event)
  73 {
  74         bfa_trc(itnim->fcs, itnim->rport->pwwn);
  75         bfa_trc(itnim->fcs, event);
  76 
  77         switch (event) {
  78         case BFA_FCS_ITNIM_SM_FCS_ONLINE:
  79                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
  80                 itnim->prli_retries = 0;
  81                 bfa_fcs_itnim_send_prli(itnim, NULL);
  82                 break;
  83 
  84         case BFA_FCS_ITNIM_SM_OFFLINE:
  85                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  86                 break;
  87 
  88         case BFA_FCS_ITNIM_SM_INITIATOR:
  89                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
  90                 break;
  91 
  92         case BFA_FCS_ITNIM_SM_DELETE:
  93                 bfa_fcs_itnim_free(itnim);
  94                 break;
  95 
  96         default:
  97                 bfa_sm_fault(itnim->fcs, event);
  98         }
  99 
 100 }
 101 
 102 static void
 103 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
 104                  enum bfa_fcs_itnim_event event)
 105 {
 106         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 107         bfa_trc(itnim->fcs, event);
 108 
 109         switch (event) {
 110         case BFA_FCS_ITNIM_SM_FRMSENT:
 111                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
 112                 break;
 113 
 114         case BFA_FCS_ITNIM_SM_INITIATOR:
 115                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
 116                 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
 117                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
 118                 break;
 119 
 120         case BFA_FCS_ITNIM_SM_OFFLINE:
 121                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 122                 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
 123                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 124                 break;
 125 
 126         case BFA_FCS_ITNIM_SM_DELETE:
 127                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 128                 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
 129                 bfa_fcs_itnim_free(itnim);
 130                 break;
 131 
 132         default:
 133                 bfa_sm_fault(itnim->fcs, event);
 134         }
 135 }
 136 
 137 static void
 138 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
 139                  enum bfa_fcs_itnim_event event)
 140 {
 141         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 142         bfa_trc(itnim->fcs, event);
 143 
 144         switch (event) {
 145         case BFA_FCS_ITNIM_SM_RSP_OK:
 146                 if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)
 147                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
 148                 else
 149                         bfa_sm_set_state(itnim,
 150                                 bfa_fcs_itnim_sm_hal_rport_online);
 151 
 152                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
 153                 break;
 154 
 155         case BFA_FCS_ITNIM_SM_RSP_ERROR:
 156                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
 157                 bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
 158                                 bfa_fcs_itnim_timeout, itnim,
 159                                 BFA_FCS_RETRY_TIMEOUT);
 160                 break;
 161 
 162         case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
 163                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 164                 break;
 165 
 166         case BFA_FCS_ITNIM_SM_OFFLINE:
 167                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 168                 bfa_fcxp_discard(itnim->fcxp);
 169                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 170                 break;
 171 
 172         case BFA_FCS_ITNIM_SM_INITIATOR:
 173                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
 174                 bfa_fcxp_discard(itnim->fcxp);
 175                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
 176                 break;
 177 
 178         case BFA_FCS_ITNIM_SM_DELETE:
 179                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 180                 bfa_fcxp_discard(itnim->fcxp);
 181                 bfa_fcs_itnim_free(itnim);
 182                 break;
 183 
 184         default:
 185                 bfa_sm_fault(itnim->fcs, event);
 186         }
 187 }
 188 
 189 static void
 190 bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
 191                                 enum bfa_fcs_itnim_event event)
 192 {
 193         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 194         bfa_trc(itnim->fcs, event);
 195 
 196         switch (event) {
 197         case BFA_FCS_ITNIM_SM_HAL_ONLINE:
 198                 if (!itnim->bfa_itnim)
 199                         itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa,
 200                                         itnim->rport->bfa_rport, itnim);
 201 
 202                 if (itnim->bfa_itnim) {
 203                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
 204                         bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
 205                 } else {
 206                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 207                         bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE);
 208                 }
 209 
 210                 break;
 211 
 212         case BFA_FCS_ITNIM_SM_OFFLINE:
 213                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 214                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 215                 break;
 216 
 217         case BFA_FCS_ITNIM_SM_DELETE:
 218                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 219                 bfa_fcs_itnim_free(itnim);
 220                 break;
 221 
 222         default:
 223                 bfa_sm_fault(itnim->fcs, event);
 224         }
 225 }
 226 
 227 static void
 228 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
 229                             enum bfa_fcs_itnim_event event)
 230 {
 231         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 232         bfa_trc(itnim->fcs, event);
 233 
 234         switch (event) {
 235         case BFA_FCS_ITNIM_SM_TIMEOUT:
 236                 if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
 237                         itnim->prli_retries++;
 238                         bfa_trc(itnim->fcs, itnim->prli_retries);
 239                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
 240                         bfa_fcs_itnim_send_prli(itnim, NULL);
 241                 } else {
 242                         /* invoke target offline */
 243                         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 244                         bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
 245                 }
 246                 break;
 247 
 248 
 249         case BFA_FCS_ITNIM_SM_OFFLINE:
 250                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 251                 bfa_timer_stop(&itnim->timer);
 252                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 253                 break;
 254 
 255         case BFA_FCS_ITNIM_SM_INITIATOR:
 256                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
 257                 bfa_timer_stop(&itnim->timer);
 258                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
 259                 break;
 260 
 261         case BFA_FCS_ITNIM_SM_DELETE:
 262                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 263                 bfa_timer_stop(&itnim->timer);
 264                 bfa_fcs_itnim_free(itnim);
 265                 break;
 266 
 267         default:
 268                 bfa_sm_fault(itnim->fcs, event);
 269         }
 270 }
 271 
 272 static void
 273 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
 274                             enum bfa_fcs_itnim_event event)
 275 {
 276         struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
 277         char    lpwwn_buf[BFA_STRING_32];
 278         char    rpwwn_buf[BFA_STRING_32];
 279 
 280         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 281         bfa_trc(itnim->fcs, event);
 282 
 283         switch (event) {
 284         case BFA_FCS_ITNIM_SM_HCB_ONLINE:
 285                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
 286                 bfa_fcb_itnim_online(itnim->itnim_drv);
 287                 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
 288                 wwn2str(rpwwn_buf, itnim->rport->pwwn);
 289                 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
 290                 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
 291                 rpwwn_buf, lpwwn_buf);
 292                 bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
 293                 break;
 294 
 295         case BFA_FCS_ITNIM_SM_OFFLINE:
 296                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
 297                 bfa_itnim_offline(itnim->bfa_itnim);
 298                 break;
 299 
 300         case BFA_FCS_ITNIM_SM_DELETE:
 301                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 302                 bfa_fcs_itnim_free(itnim);
 303                 break;
 304 
 305         default:
 306                 bfa_sm_fault(itnim->fcs, event);
 307         }
 308 }
 309 
 310 static void
 311 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
 312                  enum bfa_fcs_itnim_event event)
 313 {
 314         struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
 315         char    lpwwn_buf[BFA_STRING_32];
 316         char    rpwwn_buf[BFA_STRING_32];
 317 
 318         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 319         bfa_trc(itnim->fcs, event);
 320 
 321         switch (event) {
 322         case BFA_FCS_ITNIM_SM_OFFLINE:
 323                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
 324                 bfa_fcb_itnim_offline(itnim->itnim_drv);
 325                 bfa_itnim_offline(itnim->bfa_itnim);
 326                 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
 327                 wwn2str(rpwwn_buf, itnim->rport->pwwn);
 328                 if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) {
 329                         BFA_LOG(KERN_ERR, bfad, bfa_log_level,
 330                         "Target (WWN = %s) connectivity lost for "
 331                         "initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
 332                         bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
 333                 } else {
 334                         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
 335                         "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
 336                         rpwwn_buf, lpwwn_buf);
 337                         bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
 338                 }
 339                 break;
 340 
 341         case BFA_FCS_ITNIM_SM_DELETE:
 342                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 343                 bfa_fcs_itnim_free(itnim);
 344                 break;
 345 
 346         default:
 347                 bfa_sm_fault(itnim->fcs, event);
 348         }
 349 }
 350 
 351 static void
 352 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
 353                              enum bfa_fcs_itnim_event event)
 354 {
 355         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 356         bfa_trc(itnim->fcs, event);
 357 
 358         switch (event) {
 359         case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
 360                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 361                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 362                 break;
 363 
 364         case BFA_FCS_ITNIM_SM_DELETE:
 365                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 366                 bfa_fcs_itnim_free(itnim);
 367                 break;
 368 
 369         default:
 370                 bfa_sm_fault(itnim->fcs, event);
 371         }
 372 }
 373 
 374 /*
 375  * This state is set when a discovered rport is also in intiator mode.
 376  * This ITN is marked as no_op and is not active and will not be truned into
 377  * online state.
 378  */
 379 static void
 380 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
 381                  enum bfa_fcs_itnim_event event)
 382 {
 383         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 384         bfa_trc(itnim->fcs, event);
 385 
 386         switch (event) {
 387         case BFA_FCS_ITNIM_SM_OFFLINE:
 388                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 389                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 390                 break;
 391 
 392         /*
 393          * fcs_online is expected here for well known initiator ports
 394          */
 395         case BFA_FCS_ITNIM_SM_FCS_ONLINE:
 396                 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
 397                 break;
 398 
 399         case BFA_FCS_ITNIM_SM_RSP_ERROR:
 400         case BFA_FCS_ITNIM_SM_INITIATOR:
 401                 break;
 402 
 403         case BFA_FCS_ITNIM_SM_DELETE:
 404                 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 405                 bfa_fcs_itnim_free(itnim);
 406                 break;
 407 
 408         default:
 409                 bfa_sm_fault(itnim->fcs, event);
 410         }
 411 }
 412 
 413 static void
 414 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
 415                         enum bfa_itnim_aen_event event)
 416 {
 417         struct bfa_fcs_rport_s *rport = itnim->rport;
 418         struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
 419         struct bfa_aen_entry_s  *aen_entry;
 420 
 421         /* Don't post events for well known addresses */
 422         if (BFA_FCS_PID_IS_WKA(rport->pid))
 423                 return;
 424 
 425         bfad_get_aen_entry(bfad, aen_entry);
 426         if (!aen_entry)
 427                 return;
 428 
 429         aen_entry->aen_data.itnim.vf_id = rport->port->fabric->vf_id;
 430         aen_entry->aen_data.itnim.ppwwn = bfa_fcs_lport_get_pwwn(
 431                                         bfa_fcs_get_base_port(itnim->fcs));
 432         aen_entry->aen_data.itnim.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
 433         aen_entry->aen_data.itnim.rpwwn = rport->pwwn;
 434 
 435         /* Send the AEN notification */
 436         bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
 437                                   BFA_AEN_CAT_ITNIM, event);
 438 }
 439 
 440 static void
 441 bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 442 {
 443         struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
 444         struct bfa_fcs_rport_s *rport = itnim->rport;
 445         struct bfa_fcs_lport_s *port = rport->port;
 446         struct fchs_s   fchs;
 447         struct bfa_fcxp_s *fcxp;
 448         int             len;
 449 
 450         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 451 
 452         fcxp = fcxp_alloced ? fcxp_alloced :
 453                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
 454         if (!fcxp) {
 455                 itnim->stats.fcxp_alloc_wait++;
 456                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
 457                                 bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);
 458                 return;
 459         }
 460         itnim->fcxp = fcxp;
 461 
 462         len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 463                             itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
 464 
 465         bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
 466                       BFA_FALSE, FC_CLASS_3, len, &fchs,
 467                       bfa_fcs_itnim_prli_response, (void *)itnim,
 468                       FC_MAX_PDUSZ, FC_ELS_TOV);
 469 
 470         itnim->stats.prli_sent++;
 471         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
 472 }
 473 
 474 static void
 475 bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
 476                             bfa_status_t req_status, u32 rsp_len,
 477                             u32 resid_len, struct fchs_s *rsp_fchs)
 478 {
 479         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
 480         struct fc_els_cmd_s *els_cmd;
 481         struct fc_prli_s *prli_resp;
 482         struct fc_ls_rjt_s *ls_rjt;
 483         struct fc_prli_params_s *sparams;
 484 
 485         bfa_trc(itnim->fcs, req_status);
 486 
 487         /*
 488          * Sanity Checks
 489          */
 490         if (req_status != BFA_STATUS_OK) {
 491                 itnim->stats.prli_rsp_err++;
 492                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
 493                 return;
 494         }
 495 
 496         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
 497 
 498         if (els_cmd->els_code == FC_ELS_ACC) {
 499                 prli_resp = (struct fc_prli_s *) els_cmd;
 500 
 501                 if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
 502                         bfa_trc(itnim->fcs, rsp_len);
 503                         /*
 504                          * Check if this  r-port is also in Initiator mode.
 505                          * If so, we need to set this ITN as a no-op.
 506                          */
 507                         if (prli_resp->parampage.servparams.initiator) {
 508                                 bfa_trc(itnim->fcs, prli_resp->parampage.type);
 509                                 itnim->rport->scsi_function =
 510                                                 BFA_RPORT_INITIATOR;
 511                                 itnim->stats.prli_rsp_acc++;
 512                                 itnim->stats.initiator++;
 513                                 bfa_sm_send_event(itnim,
 514                                                   BFA_FCS_ITNIM_SM_RSP_OK);
 515                                 return;
 516                         }
 517 
 518                         itnim->stats.prli_rsp_parse_err++;
 519                         return;
 520                 }
 521                 itnim->rport->scsi_function = BFA_RPORT_TARGET;
 522 
 523                 sparams = &prli_resp->parampage.servparams;
 524                 itnim->seq_rec       = sparams->retry;
 525                 itnim->rec_support   = sparams->rec_support;
 526                 itnim->task_retry_id = sparams->task_retry_id;
 527                 itnim->conf_comp     = sparams->confirm;
 528 
 529                 itnim->stats.prli_rsp_acc++;
 530                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
 531         } else {
 532                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
 533 
 534                 bfa_trc(itnim->fcs, ls_rjt->reason_code);
 535                 bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
 536 
 537                 itnim->stats.prli_rsp_rjt++;
 538                 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
 539                         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
 540                         return;
 541                 }
 542                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
 543         }
 544 }
 545 
 546 static void
 547 bfa_fcs_itnim_timeout(void *arg)
 548 {
 549         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
 550 
 551         itnim->stats.timeout++;
 552         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
 553 }
 554 
 555 static void
 556 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
 557 {
 558         if (itnim->bfa_itnim) {
 559                 bfa_itnim_delete(itnim->bfa_itnim);
 560                 itnim->bfa_itnim = NULL;
 561         }
 562 
 563         bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
 564 }
 565 
 566 
 567 
 568 /*
 569  *  itnim_public FCS ITNIM public interfaces
 570  */
 571 
 572 /*
 573  *      Called by rport when a new rport is created.
 574  *
 575  * @param[in] rport     -  remote port.
 576  */
 577 struct bfa_fcs_itnim_s *
 578 bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
 579 {
 580         struct bfa_fcs_lport_s *port = rport->port;
 581         struct bfa_fcs_itnim_s *itnim;
 582         struct bfad_itnim_s   *itnim_drv;
 583         int ret;
 584 
 585         /*
 586          * call bfad to allocate the itnim
 587          */
 588         ret = bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
 589         if (ret) {
 590                 bfa_trc(port->fcs, rport->pwwn);
 591                 return NULL;
 592         }
 593 
 594         /*
 595          * Initialize itnim
 596          */
 597         itnim->rport = rport;
 598         itnim->fcs = rport->fcs;
 599         itnim->itnim_drv = itnim_drv;
 600 
 601         itnim->bfa_itnim     = NULL;
 602         itnim->seq_rec       = BFA_FALSE;
 603         itnim->rec_support   = BFA_FALSE;
 604         itnim->conf_comp     = BFA_FALSE;
 605         itnim->task_retry_id = BFA_FALSE;
 606 
 607         /*
 608          * Set State machine
 609          */
 610         bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 611 
 612         return itnim;
 613 }
 614 
 615 /*
 616  *      Called by rport to delete  the instance of FCPIM.
 617  *
 618  * @param[in] rport     -  remote port.
 619  */
 620 void
 621 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
 622 {
 623         bfa_trc(itnim->fcs, itnim->rport->pid);
 624         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
 625 }
 626 
 627 /*
 628  * Notification from rport that PLOGI is complete to initiate FC-4 session.
 629  */
 630 void
 631 bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)
 632 {
 633         itnim->stats.onlines++;
 634 
 635         if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid))
 636                 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);
 637 }
 638 
 639 /*
 640  * Called by rport to handle a remote device offline.
 641  */
 642 void
 643 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
 644 {
 645         itnim->stats.offlines++;
 646         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
 647 }
 648 
 649 /*
 650  * Called by rport when remote port is known to be an initiator from
 651  * PRLI received.
 652  */
 653 void
 654 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
 655 {
 656         bfa_trc(itnim->fcs, itnim->rport->pid);
 657         itnim->stats.initiator++;
 658         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
 659 }
 660 
 661 /*
 662  * Called by rport to check if the itnim is online.
 663  */
 664 bfa_status_t
 665 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
 666 {
 667         bfa_trc(itnim->fcs, itnim->rport->pid);
 668         switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
 669         case BFA_ITNIM_ONLINE:
 670         case BFA_ITNIM_INITIATIOR:
 671                 return BFA_STATUS_OK;
 672 
 673         default:
 674                 return BFA_STATUS_NO_FCPIM_NEXUS;
 675         }
 676 }
 677 
 678 /*
 679  * BFA completion callback for bfa_itnim_online().
 680  */
 681 void
 682 bfa_cb_itnim_online(void *cbarg)
 683 {
 684         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
 685 
 686         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 687         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
 688 }
 689 
 690 /*
 691  * BFA completion callback for bfa_itnim_offline().
 692  */
 693 void
 694 bfa_cb_itnim_offline(void *cb_arg)
 695 {
 696         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 697 
 698         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 699         bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
 700 }
 701 
 702 /*
 703  * Mark the beginning of PATH TOV handling. IO completion callbacks
 704  * are still pending.
 705  */
 706 void
 707 bfa_cb_itnim_tov_begin(void *cb_arg)
 708 {
 709         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 710 
 711         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 712 }
 713 
 714 /*
 715  * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
 716  */
 717 void
 718 bfa_cb_itnim_tov(void *cb_arg)
 719 {
 720         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 721         struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
 722 
 723         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 724         itnim_drv->state = ITNIM_STATE_TIMEOUT;
 725 }
 726 
 727 /*
 728  *              BFA notification to FCS/driver for second level error recovery.
 729  *
 730  * Atleast one I/O request has timedout and target is unresponsive to
 731  * repeated abort requests. Second level error recovery should be initiated
 732  * by starting implicit logout and recovery procedures.
 733  */
 734 void
 735 bfa_cb_itnim_sler(void *cb_arg)
 736 {
 737         struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 738 
 739         itnim->stats.sler++;
 740         bfa_trc(itnim->fcs, itnim->rport->pwwn);
 741         bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
 742 }
 743 
 744 struct bfa_fcs_itnim_s *
 745 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
 746 {
 747         struct bfa_fcs_rport_s *rport;
 748         rport = bfa_fcs_rport_lookup(port, rpwwn);
 749 
 750         if (!rport)
 751                 return NULL;
 752 
 753         WARN_ON(rport->itnim == NULL);
 754         return rport->itnim;
 755 }
 756 
 757 bfa_status_t
 758 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
 759                        struct bfa_itnim_attr_s *attr)
 760 {
 761         struct bfa_fcs_itnim_s *itnim = NULL;
 762 
 763         itnim = bfa_fcs_itnim_lookup(port, rpwwn);
 764 
 765         if (itnim == NULL)
 766                 return BFA_STATUS_NO_FCPIM_NEXUS;
 767 
 768         attr->state         = bfa_sm_to_state(itnim_sm_table, itnim->sm);
 769         attr->retry         = itnim->seq_rec;
 770         attr->rec_support   = itnim->rec_support;
 771         attr->conf_comp     = itnim->conf_comp;
 772         attr->task_retry_id = itnim->task_retry_id;
 773         return BFA_STATUS_OK;
 774 }
 775 
 776 bfa_status_t
 777 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
 778                         struct bfa_itnim_stats_s *stats)
 779 {
 780         struct bfa_fcs_itnim_s *itnim = NULL;
 781 
 782         WARN_ON(port == NULL);
 783 
 784         itnim = bfa_fcs_itnim_lookup(port, rpwwn);
 785 
 786         if (itnim == NULL)
 787                 return BFA_STATUS_NO_FCPIM_NEXUS;
 788 
 789         memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
 790 
 791         return BFA_STATUS_OK;
 792 }
 793 
 794 bfa_status_t
 795 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
 796 {
 797         struct bfa_fcs_itnim_s *itnim = NULL;
 798 
 799         WARN_ON(port == NULL);
 800 
 801         itnim = bfa_fcs_itnim_lookup(port, rpwwn);
 802 
 803         if (itnim == NULL)
 804                 return BFA_STATUS_NO_FCPIM_NEXUS;
 805 
 806         memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
 807         return BFA_STATUS_OK;
 808 }
 809 
 810 void
 811 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
 812                         struct fchs_s *fchs, u16 len)
 813 {
 814         struct fc_els_cmd_s *els_cmd;
 815 
 816         bfa_trc(itnim->fcs, fchs->type);
 817 
 818         if (fchs->type != FC_TYPE_ELS)
 819                 return;
 820 
 821         els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 822 
 823         bfa_trc(itnim->fcs, els_cmd->els_code);
 824 
 825         switch (els_cmd->els_code) {
 826         case FC_ELS_PRLO:
 827                 bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
 828                 break;
 829 
 830         default:
 831                 WARN_ON(1);
 832         }
 833 }

/* [<][>][^][v][top][bottom][index][help] */