3715 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Marvell Fibre Channel HBA Driver4 * Copyright (c) 2021 Marvell5 */6#include "qla_def.h"7#include "qla_edif.h"8 9#include <linux/kthread.h>10#include <linux/vmalloc.h>11#include <linux/delay.h>12#include <scsi/scsi_tcq.h>13 14static struct edif_sa_index_entry *qla_edif_sadb_find_sa_index_entry(uint16_t nport_handle,15 struct list_head *sa_list);16static uint16_t qla_edif_sadb_get_sa_index(fc_port_t *fcport,17 struct qla_sa_update_frame *sa_frame);18static int qla_edif_sadb_delete_sa_index(fc_port_t *fcport, uint16_t nport_handle,19 uint16_t sa_index);20static int qla_pur_get_pending(scsi_qla_host_t *, fc_port_t *, struct bsg_job *);21 22struct edb_node {23 struct list_head list;24 uint32_t ntype;25 union {26 port_id_t plogi_did;27 uint32_t async;28 port_id_t els_sid;29 struct edif_sa_update_aen sa_aen;30 } u;31};32 33static struct els_sub_cmd {34 uint16_t cmd;35 const char *str;36} sc_str[] = {37 {SEND_ELS, "send ELS"},38 {SEND_ELS_REPLY, "send ELS Reply"},39 {PULL_ELS, "retrieve ELS"},40};41 42const char *sc_to_str(uint16_t cmd)43{44 int i;45 struct els_sub_cmd *e;46 47 for (i = 0; i < ARRAY_SIZE(sc_str); i++) {48 e = sc_str + i;49 if (cmd == e->cmd)50 return e->str;51 }52 return "unknown";53}54 55static struct edb_node *qla_edb_getnext(scsi_qla_host_t *vha)56{57 unsigned long flags;58 struct edb_node *edbnode = NULL;59 60 spin_lock_irqsave(&vha->e_dbell.db_lock, flags);61 62 /* db nodes are fifo - no qualifications done */63 if (!list_empty(&vha->e_dbell.head)) {64 edbnode = list_first_entry(&vha->e_dbell.head,65 struct edb_node, list);66 list_del_init(&edbnode->list);67 }68 69 spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);70 71 return edbnode;72}73 74static void qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)75{76 list_del_init(&node->list);77 kfree(node);78}79 80static struct edif_list_entry *qla_edif_list_find_sa_index(fc_port_t *fcport,81 uint16_t handle)82{83 struct edif_list_entry *entry;84 struct edif_list_entry *tentry;85 struct list_head *indx_list = &fcport->edif.edif_indx_list;86 87 list_for_each_entry_safe(entry, tentry, indx_list, next) {88 if (entry->handle == handle)89 return entry;90 }91 return NULL;92}93 94/* timeout called when no traffic and delayed rx sa_index delete */95static void qla2x00_sa_replace_iocb_timeout(struct timer_list *t)96{97 struct edif_list_entry *edif_entry = from_timer(edif_entry, t, timer);98 fc_port_t *fcport = edif_entry->fcport;99 struct scsi_qla_host *vha = fcport->vha;100 struct edif_sa_ctl *sa_ctl;101 uint16_t nport_handle;102 unsigned long flags = 0;103 104 ql_dbg(ql_dbg_edif, vha, 0x3069,105 "%s: nport_handle 0x%x, SA REPL Delay Timeout, %8phC portid=%06x\n",106 __func__, edif_entry->handle, fcport->port_name, fcport->d_id.b24);107 108 /*109 * if delete_sa_index is valid then no one has serviced this110 * delayed delete111 */112 spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);113 114 /*115 * delete_sa_index is invalidated when we find the new sa_index in116 * the incoming data stream. If it is not invalidated then we are117 * still looking for the new sa_index because there is no I/O and we118 * need to just force the rx delete and move on. Otherwise119 * we could get another rekey which will result in an error 66.120 */121 if (edif_entry->delete_sa_index != INVALID_EDIF_SA_INDEX) {122 uint16_t delete_sa_index = edif_entry->delete_sa_index;123 124 edif_entry->delete_sa_index = INVALID_EDIF_SA_INDEX;125 nport_handle = edif_entry->handle;126 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);127 128 sa_ctl = qla_edif_find_sa_ctl_by_index(fcport,129 delete_sa_index, 0);130 131 if (sa_ctl) {132 ql_dbg(ql_dbg_edif, vha, 0x3063,133 "%s: sa_ctl: %p, delete index %d, update index: %d, lid: 0x%x\n",134 __func__, sa_ctl, delete_sa_index, edif_entry->update_sa_index,135 nport_handle);136 137 sa_ctl->flags = EDIF_SA_CTL_FLG_DEL;138 set_bit(EDIF_SA_CTL_REPL, &sa_ctl->state);139 qla_post_sa_replace_work(fcport->vha, fcport,140 nport_handle, sa_ctl);141 142 } else {143 ql_dbg(ql_dbg_edif, vha, 0x3063,144 "%s: sa_ctl not found for delete_sa_index: %d\n",145 __func__, edif_entry->delete_sa_index);146 }147 } else {148 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);149 }150}151 152/*153 * create a new list entry for this nport handle and154 * add an sa_update index to the list - called for sa_update155 */156static int qla_edif_list_add_sa_update_index(fc_port_t *fcport,157 uint16_t sa_index, uint16_t handle)158{159 struct edif_list_entry *entry;160 unsigned long flags = 0;161 162 /* if the entry exists, then just update the sa_index */163 entry = qla_edif_list_find_sa_index(fcport, handle);164 if (entry) {165 entry->update_sa_index = sa_index;166 entry->count = 0;167 return 0;168 }169 170 /*171 * This is the normal path - there should be no existing entry172 * when update is called. The exception is at startup173 * when update is called for the first two sa_indexes174 * followed by a delete of the first sa_index175 */176 entry = kzalloc((sizeof(struct edif_list_entry)), GFP_ATOMIC);177 if (!entry)178 return -ENOMEM;179 180 INIT_LIST_HEAD(&entry->next);181 entry->handle = handle;182 entry->update_sa_index = sa_index;183 entry->delete_sa_index = INVALID_EDIF_SA_INDEX;184 entry->count = 0;185 entry->flags = 0;186 timer_setup(&entry->timer, qla2x00_sa_replace_iocb_timeout, 0);187 spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);188 list_add_tail(&entry->next, &fcport->edif.edif_indx_list);189 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);190 return 0;191}192 193/* remove an entry from the list */194static void qla_edif_list_delete_sa_index(fc_port_t *fcport, struct edif_list_entry *entry)195{196 unsigned long flags = 0;197 198 spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);199 list_del(&entry->next);200 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);201}202 203int qla_post_sa_replace_work(struct scsi_qla_host *vha,204 fc_port_t *fcport, uint16_t nport_handle, struct edif_sa_ctl *sa_ctl)205{206 struct qla_work_evt *e;207 208 e = qla2x00_alloc_work(vha, QLA_EVT_SA_REPLACE);209 if (!e)210 return QLA_FUNCTION_FAILED;211 212 e->u.sa_update.fcport = fcport;213 e->u.sa_update.sa_ctl = sa_ctl;214 e->u.sa_update.nport_handle = nport_handle;215 fcport->flags |= FCF_ASYNC_ACTIVE;216 return qla2x00_post_work(vha, e);217}218 219static void220qla_edif_sa_ctl_init(scsi_qla_host_t *vha, struct fc_port *fcport)221{222 ql_dbg(ql_dbg_edif, vha, 0x2058,223 "Init SA_CTL List for fcport - nn %8phN pn %8phN portid=%06x.\n",224 fcport->node_name, fcport->port_name, fcport->d_id.b24);225 226 fcport->edif.tx_rekey_cnt = 0;227 fcport->edif.rx_rekey_cnt = 0;228 229 fcport->edif.tx_bytes = 0;230 fcport->edif.rx_bytes = 0;231}232 233static int qla_bsg_check(scsi_qla_host_t *vha, struct bsg_job *bsg_job,234fc_port_t *fcport)235{236 struct extra_auth_els *p;237 struct fc_bsg_reply *bsg_reply = bsg_job->reply;238 struct qla_bsg_auth_els_request *req =239 (struct qla_bsg_auth_els_request *)bsg_job->request;240 241 if (!vha->hw->flags.edif_enabled) {242 ql_dbg(ql_dbg_edif, vha, 0x9105,243 "%s edif not enabled\n", __func__);244 goto done;245 }246 if (DBELL_INACTIVE(vha)) {247 ql_dbg(ql_dbg_edif, vha, 0x09102,248 "%s doorbell not enabled\n", __func__);249 goto done;250 }251 252 p = &req->e;253 254 /* Get response */255 if (p->sub_cmd == PULL_ELS) {256 struct qla_bsg_auth_els_reply *rpl =257 (struct qla_bsg_auth_els_reply *)bsg_job->reply;258 259 qla_pur_get_pending(vha, fcport, bsg_job);260 261 ql_dbg(ql_dbg_edif, vha, 0x911d,262 "%s %s %8phN sid=%x. xchg %x, nb=%xh bsg ptr %p\n",263 __func__, sc_to_str(p->sub_cmd), fcport->port_name,264 fcport->d_id.b24, rpl->rx_xchg_address,265 rpl->r.reply_payload_rcv_len, bsg_job);266 267 goto done;268 }269 return 0;270 271done:272 273 bsg_job_done(bsg_job, bsg_reply->result,274 bsg_reply->reply_payload_rcv_len);275 return -EIO;276}277 278fc_port_t *279qla2x00_find_fcport_by_pid(scsi_qla_host_t *vha, port_id_t *id)280{281 fc_port_t *f, *tf;282 283 f = NULL;284 list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {285 if (f->d_id.b24 == id->b24)286 return f;287 }288 return NULL;289}290 291/**292 * qla_edif_app_check(): check for valid application id.293 * @vha: host adapter pointer294 * @appid: application id295 * Return: false = fail, true = pass296 */297static bool298qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)299{300 /* check that the app is allow/known to the driver */301 302 if (appid.app_vid != EDIF_APP_ID) {303 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",304 __func__, appid.app_vid);305 return false;306 }307 308 if (appid.version != EDIF_VERSION1) {309 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app version is not ok (%x)",310 __func__, appid.version);311 return false;312 }313 314 return true;315}316 317static void318qla_edif_free_sa_ctl(fc_port_t *fcport, struct edif_sa_ctl *sa_ctl,319 int index)320{321 unsigned long flags = 0;322 323 spin_lock_irqsave(&fcport->edif.sa_list_lock, flags);324 list_del(&sa_ctl->next);325 spin_unlock_irqrestore(&fcport->edif.sa_list_lock, flags);326 if (index >= 512)327 fcport->edif.tx_rekey_cnt--;328 else329 fcport->edif.rx_rekey_cnt--;330 kfree(sa_ctl);331}332 333/* return an index to the freepool */334static void qla_edif_add_sa_index_to_freepool(fc_port_t *fcport, int dir,335 uint16_t sa_index)336{337 void *sa_id_map;338 struct scsi_qla_host *vha = fcport->vha;339 struct qla_hw_data *ha = vha->hw;340 unsigned long flags = 0;341 u16 lsa_index = sa_index;342 343 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,344 "%s: entry\n", __func__);345 346 if (dir) {347 sa_id_map = ha->edif_tx_sa_id_map;348 lsa_index -= EDIF_TX_SA_INDEX_BASE;349 } else {350 sa_id_map = ha->edif_rx_sa_id_map;351 }352 353 spin_lock_irqsave(&ha->sadb_fp_lock, flags);354 clear_bit(lsa_index, sa_id_map);355 spin_unlock_irqrestore(&ha->sadb_fp_lock, flags);356 ql_dbg(ql_dbg_edif, vha, 0x3063,357 "%s: index %d added to free pool\n", __func__, sa_index);358}359 360static void __qla2x00_release_all_sadb(struct scsi_qla_host *vha,361 struct fc_port *fcport, struct edif_sa_index_entry *entry,362 int pdir)363{364 struct edif_list_entry *edif_entry;365 struct edif_sa_ctl *sa_ctl;366 int i, dir;367 int key_cnt = 0;368 369 for (i = 0; i < 2; i++) {370 if (entry->sa_pair[i].sa_index == INVALID_EDIF_SA_INDEX)371 continue;372 373 if (fcport->loop_id != entry->handle) {374 ql_dbg(ql_dbg_edif, vha, 0x3063,375 "%s: ** WARNING %d** entry handle: 0x%x, lid: 0x%x, sa_index: %d\n",376 __func__, i, entry->handle, fcport->loop_id,377 entry->sa_pair[i].sa_index);378 }379 380 /* release the sa_ctl */381 sa_ctl = qla_edif_find_sa_ctl_by_index(fcport,382 entry->sa_pair[i].sa_index, pdir);383 if (sa_ctl &&384 qla_edif_find_sa_ctl_by_index(fcport, sa_ctl->index, pdir)) {385 ql_dbg(ql_dbg_edif, vha, 0x3063,386 "%s: freeing sa_ctl for index %d\n", __func__, sa_ctl->index);387 qla_edif_free_sa_ctl(fcport, sa_ctl, sa_ctl->index);388 } else {389 ql_dbg(ql_dbg_edif, vha, 0x3063,390 "%s: sa_ctl NOT freed, sa_ctl: %p\n", __func__, sa_ctl);391 }392 393 /* Release the index */394 ql_dbg(ql_dbg_edif, vha, 0x3063,395 "%s: freeing sa_index %d, nph: 0x%x\n",396 __func__, entry->sa_pair[i].sa_index, entry->handle);397 398 dir = (entry->sa_pair[i].sa_index <399 EDIF_TX_SA_INDEX_BASE) ? 0 : 1;400 qla_edif_add_sa_index_to_freepool(fcport, dir,401 entry->sa_pair[i].sa_index);402 403 /* Delete timer on RX */404 if (pdir != SAU_FLG_TX) {405 edif_entry =406 qla_edif_list_find_sa_index(fcport, entry->handle);407 if (edif_entry) {408 ql_dbg(ql_dbg_edif, vha, 0x5033,409 "%s: remove edif_entry %p, update_sa_index: 0x%x, delete_sa_index: 0x%x\n",410 __func__, edif_entry, edif_entry->update_sa_index,411 edif_entry->delete_sa_index);412 qla_edif_list_delete_sa_index(fcport, edif_entry);413 /*414 * valid delete_sa_index indicates there is a rx415 * delayed delete queued416 */417 if (edif_entry->delete_sa_index !=418 INVALID_EDIF_SA_INDEX) {419 timer_shutdown(&edif_entry->timer);420 421 /* build and send the aen */422 fcport->edif.rx_sa_set = 1;423 fcport->edif.rx_sa_pending = 0;424 qla_edb_eventcreate(vha,425 VND_CMD_AUTH_STATE_SAUPDATE_COMPL,426 QL_VND_SA_STAT_SUCCESS,427 QL_VND_RX_SA_KEY, fcport);428 }429 ql_dbg(ql_dbg_edif, vha, 0x5033,430 "%s: release edif_entry %p, update_sa_index: 0x%x, delete_sa_index: 0x%x\n",431 __func__, edif_entry, edif_entry->update_sa_index,432 edif_entry->delete_sa_index);433 434 kfree(edif_entry);435 }436 }437 key_cnt++;438 }439 ql_dbg(ql_dbg_edif, vha, 0x3063,440 "%s: %d %s keys released\n",441 __func__, key_cnt, pdir ? "tx" : "rx");442}443 444/* find an release all outstanding sadb sa_indicies */445void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport)446{447 struct edif_sa_index_entry *entry, *tmp;448 struct qla_hw_data *ha = vha->hw;449 unsigned long flags;450 451 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,452 "%s: Starting...\n", __func__);453 454 spin_lock_irqsave(&ha->sadb_lock, flags);455 456 list_for_each_entry_safe(entry, tmp, &ha->sadb_rx_index_list, next) {457 if (entry->fcport == fcport) {458 list_del(&entry->next);459 spin_unlock_irqrestore(&ha->sadb_lock, flags);460 __qla2x00_release_all_sadb(vha, fcport, entry, 0);461 kfree(entry);462 spin_lock_irqsave(&ha->sadb_lock, flags);463 break;464 }465 }466 467 list_for_each_entry_safe(entry, tmp, &ha->sadb_tx_index_list, next) {468 if (entry->fcport == fcport) {469 list_del(&entry->next);470 spin_unlock_irqrestore(&ha->sadb_lock, flags);471 472 __qla2x00_release_all_sadb(vha, fcport, entry, SAU_FLG_TX);473 474 kfree(entry);475 spin_lock_irqsave(&ha->sadb_lock, flags);476 break;477 }478 }479 spin_unlock_irqrestore(&ha->sadb_lock, flags);480}481 482/**483 * qla_delete_n2n_sess_and_wait: search for N2N session, tear it down and484 * wait for tear down to complete. In N2N topology, there is only one485 * session being active in tracking the remote device.486 * @vha: host adapter pointer487 * return code: 0 - found the session and completed the tear down.488 * 1 - timeout occurred. Caller to use link bounce to reset.489 */490static int qla_delete_n2n_sess_and_wait(scsi_qla_host_t *vha)491{492 struct fc_port *fcport;493 int rc = -EIO;494 ulong expire = jiffies + 23 * HZ;495 496 if (!N2N_TOPO(vha->hw))497 return 0;498 499 fcport = NULL;500 list_for_each_entry(fcport, &vha->vp_fcports, list) {501 if (!fcport->n2n_flag)502 continue;503 504 ql_dbg(ql_dbg_disc, fcport->vha, 0x2016,505 "%s reset sess at app start \n", __func__);506 507 qla_edif_sa_ctl_init(vha, fcport);508 qlt_schedule_sess_for_deletion(fcport);509 510 while (time_before_eq(jiffies, expire)) {511 if (fcport->disc_state != DSC_DELETE_PEND) {512 rc = 0;513 break;514 }515 msleep(1);516 }517 518 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);519 break;520 }521 522 return rc;523}524 525/**526 * qla_edif_app_start: application has announce its present527 * @vha: host adapter pointer528 * @bsg_job: user request529 *530 * Set/activate doorbell. Reset current sessions and re-login with531 * secure flag.532 */533static int534qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)535{536 int32_t rval = 0;537 struct fc_bsg_reply *bsg_reply = bsg_job->reply;538 struct app_start appstart;539 struct app_start_reply appreply;540 struct fc_port *fcport, *tf;541 542 ql_log(ql_log_info, vha, 0x1313,543 "EDIF application registration with driver, FC device connections will be re-established.\n");544 545 sg_copy_to_buffer(bsg_job->request_payload.sg_list,546 bsg_job->request_payload.sg_cnt, &appstart,547 sizeof(struct app_start));548 549 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n",550 __func__, appstart.app_info.app_vid, appstart.app_start_flags);551 552 if (DBELL_INACTIVE(vha)) {553 /* mark doorbell as active since an app is now present */554 vha->e_dbell.db_flags |= EDB_ACTIVE;555 } else {556 goto out;557 }558 559 if (N2N_TOPO(vha->hw)) {560 list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list)561 fcport->n2n_link_reset_cnt = 0;562 563 if (vha->hw->flags.n2n_fw_acc_sec) {564 bool link_bounce = false;565 /*566 * While authentication app was not running, remote device567 * could still try to login with this local port. Let's568 * reset the session, reconnect and re-authenticate.569 */570 if (qla_delete_n2n_sess_and_wait(vha))571 link_bounce = true;572 573 /* bounce the link to start login */574 if (!vha->hw->flags.n2n_bigger || link_bounce) {575 set_bit(N2N_LINK_RESET, &vha->dpc_flags);576 qla2xxx_wake_dpc(vha);577 }578 } else {579 qla2x00_wait_for_hba_online(vha);580 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);581 qla2xxx_wake_dpc(vha);582 qla2x00_wait_for_hba_online(vha);583 }584 } else {585 list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {586 ql_dbg(ql_dbg_edif, vha, 0x2058,587 "FCSP - nn %8phN pn %8phN portid=%06x.\n",588 fcport->node_name, fcport->port_name,589 fcport->d_id.b24);590 ql_dbg(ql_dbg_edif, vha, 0xf084,591 "%s: se_sess %p / sess %p from port %8phC "592 "loop_id %#04x s_id %06x logout %d "593 "keep %d els_logo %d disc state %d auth state %d"594 "stop state %d\n",595 __func__, fcport->se_sess, fcport,596 fcport->port_name, fcport->loop_id,597 fcport->d_id.b24, fcport->logout_on_delete,598 fcport->keep_nport_handle, fcport->send_els_logo,599 fcport->disc_state, fcport->edif.auth_state,600 fcport->edif.app_stop);601 602 if (atomic_read(&vha->loop_state) == LOOP_DOWN)603 break;604 605 fcport->login_retry = vha->hw->login_retry_count;606 607 fcport->edif.app_stop = 0;608 fcport->edif.app_sess_online = 0;609 610 if (fcport->scan_state != QLA_FCPORT_FOUND)611 continue;612 613 if (fcport->port_type == FCT_UNKNOWN &&614 !fcport->fc4_features)615 rval = qla24xx_async_gffid(vha, fcport, true);616 617 if (!rval && !(fcport->fc4_features & FC4_FF_TARGET ||618 fcport->port_type & (FCT_TARGET|FCT_NVME_TARGET)))619 continue;620 621 rval = 0;622 623 ql_dbg(ql_dbg_edif, vha, 0x911e,624 "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",625 __func__, fcport->port_name);626 qlt_schedule_sess_for_deletion(fcport);627 qla_edif_sa_ctl_init(vha, fcport);628 }629 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);630 }631 632 if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {633 /* mark as active since an app is now present */634 vha->pur_cinfo.enode_flags = ENODE_ACTIVE;635 } else {636 ql_dbg(ql_dbg_edif, vha, 0x911f, "%s enode already active\n",637 __func__);638 }639 640out:641 appreply.host_support_edif = vha->hw->flags.edif_enabled;642 appreply.edif_enode_active = vha->pur_cinfo.enode_flags;643 appreply.edif_edb_active = vha->e_dbell.db_flags;644 appreply.version = EDIF_VERSION1;645 646 bsg_job->reply_len = sizeof(struct fc_bsg_reply);647 648 SET_DID_STATUS(bsg_reply->result, DID_OK);649 650 bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,651 bsg_job->reply_payload.sg_cnt,652 &appreply,653 sizeof(struct app_start_reply));654 655 ql_dbg(ql_dbg_edif, vha, 0x911d,656 "%s app start completed with 0x%x\n",657 __func__, rval);658 659 return rval;660}661 662/**663 * qla_edif_app_stop - app has announced it's exiting.664 * @vha: host adapter pointer665 * @bsg_job: user space command pointer666 *667 * Free any in flight messages, clear all doorbell events668 * to application. Reject any message relate to security.669 */670static int671qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)672{673 struct app_stop appstop;674 struct fc_bsg_reply *bsg_reply = bsg_job->reply;675 struct fc_port *fcport, *tf;676 677 sg_copy_to_buffer(bsg_job->request_payload.sg_list,678 bsg_job->request_payload.sg_cnt, &appstop,679 sizeof(struct app_stop));680 681 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s Stopping APP: app_vid=%x\n",682 __func__, appstop.app_info.app_vid);683 684 /* Call db stop and enode stop functions */685 686 /* if we leave this running short waits are operational < 16 secs */687 qla_enode_stop(vha); /* stop enode */688 qla_edb_stop(vha); /* stop db */689 690 list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {691 if (!(fcport->flags & FCF_FCSP_DEVICE))692 continue;693 694 if (fcport->flags & FCF_FCSP_DEVICE) {695 ql_dbg(ql_dbg_edif, vha, 0xf084,696 "%s: sess %p from port %8phC lid %#04x s_id %06x logout %d keep %d els_logo %d\n",697 __func__, fcport,698 fcport->port_name, fcport->loop_id, fcport->d_id.b24,699 fcport->logout_on_delete, fcport->keep_nport_handle,700 fcport->send_els_logo);701 702 if (atomic_read(&vha->loop_state) == LOOP_DOWN)703 break;704 705 fcport->edif.app_stop = 1;706 ql_dbg(ql_dbg_edif, vha, 0x911e,707 "%s wwpn %8phC calling qla_edif_reset_auth_wait\n",708 __func__, fcport->port_name);709 710 fcport->send_els_logo = 1;711 qlt_schedule_sess_for_deletion(fcport);712 }713 }714 715 bsg_job->reply_len = sizeof(struct fc_bsg_reply);716 SET_DID_STATUS(bsg_reply->result, DID_OK);717 718 /* no return interface to app - it assumes we cleaned up ok */719 720 return 0;721}722 723static int724qla_edif_app_chk_sa_update(scsi_qla_host_t *vha, fc_port_t *fcport,725 struct app_plogi_reply *appplogireply)726{727 int ret = 0;728 729 if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) {730 ql_dbg(ql_dbg_edif, vha, 0x911e,731 "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n",732 __func__, fcport->port_name, fcport->edif.tx_sa_set,733 fcport->edif.rx_sa_set);734 appplogireply->prli_status = 0;735 ret = 1;736 } else {737 ql_dbg(ql_dbg_edif, vha, 0x911e,738 "%s wwpn %8phC Both SA(s) updated.\n", __func__,739 fcport->port_name);740 fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0;741 fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0;742 appplogireply->prli_status = 1;743 }744 return ret;745}746 747/**748 * qla_edif_app_authok - authentication by app succeeded. Driver can proceed749 * with prli750 * @vha: host adapter pointer751 * @bsg_job: user request752 */753static int754qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)755{756 struct auth_complete_cmd appplogiok;757 struct app_plogi_reply appplogireply = {0};758 struct fc_bsg_reply *bsg_reply = bsg_job->reply;759 fc_port_t *fcport = NULL;760 port_id_t portid = {0};761 762 sg_copy_to_buffer(bsg_job->request_payload.sg_list,763 bsg_job->request_payload.sg_cnt, &appplogiok,764 sizeof(struct auth_complete_cmd));765 766 /* silent unaligned access warning */767 portid.b.domain = appplogiok.u.d_id.b.domain;768 portid.b.area = appplogiok.u.d_id.b.area;769 portid.b.al_pa = appplogiok.u.d_id.b.al_pa;770 771 appplogireply.version = EDIF_VERSION1;772 switch (appplogiok.type) {773 case PL_TYPE_WWPN:774 fcport = qla2x00_find_fcport_by_wwpn(vha,775 appplogiok.u.wwpn, 0);776 if (!fcport)777 ql_dbg(ql_dbg_edif, vha, 0x911d,778 "%s wwpn lookup failed: %8phC\n",779 __func__, appplogiok.u.wwpn);780 break;781 case PL_TYPE_DID:782 fcport = qla2x00_find_fcport_by_pid(vha, &portid);783 if (!fcport)784 ql_dbg(ql_dbg_edif, vha, 0x911d,785 "%s d_id lookup failed: %x\n", __func__,786 portid.b24);787 break;788 default:789 ql_dbg(ql_dbg_edif, vha, 0x911d,790 "%s undefined type: %x\n", __func__,791 appplogiok.type);792 break;793 }794 795 if (!fcport) {796 SET_DID_STATUS(bsg_reply->result, DID_ERROR);797 goto errstate_exit;798 }799 800 /*801 * if port is online then this is a REKEY operation802 * Only do sa update checking803 */804 if (atomic_read(&fcport->state) == FCS_ONLINE) {805 ql_dbg(ql_dbg_edif, vha, 0x911d,806 "%s Skipping PRLI complete based on rekey\n", __func__);807 appplogireply.prli_status = 1;808 SET_DID_STATUS(bsg_reply->result, DID_OK);809 qla_edif_app_chk_sa_update(vha, fcport, &appplogireply);810 goto errstate_exit;811 }812 813 /* make sure in AUTH_PENDING or else reject */814 if (fcport->disc_state != DSC_LOGIN_AUTH_PEND) {815 ql_dbg(ql_dbg_edif, vha, 0x911e,816 "%s wwpn %8phC is not in auth pending state (%x)\n",817 __func__, fcport->port_name, fcport->disc_state);818 SET_DID_STATUS(bsg_reply->result, DID_OK);819 appplogireply.prli_status = 0;820 goto errstate_exit;821 }822 823 SET_DID_STATUS(bsg_reply->result, DID_OK);824 appplogireply.prli_status = 1;825 fcport->edif.authok = 1;826 if (!(fcport->edif.rx_sa_set && fcport->edif.tx_sa_set)) {827 ql_dbg(ql_dbg_edif, vha, 0x911e,828 "%s: wwpn %8phC Both SA indexes has not been SET TX %d, RX %d.\n",829 __func__, fcport->port_name, fcport->edif.tx_sa_set,830 fcport->edif.rx_sa_set);831 SET_DID_STATUS(bsg_reply->result, DID_OK);832 appplogireply.prli_status = 0;833 goto errstate_exit;834 835 } else {836 ql_dbg(ql_dbg_edif, vha, 0x911e,837 "%s wwpn %8phC Both SA(s) updated.\n", __func__,838 fcport->port_name);839 fcport->edif.rx_sa_set = fcport->edif.tx_sa_set = 0;840 fcport->edif.rx_sa_pending = fcport->edif.tx_sa_pending = 0;841 }842 843 if (qla_ini_mode_enabled(vha)) {844 ql_dbg(ql_dbg_edif, vha, 0x911e,845 "%s AUTH complete - RESUME with prli for wwpn %8phC\n",846 __func__, fcport->port_name);847 qla24xx_post_prli_work(vha, fcport);848 }849 850errstate_exit:851 bsg_job->reply_len = sizeof(struct fc_bsg_reply);852 bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,853 bsg_job->reply_payload.sg_cnt,854 &appplogireply,855 sizeof(struct app_plogi_reply));856 857 return 0;858}859 860/**861 * qla_edif_app_authfail - authentication by app has failed. Driver is given862 * notice to tear down current session.863 * @vha: host adapter pointer864 * @bsg_job: user request865 */866static int867qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job)868{869 int32_t rval = 0;870 struct auth_complete_cmd appplogifail;871 struct fc_bsg_reply *bsg_reply = bsg_job->reply;872 fc_port_t *fcport = NULL;873 port_id_t portid = {0};874 875 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app auth fail\n", __func__);876 877 sg_copy_to_buffer(bsg_job->request_payload.sg_list,878 bsg_job->request_payload.sg_cnt, &appplogifail,879 sizeof(struct auth_complete_cmd));880 881 /* silent unaligned access warning */882 portid.b.domain = appplogifail.u.d_id.b.domain;883 portid.b.area = appplogifail.u.d_id.b.area;884 portid.b.al_pa = appplogifail.u.d_id.b.al_pa;885 886 /*887 * TODO: edif: app has failed this plogi. Inform driver to888 * take any action (if any).889 */890 switch (appplogifail.type) {891 case PL_TYPE_WWPN:892 fcport = qla2x00_find_fcport_by_wwpn(vha,893 appplogifail.u.wwpn, 0);894 SET_DID_STATUS(bsg_reply->result, DID_OK);895 break;896 case PL_TYPE_DID:897 fcport = qla2x00_find_fcport_by_pid(vha, &portid);898 if (!fcport)899 ql_dbg(ql_dbg_edif, vha, 0x911d,900 "%s d_id lookup failed: %x\n", __func__,901 portid.b24);902 SET_DID_STATUS(bsg_reply->result, DID_OK);903 break;904 default:905 ql_dbg(ql_dbg_edif, vha, 0x911e,906 "%s undefined type: %x\n", __func__,907 appplogifail.type);908 bsg_job->reply_len = sizeof(struct fc_bsg_reply);909 SET_DID_STATUS(bsg_reply->result, DID_ERROR);910 rval = -1;911 break;912 }913 914 ql_dbg(ql_dbg_edif, vha, 0x911d,915 "%s fcport is 0x%p\n", __func__, fcport);916 917 if (fcport) {918 /* set/reset edif values and flags */919 ql_dbg(ql_dbg_edif, vha, 0x911e,920 "%s reset the auth process - %8phC, loopid=%x portid=%06x.\n",921 __func__, fcport->port_name, fcport->loop_id, fcport->d_id.b24);922 923 if (qla_ini_mode_enabled(fcport->vha)) {924 fcport->send_els_logo = 1;925 qlt_schedule_sess_for_deletion(fcport);926 }927 }928 929 return rval;930}931 932/**933 * qla_edif_app_getfcinfo - app would like to read session info (wwpn, nportid,934 * [initiator|target] mode. It can specific session with specific nport id or935 * all sessions.936 * @vha: host adapter pointer937 * @bsg_job: user request pointer938 */939static int940qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)941{942 int32_t rval = 0;943 int32_t pcnt = 0;944 struct fc_bsg_reply *bsg_reply = bsg_job->reply;945 struct app_pinfo_req app_req;946 struct app_pinfo_reply *app_reply;947 port_id_t tdid;948 949 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app get fcinfo\n", __func__);950 951 sg_copy_to_buffer(bsg_job->request_payload.sg_list,952 bsg_job->request_payload.sg_cnt, &app_req,953 sizeof(struct app_pinfo_req));954 955 app_reply = kzalloc((sizeof(struct app_pinfo_reply) +956 sizeof(struct app_pinfo) * app_req.num_ports), GFP_KERNEL);957 958 if (!app_reply) {959 SET_DID_STATUS(bsg_reply->result, DID_ERROR);960 rval = -1;961 } else {962 struct fc_port *fcport = NULL, *tf;963 964 app_reply->version = EDIF_VERSION1;965 966 list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {967 if (!(fcport->flags & FCF_FCSP_DEVICE))968 continue;969 970 tdid.b.domain = app_req.remote_pid.domain;971 tdid.b.area = app_req.remote_pid.area;972 tdid.b.al_pa = app_req.remote_pid.al_pa;973 974 ql_dbg(ql_dbg_edif, vha, 0x2058,975 "APP request entry - portid=%06x.\n", tdid.b24);976 977 /* Ran out of space */978 if (pcnt >= app_req.num_ports)979 break;980 981 if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24)982 continue;983 984 if (!N2N_TOPO(vha->hw)) {985 if (fcport->scan_state != QLA_FCPORT_FOUND)986 continue;987 988 if (fcport->port_type == FCT_UNKNOWN &&989 !fcport->fc4_features)990 rval = qla24xx_async_gffid(vha, fcport,991 true);992 993 if (!rval &&994 !(fcport->fc4_features & FC4_FF_TARGET ||995 fcport->port_type &996 (FCT_TARGET | FCT_NVME_TARGET)))997 continue;998 }999 1000 rval = 0;1001 1002 app_reply->ports[pcnt].version = EDIF_VERSION1;1003 app_reply->ports[pcnt].remote_type =1004 VND_CMD_RTYPE_UNKNOWN;1005 if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET))1006 app_reply->ports[pcnt].remote_type |=1007 VND_CMD_RTYPE_TARGET;1008 if (fcport->port_type & (FCT_NVME_INITIATOR | FCT_INITIATOR))1009 app_reply->ports[pcnt].remote_type |=1010 VND_CMD_RTYPE_INITIATOR;1011 1012 app_reply->ports[pcnt].remote_pid = fcport->d_id;1013 1014 ql_dbg(ql_dbg_edif, vha, 0x2058,1015 "Found FC_SP fcport - nn %8phN pn %8phN pcnt %d portid=%06x secure %d.\n",1016 fcport->node_name, fcport->port_name, pcnt,1017 fcport->d_id.b24, fcport->flags & FCF_FCSP_DEVICE);1018 1019 switch (fcport->edif.auth_state) {1020 case VND_CMD_AUTH_STATE_ELS_RCVD:1021 if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) {1022 fcport->edif.auth_state = VND_CMD_AUTH_STATE_NEEDED;1023 app_reply->ports[pcnt].auth_state =1024 VND_CMD_AUTH_STATE_NEEDED;1025 } else {1026 app_reply->ports[pcnt].auth_state =1027 VND_CMD_AUTH_STATE_ELS_RCVD;1028 }1029 break;1030 default:1031 app_reply->ports[pcnt].auth_state = fcport->edif.auth_state;1032 break;1033 }1034 1035 memcpy(app_reply->ports[pcnt].remote_wwpn,1036 fcport->port_name, 8);1037 1038 app_reply->ports[pcnt].remote_state =1039 (atomic_read(&fcport->state) ==1040 FCS_ONLINE ? 1 : 0);1041 1042 pcnt++;1043 1044 if (tdid.b24 != 0)1045 break;1046 }1047 app_reply->port_count = pcnt;1048 SET_DID_STATUS(bsg_reply->result, DID_OK);1049 }1050 1051 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1052 bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,1053 bsg_job->reply_payload.sg_cnt,1054 app_reply,1055 sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * pcnt);1056 1057 kfree(app_reply);1058 1059 return rval;1060}1061 1062/**1063 * qla_edif_app_getstats - app would like to read various statistics info1064 * @vha: host adapter pointer1065 * @bsg_job: user request1066 */1067static int32_t1068qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)1069{1070 int32_t rval = 0;1071 struct fc_bsg_reply *bsg_reply = bsg_job->reply;1072 uint32_t size;1073 1074 struct app_sinfo_req app_req;1075 struct app_stats_reply *app_reply;1076 uint32_t pcnt = 0;1077 1078 sg_copy_to_buffer(bsg_job->request_payload.sg_list,1079 bsg_job->request_payload.sg_cnt, &app_req,1080 sizeof(struct app_sinfo_req));1081 if (app_req.num_ports == 0) {1082 ql_dbg(ql_dbg_async, vha, 0x911d,1083 "%s app did not indicate number of ports to return\n",1084 __func__);1085 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1086 rval = -1;1087 }1088 1089 size = sizeof(struct app_stats_reply) +1090 (sizeof(struct app_sinfo) * app_req.num_ports);1091 1092 app_reply = kzalloc(size, GFP_KERNEL);1093 if (!app_reply) {1094 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1095 rval = -1;1096 } else {1097 struct fc_port *fcport = NULL, *tf;1098 1099 app_reply->version = EDIF_VERSION1;1100 1101 list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {1102 if (fcport->edif.enable) {1103 if (pcnt >= app_req.num_ports)1104 break;1105 1106 app_reply->elem[pcnt].rekey_count =1107 fcport->edif.rekey_cnt;1108 app_reply->elem[pcnt].tx_bytes =1109 fcport->edif.tx_bytes;1110 app_reply->elem[pcnt].rx_bytes =1111 fcport->edif.rx_bytes;1112 1113 memcpy(app_reply->elem[pcnt].remote_wwpn,1114 fcport->port_name, 8);1115 1116 pcnt++;1117 }1118 }1119 app_reply->elem_count = pcnt;1120 SET_DID_STATUS(bsg_reply->result, DID_OK);1121 }1122 1123 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1124 bsg_reply->reply_payload_rcv_len =1125 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,1126 bsg_job->reply_payload.sg_cnt, app_reply,1127 sizeof(struct app_stats_reply) + (sizeof(struct app_sinfo) * pcnt));1128 1129 kfree(app_reply);1130 1131 return rval;1132}1133 1134static int32_t1135qla_edif_ack(scsi_qla_host_t *vha, struct bsg_job *bsg_job)1136{1137 struct fc_port *fcport;1138 struct aen_complete_cmd ack;1139 struct fc_bsg_reply *bsg_reply = bsg_job->reply;1140 1141 sg_copy_to_buffer(bsg_job->request_payload.sg_list,1142 bsg_job->request_payload.sg_cnt, &ack, sizeof(ack));1143 1144 ql_dbg(ql_dbg_edif, vha, 0x70cf,1145 "%s: %06x event_code %x\n",1146 __func__, ack.port_id.b24, ack.event_code);1147 1148 fcport = qla2x00_find_fcport_by_pid(vha, &ack.port_id);1149 SET_DID_STATUS(bsg_reply->result, DID_OK);1150 1151 if (!fcport) {1152 ql_dbg(ql_dbg_edif, vha, 0x70cf,1153 "%s: unable to find fcport %06x \n",1154 __func__, ack.port_id.b24);1155 return 0;1156 }1157 1158 switch (ack.event_code) {1159 case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:1160 fcport->edif.sess_down_acked = 1;1161 break;1162 default:1163 break;1164 }1165 return 0;1166}1167 1168static int qla_edif_consume_dbell(scsi_qla_host_t *vha, struct bsg_job *bsg_job)1169{1170 struct fc_bsg_reply *bsg_reply = bsg_job->reply;1171 u32 sg_skip, reply_payload_len;1172 bool keep;1173 struct edb_node *dbnode = NULL;1174 struct edif_app_dbell ap;1175 int dat_size = 0;1176 1177 sg_skip = 0;1178 reply_payload_len = bsg_job->reply_payload.payload_len;1179 1180 while ((reply_payload_len - sg_skip) >= sizeof(struct edb_node)) {1181 dbnode = qla_edb_getnext(vha);1182 if (dbnode) {1183 keep = true;1184 dat_size = 0;1185 ap.event_code = dbnode->ntype;1186 switch (dbnode->ntype) {1187 case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:1188 case VND_CMD_AUTH_STATE_NEEDED:1189 ap.port_id = dbnode->u.plogi_did;1190 dat_size += sizeof(ap.port_id);1191 break;1192 case VND_CMD_AUTH_STATE_ELS_RCVD:1193 ap.port_id = dbnode->u.els_sid;1194 dat_size += sizeof(ap.port_id);1195 break;1196 case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:1197 ap.port_id = dbnode->u.sa_aen.port_id;1198 memcpy(&ap.event_data, &dbnode->u,1199 sizeof(struct edif_sa_update_aen));1200 dat_size += sizeof(struct edif_sa_update_aen);1201 break;1202 default:1203 keep = false;1204 ql_log(ql_log_warn, vha, 0x09102,1205 "%s unknown DB type=%d %p\n",1206 __func__, dbnode->ntype, dbnode);1207 break;1208 }1209 ap.event_data_size = dat_size;1210 /* 8 = sizeof(ap.event_code + ap.event_data_size) */1211 dat_size += 8;1212 if (keep)1213 sg_skip += sg_copy_buffer(bsg_job->reply_payload.sg_list,1214 bsg_job->reply_payload.sg_cnt,1215 &ap, dat_size, sg_skip, false);1216 1217 ql_dbg(ql_dbg_edif, vha, 0x09102,1218 "%s Doorbell consumed : type=%d %p\n",1219 __func__, dbnode->ntype, dbnode);1220 1221 kfree(dbnode);1222 } else {1223 break;1224 }1225 }1226 1227 SET_DID_STATUS(bsg_reply->result, DID_OK);1228 bsg_reply->reply_payload_rcv_len = sg_skip;1229 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1230 1231 return 0;1232}1233 1234static void __qla_edif_dbell_bsg_done(scsi_qla_host_t *vha, struct bsg_job *bsg_job,1235 u32 delay)1236{1237 struct fc_bsg_reply *bsg_reply = bsg_job->reply;1238 1239 /* small sleep for doorbell events to accumulate */1240 if (delay)1241 msleep(delay);1242 1243 qla_edif_consume_dbell(vha, bsg_job);1244 1245 bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);1246}1247 1248static void qla_edif_dbell_bsg_done(scsi_qla_host_t *vha)1249{1250 unsigned long flags;1251 struct bsg_job *prev_bsg_job = NULL;1252 1253 spin_lock_irqsave(&vha->e_dbell.db_lock, flags);1254 if (vha->e_dbell.dbell_bsg_job) {1255 prev_bsg_job = vha->e_dbell.dbell_bsg_job;1256 vha->e_dbell.dbell_bsg_job = NULL;1257 }1258 spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);1259 1260 if (prev_bsg_job)1261 __qla_edif_dbell_bsg_done(vha, prev_bsg_job, 0);1262}1263 1264static int1265qla_edif_dbell_bsg(scsi_qla_host_t *vha, struct bsg_job *bsg_job)1266{1267 unsigned long flags;1268 bool return_bsg = false;1269 1270 /* flush previous dbell bsg */1271 qla_edif_dbell_bsg_done(vha);1272 1273 spin_lock_irqsave(&vha->e_dbell.db_lock, flags);1274 if (list_empty(&vha->e_dbell.head) && DBELL_ACTIVE(vha)) {1275 /*1276 * when the next db event happens, bsg_job will return.1277 * Otherwise, timer will return it.1278 */1279 vha->e_dbell.dbell_bsg_job = bsg_job;1280 vha->e_dbell.bsg_expire = jiffies + 10 * HZ;1281 } else {1282 return_bsg = true;1283 }1284 spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);1285 1286 if (return_bsg)1287 __qla_edif_dbell_bsg_done(vha, bsg_job, 1);1288 1289 return 0;1290}1291 1292int32_t1293qla_edif_app_mgmt(struct bsg_job *bsg_job)1294{1295 struct fc_bsg_request *bsg_request = bsg_job->request;1296 struct fc_bsg_reply *bsg_reply = bsg_job->reply;1297 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);1298 scsi_qla_host_t *vha = shost_priv(host);1299 struct app_id appcheck;1300 bool done = true;1301 int32_t rval = 0;1302 uint32_t vnd_sc = bsg_request->rqst_data.h_vendor.vendor_cmd[1];1303 u32 level = ql_dbg_edif;1304 1305 /* doorbell is high traffic */1306 if (vnd_sc == QL_VND_SC_READ_DBELL)1307 level = 0;1308 1309 ql_dbg(level, vha, 0x911d, "%s vnd subcmd=%x\n",1310 __func__, vnd_sc);1311 1312 sg_copy_to_buffer(bsg_job->request_payload.sg_list,1313 bsg_job->request_payload.sg_cnt, &appcheck,1314 sizeof(struct app_id));1315 1316 if (!vha->hw->flags.edif_enabled ||1317 test_bit(VPORT_DELETE, &vha->dpc_flags)) {1318 ql_dbg(level, vha, 0x911d,1319 "%s edif not enabled or vp delete. bsg ptr done %p. dpc_flags %lx\n",1320 __func__, bsg_job, vha->dpc_flags);1321 1322 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1323 goto done;1324 }1325 1326 if (!qla_edif_app_check(vha, appcheck)) {1327 ql_dbg(level, vha, 0x911d,1328 "%s app checked failed.\n",1329 __func__);1330 1331 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1332 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1333 goto done;1334 }1335 1336 switch (vnd_sc) {1337 case QL_VND_SC_SA_UPDATE:1338 done = false;1339 rval = qla24xx_sadb_update(bsg_job);1340 break;1341 case QL_VND_SC_APP_START:1342 rval = qla_edif_app_start(vha, bsg_job);1343 break;1344 case QL_VND_SC_APP_STOP:1345 rval = qla_edif_app_stop(vha, bsg_job);1346 break;1347 case QL_VND_SC_AUTH_OK:1348 rval = qla_edif_app_authok(vha, bsg_job);1349 break;1350 case QL_VND_SC_AUTH_FAIL:1351 rval = qla_edif_app_authfail(vha, bsg_job);1352 break;1353 case QL_VND_SC_GET_FCINFO:1354 rval = qla_edif_app_getfcinfo(vha, bsg_job);1355 break;1356 case QL_VND_SC_GET_STATS:1357 rval = qla_edif_app_getstats(vha, bsg_job);1358 break;1359 case QL_VND_SC_AEN_COMPLETE:1360 rval = qla_edif_ack(vha, bsg_job);1361 break;1362 case QL_VND_SC_READ_DBELL:1363 rval = qla_edif_dbell_bsg(vha, bsg_job);1364 done = false;1365 break;1366 default:1367 ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",1368 __func__,1369 bsg_request->rqst_data.h_vendor.vendor_cmd[1]);1370 rval = EXT_STATUS_INVALID_PARAM;1371 done = false;1372 break;1373 }1374 1375done:1376 if (done) {1377 ql_dbg(level, vha, 0x7009,1378 "%s: %d bsg ptr done %p\n", __func__, __LINE__, bsg_job);1379 bsg_job_done(bsg_job, bsg_reply->result,1380 bsg_reply->reply_payload_rcv_len);1381 }1382 1383 return rval;1384}1385 1386static struct edif_sa_ctl *1387qla_edif_add_sa_ctl(fc_port_t *fcport, struct qla_sa_update_frame *sa_frame,1388 int dir)1389{1390 struct edif_sa_ctl *sa_ctl;1391 struct qla_sa_update_frame *sap;1392 int index = sa_frame->fast_sa_index;1393 unsigned long flags = 0;1394 1395 sa_ctl = kzalloc(sizeof(*sa_ctl), GFP_KERNEL);1396 if (!sa_ctl) {1397 /* couldn't get space */1398 ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,1399 "unable to allocate SA CTL\n");1400 return NULL;1401 }1402 1403 /*1404 * need to allocate sa_index here and save it1405 * in both sa_ctl->index and sa_frame->fast_sa_index;1406 * If alloc fails then delete sa_ctl and return NULL1407 */1408 INIT_LIST_HEAD(&sa_ctl->next);1409 sap = &sa_ctl->sa_frame;1410 *sap = *sa_frame;1411 sa_ctl->index = index;1412 sa_ctl->fcport = fcport;1413 sa_ctl->flags = 0;1414 sa_ctl->state = 0L;1415 ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,1416 "%s: Added sa_ctl %p, index %d, state 0x%lx\n",1417 __func__, sa_ctl, sa_ctl->index, sa_ctl->state);1418 spin_lock_irqsave(&fcport->edif.sa_list_lock, flags);1419 if (dir == SAU_FLG_TX)1420 list_add_tail(&sa_ctl->next, &fcport->edif.tx_sa_list);1421 else1422 list_add_tail(&sa_ctl->next, &fcport->edif.rx_sa_list);1423 spin_unlock_irqrestore(&fcport->edif.sa_list_lock, flags);1424 1425 return sa_ctl;1426}1427 1428void1429qla_edif_flush_sa_ctl_lists(fc_port_t *fcport)1430{1431 struct edif_sa_ctl *sa_ctl, *tsa_ctl;1432 unsigned long flags = 0;1433 1434 spin_lock_irqsave(&fcport->edif.sa_list_lock, flags);1435 1436 list_for_each_entry_safe(sa_ctl, tsa_ctl, &fcport->edif.tx_sa_list,1437 next) {1438 list_del(&sa_ctl->next);1439 kfree(sa_ctl);1440 }1441 1442 list_for_each_entry_safe(sa_ctl, tsa_ctl, &fcport->edif.rx_sa_list,1443 next) {1444 list_del(&sa_ctl->next);1445 kfree(sa_ctl);1446 }1447 1448 spin_unlock_irqrestore(&fcport->edif.sa_list_lock, flags);1449}1450 1451struct edif_sa_ctl *1452qla_edif_find_sa_ctl_by_index(fc_port_t *fcport, int index, int dir)1453{1454 struct edif_sa_ctl *sa_ctl, *tsa_ctl;1455 struct list_head *sa_list;1456 1457 if (dir == SAU_FLG_TX)1458 sa_list = &fcport->edif.tx_sa_list;1459 else1460 sa_list = &fcport->edif.rx_sa_list;1461 1462 list_for_each_entry_safe(sa_ctl, tsa_ctl, sa_list, next) {1463 if (test_bit(EDIF_SA_CTL_USED, &sa_ctl->state) &&1464 sa_ctl->index == index)1465 return sa_ctl;1466 }1467 return NULL;1468}1469 1470/* add the sa to the correct list */1471static int1472qla24xx_check_sadb_avail_slot(struct bsg_job *bsg_job, fc_port_t *fcport,1473 struct qla_sa_update_frame *sa_frame)1474{1475 struct edif_sa_ctl *sa_ctl = NULL;1476 int dir;1477 uint16_t sa_index;1478 1479 dir = (sa_frame->flags & SAU_FLG_TX);1480 1481 /* map the spi to an sa_index */1482 sa_index = qla_edif_sadb_get_sa_index(fcport, sa_frame);1483 if (sa_index == RX_DELETE_NO_EDIF_SA_INDEX) {1484 /* process rx delete */1485 ql_dbg(ql_dbg_edif, fcport->vha, 0x3063,1486 "%s: rx delete for lid 0x%x, spi 0x%x, no entry found\n",1487 __func__, fcport->loop_id, sa_frame->spi);1488 1489 /* build and send the aen */1490 fcport->edif.rx_sa_set = 1;1491 fcport->edif.rx_sa_pending = 0;1492 qla_edb_eventcreate(fcport->vha,1493 VND_CMD_AUTH_STATE_SAUPDATE_COMPL,1494 QL_VND_SA_STAT_SUCCESS,1495 QL_VND_RX_SA_KEY, fcport);1496 1497 /* force a return of good bsg status; */1498 return RX_DELETE_NO_EDIF_SA_INDEX;1499 } else if (sa_index == INVALID_EDIF_SA_INDEX) {1500 ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,1501 "%s: Failed to get sa_index for spi 0x%x, dir: %d\n",1502 __func__, sa_frame->spi, dir);1503 return INVALID_EDIF_SA_INDEX;1504 }1505 1506 ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,1507 "%s: index %d allocated to spi 0x%x, dir: %d, nport_handle: 0x%x\n",1508 __func__, sa_index, sa_frame->spi, dir, fcport->loop_id);1509 1510 /* This is a local copy of sa_frame. */1511 sa_frame->fast_sa_index = sa_index;1512 /* create the sa_ctl */1513 sa_ctl = qla_edif_add_sa_ctl(fcport, sa_frame, dir);1514 if (!sa_ctl) {1515 ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,1516 "%s: Failed to add sa_ctl for spi 0x%x, dir: %d, sa_index: %d\n",1517 __func__, sa_frame->spi, dir, sa_index);1518 return -1;1519 }1520 1521 set_bit(EDIF_SA_CTL_USED, &sa_ctl->state);1522 1523 if (dir == SAU_FLG_TX)1524 fcport->edif.tx_rekey_cnt++;1525 else1526 fcport->edif.rx_rekey_cnt++;1527 1528 ql_dbg(ql_dbg_edif, fcport->vha, 0x9100,1529 "%s: Found sa_ctl %p, index %d, state 0x%lx, tx_cnt %d, rx_cnt %d, nport_handle: 0x%x\n",1530 __func__, sa_ctl, sa_ctl->index, sa_ctl->state,1531 fcport->edif.tx_rekey_cnt,1532 fcport->edif.rx_rekey_cnt, fcport->loop_id);1533 1534 return 0;1535}1536 1537#define QLA_SA_UPDATE_FLAGS_RX_KEY 0x01538#define QLA_SA_UPDATE_FLAGS_TX_KEY 0x21539#define EDIF_MSLEEP_INTERVAL 1001540#define EDIF_RETRY_COUNT 501541 1542int1543qla24xx_sadb_update(struct bsg_job *bsg_job)1544{1545 struct fc_bsg_reply *bsg_reply = bsg_job->reply;1546 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);1547 scsi_qla_host_t *vha = shost_priv(host);1548 fc_port_t *fcport = NULL;1549 srb_t *sp = NULL;1550 struct edif_list_entry *edif_entry = NULL;1551 int found = 0;1552 int rval = 0;1553 int result = 0, cnt;1554 struct qla_sa_update_frame sa_frame;1555 struct srb_iocb *iocb_cmd;1556 port_id_t portid;1557 1558 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d,1559 "%s entered, vha: 0x%p\n", __func__, vha);1560 1561 sg_copy_to_buffer(bsg_job->request_payload.sg_list,1562 bsg_job->request_payload.sg_cnt, &sa_frame,1563 sizeof(struct qla_sa_update_frame));1564 1565 /* Check if host is online */1566 if (!vha->flags.online) {1567 ql_log(ql_log_warn, vha, 0x70a1, "Host is not online\n");1568 rval = -EIO;1569 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1570 goto done;1571 }1572 1573 if (DBELL_INACTIVE(vha)) {1574 ql_log(ql_log_warn, vha, 0x70a1, "App not started\n");1575 rval = -EIO;1576 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1577 goto done;1578 }1579 1580 /* silent unaligned access warning */1581 portid.b.domain = sa_frame.port_id.b.domain;1582 portid.b.area = sa_frame.port_id.b.area;1583 portid.b.al_pa = sa_frame.port_id.b.al_pa;1584 1585 fcport = qla2x00_find_fcport_by_pid(vha, &portid);1586 if (fcport) {1587 found = 1;1588 if (sa_frame.flags == QLA_SA_UPDATE_FLAGS_TX_KEY)1589 fcport->edif.tx_bytes = 0;1590 if (sa_frame.flags == QLA_SA_UPDATE_FLAGS_RX_KEY)1591 fcport->edif.rx_bytes = 0;1592 }1593 1594 if (!found) {1595 ql_dbg(ql_dbg_edif, vha, 0x70a3, "Failed to find port= %06x\n",1596 sa_frame.port_id.b24);1597 rval = -EINVAL;1598 SET_DID_STATUS(bsg_reply->result, DID_NO_CONNECT);1599 goto done;1600 }1601 1602 /* make sure the nport_handle is valid */1603 if (fcport->loop_id == FC_NO_LOOP_ID) {1604 ql_dbg(ql_dbg_edif, vha, 0x70e1,1605 "%s: %8phN lid=FC_NO_LOOP_ID, spi: 0x%x, DS %d, returning NO_CONNECT\n",1606 __func__, fcport->port_name, sa_frame.spi,1607 fcport->disc_state);1608 rval = -EINVAL;1609 SET_DID_STATUS(bsg_reply->result, DID_NO_CONNECT);1610 goto done;1611 }1612 1613 /* allocate and queue an sa_ctl */1614 result = qla24xx_check_sadb_avail_slot(bsg_job, fcport, &sa_frame);1615 1616 /* failure of bsg */1617 if (result == INVALID_EDIF_SA_INDEX) {1618 ql_dbg(ql_dbg_edif, vha, 0x70e1,1619 "%s: %8phN, skipping update.\n",1620 __func__, fcport->port_name);1621 rval = -EINVAL;1622 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1623 goto done;1624 1625 /* rx delete failure */1626 } else if (result == RX_DELETE_NO_EDIF_SA_INDEX) {1627 ql_dbg(ql_dbg_edif, vha, 0x70e1,1628 "%s: %8phN, skipping rx delete.\n",1629 __func__, fcport->port_name);1630 SET_DID_STATUS(bsg_reply->result, DID_OK);1631 goto done;1632 }1633 1634 ql_dbg(ql_dbg_edif, vha, 0x70e1,1635 "%s: %8phN, sa_index in sa_frame: %d flags %xh\n",1636 __func__, fcport->port_name, sa_frame.fast_sa_index,1637 sa_frame.flags);1638 1639 /* looking for rx index and delete */1640 if (((sa_frame.flags & SAU_FLG_TX) == 0) &&1641 (sa_frame.flags & SAU_FLG_INV)) {1642 uint16_t nport_handle = fcport->loop_id;1643 uint16_t sa_index = sa_frame.fast_sa_index;1644 1645 /*1646 * make sure we have an existing rx key, otherwise just process1647 * this as a straight delete just like TX1648 * This is NOT a normal case, it indicates an error recovery or key cleanup1649 * by the ipsec code above us.1650 */1651 edif_entry = qla_edif_list_find_sa_index(fcport, fcport->loop_id);1652 if (!edif_entry) {1653 ql_dbg(ql_dbg_edif, vha, 0x911d,1654 "%s: WARNING: no active sa_index for nport_handle 0x%x, forcing delete for sa_index 0x%x\n",1655 __func__, fcport->loop_id, sa_index);1656 goto force_rx_delete;1657 }1658 1659 /*1660 * if we have a forced delete for rx, remove the sa_index from the edif list1661 * and proceed with normal delete. The rx delay timer should not be running1662 */1663 if ((sa_frame.flags & SAU_FLG_FORCE_DELETE) == SAU_FLG_FORCE_DELETE) {1664 qla_edif_list_delete_sa_index(fcport, edif_entry);1665 ql_dbg(ql_dbg_edif, vha, 0x911d,1666 "%s: FORCE DELETE flag found for nport_handle 0x%x, sa_index 0x%x, forcing DELETE\n",1667 __func__, fcport->loop_id, sa_index);1668 kfree(edif_entry);1669 goto force_rx_delete;1670 }1671 1672 /*1673 * delayed rx delete1674 *1675 * if delete_sa_index is not invalid then there is already1676 * a delayed index in progress, return bsg bad status1677 */1678 if (edif_entry->delete_sa_index != INVALID_EDIF_SA_INDEX) {1679 struct edif_sa_ctl *sa_ctl;1680 1681 ql_dbg(ql_dbg_edif, vha, 0x911d,1682 "%s: delete for lid 0x%x, delete_sa_index %d is pending\n",1683 __func__, edif_entry->handle, edif_entry->delete_sa_index);1684 1685 /* free up the sa_ctl that was allocated with the sa_index */1686 sa_ctl = qla_edif_find_sa_ctl_by_index(fcport, sa_index,1687 (sa_frame.flags & SAU_FLG_TX));1688 if (sa_ctl) {1689 ql_dbg(ql_dbg_edif, vha, 0x3063,1690 "%s: freeing sa_ctl for index %d\n",1691 __func__, sa_ctl->index);1692 qla_edif_free_sa_ctl(fcport, sa_ctl, sa_ctl->index);1693 }1694 1695 /* release the sa_index */1696 ql_dbg(ql_dbg_edif, vha, 0x3063,1697 "%s: freeing sa_index %d, nph: 0x%x\n",1698 __func__, sa_index, nport_handle);1699 qla_edif_sadb_delete_sa_index(fcport, nport_handle, sa_index);1700 1701 rval = -EINVAL;1702 SET_DID_STATUS(bsg_reply->result, DID_ERROR);1703 goto done;1704 }1705 1706 fcport->edif.rekey_cnt++;1707 1708 /* configure and start the rx delay timer */1709 edif_entry->fcport = fcport;1710 edif_entry->timer.expires = jiffies + RX_DELAY_DELETE_TIMEOUT * HZ;1711 1712 ql_dbg(ql_dbg_edif, vha, 0x911d,1713 "%s: adding timer, entry: %p, delete sa_index %d, lid 0x%x to edif_list\n",1714 __func__, edif_entry, sa_index, nport_handle);1715 1716 /*1717 * Start the timer when we queue the delayed rx delete.1718 * This is an activity timer that goes off if we have not1719 * received packets with the new sa_index1720 */1721 add_timer(&edif_entry->timer);1722 1723 /*1724 * sa_delete for rx key with an active rx key including this one1725 * add the delete rx sa index to the hash so we can look for it1726 * in the rsp queue. Do this after making any changes to the1727 * edif_entry as part of the rx delete.1728 */1729 1730 ql_dbg(ql_dbg_edif, vha, 0x911d,1731 "%s: delete sa_index %d, lid 0x%x to edif_list. bsg done ptr %p\n",1732 __func__, sa_index, nport_handle, bsg_job);1733 1734 edif_entry->delete_sa_index = sa_index;1735 1736 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1737 bsg_reply->result = DID_OK << 16;1738 1739 goto done;1740 1741 /*1742 * rx index and update1743 * add the index to the list and continue with normal update1744 */1745 } else if (((sa_frame.flags & SAU_FLG_TX) == 0) &&1746 ((sa_frame.flags & SAU_FLG_INV) == 0)) {1747 /* sa_update for rx key */1748 uint32_t nport_handle = fcport->loop_id;1749 uint16_t sa_index = sa_frame.fast_sa_index;1750 int result;1751 1752 /*1753 * add the update rx sa index to the hash so we can look for it1754 * in the rsp queue and continue normally1755 */1756 1757 ql_dbg(ql_dbg_edif, vha, 0x911d,1758 "%s: adding update sa_index %d, lid 0x%x to edif_list\n",1759 __func__, sa_index, nport_handle);1760 1761 result = qla_edif_list_add_sa_update_index(fcport, sa_index,1762 nport_handle);1763 if (result) {1764 ql_dbg(ql_dbg_edif, vha, 0x911d,1765 "%s: SA_UPDATE failed to add new sa index %d to list for lid 0x%x\n",1766 __func__, sa_index, nport_handle);1767 }1768 }1769 if (sa_frame.flags & SAU_FLG_GMAC_MODE)1770 fcport->edif.aes_gmac = 1;1771 else1772 fcport->edif.aes_gmac = 0;1773 1774force_rx_delete:1775 /*1776 * sa_update for both rx and tx keys, sa_delete for tx key1777 * immediately process the request1778 */1779 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);1780 if (!sp) {1781 rval = -ENOMEM;1782 SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);1783 goto done;1784 }1785 1786 sp->type = SRB_SA_UPDATE;1787 sp->name = "bsg_sa_update";1788 sp->u.bsg_job = bsg_job;1789 /* sp->free = qla2x00_bsg_sp_free; */1790 sp->free = qla2x00_rel_sp;1791 sp->done = qla2x00_bsg_job_done;1792 iocb_cmd = &sp->u.iocb_cmd;1793 iocb_cmd->u.sa_update.sa_frame = sa_frame;1794 cnt = 0;1795retry:1796 rval = qla2x00_start_sp(sp);1797 switch (rval) {1798 case QLA_SUCCESS:1799 break;1800 case EAGAIN:1801 msleep(EDIF_MSLEEP_INTERVAL);1802 cnt++;1803 if (cnt < EDIF_RETRY_COUNT)1804 goto retry;1805 1806 fallthrough;1807 default:1808 ql_log(ql_dbg_edif, vha, 0x70e3,1809 "%s qla2x00_start_sp failed=%d.\n",1810 __func__, rval);1811 1812 qla2x00_rel_sp(sp);1813 rval = -EIO;1814 SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);1815 goto done;1816 }1817 1818 ql_dbg(ql_dbg_edif, vha, 0x911d,1819 "%s: %s sent, hdl=%x, portid=%06x.\n",1820 __func__, sp->name, sp->handle, fcport->d_id.b24);1821 1822 fcport->edif.rekey_cnt++;1823 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1824 SET_DID_STATUS(bsg_reply->result, DID_OK);1825 1826 return 0;1827 1828/*1829 * send back error status1830 */1831done:1832 bsg_job->reply_len = sizeof(struct fc_bsg_reply);1833 ql_dbg(ql_dbg_edif, vha, 0x911d,1834 "%s:status: FAIL, result: 0x%x, bsg ptr done %p\n",1835 __func__, bsg_reply->result, bsg_job);1836 bsg_job_done(bsg_job, bsg_reply->result,1837 bsg_reply->reply_payload_rcv_len);1838 1839 return 0;1840}1841 1842static void1843qla_enode_free(scsi_qla_host_t *vha, struct enode *node)1844{1845 node->ntype = N_UNDEF;1846 kfree(node);1847}1848 1849/**1850 * qla_enode_init - initialize enode structs & lock1851 * @vha: host adapter pointer1852 *1853 * should only be called when driver attaching1854 */1855void1856qla_enode_init(scsi_qla_host_t *vha)1857{1858 struct qla_hw_data *ha = vha->hw;1859 char name[32];1860 1861 if (vha->pur_cinfo.enode_flags == ENODE_ACTIVE) {1862 /* list still active - error */1863 ql_dbg(ql_dbg_edif, vha, 0x09102, "%s enode still active\n",1864 __func__);1865 return;1866 }1867 1868 /* initialize lock which protects pur_core & init list */1869 spin_lock_init(&vha->pur_cinfo.pur_lock);1870 INIT_LIST_HEAD(&vha->pur_cinfo.head);1871 1872 snprintf(name, sizeof(name), "%s_%d_purex", QLA2XXX_DRIVER_NAME,1873 ha->pdev->device);1874}1875 1876/**1877 * qla_enode_stop - stop and clear and enode data1878 * @vha: host adapter pointer1879 *1880 * called when app notified it is exiting1881 */1882void1883qla_enode_stop(scsi_qla_host_t *vha)1884{1885 unsigned long flags;1886 struct enode *node, *q;1887 1888 if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {1889 /* doorbell list not enabled */1890 ql_dbg(ql_dbg_edif, vha, 0x09102,1891 "%s enode not active\n", __func__);1892 return;1893 }1894 1895 /* grab lock so list doesn't move */1896 spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);1897 1898 vha->pur_cinfo.enode_flags &= ~ENODE_ACTIVE; /* mark it not active */1899 1900 /* hopefully this is a null list at this point */1901 list_for_each_entry_safe(node, q, &vha->pur_cinfo.head, list) {1902 ql_dbg(ql_dbg_edif, vha, 0x910f,1903 "%s freeing enode type=%x, cnt=%x\n", __func__, node->ntype,1904 node->dinfo.nodecnt);1905 list_del_init(&node->list);1906 qla_enode_free(vha, node);1907 }1908 spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);1909}1910 1911static void qla_enode_clear(scsi_qla_host_t *vha, port_id_t portid)1912{1913 unsigned long flags;1914 struct enode *e, *tmp;1915 struct purexevent *purex;1916 LIST_HEAD(enode_list);1917 1918 if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {1919 ql_dbg(ql_dbg_edif, vha, 0x09102,1920 "%s enode not active\n", __func__);1921 return;1922 }1923 spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);1924 list_for_each_entry_safe(e, tmp, &vha->pur_cinfo.head, list) {1925 purex = &e->u.purexinfo;1926 if (purex->pur_info.pur_sid.b24 == portid.b24) {1927 ql_dbg(ql_dbg_edif, vha, 0x911d,1928 "%s free ELS sid=%06x. xchg %x, nb=%xh\n",1929 __func__, portid.b24,1930 purex->pur_info.pur_rx_xchg_address,1931 purex->pur_info.pur_bytes_rcvd);1932 1933 list_del_init(&e->list);1934 list_add_tail(&e->list, &enode_list);1935 }1936 }1937 spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);1938 1939 list_for_each_entry_safe(e, tmp, &enode_list, list) {1940 list_del_init(&e->list);1941 qla_enode_free(vha, e);1942 }1943}1944 1945/*1946 * allocate enode struct and populate buffer1947 * returns: enode pointer with buffers1948 * NULL on error1949 */1950static struct enode *1951qla_enode_alloc(scsi_qla_host_t *vha, uint32_t ntype)1952{1953 struct enode *node;1954 struct purexevent *purex;1955 1956 node = kzalloc(RX_ELS_SIZE, GFP_ATOMIC);1957 if (!node)1958 return NULL;1959 1960 purex = &node->u.purexinfo;1961 purex->msgp = (u8 *)(node + 1);1962 purex->msgp_len = ELS_MAX_PAYLOAD;1963 1964 node->ntype = ntype;1965 INIT_LIST_HEAD(&node->list);1966 return node;1967}1968 1969static void1970qla_enode_add(scsi_qla_host_t *vha, struct enode *ptr)1971{1972 unsigned long flags;1973 1974 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x9109,1975 "%s add enode for type=%x, cnt=%x\n",1976 __func__, ptr->ntype, ptr->dinfo.nodecnt);1977 1978 spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);1979 list_add_tail(&ptr->list, &vha->pur_cinfo.head);1980 spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);1981 1982 return;1983}1984 1985static struct enode *1986qla_enode_find(scsi_qla_host_t *vha, uint32_t ntype, uint32_t p1, uint32_t p2)1987{1988 struct enode *node_rtn = NULL;1989 struct enode *list_node, *q;1990 unsigned long flags;1991 uint32_t sid;1992 struct purexevent *purex;1993 1994 /* secure the list from moving under us */1995 spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);1996 1997 list_for_each_entry_safe(list_node, q, &vha->pur_cinfo.head, list) {1998 1999 /* node type determines what p1 and p2 are */2000 purex = &list_node->u.purexinfo;2001 sid = p1;2002 2003 if (purex->pur_info.pur_sid.b24 == sid) {2004 /* found it and its complete */2005 node_rtn = list_node;2006 list_del(&list_node->list);2007 break;2008 }2009 }2010 2011 spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);2012 2013 return node_rtn;2014}2015 2016/**2017 * qla_pur_get_pending - read/return authentication message sent2018 * from remote port2019 * @vha: host adapter pointer2020 * @fcport: session pointer2021 * @bsg_job: user request where the message is copy to.2022 */2023static int2024qla_pur_get_pending(scsi_qla_host_t *vha, fc_port_t *fcport,2025 struct bsg_job *bsg_job)2026{2027 struct enode *ptr;2028 struct purexevent *purex;2029 struct qla_bsg_auth_els_reply *rpl =2030 (struct qla_bsg_auth_els_reply *)bsg_job->reply;2031 2032 bsg_job->reply_len = sizeof(*rpl);2033 2034 ptr = qla_enode_find(vha, N_PUREX, fcport->d_id.b24, PUR_GET);2035 if (!ptr) {2036 ql_dbg(ql_dbg_edif, vha, 0x9111,2037 "%s no enode data found for %8phN sid=%06x\n",2038 __func__, fcport->port_name, fcport->d_id.b24);2039 SET_DID_STATUS(rpl->r.result, DID_IMM_RETRY);2040 return -EIO;2041 }2042 2043 /*2044 * enode is now off the linked list and is ours to deal with2045 */2046 purex = &ptr->u.purexinfo;2047 2048 /* Copy info back to caller */2049 rpl->rx_xchg_address = purex->pur_info.pur_rx_xchg_address;2050 2051 SET_DID_STATUS(rpl->r.result, DID_OK);2052 rpl->r.reply_payload_rcv_len =2053 sg_pcopy_from_buffer(bsg_job->reply_payload.sg_list,2054 bsg_job->reply_payload.sg_cnt, purex->msgp,2055 purex->pur_info.pur_bytes_rcvd, 0);2056 2057 /* data copy / passback completed - destroy enode */2058 qla_enode_free(vha, ptr);2059 2060 return 0;2061}2062 2063/* it is assume qpair lock is held */2064static int2065qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp,2066 struct qla_els_pt_arg *a)2067{2068 struct els_entry_24xx *els_iocb;2069 2070 els_iocb = __qla2x00_alloc_iocbs(qp, NULL);2071 if (!els_iocb) {2072 ql_log(ql_log_warn, vha, 0x700c,2073 "qla2x00_alloc_iocbs failed.\n");2074 return QLA_FUNCTION_FAILED;2075 }2076 2077 qla_els_pt_iocb(vha, els_iocb, a);2078 2079 ql_dbg(ql_dbg_edif, vha, 0x0183,2080 "Sending ELS reject ox_id %04x s:%06x -> d:%06x\n",2081 a->ox_id, a->sid.b24, a->did.b24);2082 ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose, vha, 0x0185,2083 vha->hw->elsrej.c, sizeof(*vha->hw->elsrej.c));2084 /* flush iocb to mem before notifying hw doorbell */2085 wmb();2086 qla2x00_start_iocbs(vha, qp->req);2087 return 0;2088}2089 2090void2091qla_edb_init(scsi_qla_host_t *vha)2092{2093 if (DBELL_ACTIVE(vha)) {2094 /* list already init'd - error */2095 ql_dbg(ql_dbg_edif, vha, 0x09102,2096 "edif db already initialized, cannot reinit\n");2097 return;2098 }2099 2100 /* initialize lock which protects doorbell & init list */2101 spin_lock_init(&vha->e_dbell.db_lock);2102 INIT_LIST_HEAD(&vha->e_dbell.head);2103}2104 2105static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid)2106{2107 unsigned long flags;2108 struct edb_node *e, *tmp;2109 port_id_t sid;2110 LIST_HEAD(edb_list);2111 2112 if (DBELL_INACTIVE(vha)) {2113 /* doorbell list not enabled */2114 ql_dbg(ql_dbg_edif, vha, 0x09102,2115 "%s doorbell not enabled\n", __func__);2116 return;2117 }2118 2119 /* grab lock so list doesn't move */2120 spin_lock_irqsave(&vha->e_dbell.db_lock, flags);2121 list_for_each_entry_safe(e, tmp, &vha->e_dbell.head, list) {2122 switch (e->ntype) {2123 case VND_CMD_AUTH_STATE_NEEDED:2124 case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:2125 sid = e->u.plogi_did;2126 break;2127 case VND_CMD_AUTH_STATE_ELS_RCVD:2128 sid = e->u.els_sid;2129 break;2130 case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:2131 /* app wants to see this */2132 continue;2133 default:2134 ql_log(ql_log_warn, vha, 0x09102,2135 "%s unknown node type: %x\n", __func__, e->ntype);2136 sid.b24 = 0;2137 break;2138 }2139 if (sid.b24 == portid.b24) {2140 ql_dbg(ql_dbg_edif, vha, 0x910f,2141 "%s free doorbell event : node type = %x %p\n",2142 __func__, e->ntype, e);2143 list_del_init(&e->list);2144 list_add_tail(&e->list, &edb_list);2145 }2146 }2147 spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);2148 2149 list_for_each_entry_safe(e, tmp, &edb_list, list)2150 qla_edb_node_free(vha, e);2151}2152 2153/* function called when app is stopping */2154 2155void2156qla_edb_stop(scsi_qla_host_t *vha)2157{2158 unsigned long flags;2159 struct edb_node *node, *q;2160 2161 if (DBELL_INACTIVE(vha)) {2162 /* doorbell list not enabled */2163 ql_dbg(ql_dbg_edif, vha, 0x09102,2164 "%s doorbell not enabled\n", __func__);2165 return;2166 }2167 2168 /* grab lock so list doesn't move */2169 spin_lock_irqsave(&vha->e_dbell.db_lock, flags);2170 2171 vha->e_dbell.db_flags &= ~EDB_ACTIVE; /* mark it not active */2172 /* hopefully this is a null list at this point */2173 list_for_each_entry_safe(node, q, &vha->e_dbell.head, list) {2174 ql_dbg(ql_dbg_edif, vha, 0x910f,2175 "%s freeing edb_node type=%x\n",2176 __func__, node->ntype);2177 qla_edb_node_free(vha, node);2178 }2179 spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);2180 2181 qla_edif_dbell_bsg_done(vha);2182}2183 2184static struct edb_node *2185qla_edb_node_alloc(scsi_qla_host_t *vha, uint32_t ntype)2186{2187 struct edb_node *node;2188 2189 node = kzalloc(sizeof(*node), GFP_ATOMIC);2190 if (!node) {2191 /* couldn't get space */2192 ql_dbg(ql_dbg_edif, vha, 0x9100,2193 "edb node unable to be allocated\n");2194 return NULL;2195 }2196 2197 node->ntype = ntype;2198 INIT_LIST_HEAD(&node->list);2199 return node;2200}2201 2202/* adds a already allocated enode to the linked list */2203static bool2204qla_edb_node_add(scsi_qla_host_t *vha, struct edb_node *ptr)2205{2206 unsigned long flags;2207 2208 if (DBELL_INACTIVE(vha)) {2209 /* doorbell list not enabled */2210 ql_dbg(ql_dbg_edif, vha, 0x09102,2211 "%s doorbell not enabled\n", __func__);2212 return false;2213 }2214 2215 spin_lock_irqsave(&vha->e_dbell.db_lock, flags);2216 list_add_tail(&ptr->list, &vha->e_dbell.head);2217 spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);2218 2219 return true;2220}2221 2222/* adds event to doorbell list */2223void2224qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype,2225 uint32_t data, uint32_t data2, fc_port_t *sfcport)2226{2227 struct edb_node *edbnode;2228 fc_port_t *fcport = sfcport;2229 port_id_t id;2230 2231 if (!vha->hw->flags.edif_enabled) {2232 /* edif not enabled */2233 return;2234 }2235 2236 if (DBELL_INACTIVE(vha)) {2237 if (fcport)2238 fcport->edif.auth_state = dbtype;2239 /* doorbell list not enabled */2240 ql_dbg(ql_dbg_edif, vha, 0x09102,2241 "%s doorbell not enabled (type=%d\n", __func__, dbtype);2242 return;2243 }2244 2245 edbnode = qla_edb_node_alloc(vha, dbtype);2246 if (!edbnode) {2247 ql_dbg(ql_dbg_edif, vha, 0x09102,2248 "%s unable to alloc db node\n", __func__);2249 return;2250 }2251 2252 if (!fcport) {2253 id.b.domain = (data >> 16) & 0xff;2254 id.b.area = (data >> 8) & 0xff;2255 id.b.al_pa = data & 0xff;2256 ql_dbg(ql_dbg_edif, vha, 0x09222,2257 "%s: Arrived s_id: %06x\n", __func__,2258 id.b24);2259 fcport = qla2x00_find_fcport_by_pid(vha, &id);2260 if (!fcport) {2261 ql_dbg(ql_dbg_edif, vha, 0x09102,2262 "%s can't find fcport for sid= 0x%x - ignoring\n",2263 __func__, id.b24);2264 kfree(edbnode);2265 return;2266 }2267 }2268 2269 /* populate the edb node */2270 switch (dbtype) {2271 case VND_CMD_AUTH_STATE_NEEDED:2272 case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:2273 edbnode->u.plogi_did.b24 = fcport->d_id.b24;2274 break;2275 case VND_CMD_AUTH_STATE_ELS_RCVD:2276 edbnode->u.els_sid.b24 = fcport->d_id.b24;2277 break;2278 case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:2279 edbnode->u.sa_aen.port_id = fcport->d_id;2280 edbnode->u.sa_aen.status = data;2281 edbnode->u.sa_aen.key_type = data2;2282 edbnode->u.sa_aen.version = EDIF_VERSION1;2283 break;2284 default:2285 ql_dbg(ql_dbg_edif, vha, 0x09102,2286 "%s unknown type: %x\n", __func__, dbtype);2287 kfree(edbnode);2288 edbnode = NULL;2289 break;2290 }2291 2292 if (edbnode) {2293 if (!qla_edb_node_add(vha, edbnode)) {2294 ql_dbg(ql_dbg_edif, vha, 0x09102,2295 "%s unable to add dbnode\n", __func__);2296 kfree(edbnode);2297 return;2298 }2299 ql_dbg(ql_dbg_edif, vha, 0x09102,2300 "%s Doorbell produced : type=%d %p\n", __func__, dbtype, edbnode);2301 qla_edif_dbell_bsg_done(vha);2302 if (fcport)2303 fcport->edif.auth_state = dbtype;2304 }2305}2306 2307void2308qla_edif_timer(scsi_qla_host_t *vha)2309{2310 struct qla_hw_data *ha = vha->hw;2311 2312 if (!vha->vp_idx && N2N_TOPO(ha) && ha->flags.n2n_fw_acc_sec) {2313 if (DBELL_INACTIVE(vha) &&2314 ha->edif_post_stop_cnt_down) {2315 ha->edif_post_stop_cnt_down--;2316 2317 /*2318 * turn off auto 'Plogi Acc + secure=1' feature2319 * Set Add FW option[3]2320 * BIT_15, if.2321 */2322 if (ha->edif_post_stop_cnt_down == 0) {2323 ql_dbg(ql_dbg_async, vha, 0x911d,2324 "%s chip reset to turn off PLOGI ACC + secure\n",2325 __func__);2326 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);2327 }2328 } else {2329 ha->edif_post_stop_cnt_down = 60;2330 }2331 }2332 2333 if (vha->e_dbell.dbell_bsg_job && time_after_eq(jiffies, vha->e_dbell.bsg_expire))2334 qla_edif_dbell_bsg_done(vha);2335}2336 2337static void qla_noop_sp_done(srb_t *sp, int res)2338{2339 sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);2340 /* ref: INIT */2341 kref_put(&sp->cmd_kref, qla2x00_sp_release);2342}2343 2344/*2345 * Called from work queue2346 * build and send the sa_update iocb to delete an rx sa_index2347 */2348int2349qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e)2350{2351 srb_t *sp;2352 fc_port_t *fcport = NULL;2353 struct srb_iocb *iocb_cmd = NULL;2354 int rval = QLA_SUCCESS;2355 struct edif_sa_ctl *sa_ctl = e->u.sa_update.sa_ctl;2356 uint16_t nport_handle = e->u.sa_update.nport_handle;2357 2358 ql_dbg(ql_dbg_edif, vha, 0x70e6,2359 "%s: starting, sa_ctl: %p\n", __func__, sa_ctl);2360 2361 if (!sa_ctl) {2362 ql_dbg(ql_dbg_edif, vha, 0x70e6,2363 "sa_ctl allocation failed\n");2364 rval = -ENOMEM;2365 return rval;2366 }2367 2368 fcport = sa_ctl->fcport;2369 2370 /* Alloc SRB structure */2371 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);2372 if (!sp) {2373 ql_dbg(ql_dbg_edif, vha, 0x70e6,2374 "SRB allocation failed\n");2375 rval = -ENOMEM;2376 goto done;2377 }2378 2379 fcport->flags |= FCF_ASYNC_SENT;2380 iocb_cmd = &sp->u.iocb_cmd;2381 iocb_cmd->u.sa_update.sa_ctl = sa_ctl;2382 2383 ql_dbg(ql_dbg_edif, vha, 0x3073,2384 "Enter: SA REPL portid=%06x, sa_ctl %p, index %x, nport_handle: 0x%x\n",2385 fcport->d_id.b24, sa_ctl, sa_ctl->index, nport_handle);2386 /*2387 * if this is a sadb cleanup delete, mark it so the isr can2388 * take the correct action2389 */2390 if (sa_ctl->flags & EDIF_SA_CTL_FLG_CLEANUP_DEL) {2391 /* mark this srb as a cleanup delete */2392 sp->flags |= SRB_EDIF_CLEANUP_DELETE;2393 ql_dbg(ql_dbg_edif, vha, 0x70e6,2394 "%s: sp 0x%p flagged as cleanup delete\n", __func__, sp);2395 }2396 2397 sp->type = SRB_SA_REPLACE;2398 sp->name = "SA_REPLACE";2399 sp->fcport = fcport;2400 sp->free = qla2x00_rel_sp;2401 sp->done = qla_noop_sp_done;2402 2403 rval = qla2x00_start_sp(sp);2404 2405 if (rval != QLA_SUCCESS) {2406 goto done_free_sp;2407 }2408 2409 return rval;2410done_free_sp:2411 kref_put(&sp->cmd_kref, qla2x00_sp_release);2412 fcport->flags &= ~FCF_ASYNC_SENT;2413done:2414 fcport->flags &= ~FCF_ASYNC_ACTIVE;2415 return rval;2416}2417 2418void qla24xx_sa_update_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb)2419{2420 int itr = 0;2421 struct scsi_qla_host *vha = sp->vha;2422 struct qla_sa_update_frame *sa_frame =2423 &sp->u.iocb_cmd.u.sa_update.sa_frame;2424 u8 flags = 0;2425 2426 switch (sa_frame->flags & (SAU_FLG_INV | SAU_FLG_TX)) {2427 case 0:2428 ql_dbg(ql_dbg_edif, vha, 0x911d,2429 "%s: EDIF SA UPDATE RX IOCB vha: 0x%p index: %d\n",2430 __func__, vha, sa_frame->fast_sa_index);2431 break;2432 case 1:2433 ql_dbg(ql_dbg_edif, vha, 0x911d,2434 "%s: EDIF SA DELETE RX IOCB vha: 0x%p index: %d\n",2435 __func__, vha, sa_frame->fast_sa_index);2436 flags |= SA_FLAG_INVALIDATE;2437 break;2438 case 2:2439 ql_dbg(ql_dbg_edif, vha, 0x911d,2440 "%s: EDIF SA UPDATE TX IOCB vha: 0x%p index: %d\n",2441 __func__, vha, sa_frame->fast_sa_index);2442 flags |= SA_FLAG_TX;2443 break;2444 case 3:2445 ql_dbg(ql_dbg_edif, vha, 0x911d,2446 "%s: EDIF SA DELETE TX IOCB vha: 0x%p index: %d\n",2447 __func__, vha, sa_frame->fast_sa_index);2448 flags |= SA_FLAG_TX | SA_FLAG_INVALIDATE;2449 break;2450 }2451 2452 sa_update_iocb->entry_type = SA_UPDATE_IOCB_TYPE;2453 sa_update_iocb->entry_count = 1;2454 sa_update_iocb->sys_define = 0;2455 sa_update_iocb->entry_status = 0;2456 sa_update_iocb->handle = sp->handle;2457 sa_update_iocb->u.nport_handle = cpu_to_le16(sp->fcport->loop_id);2458 sa_update_iocb->vp_index = sp->fcport->vha->vp_idx;2459 sa_update_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;2460 sa_update_iocb->port_id[1] = sp->fcport->d_id.b.area;2461 sa_update_iocb->port_id[2] = sp->fcport->d_id.b.domain;2462 2463 sa_update_iocb->flags = flags;2464 sa_update_iocb->salt = cpu_to_le32(sa_frame->salt);2465 sa_update_iocb->spi = cpu_to_le32(sa_frame->spi);2466 sa_update_iocb->sa_index = cpu_to_le16(sa_frame->fast_sa_index);2467 2468 sa_update_iocb->sa_control |= SA_CNTL_ENC_FCSP;2469 if (sp->fcport->edif.aes_gmac)2470 sa_update_iocb->sa_control |= SA_CNTL_AES_GMAC;2471 2472 if (sa_frame->flags & SAU_FLG_KEY256) {2473 sa_update_iocb->sa_control |= SA_CNTL_KEY256;2474 for (itr = 0; itr < 32; itr++)2475 sa_update_iocb->sa_key[itr] = sa_frame->sa_key[itr];2476 } else {2477 sa_update_iocb->sa_control |= SA_CNTL_KEY128;2478 for (itr = 0; itr < 16; itr++)2479 sa_update_iocb->sa_key[itr] = sa_frame->sa_key[itr];2480 }2481 2482 ql_dbg(ql_dbg_edif, vha, 0x921d,2483 "%s SAU Port ID = %02x%02x%02x, flags=%xh, index=%u, ctl=%xh, SPI 0x%x flags 0x%x hdl=%x gmac %d\n",2484 __func__, sa_update_iocb->port_id[2], sa_update_iocb->port_id[1],2485 sa_update_iocb->port_id[0], sa_update_iocb->flags, sa_update_iocb->sa_index,2486 sa_update_iocb->sa_control, sa_update_iocb->spi, sa_frame->flags, sp->handle,2487 sp->fcport->edif.aes_gmac);2488 2489 if (sa_frame->flags & SAU_FLG_TX)2490 sp->fcport->edif.tx_sa_pending = 1;2491 else2492 sp->fcport->edif.rx_sa_pending = 1;2493 2494 sp->fcport->vha->qla_stats.control_requests++;2495}2496 2497void2498qla24xx_sa_replace_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb)2499{2500 struct scsi_qla_host *vha = sp->vha;2501 struct srb_iocb *srb_iocb = &sp->u.iocb_cmd;2502 struct edif_sa_ctl *sa_ctl = srb_iocb->u.sa_update.sa_ctl;2503 uint16_t nport_handle = sp->fcport->loop_id;2504 2505 sa_update_iocb->entry_type = SA_UPDATE_IOCB_TYPE;2506 sa_update_iocb->entry_count = 1;2507 sa_update_iocb->sys_define = 0;2508 sa_update_iocb->entry_status = 0;2509 sa_update_iocb->handle = sp->handle;2510 2511 sa_update_iocb->u.nport_handle = cpu_to_le16(nport_handle);2512 2513 sa_update_iocb->vp_index = sp->fcport->vha->vp_idx;2514 sa_update_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;2515 sa_update_iocb->port_id[1] = sp->fcport->d_id.b.area;2516 sa_update_iocb->port_id[2] = sp->fcport->d_id.b.domain;2517 2518 /* Invalidate the index. salt, spi, control & key are ignore */2519 sa_update_iocb->flags = SA_FLAG_INVALIDATE;2520 sa_update_iocb->salt = 0;2521 sa_update_iocb->spi = 0;2522 sa_update_iocb->sa_index = cpu_to_le16(sa_ctl->index);2523 sa_update_iocb->sa_control = 0;2524 2525 ql_dbg(ql_dbg_edif, vha, 0x921d,2526 "%s SAU DELETE RX Port ID = %02x:%02x:%02x, lid %d flags=%xh, index=%u, hdl=%x\n",2527 __func__, sa_update_iocb->port_id[2], sa_update_iocb->port_id[1],2528 sa_update_iocb->port_id[0], nport_handle, sa_update_iocb->flags,2529 sa_update_iocb->sa_index, sp->handle);2530 2531 sp->fcport->vha->qla_stats.control_requests++;2532}2533 2534void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)2535{2536 struct purex_entry_24xx *p = *pkt;2537 struct enode *ptr;2538 int sid;2539 u16 totlen;2540 struct purexevent *purex;2541 struct scsi_qla_host *host = NULL;2542 int rc;2543 struct fc_port *fcport;2544 struct qla_els_pt_arg a;2545 be_id_t beid;2546 2547 memset(&a, 0, sizeof(a));2548 2549 a.els_opcode = ELS_AUTH_ELS;2550 a.nport_handle = p->nport_handle;2551 a.rx_xchg_address = p->rx_xchg_addr;2552 a.did.b.domain = p->s_id[2];2553 a.did.b.area = p->s_id[1];2554 a.did.b.al_pa = p->s_id[0];2555 a.tx_byte_count = a.tx_len = sizeof(struct fc_els_ls_rjt);2556 a.tx_addr = vha->hw->elsrej.cdma;2557 a.vp_idx = vha->vp_idx;2558 a.control_flags = EPD_ELS_RJT;2559 a.ox_id = le16_to_cpu(p->ox_id);2560 2561 sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16);2562 2563 totlen = (le16_to_cpu(p->frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;2564 if (le16_to_cpu(p->status_flags) & 0x8000) {2565 totlen = le16_to_cpu(p->trunc_frame_size);2566 qla_els_reject_iocb(vha, (*rsp)->qpair, &a);2567 __qla_consume_iocb(vha, pkt, rsp);2568 return;2569 }2570 2571 if (totlen > ELS_MAX_PAYLOAD) {2572 ql_dbg(ql_dbg_edif, vha, 0x0910d,2573 "%s WARNING: verbose ELS frame received (totlen=%x)\n",2574 __func__, totlen);2575 qla_els_reject_iocb(vha, (*rsp)->qpair, &a);2576 __qla_consume_iocb(vha, pkt, rsp);2577 return;2578 }2579 2580 if (!vha->hw->flags.edif_enabled) {2581 /* edif support not enabled */2582 ql_dbg(ql_dbg_edif, vha, 0x910e, "%s edif not enabled\n",2583 __func__);2584 qla_els_reject_iocb(vha, (*rsp)->qpair, &a);2585 __qla_consume_iocb(vha, pkt, rsp);2586 return;2587 }2588 2589 ptr = qla_enode_alloc(vha, N_PUREX);2590 if (!ptr) {2591 ql_dbg(ql_dbg_edif, vha, 0x09109,2592 "WARNING: enode alloc failed for sid=%x\n",2593 sid);2594 qla_els_reject_iocb(vha, (*rsp)->qpair, &a);2595 __qla_consume_iocb(vha, pkt, rsp);2596 return;2597 }2598 2599 purex = &ptr->u.purexinfo;2600 purex->pur_info.pur_sid = a.did;2601 purex->pur_info.pur_bytes_rcvd = totlen;2602 purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr);2603 purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle);2604 purex->pur_info.pur_did.b.domain = p->d_id[2];2605 purex->pur_info.pur_did.b.area = p->d_id[1];2606 purex->pur_info.pur_did.b.al_pa = p->d_id[0];2607 purex->pur_info.vp_idx = p->vp_idx;2608 2609 a.sid = purex->pur_info.pur_did;2610 2611 rc = __qla_copy_purex_to_buffer(vha, pkt, rsp, purex->msgp,2612 purex->msgp_len);2613 if (rc) {2614 qla_els_reject_iocb(vha, (*rsp)->qpair, &a);2615 qla_enode_free(vha, ptr);2616 return;2617 }2618 beid.al_pa = purex->pur_info.pur_did.b.al_pa;2619 beid.area = purex->pur_info.pur_did.b.area;2620 beid.domain = purex->pur_info.pur_did.b.domain;2621 host = qla_find_host_by_d_id(vha, beid);2622 if (!host) {2623 ql_log(ql_log_fatal, vha, 0x508b,2624 "%s Drop ELS due to unable to find host %06x\n",2625 __func__, purex->pur_info.pur_did.b24);2626 2627 qla_els_reject_iocb(vha, (*rsp)->qpair, &a);2628 qla_enode_free(vha, ptr);2629 return;2630 }2631 2632 fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid);2633 2634 if (DBELL_INACTIVE(vha)) {2635 ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n",2636 __func__, host->e_dbell.db_flags,2637 fcport ? fcport->d_id.b24 : 0);2638 2639 qla_els_reject_iocb(host, (*rsp)->qpair, &a);2640 qla_enode_free(host, ptr);2641 return;2642 }2643 2644 if (fcport && EDIF_SESSION_DOWN(fcport)) {2645 ql_dbg(ql_dbg_edif, host, 0x13b6,2646 "%s terminate exchange. Send logo to 0x%x\n",2647 __func__, a.did.b24);2648 2649 a.tx_byte_count = a.tx_len = 0;2650 a.tx_addr = 0;2651 a.control_flags = EPD_RX_XCHG; /* EPD_RX_XCHG = terminate cmd */2652 qla_els_reject_iocb(host, (*rsp)->qpair, &a);2653 qla_enode_free(host, ptr);2654 /* send logo to let remote port knows to tear down session */2655 fcport->send_els_logo = 1;2656 qlt_schedule_sess_for_deletion(fcport);2657 return;2658 }2659 2660 /* add the local enode to the list */2661 qla_enode_add(host, ptr);2662 2663 ql_dbg(ql_dbg_edif, host, 0x0910c,2664 "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",2665 __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24,2666 purex->pur_info.pur_did.b24, purex->pur_info.pur_rx_xchg_address);2667 2668 qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL);2669}2670 2671static uint16_t qla_edif_get_sa_index_from_freepool(fc_port_t *fcport, int dir)2672{2673 struct scsi_qla_host *vha = fcport->vha;2674 struct qla_hw_data *ha = vha->hw;2675 void *sa_id_map;2676 unsigned long flags = 0;2677 u16 sa_index;2678 2679 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,2680 "%s: entry\n", __func__);2681 2682 if (dir)2683 sa_id_map = ha->edif_tx_sa_id_map;2684 else2685 sa_id_map = ha->edif_rx_sa_id_map;2686 2687 spin_lock_irqsave(&ha->sadb_fp_lock, flags);2688 sa_index = find_first_zero_bit(sa_id_map, EDIF_NUM_SA_INDEX);2689 if (sa_index >= EDIF_NUM_SA_INDEX) {2690 spin_unlock_irqrestore(&ha->sadb_fp_lock, flags);2691 return INVALID_EDIF_SA_INDEX;2692 }2693 set_bit(sa_index, sa_id_map);2694 spin_unlock_irqrestore(&ha->sadb_fp_lock, flags);2695 2696 if (dir)2697 sa_index += EDIF_TX_SA_INDEX_BASE;2698 2699 ql_dbg(ql_dbg_edif, vha, 0x3063,2700 "%s: index retrieved from free pool %d\n", __func__, sa_index);2701 2702 return sa_index;2703}2704 2705/* find an sadb entry for an nport_handle */2706static struct edif_sa_index_entry *2707qla_edif_sadb_find_sa_index_entry(uint16_t nport_handle,2708 struct list_head *sa_list)2709{2710 struct edif_sa_index_entry *entry;2711 struct edif_sa_index_entry *tentry;2712 struct list_head *indx_list = sa_list;2713 2714 list_for_each_entry_safe(entry, tentry, indx_list, next) {2715 if (entry->handle == nport_handle)2716 return entry;2717 }2718 return NULL;2719}2720 2721/* remove an sa_index from the nport_handle and return it to the free pool */2722static int qla_edif_sadb_delete_sa_index(fc_port_t *fcport, uint16_t nport_handle,2723 uint16_t sa_index)2724{2725 struct edif_sa_index_entry *entry;2726 struct list_head *sa_list;2727 int dir = (sa_index < EDIF_TX_SA_INDEX_BASE) ? 0 : 1;2728 int slot = 0;2729 int free_slot_count = 0;2730 scsi_qla_host_t *vha = fcport->vha;2731 struct qla_hw_data *ha = vha->hw;2732 unsigned long flags = 0;2733 2734 ql_dbg(ql_dbg_edif, vha, 0x3063,2735 "%s: entry\n", __func__);2736 2737 if (dir)2738 sa_list = &ha->sadb_tx_index_list;2739 else2740 sa_list = &ha->sadb_rx_index_list;2741 2742 entry = qla_edif_sadb_find_sa_index_entry(nport_handle, sa_list);2743 if (!entry) {2744 ql_dbg(ql_dbg_edif, vha, 0x3063,2745 "%s: no entry found for nport_handle 0x%x\n",2746 __func__, nport_handle);2747 return -1;2748 }2749 2750 spin_lock_irqsave(&ha->sadb_lock, flags);2751 /*2752 * each tx/rx direction has up to 2 sa indexes/slots. 1 slot for in flight traffic2753 * the other is use at re-key time.2754 */2755 for (slot = 0; slot < 2; slot++) {2756 if (entry->sa_pair[slot].sa_index == sa_index) {2757 entry->sa_pair[slot].sa_index = INVALID_EDIF_SA_INDEX;2758 entry->sa_pair[slot].spi = 0;2759 free_slot_count++;2760 qla_edif_add_sa_index_to_freepool(fcport, dir, sa_index);2761 } else if (entry->sa_pair[slot].sa_index == INVALID_EDIF_SA_INDEX) {2762 free_slot_count++;2763 }2764 }2765 2766 if (free_slot_count == 2) {2767 list_del(&entry->next);2768 kfree(entry);2769 }2770 spin_unlock_irqrestore(&ha->sadb_lock, flags);2771 2772 ql_dbg(ql_dbg_edif, vha, 0x3063,2773 "%s: sa_index %d removed, free_slot_count: %d\n",2774 __func__, sa_index, free_slot_count);2775 2776 return 0;2777}2778 2779void2780qla28xx_sa_update_iocb_entry(scsi_qla_host_t *v, struct req_que *req,2781 struct sa_update_28xx *pkt)2782{2783 const char *func = "SA_UPDATE_RESPONSE_IOCB";2784 srb_t *sp;2785 struct edif_sa_ctl *sa_ctl;2786 int old_sa_deleted = 1;2787 uint16_t nport_handle;2788 struct scsi_qla_host *vha;2789 2790 sp = qla2x00_get_sp_from_handle(v, func, req, pkt);2791 2792 if (!sp) {2793 ql_dbg(ql_dbg_edif, v, 0x3063,2794 "%s: no sp found for pkt\n", __func__);2795 return;2796 }2797 /* use sp->vha due to npiv */2798 vha = sp->vha;2799 2800 switch (pkt->flags & (SA_FLAG_INVALIDATE | SA_FLAG_TX)) {2801 case 0:2802 ql_dbg(ql_dbg_edif, vha, 0x3063,2803 "%s: EDIF SA UPDATE RX IOCB vha: 0x%p index: %d\n",2804 __func__, vha, pkt->sa_index);2805 break;2806 case 1:2807 ql_dbg(ql_dbg_edif, vha, 0x3063,2808 "%s: EDIF SA DELETE RX IOCB vha: 0x%p index: %d\n",2809 __func__, vha, pkt->sa_index);2810 break;2811 case 2:2812 ql_dbg(ql_dbg_edif, vha, 0x3063,2813 "%s: EDIF SA UPDATE TX IOCB vha: 0x%p index: %d\n",2814 __func__, vha, pkt->sa_index);2815 break;2816 case 3:2817 ql_dbg(ql_dbg_edif, vha, 0x3063,2818 "%s: EDIF SA DELETE TX IOCB vha: 0x%p index: %d\n",2819 __func__, vha, pkt->sa_index);2820 break;2821 }2822 2823 /*2824 * dig the nport handle out of the iocb, fcport->loop_id can not be trusted2825 * to be correct during cleanup sa_update iocbs.2826 */2827 nport_handle = sp->fcport->loop_id;2828 2829 ql_dbg(ql_dbg_edif, vha, 0x3063,2830 "%s: %8phN comp status=%x old_sa_info=%x new_sa_info=%x lid %d, index=0x%x pkt_flags %xh hdl=%x\n",2831 __func__, sp->fcport->port_name, pkt->u.comp_sts, pkt->old_sa_info, pkt->new_sa_info,2832 nport_handle, pkt->sa_index, pkt->flags, sp->handle);2833 2834 /* if rx delete, remove the timer */2835 if ((pkt->flags & (SA_FLAG_INVALIDATE | SA_FLAG_TX)) == SA_FLAG_INVALIDATE) {2836 struct edif_list_entry *edif_entry;2837 2838 sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);2839 2840 edif_entry = qla_edif_list_find_sa_index(sp->fcport, nport_handle);2841 if (edif_entry) {2842 ql_dbg(ql_dbg_edif, vha, 0x5033,2843 "%s: removing edif_entry %p, new sa_index: 0x%x\n",2844 __func__, edif_entry, pkt->sa_index);2845 qla_edif_list_delete_sa_index(sp->fcport, edif_entry);2846 timer_shutdown(&edif_entry->timer);2847 2848 ql_dbg(ql_dbg_edif, vha, 0x5033,2849 "%s: releasing edif_entry %p, new sa_index: 0x%x\n",2850 __func__, edif_entry, pkt->sa_index);2851 2852 kfree(edif_entry);2853 }2854 }2855 2856 /*2857 * if this is a delete for either tx or rx, make sure it succeeded.2858 * The new_sa_info field should be 0xffff on success2859 */2860 if (pkt->flags & SA_FLAG_INVALIDATE)2861 old_sa_deleted = (le16_to_cpu(pkt->new_sa_info) == 0xffff) ? 1 : 0;2862 2863 /* Process update and delete the same way */2864 2865 /* If this is an sadb cleanup delete, bypass sending events to IPSEC */2866 if (sp->flags & SRB_EDIF_CLEANUP_DELETE) {2867 sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);2868 ql_dbg(ql_dbg_edif, vha, 0x3063,2869 "%s: nph 0x%x, sa_index %d removed from fw\n",2870 __func__, sp->fcport->loop_id, pkt->sa_index);2871 2872 } else if ((pkt->entry_status == 0) && (pkt->u.comp_sts == 0) &&2873 old_sa_deleted) {2874 /*2875 * Note: Wa are only keeping track of latest SA,2876 * so we know when we can start enableing encryption per I/O.2877 * If all SA's get deleted, let FW reject the IOCB.2878 2879 * TODO: edif: don't set enabled here I think2880 * TODO: edif: prli complete is where it should be set2881 */2882 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,2883 "SA(%x)updated for s_id %02x%02x%02x\n",2884 pkt->new_sa_info,2885 pkt->port_id[2], pkt->port_id[1], pkt->port_id[0]);2886 sp->fcport->edif.enable = 1;2887 if (pkt->flags & SA_FLAG_TX) {2888 sp->fcport->edif.tx_sa_set = 1;2889 sp->fcport->edif.tx_sa_pending = 0;2890 qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,2891 QL_VND_SA_STAT_SUCCESS,2892 QL_VND_TX_SA_KEY, sp->fcport);2893 } else {2894 sp->fcport->edif.rx_sa_set = 1;2895 sp->fcport->edif.rx_sa_pending = 0;2896 qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,2897 QL_VND_SA_STAT_SUCCESS,2898 QL_VND_RX_SA_KEY, sp->fcport);2899 }2900 } else {2901 ql_dbg(ql_dbg_edif, vha, 0x3063,2902 "%s: %8phN SA update FAILED: sa_index: %d, new_sa_info %d, %02x%02x%02x\n",2903 __func__, sp->fcport->port_name, pkt->sa_index, pkt->new_sa_info,2904 pkt->port_id[2], pkt->port_id[1], pkt->port_id[0]);2905 2906 if (pkt->flags & SA_FLAG_TX)2907 qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,2908 (le16_to_cpu(pkt->u.comp_sts) << 16) | QL_VND_SA_STAT_FAILED,2909 QL_VND_TX_SA_KEY, sp->fcport);2910 else2911 qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SAUPDATE_COMPL,2912 (le16_to_cpu(pkt->u.comp_sts) << 16) | QL_VND_SA_STAT_FAILED,2913 QL_VND_RX_SA_KEY, sp->fcport);2914 }2915 2916 /* for delete, release sa_ctl, sa_index */2917 if (pkt->flags & SA_FLAG_INVALIDATE) {2918 /* release the sa_ctl */2919 sa_ctl = qla_edif_find_sa_ctl_by_index(sp->fcport,2920 le16_to_cpu(pkt->sa_index), (pkt->flags & SA_FLAG_TX));2921 if (sa_ctl &&2922 qla_edif_find_sa_ctl_by_index(sp->fcport, sa_ctl->index,2923 (pkt->flags & SA_FLAG_TX)) != NULL) {2924 ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x3063,2925 "%s: freeing sa_ctl for index %d\n",2926 __func__, sa_ctl->index);2927 qla_edif_free_sa_ctl(sp->fcport, sa_ctl, sa_ctl->index);2928 } else {2929 ql_dbg(ql_dbg_edif, vha, 0x3063,2930 "%s: sa_ctl NOT freed, sa_ctl: %p\n",2931 __func__, sa_ctl);2932 }2933 ql_dbg(ql_dbg_edif, vha, 0x3063,2934 "%s: freeing sa_index %d, nph: 0x%x\n",2935 __func__, le16_to_cpu(pkt->sa_index), nport_handle);2936 qla_edif_sadb_delete_sa_index(sp->fcport, nport_handle,2937 le16_to_cpu(pkt->sa_index));2938 /*2939 * check for a failed sa_update and remove2940 * the sadb entry.2941 */2942 } else if (pkt->u.comp_sts) {2943 ql_dbg(ql_dbg_edif, vha, 0x3063,2944 "%s: freeing sa_index %d, nph: 0x%x\n",2945 __func__, pkt->sa_index, nport_handle);2946 qla_edif_sadb_delete_sa_index(sp->fcport, nport_handle,2947 le16_to_cpu(pkt->sa_index));2948 switch (le16_to_cpu(pkt->u.comp_sts)) {2949 case CS_PORT_EDIF_UNAVAIL:2950 case CS_PORT_EDIF_LOGOUT:2951 qlt_schedule_sess_for_deletion(sp->fcport);2952 break;2953 default:2954 break;2955 }2956 }2957 2958 sp->done(sp, 0);2959}2960 2961/**2962 * qla28xx_start_scsi_edif() - Send a SCSI type 6 command to the ISP2963 * @sp: command to send to the ISP2964 *2965 * Return: non-zero if a failure occurred, else zero.2966 */2967int2968qla28xx_start_scsi_edif(srb_t *sp)2969{2970 int nseg;2971 unsigned long flags;2972 struct scsi_cmnd *cmd;2973 uint32_t *clr_ptr;2974 uint32_t index, i;2975 uint32_t handle;2976 uint16_t cnt;2977 int16_t req_cnt;2978 uint16_t tot_dsds;2979 __be32 *fcp_dl;2980 uint8_t additional_cdb_len;2981 struct ct6_dsd *ctx;2982 struct scsi_qla_host *vha = sp->vha;2983 struct qla_hw_data *ha = vha->hw;2984 struct cmd_type_6 *cmd_pkt;2985 struct dsd64 *cur_dsd;2986 uint8_t avail_dsds = 0;2987 struct scatterlist *sg;2988 struct req_que *req = sp->qpair->req;2989 spinlock_t *lock = sp->qpair->qp_lock_ptr;2990 2991 /* Setup device pointers. */2992 cmd = GET_CMD_SP(sp);2993 2994 /* So we know we haven't pci_map'ed anything yet */2995 tot_dsds = 0;2996 2997 /* Send marker if required */2998 if (vha->marker_needed != 0) {2999 if (qla2x00_marker(vha, sp->qpair, 0, 0, MK_SYNC_ALL) !=3000 QLA_SUCCESS) {3001 ql_log(ql_log_warn, vha, 0x300c,3002 "qla2x00_marker failed for cmd=%p.\n", cmd);3003 return QLA_FUNCTION_FAILED;3004 }3005 vha->marker_needed = 0;3006 }3007 3008 /* Acquire ring specific lock */3009 spin_lock_irqsave(lock, flags);3010 3011 /* Check for room in outstanding command list. */3012 handle = req->current_outstanding_cmd;3013 for (index = 1; index < req->num_outstanding_cmds; index++) {3014 handle++;3015 if (handle == req->num_outstanding_cmds)3016 handle = 1;3017 if (!req->outstanding_cmds[handle])3018 break;3019 }3020 if (index == req->num_outstanding_cmds)3021 goto queuing_error;3022 3023 /* Map the sg table so we have an accurate count of sg entries needed */3024 if (scsi_sg_count(cmd)) {3025 nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),3026 scsi_sg_count(cmd), cmd->sc_data_direction);3027 if (unlikely(!nseg))3028 goto queuing_error;3029 } else {3030 nseg = 0;3031 }3032 3033 tot_dsds = nseg;3034 req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);3035 3036 sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH;3037 sp->iores.exch_cnt = 1;3038 sp->iores.iocb_cnt = req_cnt;3039 if (qla_get_fw_resources(sp->qpair, &sp->iores))3040 goto queuing_error;3041 3042 if (req->cnt < (req_cnt + 2)) {3043 cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :3044 rd_reg_dword(req->req_q_out);3045 if (req->ring_index < cnt)3046 req->cnt = cnt - req->ring_index;3047 else3048 req->cnt = req->length -3049 (req->ring_index - cnt);3050 if (req->cnt < (req_cnt + 2))3051 goto queuing_error;3052 }3053 3054 if (qla_get_buf(vha, sp->qpair, &sp->u.scmd.buf_dsc)) {3055 ql_log(ql_log_fatal, vha, 0x3011,3056 "Failed to allocate buf for fcp_cmnd for cmd=%p.\n", cmd);3057 goto queuing_error;3058 }3059 3060 sp->flags |= SRB_GOT_BUF;3061 ctx = &sp->u.scmd.ct6_ctx;3062 ctx->fcp_cmnd = sp->u.scmd.buf_dsc.buf;3063 ctx->fcp_cmnd_dma = sp->u.scmd.buf_dsc.buf_dma;3064 3065 if (cmd->cmd_len > 16) {3066 additional_cdb_len = cmd->cmd_len - 16;3067 if ((cmd->cmd_len % 4) != 0) {3068 /*3069 * SCSI command bigger than 16 bytes must be3070 * multiple of 43071 */3072 ql_log(ql_log_warn, vha, 0x3012,3073 "scsi cmd len %d not multiple of 4 for cmd=%p.\n",3074 cmd->cmd_len, cmd);3075 goto queuing_error_fcp_cmnd;3076 }3077 ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4;3078 } else {3079 additional_cdb_len = 0;3080 ctx->fcp_cmnd_len = 12 + 16 + 4;3081 }3082 3083 cmd_pkt = (struct cmd_type_6 *)req->ring_ptr;3084 cmd_pkt->handle = make_handle(req->id, handle);3085 3086 /*3087 * Zero out remaining portion of packet.3088 * tagged queuing modifier -- default is TSK_SIMPLE (0).3089 */3090 clr_ptr = (uint32_t *)cmd_pkt + 2;3091 memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);3092 cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);3093 3094 /* No data transfer */3095 if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {3096 cmd_pkt->byte_count = cpu_to_le32(0);3097 goto no_dsds;3098 }3099 3100 /* Set transfer direction */3101 if (cmd->sc_data_direction == DMA_TO_DEVICE) {3102 cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA);3103 vha->qla_stats.output_bytes += scsi_bufflen(cmd);3104 vha->qla_stats.output_requests++;3105 sp->fcport->edif.tx_bytes += scsi_bufflen(cmd);3106 } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {3107 cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA);3108 vha->qla_stats.input_bytes += scsi_bufflen(cmd);3109 vha->qla_stats.input_requests++;3110 sp->fcport->edif.rx_bytes += scsi_bufflen(cmd);3111 }3112 3113 cmd_pkt->control_flags |= cpu_to_le16(CF_EN_EDIF);3114 cmd_pkt->control_flags &= ~(cpu_to_le16(CF_NEW_SA));3115 3116 /* One DSD is available in the Command Type 6 IOCB */3117 avail_dsds = 1;3118 cur_dsd = &cmd_pkt->fcp_dsd;3119 3120 /* Load data segments */3121 scsi_for_each_sg(cmd, sg, tot_dsds, i) {3122 dma_addr_t sle_dma;3123 cont_a64_entry_t *cont_pkt;3124 3125 /* Allocate additional continuation packets? */3126 if (avail_dsds == 0) {3127 /*3128 * Five DSDs are available in the Continuation3129 * Type 1 IOCB.3130 */3131 cont_pkt = qla2x00_prep_cont_type1_iocb(vha, req);3132 cur_dsd = cont_pkt->dsd;3133 avail_dsds = 5;3134 }3135 3136 sle_dma = sg_dma_address(sg);3137 put_unaligned_le64(sle_dma, &cur_dsd->address);3138 cur_dsd->length = cpu_to_le32(sg_dma_len(sg));3139 cur_dsd++;3140 avail_dsds--;3141 }3142 3143no_dsds:3144 /* Set NPORT-ID and LUN number*/3145 cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);3146 cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;3147 cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;3148 cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;3149 cmd_pkt->vp_index = sp->vha->vp_idx;3150 3151 cmd_pkt->entry_type = COMMAND_TYPE_6;3152 3153 /* Set total data segment count. */3154 cmd_pkt->entry_count = (uint8_t)req_cnt;3155 3156 int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);3157 host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));3158 3159 /* build FCP_CMND IU */3160 int_to_scsilun(cmd->device->lun, &ctx->fcp_cmnd->lun);3161 ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;3162 3163 if (cmd->sc_data_direction == DMA_TO_DEVICE)3164 ctx->fcp_cmnd->additional_cdb_len |= 1;3165 else if (cmd->sc_data_direction == DMA_FROM_DEVICE)3166 ctx->fcp_cmnd->additional_cdb_len |= 2;3167 3168 /* Populate the FCP_PRIO. */3169 if (ha->flags.fcp_prio_enabled)3170 ctx->fcp_cmnd->task_attribute |=3171 sp->fcport->fcp_prio << 3;3172 3173 memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);3174 3175 fcp_dl = (__be32 *)(ctx->fcp_cmnd->cdb + 16 +3176 additional_cdb_len);3177 *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd));3178 3179 cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len);3180 put_unaligned_le64(ctx->fcp_cmnd_dma, &cmd_pkt->fcp_cmnd_dseg_address);3181 3182 cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));3183 /* Set total data segment count. */3184 cmd_pkt->entry_count = (uint8_t)req_cnt;3185 cmd_pkt->entry_status = 0;3186 3187 /* Build command packet. */3188 req->current_outstanding_cmd = handle;3189 req->outstanding_cmds[handle] = sp;3190 sp->handle = handle;3191 cmd->host_scribble = (unsigned char *)(unsigned long)handle;3192 req->cnt -= req_cnt;3193 3194 /* Adjust ring index. */3195 wmb();3196 req->ring_index++;3197 if (req->ring_index == req->length) {3198 req->ring_index = 0;3199 req->ring_ptr = req->ring;3200 } else {3201 req->ring_ptr++;3202 }3203 3204 sp->qpair->cmd_cnt++;3205 /* Set chip new ring index. */3206 wrt_reg_dword(req->req_q_in, req->ring_index);3207 3208 spin_unlock_irqrestore(lock, flags);3209 3210 return QLA_SUCCESS;3211 3212queuing_error_fcp_cmnd:3213queuing_error:3214 if (tot_dsds)3215 scsi_dma_unmap(cmd);3216 3217 qla_put_buf(sp->qpair, &sp->u.scmd.buf_dsc);3218 qla_put_fw_resources(sp->qpair, &sp->iores);3219 spin_unlock_irqrestore(lock, flags);3220 3221 return QLA_FUNCTION_FAILED;3222}3223 3224/**********************************************3225 * edif update/delete sa_index list functions *3226 **********************************************/3227 3228/* clear the edif_indx_list for this port */3229void qla_edif_list_del(fc_port_t *fcport)3230{3231 struct edif_list_entry *indx_lst;3232 struct edif_list_entry *tindx_lst;3233 struct list_head *indx_list = &fcport->edif.edif_indx_list;3234 unsigned long flags = 0;3235 3236 spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);3237 list_for_each_entry_safe(indx_lst, tindx_lst, indx_list, next) {3238 list_del(&indx_lst->next);3239 kfree(indx_lst);3240 }3241 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);3242}3243 3244/******************3245 * SADB functions *3246 ******************/3247 3248/* allocate/retrieve an sa_index for a given spi */3249static uint16_t qla_edif_sadb_get_sa_index(fc_port_t *fcport,3250 struct qla_sa_update_frame *sa_frame)3251{3252 struct edif_sa_index_entry *entry;3253 struct list_head *sa_list;3254 uint16_t sa_index;3255 int dir = sa_frame->flags & SAU_FLG_TX;3256 int slot = 0;3257 int free_slot = -1;3258 scsi_qla_host_t *vha = fcport->vha;3259 struct qla_hw_data *ha = vha->hw;3260 unsigned long flags = 0;3261 uint16_t nport_handle = fcport->loop_id;3262 3263 ql_dbg(ql_dbg_edif, vha, 0x3063,3264 "%s: entry fc_port: %p, nport_handle: 0x%x\n",3265 __func__, fcport, nport_handle);3266 3267 if (dir)3268 sa_list = &ha->sadb_tx_index_list;3269 else3270 sa_list = &ha->sadb_rx_index_list;3271 3272 entry = qla_edif_sadb_find_sa_index_entry(nport_handle, sa_list);3273 if (!entry) {3274 if ((sa_frame->flags & (SAU_FLG_TX | SAU_FLG_INV)) == SAU_FLG_INV) {3275 ql_dbg(ql_dbg_edif, vha, 0x3063,3276 "%s: rx delete request with no entry\n", __func__);3277 return RX_DELETE_NO_EDIF_SA_INDEX;3278 }3279 3280 /* if there is no entry for this nport, add one */3281 entry = kzalloc((sizeof(struct edif_sa_index_entry)), GFP_ATOMIC);3282 if (!entry)3283 return INVALID_EDIF_SA_INDEX;3284 3285 sa_index = qla_edif_get_sa_index_from_freepool(fcport, dir);3286 if (sa_index == INVALID_EDIF_SA_INDEX) {3287 kfree(entry);3288 return INVALID_EDIF_SA_INDEX;3289 }3290 3291 INIT_LIST_HEAD(&entry->next);3292 entry->handle = nport_handle;3293 entry->fcport = fcport;3294 entry->sa_pair[0].spi = sa_frame->spi;3295 entry->sa_pair[0].sa_index = sa_index;3296 entry->sa_pair[1].spi = 0;3297 entry->sa_pair[1].sa_index = INVALID_EDIF_SA_INDEX;3298 spin_lock_irqsave(&ha->sadb_lock, flags);3299 list_add_tail(&entry->next, sa_list);3300 spin_unlock_irqrestore(&ha->sadb_lock, flags);3301 ql_dbg(ql_dbg_edif, vha, 0x3063,3302 "%s: Created new sadb entry for nport_handle 0x%x, spi 0x%x, returning sa_index %d\n",3303 __func__, nport_handle, sa_frame->spi, sa_index);3304 3305 return sa_index;3306 }3307 3308 spin_lock_irqsave(&ha->sadb_lock, flags);3309 3310 /* see if we already have an entry for this spi */3311 for (slot = 0; slot < 2; slot++) {3312 if (entry->sa_pair[slot].sa_index == INVALID_EDIF_SA_INDEX) {3313 free_slot = slot;3314 } else {3315 if (entry->sa_pair[slot].spi == sa_frame->spi) {3316 spin_unlock_irqrestore(&ha->sadb_lock, flags);3317 ql_dbg(ql_dbg_edif, vha, 0x3063,3318 "%s: sadb slot %d entry for lid 0x%x, spi 0x%x found, sa_index %d\n",3319 __func__, slot, entry->handle, sa_frame->spi,3320 entry->sa_pair[slot].sa_index);3321 return entry->sa_pair[slot].sa_index;3322 }3323 }3324 }3325 spin_unlock_irqrestore(&ha->sadb_lock, flags);3326 3327 /* both slots are used */3328 if (free_slot == -1) {3329 ql_dbg(ql_dbg_edif, vha, 0x3063,3330 "%s: WARNING: No free slots in sadb for nport_handle 0x%x, spi: 0x%x\n",3331 __func__, entry->handle, sa_frame->spi);3332 ql_dbg(ql_dbg_edif, vha, 0x3063,3333 "%s: Slot 0 spi: 0x%x sa_index: %d, Slot 1 spi: 0x%x sa_index: %d\n",3334 __func__, entry->sa_pair[0].spi, entry->sa_pair[0].sa_index,3335 entry->sa_pair[1].spi, entry->sa_pair[1].sa_index);3336 3337 return INVALID_EDIF_SA_INDEX;3338 }3339 3340 /* there is at least one free slot, use it */3341 sa_index = qla_edif_get_sa_index_from_freepool(fcport, dir);3342 if (sa_index == INVALID_EDIF_SA_INDEX) {3343 ql_dbg(ql_dbg_edif, fcport->vha, 0x3063,3344 "%s: empty freepool!!\n", __func__);3345 return INVALID_EDIF_SA_INDEX;3346 }3347 3348 spin_lock_irqsave(&ha->sadb_lock, flags);3349 entry->sa_pair[free_slot].spi = sa_frame->spi;3350 entry->sa_pair[free_slot].sa_index = sa_index;3351 spin_unlock_irqrestore(&ha->sadb_lock, flags);3352 ql_dbg(ql_dbg_edif, fcport->vha, 0x3063,3353 "%s: sadb slot %d entry for nport_handle 0x%x, spi 0x%x added, returning sa_index %d\n",3354 __func__, free_slot, entry->handle, sa_frame->spi, sa_index);3355 3356 return sa_index;3357}3358 3359/* release any sadb entries -- only done at teardown */3360void qla_edif_sadb_release(struct qla_hw_data *ha)3361{3362 struct edif_sa_index_entry *entry, *tmp;3363 3364 list_for_each_entry_safe(entry, tmp, &ha->sadb_rx_index_list, next) {3365 list_del(&entry->next);3366 kfree(entry);3367 }3368 3369 list_for_each_entry_safe(entry, tmp, &ha->sadb_tx_index_list, next) {3370 list_del(&entry->next);3371 kfree(entry);3372 }3373}3374 3375/**************************3376 * sadb freepool functions3377 **************************/3378 3379/* build the rx and tx sa_index free pools -- only done at fcport init */3380int qla_edif_sadb_build_free_pool(struct qla_hw_data *ha)3381{3382 ha->edif_tx_sa_id_map =3383 kcalloc(BITS_TO_LONGS(EDIF_NUM_SA_INDEX), sizeof(long), GFP_KERNEL);3384 3385 if (!ha->edif_tx_sa_id_map) {3386 ql_log_pci(ql_log_fatal, ha->pdev, 0x0009,3387 "Unable to allocate memory for sadb tx.\n");3388 return -ENOMEM;3389 }3390 3391 ha->edif_rx_sa_id_map =3392 kcalloc(BITS_TO_LONGS(EDIF_NUM_SA_INDEX), sizeof(long), GFP_KERNEL);3393 if (!ha->edif_rx_sa_id_map) {3394 kfree(ha->edif_tx_sa_id_map);3395 ha->edif_tx_sa_id_map = NULL;3396 ql_log_pci(ql_log_fatal, ha->pdev, 0x0009,3397 "Unable to allocate memory for sadb rx.\n");3398 return -ENOMEM;3399 }3400 return 0;3401}3402 3403/* release the free pool - only done during fcport teardown */3404void qla_edif_sadb_release_free_pool(struct qla_hw_data *ha)3405{3406 kfree(ha->edif_tx_sa_id_map);3407 ha->edif_tx_sa_id_map = NULL;3408 kfree(ha->edif_rx_sa_id_map);3409 ha->edif_rx_sa_id_map = NULL;3410}3411 3412static void __chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha,3413 fc_port_t *fcport, uint32_t handle, uint16_t sa_index)3414{3415 struct edif_list_entry *edif_entry;3416 struct edif_sa_ctl *sa_ctl;3417 uint16_t delete_sa_index = INVALID_EDIF_SA_INDEX;3418 unsigned long flags = 0;3419 uint16_t nport_handle = fcport->loop_id;3420 uint16_t cached_nport_handle;3421 3422 spin_lock_irqsave(&fcport->edif.indx_list_lock, flags);3423 edif_entry = qla_edif_list_find_sa_index(fcport, nport_handle);3424 if (!edif_entry) {3425 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);3426 return; /* no pending delete for this handle */3427 }3428 3429 /*3430 * check for no pending delete for this index or iocb does not3431 * match rx sa_index3432 */3433 if (edif_entry->delete_sa_index == INVALID_EDIF_SA_INDEX ||3434 edif_entry->update_sa_index != sa_index) {3435 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);3436 return;3437 }3438 3439 /*3440 * wait until we have seen at least EDIF_DELAY_COUNT transfers before3441 * queueing RX delete3442 */3443 if (edif_entry->count++ < EDIF_RX_DELETE_FILTER_COUNT) {3444 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);3445 return;3446 }3447 3448 ql_dbg(ql_dbg_edif, vha, 0x5033,3449 "%s: invalidating delete_sa_index, update_sa_index: 0x%x sa_index: 0x%x, delete_sa_index: 0x%x\n",3450 __func__, edif_entry->update_sa_index, sa_index, edif_entry->delete_sa_index);3451 3452 delete_sa_index = edif_entry->delete_sa_index;3453 edif_entry->delete_sa_index = INVALID_EDIF_SA_INDEX;3454 cached_nport_handle = edif_entry->handle;3455 spin_unlock_irqrestore(&fcport->edif.indx_list_lock, flags);3456 3457 /* sanity check on the nport handle */3458 if (nport_handle != cached_nport_handle) {3459 ql_dbg(ql_dbg_edif, vha, 0x3063,3460 "%s: POST SA DELETE nport_handle mismatch: lid: 0x%x, edif_entry nph: 0x%x\n",3461 __func__, nport_handle, cached_nport_handle);3462 }3463 3464 /* find the sa_ctl for the delete and schedule the delete */3465 sa_ctl = qla_edif_find_sa_ctl_by_index(fcport, delete_sa_index, 0);3466 if (sa_ctl) {3467 ql_dbg(ql_dbg_edif, vha, 0x3063,3468 "%s: POST SA DELETE sa_ctl: %p, index recvd %d\n",3469 __func__, sa_ctl, sa_index);3470 ql_dbg(ql_dbg_edif, vha, 0x3063,3471 "delete index %d, update index: %d, nport handle: 0x%x, handle: 0x%x\n",3472 delete_sa_index,3473 edif_entry->update_sa_index, nport_handle, handle);3474 3475 sa_ctl->flags = EDIF_SA_CTL_FLG_DEL;3476 set_bit(EDIF_SA_CTL_REPL, &sa_ctl->state);3477 qla_post_sa_replace_work(fcport->vha, fcport,3478 nport_handle, sa_ctl);3479 } else {3480 ql_dbg(ql_dbg_edif, vha, 0x3063,3481 "%s: POST SA DELETE sa_ctl not found for delete_sa_index: %d\n",3482 __func__, delete_sa_index);3483 }3484}3485 3486void qla_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha,3487 srb_t *sp, struct sts_entry_24xx *sts24)3488{3489 fc_port_t *fcport = sp->fcport;3490 /* sa_index used by this iocb */3491 struct scsi_cmnd *cmd = GET_CMD_SP(sp);3492 uint32_t handle;3493 3494 handle = (uint32_t)LSW(sts24->handle);3495 3496 /* find out if this status iosb is for a scsi read */3497 if (cmd->sc_data_direction != DMA_FROM_DEVICE)3498 return;3499 3500 return __chk_edif_rx_sa_delete_pending(vha, fcport, handle,3501 le16_to_cpu(sts24->edif_sa_index));3502}3503 3504void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport,3505 struct ctio7_from_24xx *pkt)3506{3507 __chk_edif_rx_sa_delete_pending(vha, fcport,3508 pkt->handle, le16_to_cpu(pkt->edif_sa_index));3509}3510 3511static void qla_parse_auth_els_ctl(struct srb *sp)3512{3513 struct qla_els_pt_arg *a = &sp->u.bsg_cmd.u.els_arg;3514 struct bsg_job *bsg_job = sp->u.bsg_cmd.bsg_job;3515 struct fc_bsg_request *request = bsg_job->request;3516 struct qla_bsg_auth_els_request *p =3517 (struct qla_bsg_auth_els_request *)bsg_job->request;3518 3519 a->tx_len = a->tx_byte_count = sp->remap.req.len;3520 a->tx_addr = sp->remap.req.dma;3521 a->rx_len = a->rx_byte_count = sp->remap.rsp.len;3522 a->rx_addr = sp->remap.rsp.dma;3523 3524 if (p->e.sub_cmd == SEND_ELS_REPLY) {3525 a->control_flags = p->e.extra_control_flags << 13;3526 a->rx_xchg_address = cpu_to_le32(p->e.extra_rx_xchg_address);3527 if (p->e.extra_control_flags == BSG_CTL_FLAG_LS_ACC)3528 a->els_opcode = ELS_LS_ACC;3529 else if (p->e.extra_control_flags == BSG_CTL_FLAG_LS_RJT)3530 a->els_opcode = ELS_LS_RJT;3531 }3532 a->did = sp->fcport->d_id;3533 a->els_opcode = request->rqst_data.h_els.command_code;3534 a->nport_handle = cpu_to_le16(sp->fcport->loop_id);3535 a->vp_idx = sp->vha->vp_idx;3536}3537 3538int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)3539{3540 struct fc_bsg_request *bsg_request = bsg_job->request;3541 struct fc_bsg_reply *bsg_reply = bsg_job->reply;3542 fc_port_t *fcport = NULL;3543 struct qla_hw_data *ha = vha->hw;3544 srb_t *sp;3545 int rval = (DID_ERROR << 16), cnt;3546 port_id_t d_id;3547 struct qla_bsg_auth_els_request *p =3548 (struct qla_bsg_auth_els_request *)bsg_job->request;3549 struct qla_bsg_auth_els_reply *rpl =3550 (struct qla_bsg_auth_els_reply *)bsg_job->reply;3551 3552 rpl->version = EDIF_VERSION1;3553 3554 d_id.b.al_pa = bsg_request->rqst_data.h_els.port_id[2];3555 d_id.b.area = bsg_request->rqst_data.h_els.port_id[1];3556 d_id.b.domain = bsg_request->rqst_data.h_els.port_id[0];3557 3558 /* find matching d_id in fcport list */3559 fcport = qla2x00_find_fcport_by_pid(vha, &d_id);3560 if (!fcport) {3561 ql_dbg(ql_dbg_edif, vha, 0x911a,3562 "%s fcport not find online portid=%06x.\n",3563 __func__, d_id.b24);3564 SET_DID_STATUS(bsg_reply->result, DID_ERROR);3565 return -EIO;3566 }3567 3568 if (qla_bsg_check(vha, bsg_job, fcport))3569 return 0;3570 3571 if (EDIF_SESS_DELETE(fcport)) {3572 ql_dbg(ql_dbg_edif, vha, 0x910d,3573 "%s ELS code %x, no loop id.\n", __func__,3574 bsg_request->rqst_data.r_els.els_code);3575 SET_DID_STATUS(bsg_reply->result, DID_BAD_TARGET);3576 return -ENXIO;3577 }3578 3579 if (!vha->flags.online) {3580 ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");3581 SET_DID_STATUS(bsg_reply->result, DID_BAD_TARGET);3582 rval = -EIO;3583 goto done;3584 }3585 3586 /* pass through is supported only for ISP 4Gb or higher */3587 if (!IS_FWI2_CAPABLE(ha)) {3588 ql_dbg(ql_dbg_user, vha, 0x7001,3589 "ELS passthru not supported for ISP23xx based adapters.\n");3590 SET_DID_STATUS(bsg_reply->result, DID_BAD_TARGET);3591 rval = -EPERM;3592 goto done;3593 }3594 3595 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);3596 if (!sp) {3597 ql_dbg(ql_dbg_user, vha, 0x7004,3598 "Failed get sp pid=%06x\n", fcport->d_id.b24);3599 rval = -ENOMEM;3600 SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);3601 goto done;3602 }3603 3604 sp->remap.req.len = bsg_job->request_payload.payload_len;3605 sp->remap.req.buf = dma_pool_alloc(ha->purex_dma_pool,3606 GFP_KERNEL, &sp->remap.req.dma);3607 if (!sp->remap.req.buf) {3608 ql_dbg(ql_dbg_user, vha, 0x7005,3609 "Failed allocate request dma len=%x\n",3610 bsg_job->request_payload.payload_len);3611 rval = -ENOMEM;3612 SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);3613 goto done_free_sp;3614 }3615 3616 sp->remap.rsp.len = bsg_job->reply_payload.payload_len;3617 sp->remap.rsp.buf = dma_pool_alloc(ha->purex_dma_pool,3618 GFP_KERNEL, &sp->remap.rsp.dma);3619 if (!sp->remap.rsp.buf) {3620 ql_dbg(ql_dbg_user, vha, 0x7006,3621 "Failed allocate response dma len=%x\n",3622 bsg_job->reply_payload.payload_len);3623 rval = -ENOMEM;3624 SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);3625 goto done_free_remap_req;3626 }3627 sg_copy_to_buffer(bsg_job->request_payload.sg_list,3628 bsg_job->request_payload.sg_cnt, sp->remap.req.buf,3629 sp->remap.req.len);3630 sp->remap.remapped = true;3631 3632 sp->type = SRB_ELS_CMD_HST_NOLOGIN;3633 sp->name = "SPCN_BSG_HST_NOLOGIN";3634 sp->u.bsg_cmd.bsg_job = bsg_job;3635 qla_parse_auth_els_ctl(sp);3636 3637 sp->free = qla2x00_bsg_sp_free;3638 sp->done = qla2x00_bsg_job_done;3639 3640 cnt = 0;3641retry:3642 rval = qla2x00_start_sp(sp);3643 switch (rval) {3644 case QLA_SUCCESS:3645 ql_dbg(ql_dbg_edif, vha, 0x700a,3646 "%s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p\n",3647 __func__, sc_to_str(p->e.sub_cmd), fcport->port_name,3648 p->e.extra_rx_xchg_address, p->e.extra_control_flags,3649 sp->handle, sp->remap.req.len, bsg_job);3650 break;3651 case EAGAIN:3652 msleep(EDIF_MSLEEP_INTERVAL);3653 cnt++;3654 if (cnt < EDIF_RETRY_COUNT)3655 goto retry;3656 fallthrough;3657 default:3658 ql_log(ql_log_warn, vha, 0x700e,3659 "%s qla2x00_start_sp failed = %d\n", __func__, rval);3660 SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);3661 rval = -EIO;3662 goto done_free_remap_rsp;3663 }3664 return rval;3665 3666done_free_remap_rsp:3667 dma_pool_free(ha->purex_dma_pool, sp->remap.rsp.buf,3668 sp->remap.rsp.dma);3669done_free_remap_req:3670 dma_pool_free(ha->purex_dma_pool, sp->remap.req.buf,3671 sp->remap.req.dma);3672done_free_sp:3673 qla2x00_rel_sp(sp);3674 3675done:3676 return rval;3677}3678 3679void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)3680{3681 u16 cnt = 0;3682 3683 if (sess->edif.app_sess_online && DBELL_ACTIVE(vha)) {3684 ql_dbg(ql_dbg_disc, vha, 0xf09c,3685 "%s: sess %8phN send port_offline event\n",3686 __func__, sess->port_name);3687 sess->edif.app_sess_online = 0;3688 sess->edif.sess_down_acked = 0;3689 qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SESSION_SHUTDOWN,3690 sess->d_id.b24, 0, sess);3691 qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);3692 3693 while (!READ_ONCE(sess->edif.sess_down_acked) &&3694 !test_bit(VPORT_DELETE, &vha->dpc_flags)) {3695 msleep(100);3696 cnt++;3697 if (cnt > 100)3698 break;3699 }3700 sess->edif.sess_down_acked = 0;3701 ql_dbg(ql_dbg_disc, vha, 0xf09c,3702 "%s: sess %8phN port_offline event completed\n",3703 __func__, sess->port_name);3704 }3705}3706 3707void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport)3708{3709 if (!(fcport->flags & FCF_FCSP_DEVICE))3710 return;3711 3712 qla_edb_clear(vha, fcport->d_id);3713 qla_enode_clear(vha, fcport->d_id);3714}3715