15efdd5cfSKaran Tilak Kumar // SPDX-License-Identifier: GPL-2.0-only 25efdd5cfSKaran Tilak Kumar /* 35efdd5cfSKaran Tilak Kumar * Copyright 2008 Cisco Systems, Inc. All rights reserved. 45efdd5cfSKaran Tilak Kumar * Copyright 2007 Nuova Systems, Inc. All rights reserved. 55efdd5cfSKaran Tilak Kumar */ 65efdd5cfSKaran Tilak Kumar #include <linux/mempool.h> 75efdd5cfSKaran Tilak Kumar #include <linux/errno.h> 85efdd5cfSKaran Tilak Kumar #include <linux/init.h> 95efdd5cfSKaran Tilak Kumar #include <linux/workqueue.h> 105efdd5cfSKaran Tilak Kumar #include <linux/pci.h> 115efdd5cfSKaran Tilak Kumar #include <linux/scatterlist.h> 125efdd5cfSKaran Tilak Kumar #include <linux/skbuff.h> 135efdd5cfSKaran Tilak Kumar #include <linux/spinlock.h> 145efdd5cfSKaran Tilak Kumar #include <linux/kthread.h> 155efdd5cfSKaran Tilak Kumar #include <linux/if_ether.h> 165efdd5cfSKaran Tilak Kumar #include <linux/if_vlan.h> 175efdd5cfSKaran Tilak Kumar #include <linux/delay.h> 185efdd5cfSKaran Tilak Kumar #include <linux/gfp.h> 195efdd5cfSKaran Tilak Kumar #include <linux/nvme.h> 205efdd5cfSKaran Tilak Kumar #include <linux/nvme-fc.h> 215efdd5cfSKaran Tilak Kumar #include "fnic.h" 225efdd5cfSKaran Tilak Kumar #include "fnic_trace.h" 235efdd5cfSKaran Tilak Kumar #include "fdls_fc.h" 245efdd5cfSKaran Tilak Kumar 25*376a3960SKaran Tilak Kumar #if IS_REACHABLE(CONFIG_NVME_FC) 265efdd5cfSKaran Tilak Kumar 27f06ee33dSKaran Tilak Kumar static bool nvfnic_ls_req_cleanup(struct fnic_iport_s *iport, 28f06ee33dSKaran Tilak Kumar struct nvmefc_ls_req *lsreq, 29f06ee33dSKaran Tilak Kumar uint16_t oxid); 30f06ee33dSKaran Tilak Kumar 315efdd5cfSKaran Tilak Kumar int nvfnic_get_sg_count(struct fnic_io_req *io_req) 325efdd5cfSKaran Tilak Kumar { 335efdd5cfSKaran Tilak Kumar return io_req->fcp_req->sg_cnt; 345efdd5cfSKaran Tilak Kumar } 355efdd5cfSKaran Tilak Kumar 365efdd5cfSKaran Tilak Kumar int nvfnic_dma_map_sgl(struct fnic *fnic, struct fnic_io_req *io_req, 375efdd5cfSKaran Tilak Kumar int sg_count) 385efdd5cfSKaran Tilak Kumar { 395efdd5cfSKaran Tilak Kumar io_req->sgl_list_pa = dma_map_single(&fnic->pdev->dev, 405efdd5cfSKaran Tilak Kumar io_req->sgl_list, 415efdd5cfSKaran Tilak Kumar sizeof(io_req->sgl_list[0]) * 425efdd5cfSKaran Tilak Kumar sg_count, DMA_TO_DEVICE); 435efdd5cfSKaran Tilak Kumar if (dma_mapping_error(&fnic->pdev->dev, io_req->sgl_list_pa)) { 445efdd5cfSKaran Tilak Kumar dev_err(&fnic->pdev->dev, "DMA mapping failed\n"); 455efdd5cfSKaran Tilak Kumar io_req->sgl_list_pa = 0; 465efdd5cfSKaran Tilak Kumar io_req->sgl_mapped = 0; 475efdd5cfSKaran Tilak Kumar return -EBUSY; 485efdd5cfSKaran Tilak Kumar } 495efdd5cfSKaran Tilak Kumar 505efdd5cfSKaran Tilak Kumar io_req->sgl_mapped = 1; 515efdd5cfSKaran Tilak Kumar return 0; 525efdd5cfSKaran Tilak Kumar } 535efdd5cfSKaran Tilak Kumar 545efdd5cfSKaran Tilak Kumar void nvfnic_dma_unmap_sgl(struct fnic *fnic, struct fnic_io_req *io_req) 555efdd5cfSKaran Tilak Kumar { 565efdd5cfSKaran Tilak Kumar if (io_req->sgl_mapped) { 575efdd5cfSKaran Tilak Kumar dma_unmap_single(&fnic->pdev->dev, io_req->sgl_list_pa, 585efdd5cfSKaran Tilak Kumar sizeof(io_req->sgl_list[0]) * io_req->sgl_cnt, 595efdd5cfSKaran Tilak Kumar DMA_TO_DEVICE); 605efdd5cfSKaran Tilak Kumar io_req->sgl_mapped = 0; 615efdd5cfSKaran Tilak Kumar io_req->sgl_list_pa = 0; 625efdd5cfSKaran Tilak Kumar } 635efdd5cfSKaran Tilak Kumar } 645efdd5cfSKaran Tilak Kumar 655efdd5cfSKaran Tilak Kumar static void nvfnic_update_io_bytes(struct fnic *fnic, 665efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req, u8 opcode) 675efdd5cfSKaran Tilak Kumar { 685efdd5cfSKaran Tilak Kumar if (opcode == nvme_cmd_read) 695efdd5cfSKaran Tilak Kumar fnic->fcp_input_bytes += io_req->fcp_req->transferred_length; 705efdd5cfSKaran Tilak Kumar else if (opcode == nvme_cmd_write) 715efdd5cfSKaran Tilak Kumar fnic->fcp_output_bytes += io_req->fcp_req->transferred_length; 725efdd5cfSKaran Tilak Kumar } 735efdd5cfSKaran Tilak Kumar 74d25a557dSKaran Tilak Kumar static void nvfnic_update_io_stats(struct fnic *fnic, u8 opcode) 75d25a557dSKaran Tilak Kumar { 76d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 77d25a557dSKaran Tilak Kumar 78d25a557dSKaran Tilak Kumar switch (opcode) { 79d25a557dSKaran Tilak Kumar case nvme_cmd_read: 80d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_input_requests); 81d25a557dSKaran Tilak Kumar break; 82d25a557dSKaran Tilak Kumar case nvme_cmd_write: 83d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_output_requests); 84d25a557dSKaran Tilak Kumar break; 85d25a557dSKaran Tilak Kumar default: 86d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_control_requests); 87d25a557dSKaran Tilak Kumar break; 88d25a557dSKaran Tilak Kumar } 89d25a557dSKaran Tilak Kumar } 90d25a557dSKaran Tilak Kumar 91d25a557dSKaran Tilak Kumar static void nvfnic_update_cmpl_stats(struct fnic *fnic, 92d25a557dSKaran Tilak Kumar struct fnic_io_req *io_req) 93d25a557dSKaran Tilak Kumar { 94d25a557dSKaran Tilak Kumar struct io_path_stats *io_stats = &fnic->fnic_stats.io_stats; 95d25a557dSKaran Tilak Kumar atomic64_t *duration_stat; 96d25a557dSKaran Tilak Kumar unsigned long io_duration_time; 97d25a557dSKaran Tilak Kumar 98d25a557dSKaran Tilak Kumar atomic64_dec(&io_stats->active_ios); 99d25a557dSKaran Tilak Kumar if (atomic64_read(&fnic->io_cmpl_skip)) 100d25a557dSKaran Tilak Kumar atomic64_dec(&fnic->io_cmpl_skip); 101d25a557dSKaran Tilak Kumar else 102d25a557dSKaran Tilak Kumar atomic64_inc(&io_stats->io_completions); 103d25a557dSKaran Tilak Kumar 104d25a557dSKaran Tilak Kumar io_duration_time = jiffies_to_msecs(jiffies - io_req->start_time); 105d25a557dSKaran Tilak Kumar 106d25a557dSKaran Tilak Kumar if (io_duration_time <= 10) 107d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_btw_0_to_10_msec; 108d25a557dSKaran Tilak Kumar else if (io_duration_time <= 100) 109d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_btw_10_to_100_msec; 110d25a557dSKaran Tilak Kumar else if (io_duration_time <= 500) 111d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_btw_100_to_500_msec; 112d25a557dSKaran Tilak Kumar else if (io_duration_time <= 5000) 113d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_btw_500_to_5000_msec; 114d25a557dSKaran Tilak Kumar else if (io_duration_time <= 10000) 115d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_btw_5000_to_10000_msec; 116d25a557dSKaran Tilak Kumar else if (io_duration_time <= 30000) 117d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_btw_10000_to_30000_msec; 118d25a557dSKaran Tilak Kumar else { 119d25a557dSKaran Tilak Kumar duration_stat = &io_stats->io_greater_than_30000_msec; 120d25a557dSKaran Tilak Kumar if (io_duration_time > 121d25a557dSKaran Tilak Kumar atomic64_read(&io_stats->current_max_io_time)) 122d25a557dSKaran Tilak Kumar atomic64_set(&io_stats->current_max_io_time, 123d25a557dSKaran Tilak Kumar io_duration_time); 124d25a557dSKaran Tilak Kumar } 125d25a557dSKaran Tilak Kumar 126d25a557dSKaran Tilak Kumar atomic64_inc(duration_stat); 127d25a557dSKaran Tilak Kumar } 128d25a557dSKaran Tilak Kumar 1295efdd5cfSKaran Tilak Kumar int 1305efdd5cfSKaran Tilak Kumar nvfnic_alloc_fcpio_tag(struct fnic_iport_s *iport, struct fnic_io_req *io_req) 1315efdd5cfSKaran Tilak Kumar { 1325efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 1335efdd5cfSKaran Tilak Kumar int tag; 1345efdd5cfSKaran Tilak Kumar 1355efdd5cfSKaran Tilak Kumar tag = sbitmap_get(&fnic->nvfnic_tag_map); 1365efdd5cfSKaran Tilak Kumar if (tag >= 0) { 1375efdd5cfSKaran Tilak Kumar WRITE_ONCE(io_req->tag, tag); 1385efdd5cfSKaran Tilak Kumar fnic->sw_copy_wq[0].io_req_table[tag] = io_req; 1395efdd5cfSKaran Tilak Kumar return tag; 1405efdd5cfSKaran Tilak Kumar } 1415efdd5cfSKaran Tilak Kumar return FNIC_NVME_NO_FREE_TAG; 1425efdd5cfSKaran Tilak Kumar } 1435efdd5cfSKaran Tilak Kumar 1445efdd5cfSKaran Tilak Kumar void 1455efdd5cfSKaran Tilak Kumar nvfnic_free_fcpio_tag(struct fnic_iport_s *iport, struct fnic_io_req *io_req) 1465efdd5cfSKaran Tilak Kumar { 1475efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 1485efdd5cfSKaran Tilak Kumar uint16_t tag = io_req->tag; 1495efdd5cfSKaran Tilak Kumar 1505efdd5cfSKaran Tilak Kumar if (tag == FNIC_NVME_NO_FREE_TAG) { 1515efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 1525efdd5cfSKaran Tilak Kumar "Attempting to free invalid tag: 0x%x\n", tag); 1535efdd5cfSKaran Tilak Kumar return; 1545efdd5cfSKaran Tilak Kumar } 1555efdd5cfSKaran Tilak Kumar fnic->sw_copy_wq[0].io_req_table[tag] = NULL; 1565efdd5cfSKaran Tilak Kumar WRITE_ONCE(io_req->tag, FNIC_NVME_NO_FREE_TAG); 1575efdd5cfSKaran Tilak Kumar sbitmap_clear_bit(&fnic->nvfnic_tag_map, tag); 1585efdd5cfSKaran Tilak Kumar } 1595efdd5cfSKaran Tilak Kumar 1605efdd5cfSKaran Tilak Kumar void 1615efdd5cfSKaran Tilak Kumar nvfnic_reset_fcpio_tag_pool(struct fnic_iport_s *iport) 1625efdd5cfSKaran Tilak Kumar { 1635efdd5cfSKaran Tilak Kumar WARN_ON(sbitmap_weight(&iport->fnic->nvfnic_tag_map)); 1645efdd5cfSKaran Tilak Kumar } 1655efdd5cfSKaran Tilak Kumar 1665efdd5cfSKaran Tilak Kumar struct fnic_io_req * 1675efdd5cfSKaran Tilak Kumar nvfnic_find_io_req_by_tag(struct fnic *fnic, uint16_t tag) 1685efdd5cfSKaran Tilak Kumar { 1695efdd5cfSKaran Tilak Kumar if (tag == FNIC_NVME_NO_FREE_TAG || 1705efdd5cfSKaran Tilak Kumar !sbitmap_test_bit(&fnic->nvfnic_tag_map, tag)) 1715efdd5cfSKaran Tilak Kumar return NULL; 1725efdd5cfSKaran Tilak Kumar return fnic->sw_copy_wq[0].io_req_table[tag]; 1735efdd5cfSKaran Tilak Kumar } 1745efdd5cfSKaran Tilak Kumar 1755efdd5cfSKaran Tilak Kumar /* 1765efdd5cfSKaran Tilak Kumar * Unmap the data buffer and sense buffer for an io_req, 1775efdd5cfSKaran Tilak Kumar * also unmap and free the device-private scatter/gather list. 1785efdd5cfSKaran Tilak Kumar */ 1795efdd5cfSKaran Tilak Kumar void nvfnic_release_nvme_ioreq_buf(struct fnic_iport_s *iport, 1805efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req) 1815efdd5cfSKaran Tilak Kumar { 1825efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 1835efdd5cfSKaran Tilak Kumar 1845efdd5cfSKaran Tilak Kumar nvfnic_dma_unmap_sgl(fnic, io_req); 1855efdd5cfSKaran Tilak Kumar 1865efdd5cfSKaran Tilak Kumar if (io_req->sgl_cnt) 1875efdd5cfSKaran Tilak Kumar mempool_free(io_req->sgl_list_alloc, 1885efdd5cfSKaran Tilak Kumar fnic->io_sgl_pool[io_req->sgl_type]); 1895efdd5cfSKaran Tilak Kumar } 1905efdd5cfSKaran Tilak Kumar 1918ef412ceSKaran Tilak Kumar int nvfnic_get_nvmef_info(struct fnic *fnic, struct fnic_nvmef_info *info) 1928ef412ceSKaran Tilak Kumar { 1938ef412ceSKaran Tilak Kumar int len = 0; 1948ef412ceSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport; 1958ef412ceSKaran Tilak Kumar int buf_size = info->buf_size; 1968ef412ceSKaran Tilak Kumar struct fnic_tport_s *tport; 1978ef412ceSKaran Tilak Kumar struct fnic_tport_s *next; 1988ef412ceSKaran Tilak Kumar unsigned long flags; 1998ef412ceSKaran Tilak Kumar 2008ef412ceSKaran Tilak Kumar if (buf_size <= 0) 2018ef412ceSKaran Tilak Kumar return 0; 2028ef412ceSKaran Tilak Kumar 2038ef412ceSKaran Tilak Kumar len += scnprintf(info->info_buffer + len, buf_size - len, 2048ef412ceSKaran Tilak Kumar "lport wwpn 0x%llx wwnn 0x%llx fcid 0x%06x\n", 2058ef412ceSKaran Tilak Kumar iport->wwpn, iport->wwnn, iport->fcid); 2068ef412ceSKaran Tilak Kumar 2078ef412ceSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 2088ef412ceSKaran Tilak Kumar list_for_each_entry_safe(tport, next, &iport->tport_list, links) { 2098ef412ceSKaran Tilak Kumar if (len >= buf_size - 1) 2108ef412ceSKaran Tilak Kumar break; 2118ef412ceSKaran Tilak Kumar 2128ef412ceSKaran Tilak Kumar len += scnprintf(info->info_buffer + len, buf_size - len, 2138ef412ceSKaran Tilak Kumar "tport wwpn 0x%llx wwnn 0x%llx fcid 0x%06x\n", 2148ef412ceSKaran Tilak Kumar tport->wwpn, tport->wwnn, tport->fcid); 2158ef412ceSKaran Tilak Kumar } 2168ef412ceSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 2178ef412ceSKaran Tilak Kumar 2188ef412ceSKaran Tilak Kumar return len; 2198ef412ceSKaran Tilak Kumar } 2208ef412ceSKaran Tilak Kumar 2215efdd5cfSKaran Tilak Kumar inline int nvfnic_queue_wq_nvme_copy_desc(struct fnic *fnic, 2225efdd5cfSKaran Tilak Kumar struct vnic_wq_copy *wq, 2235efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req, 2245efdd5cfSKaran Tilak Kumar int sg_count) 2255efdd5cfSKaran Tilak Kumar { 2265efdd5cfSKaran Tilak Kumar struct scatterlist *sg; 2275efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport = io_req->tport; 2285efdd5cfSKaran Tilak Kumar struct host_sg_desc *desc; 229d25a557dSKaran Tilak Kumar struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; 2305efdd5cfSKaran Tilak Kumar unsigned int i; 2315efdd5cfSKaran Tilak Kumar unsigned long intr_flags; 2325efdd5cfSKaran Tilak Kumar int flags; 2335efdd5cfSKaran Tilak Kumar u8 exch_flags; 2345efdd5cfSKaran Tilak Kumar struct scatterlist *sgl; 2355efdd5cfSKaran Tilak Kumar int idx; 2365efdd5cfSKaran Tilak Kumar int ret = 0; 2375efdd5cfSKaran Tilak Kumar 2385efdd5cfSKaran Tilak Kumar if (sg_count) { 2395efdd5cfSKaran Tilak Kumar /* For each SGE, create a device desc entry */ 2405efdd5cfSKaran Tilak Kumar desc = io_req->sgl_list; 2415efdd5cfSKaran Tilak Kumar sgl = io_req->fcp_req->first_sgl; 2425efdd5cfSKaran Tilak Kumar for_each_sg(sgl, sg, sg_count, i) { 2435efdd5cfSKaran Tilak Kumar desc->addr = cpu_to_le64(sg_dma_address(sg)); 2445efdd5cfSKaran Tilak Kumar desc->len = cpu_to_le32(sg_dma_len(sg)); 2455efdd5cfSKaran Tilak Kumar desc->_resvd = 0; 2465efdd5cfSKaran Tilak Kumar desc++; 2475efdd5cfSKaran Tilak Kumar } 2485efdd5cfSKaran Tilak Kumar 2495efdd5cfSKaran Tilak Kumar ret = nvfnic_dma_map_sgl(fnic, io_req, sg_count); 2505efdd5cfSKaran Tilak Kumar if (ret) 2515efdd5cfSKaran Tilak Kumar return ret; 2525efdd5cfSKaran Tilak Kumar } 2535efdd5cfSKaran Tilak Kumar 2545efdd5cfSKaran Tilak Kumar idx = (struct vnic_wq_copy *)wq - &fnic->hw_copy_wq[0]; 2555efdd5cfSKaran Tilak Kumar 2565efdd5cfSKaran Tilak Kumar /* Enqueue the descriptor in the Copy WQ */ 2575efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->wq_copy_lock[idx], intr_flags); 2585efdd5cfSKaran Tilak Kumar 2595efdd5cfSKaran Tilak Kumar if (vnic_wq_copy_desc_avail(wq) <= fnic->wq_copy_desc_low[idx]) 2605efdd5cfSKaran Tilak Kumar free_wq_copy_descs(fnic, wq, idx); 2615efdd5cfSKaran Tilak Kumar 2625efdd5cfSKaran Tilak Kumar if (unlikely(!vnic_wq_copy_desc_avail(wq))) { 2635efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], intr_flags); 2645efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 2655efdd5cfSKaran Tilak Kumar "Enqueue failure: No descriptors\n"); 266d25a557dSKaran Tilak Kumar atomic64_inc(&misc_stats->io_cpwq_alloc_failures); 2675efdd5cfSKaran Tilak Kumar return -EBUSY; 2685efdd5cfSKaran Tilak Kumar } 2695efdd5cfSKaran Tilak Kumar 2705efdd5cfSKaran Tilak Kumar flags = 0; 2715efdd5cfSKaran Tilak Kumar if (io_req->fcp_req->io_dir == NVMEFC_FCP_READ) 2725efdd5cfSKaran Tilak Kumar flags = FCPIO_ICMND_RDDATA; 2735efdd5cfSKaran Tilak Kumar else if (io_req->fcp_req->io_dir == NVMEFC_FCP_WRITE) 2745efdd5cfSKaran Tilak Kumar flags = FCPIO_ICMND_WRDATA; 2755efdd5cfSKaran Tilak Kumar 2765efdd5cfSKaran Tilak Kumar exch_flags = 0; 2775efdd5cfSKaran Tilak Kumar 2785efdd5cfSKaran Tilak Kumar fnic_queue_wq_copy_desc_nvme_io(wq, io_req->tag, 2795efdd5cfSKaran Tilak Kumar exch_flags, io_req->sgl_cnt, 2805efdd5cfSKaran Tilak Kumar io_req->sgl_list_pa, flags, 2815efdd5cfSKaran Tilak Kumar io_req->fcp_req->cmdaddr, 2825efdd5cfSKaran Tilak Kumar io_req->fcp_req->cmdlen, 2835efdd5cfSKaran Tilak Kumar io_req->fcp_req->payload_length, 2845efdd5cfSKaran Tilak Kumar io_req->port_id, 2855efdd5cfSKaran Tilak Kumar tport->max_payload_size, tport->r_a_tov, 2865efdd5cfSKaran Tilak Kumar tport->e_d_tov); 2875efdd5cfSKaran Tilak Kumar 288d25a557dSKaran Tilak Kumar atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); 289d25a557dSKaran Tilak Kumar if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > 290d25a557dSKaran Tilak Kumar atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) 291d25a557dSKaran Tilak Kumar atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, 292d25a557dSKaran Tilak Kumar atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs)); 2935efdd5cfSKaran Tilak Kumar 2945efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], intr_flags); 2955efdd5cfSKaran Tilak Kumar return 0; 2965efdd5cfSKaran Tilak Kumar } 2975efdd5cfSKaran Tilak Kumar 2985efdd5cfSKaran Tilak Kumar bool 2995efdd5cfSKaran Tilak Kumar nvfnic_transport_ready(struct fnic_iport_s *iport, struct fnic_tport_s *tport) 3005efdd5cfSKaran Tilak Kumar { 3015efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 302d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 3035efdd5cfSKaran Tilak Kumar 3045efdd5cfSKaran Tilak Kumar if (tport == NULL) 3055efdd5cfSKaran Tilak Kumar return false; 3065efdd5cfSKaran Tilak Kumar 3075efdd5cfSKaran Tilak Kumar if (fdls_get_state(&iport->fabric) == FDLS_STATE_LINKDOWN || 3085efdd5cfSKaran Tilak Kumar iport->state != FNIC_IPORT_STATE_READY) { 309d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->misc_stats.iport_not_ready); 3105efdd5cfSKaran Tilak Kumar return false; 3115efdd5cfSKaran Tilak Kumar } 3125efdd5cfSKaran Tilak Kumar 3135efdd5cfSKaran Tilak Kumar if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) 3145efdd5cfSKaran Tilak Kumar return false; 3155efdd5cfSKaran Tilak Kumar 316d25a557dSKaran Tilak Kumar if (fdls_tport_is_offline(tport)) { 317d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->misc_stats.tport_not_ready); 3185efdd5cfSKaran Tilak Kumar return false; 319d25a557dSKaran Tilak Kumar } 3205efdd5cfSKaran Tilak Kumar 3215efdd5cfSKaran Tilak Kumar return true; 3225efdd5cfSKaran Tilak Kumar } 3235efdd5cfSKaran Tilak Kumar 3245efdd5cfSKaran Tilak Kumar int nvfnic_queuecommand(struct fnic_io_req *io_req) 3255efdd5cfSKaran Tilak Kumar { 3265efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = io_req->iport; 3275efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 3285efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport = io_req->tport; 329d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 330d25a557dSKaran Tilak Kumar struct vnic_wq_copy *wq = io_req->wq; 3315efdd5cfSKaran Tilak Kumar int ret = 0; 3325efdd5cfSKaran Tilak Kumar int sg_count = 0; 3335efdd5cfSKaran Tilak Kumar unsigned long ptr; 3345efdd5cfSKaran Tilak Kumar unsigned char *lba; 3355efdd5cfSKaran Tilak Kumar u64 cmd_trace; 336d25a557dSKaran Tilak Kumar int idx; 3375efdd5cfSKaran Tilak Kumar struct nvme_fc_cmd_iu *cmdiu = io_req->fcp_req->cmdaddr; 3385efdd5cfSKaran Tilak Kumar 3395efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_NOT_INITED; 3405efdd5cfSKaran Tilak Kumar io_req->cmd_flags = FNIC_NO_FLAGS; 3415efdd5cfSKaran Tilak Kumar /* Map the data buffer */ 3425efdd5cfSKaran Tilak Kumar sg_count = nvfnic_get_sg_count(io_req); 3435efdd5cfSKaran Tilak Kumar if (sg_count < 0) { 3445efdd5cfSKaran Tilak Kumar FNIC_TRACE(nvfnic_queuecommand, fnic->fnic_num, 3455efdd5cfSKaran Tilak Kumar io_req->tag, io_req, 0, io_req->fcp_req->io_dir, 3465efdd5cfSKaran Tilak Kumar sg_count, io_req->cmd_state); 3475efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, "sg count is less-than-zero\n"); 3485efdd5cfSKaran Tilak Kumar ret = -1; 3495efdd5cfSKaran Tilak Kumar goto out; 3505efdd5cfSKaran Tilak Kumar } 3515efdd5cfSKaran Tilak Kumar 3525efdd5cfSKaran Tilak Kumar /* Determine the type of scatter/gather list we need */ 3535efdd5cfSKaran Tilak Kumar io_req->sgl_cnt = sg_count; 3545efdd5cfSKaran Tilak Kumar io_req->sgl_type = FNIC_SGL_CACHE_DFLT; 3555efdd5cfSKaran Tilak Kumar if (sg_count > FNIC_DFLT_SG_DESC_CNT) 3565efdd5cfSKaran Tilak Kumar io_req->sgl_type = FNIC_SGL_CACHE_MAX; 3575efdd5cfSKaran Tilak Kumar 3585efdd5cfSKaran Tilak Kumar if (sg_count) { 3595efdd5cfSKaran Tilak Kumar io_req->sgl_list = 3605efdd5cfSKaran Tilak Kumar mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type], 3615efdd5cfSKaran Tilak Kumar GFP_ATOMIC); 3625efdd5cfSKaran Tilak Kumar if (!io_req->sgl_list) { 363d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.alloc_failures); 3645efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 3655efdd5cfSKaran Tilak Kumar "Unable to alloc SGLs\n"); 3665efdd5cfSKaran Tilak Kumar ret = -ENOMEM; 3675efdd5cfSKaran Tilak Kumar goto out; 3685efdd5cfSKaran Tilak Kumar } 3695efdd5cfSKaran Tilak Kumar 3705efdd5cfSKaran Tilak Kumar /* Cache sgl list allocated address before alignment */ 3715efdd5cfSKaran Tilak Kumar io_req->sgl_list_alloc = io_req->sgl_list; 3725efdd5cfSKaran Tilak Kumar ptr = (unsigned long)io_req->sgl_list; 3735efdd5cfSKaran Tilak Kumar if (ptr % FNIC_SG_DESC_ALIGN) { 3745efdd5cfSKaran Tilak Kumar io_req->sgl_list = (struct host_sg_desc *) 3755efdd5cfSKaran Tilak Kumar (((unsigned long)ptr + FNIC_SG_DESC_ALIGN - 1) 3765efdd5cfSKaran Tilak Kumar & ~(FNIC_SG_DESC_ALIGN - 1)); 3775efdd5cfSKaran Tilak Kumar } 3785efdd5cfSKaran Tilak Kumar } 3795efdd5cfSKaran Tilak Kumar 3805efdd5cfSKaran Tilak Kumar io_req->port_id = tport->fcid; 3815efdd5cfSKaran Tilak Kumar io_req->start_time = jiffies; 3825efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_CMD_PENDING; 3835efdd5cfSKaran Tilak Kumar io_req->cmd_flags = FNIC_IO_INITIALIZED; 3845efdd5cfSKaran Tilak Kumar 3855efdd5cfSKaran Tilak Kumar /* create copy wq desc and enqueue it */ 386d25a557dSKaran Tilak Kumar idx = wq - &fnic->hw_copy_wq[0]; 387d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.ios[idx]); 3885efdd5cfSKaran Tilak Kumar ret = nvfnic_queue_wq_nvme_copy_desc(fnic, io_req->wq, io_req, sg_count); 3895efdd5cfSKaran Tilak Kumar if (ret) { 3905efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, "Unable to queue frame\n"); 3915efdd5cfSKaran Tilak Kumar /* 3925efdd5cfSKaran Tilak Kumar * In case another thread cancelled the request, 3935efdd5cfSKaran Tilak Kumar * refetch the pointer under the lock. 3945efdd5cfSKaran Tilak Kumar */ 3955efdd5cfSKaran Tilak Kumar nvfnic_release_nvme_ioreq_buf(iport, io_req); 3965efdd5cfSKaran Tilak Kumar FNIC_TRACE(nvfnic_queuecommand, fnic->fnic_num, 3975efdd5cfSKaran Tilak Kumar io_req->tag, io_req->fcp_req, 0, 0, 0, 3985efdd5cfSKaran Tilak Kumar (((u64)io_req->cmd_flags << 32) | io_req->cmd_state)); 3995efdd5cfSKaran Tilak Kumar return ret; 4005efdd5cfSKaran Tilak Kumar } 401d25a557dSKaran Tilak Kumar 402d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.active_ios); 403d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.num_ios); 404d25a557dSKaran Tilak Kumar if (atomic64_read(&fnic_stats->io_stats.active_ios) > 405d25a557dSKaran Tilak Kumar atomic64_read(&fnic_stats->io_stats.max_active_ios)) 406d25a557dSKaran Tilak Kumar atomic64_set(&fnic_stats->io_stats.max_active_ios, 407d25a557dSKaran Tilak Kumar atomic64_read(&fnic_stats->io_stats.active_ios)); 4085efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_ISSUED; 4095efdd5cfSKaran Tilak Kumar out: 4105efdd5cfSKaran Tilak Kumar lba = (char *)&cmdiu->sqe.rw.slba; 4115efdd5cfSKaran Tilak Kumar cmd_trace = ((u64) cmdiu->sqe.rw.opcode << 56 | (u64) lba[4] << 40 | 4125efdd5cfSKaran Tilak Kumar (u64) lba[5] << 32 | (u64) lba[0] << 24 | 4135efdd5cfSKaran Tilak Kumar (u64) lba[1] << 16 | (u64) lba[2] << 8 | lba[3]); 4145efdd5cfSKaran Tilak Kumar 4155efdd5cfSKaran Tilak Kumar FNIC_TRACE(nvfnic_queuecommand, fnic->fnic_num, 4165efdd5cfSKaran Tilak Kumar io_req->tag, 0, io_req, 4175efdd5cfSKaran Tilak Kumar sg_count, cmd_trace, 4185efdd5cfSKaran Tilak Kumar (((u64)io_req->cmd_flags >> 32) | 4195efdd5cfSKaran Tilak Kumar io_req->cmd_state)); 4205efdd5cfSKaran Tilak Kumar 4215efdd5cfSKaran Tilak Kumar return ret; 4225efdd5cfSKaran Tilak Kumar } 4235efdd5cfSKaran Tilak Kumar 4245efdd5cfSKaran Tilak Kumar int nvfnic_fcpio_send(struct nvme_fc_local_port *lport, 4255efdd5cfSKaran Tilak Kumar struct nvme_fc_remote_port *rport, void *hw_queue_handle, 4265efdd5cfSKaran Tilak Kumar struct nvmefc_fcp_req *fcp_req) 4275efdd5cfSKaran Tilak Kumar { 4285efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = lport->private; 4295efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 4305efdd5cfSKaran Tilak Kumar int ret; 4315efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 4325efdd5cfSKaran Tilak Kumar unsigned long flags = 0; 4335efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport; 434d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 4355efdd5cfSKaran Tilak Kumar 4365efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 4375efdd5cfSKaran Tilak Kumar 4385efdd5cfSKaran Tilak Kumar tport = (struct fnic_tport_s *)rport->private; 439d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.nvme_io_reqs_rcvd); 4405efdd5cfSKaran Tilak Kumar if (!nvfnic_transport_ready(iport, tport)) { 441d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.nvme_io_rsps_sent); 4425efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 4435efdd5cfSKaran Tilak Kumar if (tport != NULL) 4445efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 4455efdd5cfSKaran Tilak Kumar "iport: 0x%x tport: 0x%x not ready\n", 4465efdd5cfSKaran Tilak Kumar iport->fcid, tport->fcid); 4475efdd5cfSKaran Tilak Kumar else 4485efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 4495efdd5cfSKaran Tilak Kumar "iport: 0x%x tport not ready\n", 4505efdd5cfSKaran Tilak Kumar iport->fcid); 4515efdd5cfSKaran Tilak Kumar return -ENODEV; 4525efdd5cfSKaran Tilak Kumar } 4535efdd5cfSKaran Tilak Kumar atomic_inc(&fnic->in_flight); 4545efdd5cfSKaran Tilak Kumar 4555efdd5cfSKaran Tilak Kumar io_req = (struct fnic_io_req *) fcp_req->private; 4565efdd5cfSKaran Tilak Kumar io_req->iport = iport; 4575efdd5cfSKaran Tilak Kumar io_req->tport = (struct fnic_tport_s *)rport->private; 4585efdd5cfSKaran Tilak Kumar io_req->fcp_req = fcp_req; 4595efdd5cfSKaran Tilak Kumar io_req->done = nvfnic_fcpio_cmpl; 4605efdd5cfSKaran Tilak Kumar io_req->sgl_list = NULL; 4615efdd5cfSKaran Tilak Kumar io_req->sgl_list_alloc = NULL; 4625efdd5cfSKaran Tilak Kumar io_req->sgl_list_pa = 0; 4635efdd5cfSKaran Tilak Kumar io_req->sgl_cnt = 0; 4645efdd5cfSKaran Tilak Kumar io_req->sgl_mapped = 0; 4655efdd5cfSKaran Tilak Kumar io_req->wq = hw_queue_handle; 4665efdd5cfSKaran Tilak Kumar init_llist_node(&io_req->nvfnic_io_cmpl); 4675efdd5cfSKaran Tilak Kumar 4685efdd5cfSKaran Tilak Kumar io_req->tag = nvfnic_alloc_fcpio_tag(iport, io_req); 4695efdd5cfSKaran Tilak Kumar if (io_req->tag == FNIC_NVME_NO_FREE_TAG) { 4705efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 4715efdd5cfSKaran Tilak Kumar "No free tag available. Failing IO\n"); 472d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.alloc_failures); 4735efdd5cfSKaran Tilak Kumar atomic_dec(&fnic->in_flight); 474d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.nvme_io_rsps_sent); 4755efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 4765efdd5cfSKaran Tilak Kumar return -EBUSY; 4775efdd5cfSKaran Tilak Kumar } 4785efdd5cfSKaran Tilak Kumar 4795efdd5cfSKaran Tilak Kumar ret = nvfnic_queuecommand(io_req); 4805efdd5cfSKaran Tilak Kumar if (ret) { 4815efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 4825efdd5cfSKaran Tilak Kumar "Queuecommand failed tag: 0x%x\n", 4835efdd5cfSKaran Tilak Kumar io_req->tag); 4845efdd5cfSKaran Tilak Kumar nvfnic_free_fcpio_tag(iport, io_req); 4855efdd5cfSKaran Tilak Kumar } 4865efdd5cfSKaran Tilak Kumar 4875efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 4885efdd5cfSKaran Tilak Kumar atomic_dec(&fnic->in_flight); 4895efdd5cfSKaran Tilak Kumar return ret; 4905efdd5cfSKaran Tilak Kumar } 4915efdd5cfSKaran Tilak Kumar 4925efdd5cfSKaran Tilak Kumar void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic, 4935efdd5cfSKaran Tilak Kumar struct fcpio_fw_req *desc) 4945efdd5cfSKaran Tilak Kumar { 4955efdd5cfSKaran Tilak Kumar u8 type; 4965efdd5cfSKaran Tilak Kumar u8 hdr_status; 4975efdd5cfSKaran Tilak Kumar struct fcpio_tag ftag; 4985efdd5cfSKaran Tilak Kumar u32 id; 4995efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 500d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 5015efdd5cfSKaran Tilak Kumar unsigned long start_time; 5025efdd5cfSKaran Tilak Kumar u64 cmd_trace; 5035efdd5cfSKaran Tilak Kumar char *lba; 5045efdd5cfSKaran Tilak Kumar struct nvme_fc_cmd_iu *cmdiu; 5055efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport; 5065efdd5cfSKaran Tilak Kumar unsigned int tag; 5075efdd5cfSKaran Tilak Kumar 5085efdd5cfSKaran Tilak Kumar /* Decode the cmpl description to get the io_req id */ 5095efdd5cfSKaran Tilak Kumar fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag); 5105efdd5cfSKaran Tilak Kumar fcpio_tag_id_dec(&ftag, &id); 5115efdd5cfSKaran Tilak Kumar tag = id & FNIC_TAG_MASK; 5125efdd5cfSKaran Tilak Kumar 5135efdd5cfSKaran Tilak Kumar if (tag >= fnic->fnic_max_tag_id) { 5145efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 5155efdd5cfSKaran Tilak Kumar "Tag out of range tag: 0x%x hdr status: %s\n", tag, 5165efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status)); 5175efdd5cfSKaran Tilak Kumar return; 5185efdd5cfSKaran Tilak Kumar } 5195efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 5205efdd5cfSKaran Tilak Kumar 5215efdd5cfSKaran Tilak Kumar io_req = nvfnic_find_io_req_by_tag(fnic, tag); 5225efdd5cfSKaran Tilak Kumar 5235efdd5cfSKaran Tilak Kumar WARN_ON_ONCE(!io_req); 5245efdd5cfSKaran Tilak Kumar if (!io_req) { 525d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.ioreq_null); 5265efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 5275efdd5cfSKaran Tilak Kumar "IO req null hdr: %s tag: 0x%x desc: 0x%p\n", 5285efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status), id, desc); 5295efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 5305efdd5cfSKaran Tilak Kumar "type: 0x%x status: 0x%x rsvd: 0x%x tag: 0x%x\n", 5315efdd5cfSKaran Tilak Kumar desc->hdr.type, desc->hdr.status, desc->hdr._resvd, 5325efdd5cfSKaran Tilak Kumar id); 5335efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 5345efdd5cfSKaran Tilak Kumar return; 5355efdd5cfSKaran Tilak Kumar } 5365efdd5cfSKaran Tilak Kumar 5375efdd5cfSKaran Tilak Kumar cmdiu = io_req->fcp_req->cmdaddr; 5385efdd5cfSKaran Tilak Kumar if (io_req->tag != tag) { 5395efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 5405efdd5cfSKaran Tilak Kumar "Tag mismatch tag:%d io:0x%x id:0x%x csn:%08x\n", 5415efdd5cfSKaran Tilak Kumar tag, io_req->tag, id, be32_to_cpu(cmdiu->csn)); 5425efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 5435efdd5cfSKaran Tilak Kumar return; 5445efdd5cfSKaran Tilak Kumar } 5455efdd5cfSKaran Tilak Kumar iport = io_req->iport; 5465efdd5cfSKaran Tilak Kumar 5475efdd5cfSKaran Tilak Kumar start_time = io_req->start_time; 5485efdd5cfSKaran Tilak Kumar 5495efdd5cfSKaran Tilak Kumar /* firmware completed the io */ 5505efdd5cfSKaran Tilak Kumar io_req->io_completed = 1; 5515efdd5cfSKaran Tilak Kumar if (io_req->cmd_state == FNIC_IOREQ_ABTS_PENDING) { 5525efdd5cfSKaran Tilak Kumar /* 5535efdd5cfSKaran Tilak Kumar * set the FNIC_IO_DONE so that this doesn't get 5545efdd5cfSKaran Tilak Kumar * flagged as 'out of order' if it was not aborted 5555efdd5cfSKaran Tilak Kumar */ 5565efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_DONE; 5575efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_ABTS_PENDING; 5585efdd5cfSKaran Tilak Kumar if (hdr_status == FCPIO_ABORTED) 5595efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_ABORTED; 5605efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 5615efdd5cfSKaran Tilak Kumar 5625efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 5635efdd5cfSKaran Tilak Kumar "icmnd abts hdr:%d %s tag:0x%x io:%p", 5645efdd5cfSKaran Tilak Kumar hdr_status, fnic_fcpio_status_to_str(hdr_status), 5655efdd5cfSKaran Tilak Kumar id, io_req); 5665efdd5cfSKaran Tilak Kumar return; 5675efdd5cfSKaran Tilak Kumar } 5685efdd5cfSKaran Tilak Kumar 5695efdd5cfSKaran Tilak Kumar if (io_req->cmd_state != FNIC_IOREQ_CMD_PENDING) { 5705efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 5715efdd5cfSKaran Tilak Kumar "IO freed id:%d tag:0x%x st:0x%x csn:%08x\n", 5725efdd5cfSKaran Tilak Kumar id, io_req->tag, io_req->cmd_state, 5735efdd5cfSKaran Tilak Kumar be32_to_cpu(cmdiu->csn)); 5745efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 5755efdd5cfSKaran Tilak Kumar return; 5765efdd5cfSKaran Tilak Kumar } 5775efdd5cfSKaran Tilak Kumar 5785efdd5cfSKaran Tilak Kumar /* Mark the IO as complete */ 5795efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_CMD_COMPLETE; 5805efdd5cfSKaran Tilak Kumar switch (hdr_status) { 5815efdd5cfSKaran Tilak Kumar case FCPIO_SUCCESS: 5825efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = 0; 5835efdd5cfSKaran Tilak Kumar io_req->fcp_req->transferred_length = 5845efdd5cfSKaran Tilak Kumar io_req->fcp_req->payload_length; 5855efdd5cfSKaran Tilak Kumar io_req->fcp_req->rcv_rsplen = 12; 5865efdd5cfSKaran Tilak Kumar break; 5875efdd5cfSKaran Tilak Kumar default: 5885efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, "HDR status is non-zero\n"); 5895efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = NVME_SC_INTERNAL; 5905efdd5cfSKaran Tilak Kumar break; 5915efdd5cfSKaran Tilak Kumar } 5925efdd5cfSKaran Tilak Kumar 5935efdd5cfSKaran Tilak Kumar if (hdr_status != FCPIO_SUCCESS) { 594d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.io_failures); 5955efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, "hdr status: %s\n", 5965efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status)); 5975efdd5cfSKaran Tilak Kumar } 5985efdd5cfSKaran Tilak Kumar 5995efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_DONE; 6005efdd5cfSKaran Tilak Kumar 6015efdd5cfSKaran Tilak Kumar cmdiu = io_req->fcp_req->cmdaddr; 6025efdd5cfSKaran Tilak Kumar lba = (char *)&cmdiu->sqe.rw.slba; 6035efdd5cfSKaran Tilak Kumar cmd_trace = ((u64) hdr_status << 56) | 6045efdd5cfSKaran Tilak Kumar (u64) cmdiu->sqe.rw.opcode << 32 | 6055efdd5cfSKaran Tilak Kumar (u64) lba[0] << 24 | (u64) lba[1] << 16 | 6065efdd5cfSKaran Tilak Kumar (u64) lba[2] << 8 | lba[3]; 6075efdd5cfSKaran Tilak Kumar 6085efdd5cfSKaran Tilak Kumar FNIC_TRACE(nvfnic_fcpio_nvme_fast_cmpl_handler, fnic->fnic_num, 6095efdd5cfSKaran Tilak Kumar tag, io_req, 6105efdd5cfSKaran Tilak Kumar jiffies_to_msecs(jiffies - start_time), 6115efdd5cfSKaran Tilak Kumar desc, cmd_trace, 6125efdd5cfSKaran Tilak Kumar (((u64) io_req->cmd_flags << 32) | 6135efdd5cfSKaran Tilak Kumar io_req->cmd_state)); 6145efdd5cfSKaran Tilak Kumar 615d25a557dSKaran Tilak Kumar nvfnic_update_io_stats(fnic, cmdiu->sqe.rw.opcode); 6165efdd5cfSKaran Tilak Kumar nvfnic_update_io_bytes(fnic, io_req, cmdiu->sqe.rw.opcode); 617d25a557dSKaran Tilak Kumar nvfnic_update_cmpl_stats(fnic, io_req); 6185efdd5cfSKaran Tilak Kumar 6195efdd5cfSKaran Tilak Kumar nvfnic_release_nvme_ioreq_buf(iport, io_req); 6205efdd5cfSKaran Tilak Kumar if (io_req->done) 6215efdd5cfSKaran Tilak Kumar io_req->done(io_req); 6225efdd5cfSKaran Tilak Kumar 6235efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 6245efdd5cfSKaran Tilak Kumar } 6255efdd5cfSKaran Tilak Kumar 6265efdd5cfSKaran Tilak Kumar void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic, 6275efdd5cfSKaran Tilak Kumar struct fcpio_fw_req *desc, int sw_flag) 6285efdd5cfSKaran Tilak Kumar { 6295efdd5cfSKaran Tilak Kumar u8 type; 6305efdd5cfSKaran Tilak Kumar u8 hdr_status; 6315efdd5cfSKaran Tilak Kumar struct fcpio_tag ftag; 6325efdd5cfSKaran Tilak Kumar u32 id; 6335efdd5cfSKaran Tilak Kumar struct fcpio_nvme_cmpl *nvme_cmpl; 6345efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 635d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 6365efdd5cfSKaran Tilak Kumar unsigned long start_time; 6375efdd5cfSKaran Tilak Kumar uint32_t rsplen; 6385efdd5cfSKaran Tilak Kumar struct nvme_fc_ersp_iu *ersp; 6395efdd5cfSKaran Tilak Kumar struct nvme_fc_ersp_iu *nrsp; 6405efdd5cfSKaran Tilak Kumar struct nvme_fc_cmd_iu *cmdiu; 6415efdd5cfSKaran Tilak Kumar struct nvme_command *sqe; 6425efdd5cfSKaran Tilak Kumar struct nvme_completion *cqe; 6435efdd5cfSKaran Tilak Kumar u64 cmd_trace; 6445efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport; 6455efdd5cfSKaran Tilak Kumar unsigned int tag; 6465efdd5cfSKaran Tilak Kumar char *lba; 6475efdd5cfSKaran Tilak Kumar uint64_t tport_wwpn = 0; 6485efdd5cfSKaran Tilak Kumar 6495efdd5cfSKaran Tilak Kumar /* Decode the cmpl description to get the io_req id */ 6505efdd5cfSKaran Tilak Kumar fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag); 6515efdd5cfSKaran Tilak Kumar fcpio_tag_id_dec(&ftag, &id); 6525efdd5cfSKaran Tilak Kumar nvme_cmpl = &desc->u.nvme_cmpl; 6535efdd5cfSKaran Tilak Kumar ersp = (struct nvme_fc_ersp_iu *) nvme_cmpl->resp_bytes; 6545efdd5cfSKaran Tilak Kumar tag = id & FNIC_TAG_MASK; 6555efdd5cfSKaran Tilak Kumar 6565efdd5cfSKaran Tilak Kumar if (tag >= fnic->fnic_max_tag_id) { 6575efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 6585efdd5cfSKaran Tilak Kumar "Tag out of range tag:0x%x hdr:%s\n", tag, 6595efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status)); 6605efdd5cfSKaran Tilak Kumar return; 6615efdd5cfSKaran Tilak Kumar } 6625efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 6635efdd5cfSKaran Tilak Kumar 6645efdd5cfSKaran Tilak Kumar io_req = nvfnic_find_io_req_by_tag(fnic, tag); 6655efdd5cfSKaran Tilak Kumar if (!io_req) { 666d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.ioreq_null); 6675efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 6685efdd5cfSKaran Tilak Kumar "IOREQ is null hdr status: %s tag: 0x%x desc: %p\n", 6695efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status), tag, desc); 6705efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 6715efdd5cfSKaran Tilak Kumar "type: 0x%x status: 0x%x rsvd: 0x%x\n", 6725efdd5cfSKaran Tilak Kumar desc->hdr.type, desc->hdr.status, desc->hdr._resvd); 6735efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 6745efdd5cfSKaran Tilak Kumar return; 6755efdd5cfSKaran Tilak Kumar } 6765efdd5cfSKaran Tilak Kumar iport = io_req->iport; 6775efdd5cfSKaran Tilak Kumar if (io_req->tport != NULL) 6785efdd5cfSKaran Tilak Kumar tport_wwpn = io_req->tport->wwpn; 6795efdd5cfSKaran Tilak Kumar cmdiu = io_req->fcp_req->cmdaddr; 6805efdd5cfSKaran Tilak Kumar 6815efdd5cfSKaran Tilak Kumar if (io_req->tag != tag) { 6825efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 6835efdd5cfSKaran Tilak Kumar "Tag mismatch io:0x%x tag:0x%x id:0x%x\n", 6845efdd5cfSKaran Tilak Kumar io_req->tag, tag, id); 6855efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 6865efdd5cfSKaran Tilak Kumar return; 6875efdd5cfSKaran Tilak Kumar } 6885efdd5cfSKaran Tilak Kumar 6895efdd5cfSKaran Tilak Kumar nrsp = (struct nvme_fc_ersp_iu *)io_req->fcp_req->rspaddr; 6905efdd5cfSKaran Tilak Kumar cmdiu = (struct nvme_fc_cmd_iu *)io_req->fcp_req->cmdaddr; 6915efdd5cfSKaran Tilak Kumar sqe = &cmdiu->sqe; 6925efdd5cfSKaran Tilak Kumar cqe = &nrsp->cqe; 6935efdd5cfSKaran Tilak Kumar start_time = io_req->start_time; 6945efdd5cfSKaran Tilak Kumar 6955efdd5cfSKaran Tilak Kumar /* firmware completed the io */ 6965efdd5cfSKaran Tilak Kumar io_req->io_completed = 1; 6975efdd5cfSKaran Tilak Kumar 6985efdd5cfSKaran Tilak Kumar if (io_req->cmd_state == FNIC_IOREQ_ABTS_PENDING) { 6995efdd5cfSKaran Tilak Kumar /* 7005efdd5cfSKaran Tilak Kumar * set the FNIC_IO_DONE so that this doesn't get 7015efdd5cfSKaran Tilak Kumar * flagged as 'out of order' if it was not aborted 7025efdd5cfSKaran Tilak Kumar */ 7035efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_DONE; 7045efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_ABTS_PENDING; 7055efdd5cfSKaran Tilak Kumar if (hdr_status == FCPIO_ABORTED) 7065efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_ABORTED; 7075efdd5cfSKaran Tilak Kumar 7085efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 7095efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 7105efdd5cfSKaran Tilak Kumar "ABTS pending hdr status: %s tag: 0x%x", 7115efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status), tag); 7125efdd5cfSKaran Tilak Kumar return; 7135efdd5cfSKaran Tilak Kumar } 7145efdd5cfSKaran Tilak Kumar 7155efdd5cfSKaran Tilak Kumar if (io_req->cmd_state != FNIC_IOREQ_CMD_PENDING) { 7165efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 7175efdd5cfSKaran Tilak Kumar "IO already freed by abort. tag: 0x%x id: 0x%x\n", 7185efdd5cfSKaran Tilak Kumar io_req->tag, id); 7195efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 7205efdd5cfSKaran Tilak Kumar return; 7215efdd5cfSKaran Tilak Kumar } 7225efdd5cfSKaran Tilak Kumar 7235efdd5cfSKaran Tilak Kumar /* Mark the IO as complete */ 7245efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_CMD_COMPLETE; 7255efdd5cfSKaran Tilak Kumar 7265efdd5cfSKaran Tilak Kumar switch (hdr_status) { 7275efdd5cfSKaran Tilak Kumar case FCPIO_SUCCESS: 7285efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = 0; 7295efdd5cfSKaran Tilak Kumar if (!sw_flag) { 7305efdd5cfSKaran Tilak Kumar io_req->fcp_req->transferred_length = 7315efdd5cfSKaran Tilak Kumar io_req->fcp_req->payload_length; 7325efdd5cfSKaran Tilak Kumar rsplen = 32; 7335efdd5cfSKaran Tilak Kumar nrsp->iu_len = 7345efdd5cfSKaran Tilak Kumar cpu_to_be16(sizeof(struct nvme_fc_ersp_iu) / 4); 7355efdd5cfSKaran Tilak Kumar nrsp->xfrd_len = 7365efdd5cfSKaran Tilak Kumar cpu_to_be32(io_req->fcp_req->payload_length); 7375efdd5cfSKaran Tilak Kumar 7385efdd5cfSKaran Tilak Kumar nrsp->ersp_result = 0; 7395efdd5cfSKaran Tilak Kumar cqe->command_id = sqe->common.command_id; 7405efdd5cfSKaran Tilak Kumar cqe->status = 0; 7415efdd5cfSKaran Tilak Kumar cqe->result.u64 = 0; 7425efdd5cfSKaran Tilak Kumar } else { 7435efdd5cfSKaran Tilak Kumar io_req->fcp_req->transferred_length = 7445efdd5cfSKaran Tilak Kumar be32_to_cpu(ersp->xfrd_len); 7455efdd5cfSKaran Tilak Kumar rsplen = be16_to_cpu(ersp->iu_len) * 4; 7465efdd5cfSKaran Tilak Kumar if (rsplen > sizeof(nvme_cmpl->resp_bytes) || 7475efdd5cfSKaran Tilak Kumar rsplen > io_req->fcp_req->rsplen) { 7485efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 7495efdd5cfSKaran Tilak Kumar "tport wwpn 0x%llx ERSP len %u desc %u req %u\n", 7505efdd5cfSKaran Tilak Kumar tport_wwpn, rsplen, 7515efdd5cfSKaran Tilak Kumar (u32)sizeof(nvme_cmpl->resp_bytes), 7525efdd5cfSKaran Tilak Kumar io_req->fcp_req->rsplen); 7535efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = NVME_SC_INTERNAL; 7545efdd5cfSKaran Tilak Kumar io_req->fcp_req->rcv_rsplen = 0; 7555efdd5cfSKaran Tilak Kumar break; 7565efdd5cfSKaran Tilak Kumar } 7575efdd5cfSKaran Tilak Kumar memcpy(io_req->fcp_req->rspaddr, ersp, rsplen); 7585efdd5cfSKaran Tilak Kumar } 759d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_ersps); 7605efdd5cfSKaran Tilak Kumar io_req->fcp_req->rcv_rsplen = rsplen; 7615efdd5cfSKaran Tilak Kumar break; 7625efdd5cfSKaran Tilak Kumar 7635efdd5cfSKaran Tilak Kumar default: 7645efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 7655efdd5cfSKaran Tilak Kumar "Unexpected header status: %d\n", hdr_status); 7665efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = NVME_SC_INTERNAL; 7675efdd5cfSKaran Tilak Kumar break; 7685efdd5cfSKaran Tilak Kumar } 7695efdd5cfSKaran Tilak Kumar 7705efdd5cfSKaran Tilak Kumar if (hdr_status != FCPIO_SUCCESS) { 771d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.io_failures); 7725efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, "hdr status: %s tag: 0x%x\n", 7735efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status), tag); 7745efdd5cfSKaran Tilak Kumar } 7755efdd5cfSKaran Tilak Kumar 7765efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_DONE; 7775efdd5cfSKaran Tilak Kumar 7785efdd5cfSKaran Tilak Kumar lba = (char *) &cmdiu->sqe.rw.slba; 7795efdd5cfSKaran Tilak Kumar cmd_trace = ((u64) hdr_status << 56) | 7805efdd5cfSKaran Tilak Kumar (u64) ersp->ersp_result << 48 | 7815efdd5cfSKaran Tilak Kumar (u64) cmdiu->sqe.rw.opcode << 32 | 7825efdd5cfSKaran Tilak Kumar (u64) lba[0] << 24 | (u64) lba[1] << 16 | 7835efdd5cfSKaran Tilak Kumar (u64) lba[2] << 8 | lba[3]; 7845efdd5cfSKaran Tilak Kumar 7855efdd5cfSKaran Tilak Kumar FNIC_TRACE(nvfnic_fcpio_ersp_cmpl_handler, fnic->fnic_num, 7865efdd5cfSKaran Tilak Kumar tag, io_req, 7875efdd5cfSKaran Tilak Kumar ((u64) nvme_cmpl->resvd[1] << 56 | 7885efdd5cfSKaran Tilak Kumar (u64) nvme_cmpl->resvd[0] << 48 | 7895efdd5cfSKaran Tilak Kumar jiffies_to_msecs(jiffies - start_time)), 7905efdd5cfSKaran Tilak Kumar desc, cmd_trace, 7915efdd5cfSKaran Tilak Kumar (((u64) io_req->cmd_flags << 32) | 7925efdd5cfSKaran Tilak Kumar io_req->cmd_state)); 7935efdd5cfSKaran Tilak Kumar 794d25a557dSKaran Tilak Kumar nvfnic_update_io_stats(fnic, cmdiu->sqe.rw.opcode); 7955efdd5cfSKaran Tilak Kumar nvfnic_update_io_bytes(fnic, io_req, cmdiu->sqe.rw.opcode); 796d25a557dSKaran Tilak Kumar nvfnic_update_cmpl_stats(fnic, io_req); 7975efdd5cfSKaran Tilak Kumar 7985efdd5cfSKaran Tilak Kumar nvfnic_release_nvme_ioreq_buf(iport, io_req); 7995efdd5cfSKaran Tilak Kumar 8005efdd5cfSKaran Tilak Kumar /* Call NVME completion function to complete the IO */ 8015efdd5cfSKaran Tilak Kumar if (io_req->done) 8025efdd5cfSKaran Tilak Kumar io_req->done(io_req); 8035efdd5cfSKaran Tilak Kumar 8045efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 8055efdd5cfSKaran Tilak Kumar } 8065efdd5cfSKaran Tilak Kumar 8075efdd5cfSKaran Tilak Kumar void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic, 8085efdd5cfSKaran Tilak Kumar struct fcpio_fw_req *desc) 8095efdd5cfSKaran Tilak Kumar { 8105efdd5cfSKaran Tilak Kumar u8 type; 8115efdd5cfSKaran Tilak Kumar u8 hdr_status; 8125efdd5cfSKaran Tilak Kumar struct fcpio_tag ftag; 8135efdd5cfSKaran Tilak Kumar u32 id; 8145efdd5cfSKaran Tilak Kumar unsigned int tag; 8155efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 8165efdd5cfSKaran Tilak Kumar struct nvme_fc_cmd_iu *cmd_iu; 817d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 818d25a557dSKaran Tilak Kumar struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats; 819d25a557dSKaran Tilak Kumar struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats; 820d25a557dSKaran Tilak Kumar struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; 8215efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport; 8225efdd5cfSKaran Tilak Kumar 8235efdd5cfSKaran Tilak Kumar fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag); 8245efdd5cfSKaran Tilak Kumar fcpio_tag_id_dec(&ftag, &id); 8255efdd5cfSKaran Tilak Kumar tag = id & FNIC_TAG_MASK; 8265efdd5cfSKaran Tilak Kumar 8275efdd5cfSKaran Tilak Kumar if (tag >= fnic->fnic_max_tag_id) { 8285efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8295efdd5cfSKaran Tilak Kumar "Tag out of range id:0x%x tag:0x%x hdr:%s\n", 8305efdd5cfSKaran Tilak Kumar id, tag, fnic_fcpio_status_to_str(hdr_status)); 8315efdd5cfSKaran Tilak Kumar return; 8325efdd5cfSKaran Tilak Kumar } 8335efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 8345efdd5cfSKaran Tilak Kumar 8355efdd5cfSKaran Tilak Kumar io_req = nvfnic_find_io_req_by_tag(fnic, tag); 8365efdd5cfSKaran Tilak Kumar WARN_ON_ONCE(!io_req); 8375efdd5cfSKaran Tilak Kumar if (!io_req) { 838d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.ioreq_null); 8395efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8405efdd5cfSKaran Tilak Kumar "IOREQ null hdr:%s tag:0x%x desc:%p\n", 8415efdd5cfSKaran Tilak Kumar fnic_fcpio_status_to_str(hdr_status), tag, desc); 8425efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8435efdd5cfSKaran Tilak Kumar "type: 0x%x status: 0x%x rsvd: 0x%x\n", 8445efdd5cfSKaran Tilak Kumar desc->hdr.type, desc->hdr.status, desc->hdr._resvd); 8455efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 8465efdd5cfSKaran Tilak Kumar return; 8475efdd5cfSKaran Tilak Kumar } 8485efdd5cfSKaran Tilak Kumar 8495efdd5cfSKaran Tilak Kumar cmd_iu = io_req->fcp_req->cmdaddr; 8505efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 8515efdd5cfSKaran Tilak Kumar "Received ITMF completion tag: 0x%x hdr_status: %d csn: 0x%08x\n", 8525efdd5cfSKaran Tilak Kumar tag, hdr_status, be32_to_cpu(cmd_iu->csn)); 8535efdd5cfSKaran Tilak Kumar 8545efdd5cfSKaran Tilak Kumar iport = io_req->iport; 8555efdd5cfSKaran Tilak Kumar 8565efdd5cfSKaran Tilak Kumar /* Completion of abort cmd */ 8575efdd5cfSKaran Tilak Kumar switch (hdr_status) { 8585efdd5cfSKaran Tilak Kumar case FCPIO_SUCCESS: 8595efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, fnic, 8605efdd5cfSKaran Tilak Kumar "Abort success received tag: 0x%x id: 0x%x\n", 8615efdd5cfSKaran Tilak Kumar tag, id); 8625efdd5cfSKaran Tilak Kumar break; 8635efdd5cfSKaran Tilak Kumar case FCPIO_TIMEOUT: 8645efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8655efdd5cfSKaran Tilak Kumar "Abort timeout received tag: 0x%x id: 0x%x\n", 8665efdd5cfSKaran Tilak Kumar tag, id); 867d25a557dSKaran Tilak Kumar if (io_req->cmd_flags & FNIC_IO_ABTS_ISSUED) 868d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_fw_timeouts); 869d25a557dSKaran Tilak Kumar else 870d25a557dSKaran Tilak Kumar atomic64_inc(&term_stats->terminate_fw_timeouts); 8715efdd5cfSKaran Tilak Kumar break; 8725efdd5cfSKaran Tilak Kumar case FCPIO_ITMF_REJECTED: 8735efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8745efdd5cfSKaran Tilak Kumar "Abort reject received tag: 0x%x id: 0x%x\n", 8755efdd5cfSKaran Tilak Kumar tag, id); 8765efdd5cfSKaran Tilak Kumar break; 8775efdd5cfSKaran Tilak Kumar 8785efdd5cfSKaran Tilak Kumar case FCPIO_IO_NOT_FOUND: 8795efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8805efdd5cfSKaran Tilak Kumar "Abort IO not found tag:0x%x id:0x%x\n", 8815efdd5cfSKaran Tilak Kumar tag, id); 882d25a557dSKaran Tilak Kumar if (io_req->cmd_flags & FNIC_IO_ABTS_ISSUED) 883d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_io_not_found); 884d25a557dSKaran Tilak Kumar else 885d25a557dSKaran Tilak Kumar atomic64_inc(&term_stats->terminate_io_not_found); 8865efdd5cfSKaran Tilak Kumar break; 8875efdd5cfSKaran Tilak Kumar default: 8885efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 8895efdd5cfSKaran Tilak Kumar "Abort unknown received tag: 0x%x id: 0x%x\n", 8905efdd5cfSKaran Tilak Kumar tag, id); 891d25a557dSKaran Tilak Kumar if (io_req->cmd_flags & FNIC_IO_ABTS_ISSUED) 892d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_failures); 893d25a557dSKaran Tilak Kumar else 894d25a557dSKaran Tilak Kumar atomic64_inc(&term_stats->terminate_failures); 8955efdd5cfSKaran Tilak Kumar break; 8965efdd5cfSKaran Tilak Kumar } 8975efdd5cfSKaran Tilak Kumar 8985efdd5cfSKaran Tilak Kumar if (io_req->cmd_state != FNIC_IOREQ_ABTS_PENDING) { 8995efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 9005efdd5cfSKaran Tilak Kumar "Abort late completion tag:0x%x id:0x%x\n", 9015efdd5cfSKaran Tilak Kumar tag, id); 9025efdd5cfSKaran Tilak Kumar /* This is a late completion. Ignore it */ 9035efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 9045efdd5cfSKaran Tilak Kumar return; 9055efdd5cfSKaran Tilak Kumar } 9065efdd5cfSKaran Tilak Kumar 9075efdd5cfSKaran Tilak Kumar io_req->abts_state = hdr_status; 9085efdd5cfSKaran Tilak Kumar 9095efdd5cfSKaran Tilak Kumar /* If the status is IO not found consider it as success. 9105efdd5cfSKaran Tilak Kumar * NVME sends abort even if rport is down in which case 9115efdd5cfSKaran Tilak Kumar * we will get FCPIO_TIMEOUT. Consider this as success. 9125efdd5cfSKaran Tilak Kumar */ 9135efdd5cfSKaran Tilak Kumar if ((hdr_status == FCPIO_IO_NOT_FOUND) || 9145efdd5cfSKaran Tilak Kumar (hdr_status == FCPIO_TIMEOUT) || 9155efdd5cfSKaran Tilak Kumar (hdr_status == FCPIO_ITMF_REJECTED)) 9165efdd5cfSKaran Tilak Kumar io_req->abts_state = FCPIO_SUCCESS; 9175efdd5cfSKaran Tilak Kumar 9185efdd5cfSKaran Tilak Kumar io_req->cmd_flags |= FNIC_IO_ABT_TERM_DONE; 9195efdd5cfSKaran Tilak Kumar 920d25a557dSKaran Tilak Kumar if (!(io_req->cmd_flags & (FNIC_IO_ABORTED | FNIC_IO_DONE))) 921d25a557dSKaran Tilak Kumar atomic64_inc(&misc_stats->no_icmnd_itmf_cmpls); 9225efdd5cfSKaran Tilak Kumar 9235efdd5cfSKaran Tilak Kumar io_req->fcp_req->transferred_length = 0; 9245efdd5cfSKaran Tilak Kumar io_req->fcp_req->rcv_rsplen = 0; 9255efdd5cfSKaran Tilak Kumar if (io_req->abts_state == FCPIO_SUCCESS) 9265efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = NVME_SC_ABORT_REQ; 9275efdd5cfSKaran Tilak Kumar else 9285efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = NVME_SC_INTERNAL; 9295efdd5cfSKaran Tilak Kumar 930d25a557dSKaran Tilak Kumar atomic64_dec(&fnic_stats->io_stats.active_ios); 931d25a557dSKaran Tilak Kumar if (atomic64_read(&fnic->io_cmpl_skip)) 932d25a557dSKaran Tilak Kumar atomic64_dec(&fnic->io_cmpl_skip); 933d25a557dSKaran Tilak Kumar else 934d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.io_completions); 935d25a557dSKaran Tilak Kumar 9365efdd5cfSKaran Tilak Kumar nvfnic_release_nvme_ioreq_buf(iport, io_req); 9375efdd5cfSKaran Tilak Kumar if (io_req->done) 9385efdd5cfSKaran Tilak Kumar io_req->done(io_req); 9395efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 9405efdd5cfSKaran Tilak Kumar } 9415efdd5cfSKaran Tilak Kumar 9425efdd5cfSKaran Tilak Kumar bool _cleanup_tport_io(struct sbitmap *map, unsigned int tag, 9435efdd5cfSKaran Tilak Kumar void *data) 9445efdd5cfSKaran Tilak Kumar { 9455efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport = data; 9465efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = tport->iport; 9475efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 9485efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 9495efdd5cfSKaran Tilak Kumar enum fnic_ioreq_state old_ioreq_state; 9505efdd5cfSKaran Tilak Kumar unsigned long flags; 9515efdd5cfSKaran Tilak Kumar 9525efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 9535efdd5cfSKaran Tilak Kumar io_req = nvfnic_find_io_req_by_tag(fnic, tag); 9545efdd5cfSKaran Tilak Kumar if (!io_req || io_req->tport != tport) { 9555efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 9565efdd5cfSKaran Tilak Kumar return true; 9575efdd5cfSKaran Tilak Kumar } 9585efdd5cfSKaran Tilak Kumar 9595efdd5cfSKaran Tilak Kumar if ((io_req->cmd_state == FNIC_IOREQ_ABTS_PENDING) || 9605efdd5cfSKaran Tilak Kumar (io_req->cmd_state == FNIC_DEV_RST_TERM_ISSUED)) { 9615efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 9625efdd5cfSKaran Tilak Kumar "Abort already pending 0x%x\n", io_req->tag); 9635efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 9645efdd5cfSKaran Tilak Kumar return true; 9655efdd5cfSKaran Tilak Kumar } 9665efdd5cfSKaran Tilak Kumar 9675efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 9685efdd5cfSKaran Tilak Kumar "io_req tag: 0x%x abort after unregister timeout\n", 9695efdd5cfSKaran Tilak Kumar io_req->tag); 9705efdd5cfSKaran Tilak Kumar 9715efdd5cfSKaran Tilak Kumar old_ioreq_state = io_req->cmd_state; 9725efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_ABTS_PENDING; 9735efdd5cfSKaran Tilak Kumar io_req->abts_state = FCPIO_INVALID_CODE; 9745efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 9755efdd5cfSKaran Tilak Kumar 9765efdd5cfSKaran Tilak Kumar if (!nvfnic_queue_abort_io_req(fnic, io_req->tag, 9775efdd5cfSKaran Tilak Kumar FCPIO_ITMF_ABT_TASK_TERM, 9785efdd5cfSKaran Tilak Kumar io_req)) { 9795efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 9805efdd5cfSKaran Tilak Kumar "Failed to enqueue abort for ioreq tag: 0x%x\n", 9815efdd5cfSKaran Tilak Kumar io_req->tag); 9825efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 9835efdd5cfSKaran Tilak Kumar io_req->cmd_state = old_ioreq_state; 9845efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 9855efdd5cfSKaran Tilak Kumar } 9865efdd5cfSKaran Tilak Kumar return true; 9875efdd5cfSKaran Tilak Kumar } 9885efdd5cfSKaran Tilak Kumar 9895efdd5cfSKaran Tilak Kumar void 9905efdd5cfSKaran Tilak Kumar nvfnic_cleanup_tport_io(struct fnic *fnic, struct fnic_tport_s *tport) 9915efdd5cfSKaran Tilak Kumar { 9925efdd5cfSKaran Tilak Kumar unsigned long flags; 9935efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req, *next; 9945efdd5cfSKaran Tilak Kumar struct nvmefc_ls_req *lsreq; 9955efdd5cfSKaran Tilak Kumar uint16_t oxid; 9965efdd5cfSKaran Tilak Kumar LIST_HEAD(done_reqs); 9975efdd5cfSKaran Tilak Kumar 9985efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 9995efdd5cfSKaran Tilak Kumar list_for_each_entry_safe(nvfnic_ls_req, next, 10005efdd5cfSKaran Tilak Kumar &(tport->ls_req_list), list) { 10015efdd5cfSKaran Tilak Kumar lsreq = nvfnic_ls_req->ls_req; 10025efdd5cfSKaran Tilak Kumar if (!lsreq || (lsreq->private == NULL)) { 10035efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 10045efdd5cfSKaran Tilak Kumar "fnic_cleanup_tport_io lsreq NULL\n"); 10055efdd5cfSKaran Tilak Kumar continue; 10065efdd5cfSKaran Tilak Kumar } 10075efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_STARTED) { 10085efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 10095efdd5cfSKaran Tilak Kumar "fnic_cleanup_tport_io lsreq abort started\n"); 10105efdd5cfSKaran Tilak Kumar continue; 10115efdd5cfSKaran Tilak Kumar } 10125efdd5cfSKaran Tilak Kumar list_del_init(&nvfnic_ls_req->list); 10135efdd5cfSKaran Tilak Kumar lsreq->private = NULL; 10145efdd5cfSKaran Tilak Kumar oxid = nvfnic_ls_req->oxid; 10155efdd5cfSKaran Tilak Kumar fdls_free_oxid(&fnic->iport, oxid, &nvfnic_ls_req->oxid); 10165efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_COMPLETE; 10175efdd5cfSKaran Tilak Kumar list_add_tail(&nvfnic_ls_req->list, &done_reqs); 10185efdd5cfSKaran Tilak Kumar } 10195efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 10205efdd5cfSKaran Tilak Kumar 10215efdd5cfSKaran Tilak Kumar list_for_each_entry_safe(nvfnic_ls_req, next, &done_reqs, list) { 10225efdd5cfSKaran Tilak Kumar list_del_init(&nvfnic_ls_req->list); 10235efdd5cfSKaran Tilak Kumar lsreq = nvfnic_ls_req->ls_req; 10245efdd5cfSKaran Tilak Kumar timer_delete_sync(&nvfnic_ls_req->ls_req_timer); 10255efdd5cfSKaran Tilak Kumar lsreq->done(lsreq, -ENXIO); 10265efdd5cfSKaran Tilak Kumar } 10275efdd5cfSKaran Tilak Kumar 10285efdd5cfSKaran Tilak Kumar /* For link-down, IOs are freed by firmware reset completion */ 10295efdd5cfSKaran Tilak Kumar if (fdls_get_state(&fnic->iport.fabric) == FDLS_STATE_LINKDOWN) 10305efdd5cfSKaran Tilak Kumar return; 10315efdd5cfSKaran Tilak Kumar 10325efdd5cfSKaran Tilak Kumar sbitmap_for_each_set(&fnic->nvfnic_tag_map, _cleanup_tport_io, tport); 10335efdd5cfSKaran Tilak Kumar } 10345efdd5cfSKaran Tilak Kumar 10355efdd5cfSKaran Tilak Kumar void 10365efdd5cfSKaran Tilak Kumar nvfnic_terminate_tport_ls_reqs(struct fnic *fnic, struct fnic_tport_s *tport) 10375efdd5cfSKaran Tilak Kumar { 10385efdd5cfSKaran Tilak Kumar struct nvmefc_ls_req *lsreq; 10395efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req, *next; 10405efdd5cfSKaran Tilak Kumar int count = 0; 10415efdd5cfSKaran Tilak Kumar uint16_t oxid; 10425efdd5cfSKaran Tilak Kumar LIST_HEAD(done_reqs); 10435efdd5cfSKaran Tilak Kumar 10445efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 10455efdd5cfSKaran Tilak Kumar list_for_each_entry_safe(nvfnic_ls_req, next, 10465efdd5cfSKaran Tilak Kumar &(tport->ls_req_list), list) { 10475efdd5cfSKaran Tilak Kumar 10485efdd5cfSKaran Tilak Kumar lsreq = nvfnic_ls_req->ls_req; 10495efdd5cfSKaran Tilak Kumar if (!lsreq || (lsreq->private == NULL)) { 10505efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 10515efdd5cfSKaran Tilak Kumar "lsreq is NULL\n"); 10525efdd5cfSKaran Tilak Kumar continue; 10535efdd5cfSKaran Tilak Kumar } 10545efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_STARTED) { 10555efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 10565efdd5cfSKaran Tilak Kumar "lsreq abort started\n"); 10575efdd5cfSKaran Tilak Kumar continue; 10585efdd5cfSKaran Tilak Kumar } 10595efdd5cfSKaran Tilak Kumar oxid = nvfnic_ls_req->oxid; 10605efdd5cfSKaran Tilak Kumar list_del_init(&nvfnic_ls_req->list); 10615efdd5cfSKaran Tilak Kumar lsreq->private = NULL; 10625efdd5cfSKaran Tilak Kumar fdls_free_oxid(&fnic->iport, oxid, &nvfnic_ls_req->oxid); 10635efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_COMPLETE; 10645efdd5cfSKaran Tilak Kumar list_add_tail(&nvfnic_ls_req->list, &done_reqs); 10655efdd5cfSKaran Tilak Kumar } 10665efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 10675efdd5cfSKaran Tilak Kumar 10685efdd5cfSKaran Tilak Kumar list_for_each_entry_safe(nvfnic_ls_req, next, &done_reqs, list) { 10695efdd5cfSKaran Tilak Kumar list_del_init(&nvfnic_ls_req->list); 10705efdd5cfSKaran Tilak Kumar lsreq = nvfnic_ls_req->ls_req; 10715efdd5cfSKaran Tilak Kumar timer_delete_sync(&nvfnic_ls_req->ls_req_timer); 10725efdd5cfSKaran Tilak Kumar lsreq->done(lsreq, -ENXIO); 10735efdd5cfSKaran Tilak Kumar count++; 10745efdd5cfSKaran Tilak Kumar } 10755efdd5cfSKaran Tilak Kumar 10765efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 10775efdd5cfSKaran Tilak Kumar "fnic_terminate_tport_lsreqs tport: 0x%x: freed lsreq: %d\n", 10785efdd5cfSKaran Tilak Kumar tport->fcid, count); 10795efdd5cfSKaran Tilak Kumar } 10805efdd5cfSKaran Tilak Kumar 10815efdd5cfSKaran Tilak Kumar bool _terminate_tport_ios(struct sbitmap *map, unsigned int tag, 10825efdd5cfSKaran Tilak Kumar void *data) 10835efdd5cfSKaran Tilak Kumar { 10845efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport = data; 10855efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = tport->iport; 10865efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 10875efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 10885efdd5cfSKaran Tilak Kumar enum fnic_ioreq_state old_ioreq_state; 10895efdd5cfSKaran Tilak Kumar unsigned long flags; 10905efdd5cfSKaran Tilak Kumar 10915efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 10925efdd5cfSKaran Tilak Kumar io_req = fnic->sw_copy_wq[0].io_req_table[tag]; 10935efdd5cfSKaran Tilak Kumar if (!io_req) { 10945efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 10955efdd5cfSKaran Tilak Kumar return true; 10965efdd5cfSKaran Tilak Kumar } 10975efdd5cfSKaran Tilak Kumar 10985efdd5cfSKaran Tilak Kumar if (io_req->tport != tport) { 10995efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 11005efdd5cfSKaran Tilak Kumar return true; 11015efdd5cfSKaran Tilak Kumar } 11025efdd5cfSKaran Tilak Kumar 11035efdd5cfSKaran Tilak Kumar if ((io_req->cmd_state == FNIC_IOREQ_ABTS_PENDING) || 11045efdd5cfSKaran Tilak Kumar (io_req->cmd_state == FNIC_DEV_RST_TERM_ISSUED)) { 11055efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 11065efdd5cfSKaran Tilak Kumar "Abort already pending 0x%x\n", io_req->tag); 11075efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 11085efdd5cfSKaran Tilak Kumar return true; 11095efdd5cfSKaran Tilak Kumar } 11105efdd5cfSKaran Tilak Kumar 11115efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 11125efdd5cfSKaran Tilak Kumar "Terminate tag: 0x%x (tport fcid 0x%x)\n", 11135efdd5cfSKaran Tilak Kumar io_req->tag, io_req->tport->fcid); 11145efdd5cfSKaran Tilak Kumar 11155efdd5cfSKaran Tilak Kumar old_ioreq_state = io_req->cmd_state; 11165efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_ABTS_PENDING; 11175efdd5cfSKaran Tilak Kumar io_req->abts_state = FCPIO_INVALID_CODE; 11185efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 11195efdd5cfSKaran Tilak Kumar 11205efdd5cfSKaran Tilak Kumar if (!nvfnic_queue_abort_io_req(fnic, io_req->tag, 11215efdd5cfSKaran Tilak Kumar FCPIO_ITMF_ABT_TASK_TERM, io_req)) { 11225efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 11235efdd5cfSKaran Tilak Kumar "Failed to enqueue abort for ioreq tag: 0x%x\n", 11245efdd5cfSKaran Tilak Kumar io_req->tag); 11255efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 11265efdd5cfSKaran Tilak Kumar io_req->cmd_state = old_ioreq_state; 11275efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 11285efdd5cfSKaran Tilak Kumar } 11295efdd5cfSKaran Tilak Kumar return true; 11305efdd5cfSKaran Tilak Kumar } 11315efdd5cfSKaran Tilak Kumar 11325efdd5cfSKaran Tilak Kumar void nvfnic_terminate_tport_ios(struct fnic *fnic, 11335efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport) 11345efdd5cfSKaran Tilak Kumar { 1135d25a557dSKaran Tilak Kumar struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats; 11365efdd5cfSKaran Tilak Kumar 11375efdd5cfSKaran Tilak Kumar sbitmap_for_each_set(&fnic->nvfnic_tag_map, _terminate_tport_ios, tport); 11385efdd5cfSKaran Tilak Kumar 1139d25a557dSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 1140d25a557dSKaran Tilak Kumar "tport: 0x%x aborted %lld in_flight %d\n", 1141d25a557dSKaran Tilak Kumar tport->fcid, atomic64_read(&abts_stats->aborts), 1142d25a557dSKaran Tilak Kumar atomic_read(&fnic->in_flight)); 11435efdd5cfSKaran Tilak Kumar } 11445efdd5cfSKaran Tilak Kumar 11455efdd5cfSKaran Tilak Kumar bool _cleanup_all_nvme_io(struct sbitmap *map, unsigned int tag, 11465efdd5cfSKaran Tilak Kumar void *data) 11475efdd5cfSKaran Tilak Kumar { 11485efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = data; 11495efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req; 11505efdd5cfSKaran Tilak Kumar 11515efdd5cfSKaran Tilak Kumar io_req = iport->fnic->sw_copy_wq[0].io_req_table[tag]; 11525efdd5cfSKaran Tilak Kumar if (!io_req) 11535efdd5cfSKaran Tilak Kumar return true; 11545efdd5cfSKaran Tilak Kumar 11555efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_DEV_RST_TERM_ISSUED; 11565efdd5cfSKaran Tilak Kumar io_req->fcp_req->status = NVME_SC_INTERNAL; 11575efdd5cfSKaran Tilak Kumar io_req->fcp_req->transferred_length = 0; 11585efdd5cfSKaran Tilak Kumar io_req->fcp_req->rcv_rsplen = 0; 11595efdd5cfSKaran Tilak Kumar nvfnic_release_nvme_ioreq_buf(iport, io_req); 11605efdd5cfSKaran Tilak Kumar io_req->done(io_req); 11615efdd5cfSKaran Tilak Kumar return true; 11625efdd5cfSKaran Tilak Kumar } 11635efdd5cfSKaran Tilak Kumar 11645efdd5cfSKaran Tilak Kumar void nvfnic_cleanup_all_nvme_ios(struct fnic *fnic) 11655efdd5cfSKaran Tilak Kumar { 11665efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport; 11675efdd5cfSKaran Tilak Kumar 11685efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 11695efdd5cfSKaran Tilak Kumar sbitmap_for_each_set(&fnic->nvfnic_tag_map, _cleanup_all_nvme_io, 11705efdd5cfSKaran Tilak Kumar iport); 11715efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 11725efdd5cfSKaran Tilak Kumar } 11735efdd5cfSKaran Tilak Kumar 11745efdd5cfSKaran Tilak Kumar void nvfnic_nvme_zero_devloss_tports(struct fnic *fnic) 11755efdd5cfSKaran Tilak Kumar { 11765efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport, *next; 11775efdd5cfSKaran Tilak Kumar 11785efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 11795efdd5cfSKaran Tilak Kumar list_for_each_entry_safe(tport, next, &fnic->iport.tport_list, links) { 11805efdd5cfSKaran Tilak Kumar if (tport->flags & FNIC_FDLS_NVME_REGISTERED) { 11815efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 11825efdd5cfSKaran Tilak Kumar nvme_fc_set_remoteport_devloss(tport->nv_rport, 0); 11835efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 11845efdd5cfSKaran Tilak Kumar } 11855efdd5cfSKaran Tilak Kumar } 11865efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 11875efdd5cfSKaran Tilak Kumar } 11885efdd5cfSKaran Tilak Kumar 11895efdd5cfSKaran Tilak Kumar void nvfnic_nvme_unload(struct fnic *fnic) 11905efdd5cfSKaran Tilak Kumar { 11915efdd5cfSKaran Tilak Kumar int ret = 0; 11925efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport; 11935efdd5cfSKaran Tilak Kumar unsigned long flags; 11945efdd5cfSKaran Tilak Kumar unsigned int time_wait = FNIC_NVME_LPORT_REMOVE_WAIT; 11955efdd5cfSKaran Tilak Kumar unsigned int time_remain; 11965efdd5cfSKaran Tilak Kumar DECLARE_COMPLETION_ONSTACK(nvme_lport_unreg_done); 11975efdd5cfSKaran Tilak Kumar 11985efdd5cfSKaran Tilak Kumar /* Mark iport state as INIT so that no IOs can be issued from this point */ 11995efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 12005efdd5cfSKaran Tilak Kumar fnic->in_remove = 1; 12015efdd5cfSKaran Tilak Kumar fnic->iport.state = FNIC_IPORT_STATE_LINK_WAIT; 12025efdd5cfSKaran Tilak Kumar fnic->nvme_lport_unreg_done = &nvme_lport_unreg_done; 12035efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 12045efdd5cfSKaran Tilak Kumar 12055efdd5cfSKaran Tilak Kumar /* 12065efdd5cfSKaran Tilak Kumar * If fnic is already processing link-down or fnic is held 12075efdd5cfSKaran Tilak Kumar * in disabled state following a reboot we dont need to issue 12085efdd5cfSKaran Tilak Kumar * firmware reset and unregister remote ports as it is already 12095efdd5cfSKaran Tilak Kumar * done as part of link down handling. 12105efdd5cfSKaran Tilak Kumar */ 12115efdd5cfSKaran Tilak Kumar if (fdls_get_state(&iport->fabric) == FDLS_STATE_LINKDOWN) { 12125efdd5cfSKaran Tilak Kumar while (fnic->reset_in_progress == IN_PROGRESS) { 12135efdd5cfSKaran Tilak Kumar wait_for_completion_timeout(&fnic->reset_completion_wait, 12145efdd5cfSKaran Tilak Kumar msecs_to_jiffies(5000)); 12155efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 12165efdd5cfSKaran Tilak Kumar "rmmod waiting for reset %p\n", fnic); 12175efdd5cfSKaran Tilak Kumar } 12185efdd5cfSKaran Tilak Kumar } else if (fdls_get_state(&iport->fabric) != FDLS_STATE_INIT) 12195efdd5cfSKaran Tilak Kumar fnic_fcpio_reset(fnic); 12205efdd5cfSKaran Tilak Kumar 12215efdd5cfSKaran Tilak Kumar /* 12225efdd5cfSKaran Tilak Kumar * Mark state so that the workqueue thread stops forwarding 12235efdd5cfSKaran Tilak Kumar * received frames and link events to the local port. ISR and 12245efdd5cfSKaran Tilak Kumar * other threads that can queue work items will also stop 12255efdd5cfSKaran Tilak Kumar * creating work items on the fnic workqueue 12265efdd5cfSKaran Tilak Kumar */ 12275efdd5cfSKaran Tilak Kumar nvfnic_nvme_zero_devloss_tports(fnic); 12285efdd5cfSKaran Tilak Kumar fnic_flush_tport_event_list(fnic); 12295efdd5cfSKaran Tilak Kumar fnic_delete_fcp_tports(fnic); 12305efdd5cfSKaran Tilak Kumar 12315efdd5cfSKaran Tilak Kumar if (iport->flags & FNIC_LPORT_NVME_REGISTERED) { 12325efdd5cfSKaran Tilak Kumar ret = nvme_fc_unregister_localport(fnic->iport.nv_lport); 12335efdd5cfSKaran Tilak Kumar if (ret) { 12345efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 12355efdd5cfSKaran Tilak Kumar "Unregister nvme localport failed: %d\n", ret); 12365efdd5cfSKaran Tilak Kumar } else { 12375efdd5cfSKaran Tilak Kumar time_remain = wait_for_completion_timeout( 12385efdd5cfSKaran Tilak Kumar fnic->nvme_lport_unreg_done, 12395efdd5cfSKaran Tilak Kumar msecs_to_jiffies(time_wait)); 12405efdd5cfSKaran Tilak Kumar if (!time_remain) { 12415efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 12425efdd5cfSKaran Tilak Kumar "Local port removal timed out\n"); 12435efdd5cfSKaran Tilak Kumar WARN_ON(1); 12445efdd5cfSKaran Tilak Kumar } 12455efdd5cfSKaran Tilak Kumar iport->flags &= ~FNIC_LPORT_NVME_REGISTERED; 12465efdd5cfSKaran Tilak Kumar kfree(iport->nv_tmpl); 12475efdd5cfSKaran Tilak Kumar } 12485efdd5cfSKaran Tilak Kumar } 12495efdd5cfSKaran Tilak Kumar 12505efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 12515efdd5cfSKaran Tilak Kumar fnic->nvme_lport_unreg_done = NULL; 12525efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 12535efdd5cfSKaran Tilak Kumar 12545efdd5cfSKaran Tilak Kumar nvfnic_flush_nvme_io_list(fnic); 12555efdd5cfSKaran Tilak Kumar } 12565efdd5cfSKaran Tilak Kumar 12575efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req* 12585efdd5cfSKaran Tilak Kumar nvfnic_find_ls_req(struct fnic_tport_s *tport, uint16_t oxid) 12595efdd5cfSKaran Tilak Kumar { 12605efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req, *next; 12615efdd5cfSKaran Tilak Kumar 12625efdd5cfSKaran Tilak Kumar list_for_each_entry_safe(nvfnic_ls_req, next, &(tport->ls_req_list), list) { 12635efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req->oxid == oxid) 12645efdd5cfSKaran Tilak Kumar return nvfnic_ls_req; 12655efdd5cfSKaran Tilak Kumar } 12665efdd5cfSKaran Tilak Kumar return NULL; 12675efdd5cfSKaran Tilak Kumar } 12685efdd5cfSKaran Tilak Kumar 12695efdd5cfSKaran Tilak Kumar void nvfnic_fcpio_cmpl(struct fnic_io_req *io_req) 12705efdd5cfSKaran Tilak Kumar { 12715efdd5cfSKaran Tilak Kumar struct fnic *fnic = io_req->iport->fnic; 1272d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 12735efdd5cfSKaran Tilak Kumar 12745efdd5cfSKaran Tilak Kumar nvfnic_free_fcpio_tag(io_req->iport, io_req); 1275d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.nvme_ios_queued_for_rsp); 12765efdd5cfSKaran Tilak Kumar io_req->waitq_start_time = jiffies; 12775efdd5cfSKaran Tilak Kumar 12785efdd5cfSKaran Tilak Kumar llist_add(&io_req->nvfnic_io_cmpl, &fnic->nvme_io_event_llist); 12795efdd5cfSKaran Tilak Kumar atomic_inc(&fnic->nvme_io_event_queued); 1280d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->io_stats.nvme_num_ios_in_waitq); 12815efdd5cfSKaran Tilak Kumar 12825efdd5cfSKaran Tilak Kumar queue_work(fnic_cmpl_queue, &fnic->nvme_io_cmpl_work); 12835efdd5cfSKaran Tilak Kumar } 12845efdd5cfSKaran Tilak Kumar 12855efdd5cfSKaran Tilak Kumar void nvfnic_process_ls_abts_rsp(struct fnic_iport_s *iport, 12865efdd5cfSKaran Tilak Kumar struct fc_frame_header *fchdr) 12875efdd5cfSKaran Tilak Kumar { 12885efdd5cfSKaran Tilak Kumar uint32_t tport_fcid; 12895efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport; 12905efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req; 12915efdd5cfSKaran Tilak Kumar struct nvmefc_ls_req *lsreq; 12925efdd5cfSKaran Tilak Kumar uint8_t *fcid; 12935efdd5cfSKaran Tilak Kumar uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr); 12945efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 1295d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 12965efdd5cfSKaran Tilak Kumar 12975efdd5cfSKaran Tilak Kumar fcid = FNIC_STD_GET_S_ID(fchdr); 12985efdd5cfSKaran Tilak Kumar tport_fcid = ntoh24(fcid); 12995efdd5cfSKaran Tilak Kumar 13005efdd5cfSKaran Tilak Kumar tport = fnic_find_tport_by_fcid(iport, tport_fcid); 13015efdd5cfSKaran Tilak Kumar if (tport == NULL) { 13025efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 13035efdd5cfSKaran Tilak Kumar "tport: 0x%x not found\n", tport_fcid); 13045efdd5cfSKaran Tilak Kumar return; 13055efdd5cfSKaran Tilak Kumar } 13065efdd5cfSKaran Tilak Kumar 13075efdd5cfSKaran Tilak Kumar nvfnic_ls_req = nvfnic_find_ls_req(tport, oxid); 13085efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req == NULL) { 13095efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 13105efdd5cfSKaran Tilak Kumar "tport: 0x%x lsreq oxid: 0x%x not found\n", 13115efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 13125efdd5cfSKaran Tilak Kumar return; 13135efdd5cfSKaran Tilak Kumar } 13145efdd5cfSKaran Tilak Kumar 13155efdd5cfSKaran Tilak Kumar lsreq = nvfnic_ls_req->ls_req; 13165efdd5cfSKaran Tilak Kumar if ((lsreq == NULL) || (lsreq->private == NULL)) { 13175efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 13185efdd5cfSKaran Tilak Kumar "tport: 0x%x lsreq oxid: 0x%x already aborted\n", 13195efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 13205efdd5cfSKaran Tilak Kumar return; 13215efdd5cfSKaran Tilak Kumar } 13225efdd5cfSKaran Tilak Kumar 1323d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_abort_responses); 13245efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_ABTS_COMPLETE; 13255efdd5cfSKaran Tilak Kumar 1326d25a557dSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, fnic, "nvme_ls_requests: %lld\n", 1327d25a557dSKaran Tilak Kumar (u64) atomic64_read(&fnic_stats->nvme_stats.nvme_ls_requests)); 1328d25a557dSKaran Tilak Kumar 13295efdd5cfSKaran Tilak Kumar list_del(&nvfnic_ls_req->list); 13305efdd5cfSKaran Tilak Kumar fdls_free_oxid(iport, oxid, &nvfnic_ls_req->oxid); 13315efdd5cfSKaran Tilak Kumar lsreq->private = NULL; 13325efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 13335efdd5cfSKaran Tilak Kumar timer_delete_sync(&nvfnic_ls_req->ls_req_timer); 13345efdd5cfSKaran Tilak Kumar lsreq->done(lsreq, NVME_SC_HOST_ABORTED_CMD); 13355efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 13365efdd5cfSKaran Tilak Kumar } 13375efdd5cfSKaran Tilak Kumar 13385efdd5cfSKaran Tilak Kumar /** 13395efdd5cfSKaran Tilak Kumar * nvfnic_ls_rsp_recv - Handle received NVMe FC link service (LS) response 13405efdd5cfSKaran Tilak Kumar * @iport: Pointer to the local FNIC port structure 13415efdd5cfSKaran Tilak Kumar * @fchdr: Pointer to the Fibre Channel frame header for the 13425efdd5cfSKaran Tilak Kumar * received response 13435efdd5cfSKaran Tilak Kumar * @len: Length of the received frame 13445efdd5cfSKaran Tilak Kumar * 13455efdd5cfSKaran Tilak Kumar * This function processes link service (LS) responses received from 13465efdd5cfSKaran Tilak Kumar * NVMe Discovery Controllers or regular NVMe subsystems during 13475efdd5cfSKaran Tilak Kumar * association. 13485efdd5cfSKaran Tilak Kumar */ 13495efdd5cfSKaran Tilak Kumar void nvfnic_ls_rsp_recv(struct fnic_iport_s *iport, 13505efdd5cfSKaran Tilak Kumar struct fc_frame_header *fchdr, int len) 13515efdd5cfSKaran Tilak Kumar { 13525efdd5cfSKaran Tilak Kumar uint8_t *fcid; 13535efdd5cfSKaran Tilak Kumar uint32_t tport_fcid; 13545efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport; 13555efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req; 13565efdd5cfSKaran Tilak Kumar struct nvmefc_ls_req *lsreq; 13575efdd5cfSKaran Tilak Kumar uint16_t oxid; 13585efdd5cfSKaran Tilak Kumar uint32_t rsp_len; 13595efdd5cfSKaran Tilak Kumar int sid_len = offsetof(struct fc_frame_header, fh_s_id) + 13605efdd5cfSKaran Tilak Kumar sizeof(fchdr->fh_s_id); 13615efdd5cfSKaran Tilak Kumar int status = 0; 13625efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 1363d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 13645efdd5cfSKaran Tilak Kumar 13655efdd5cfSKaran Tilak Kumar if (len < (int)sizeof(*fchdr)) { 13665efdd5cfSKaran Tilak Kumar if (len >= sid_len) { 13675efdd5cfSKaran Tilak Kumar fcid = FNIC_STD_GET_S_ID(fchdr); 13685efdd5cfSKaran Tilak Kumar tport_fcid = ntoh24(fcid); 13695efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 13705efdd5cfSKaran Tilak Kumar "tport: 0x%x LS rsp len %d too short\n", 13715efdd5cfSKaran Tilak Kumar tport_fcid, len); 13725efdd5cfSKaran Tilak Kumar } else { 13735efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 13745efdd5cfSKaran Tilak Kumar "LS response len %d too short\n", len); 13755efdd5cfSKaran Tilak Kumar } 13765efdd5cfSKaran Tilak Kumar return; 13775efdd5cfSKaran Tilak Kumar } 13785efdd5cfSKaran Tilak Kumar rsp_len = len - sizeof(*fchdr); 13795efdd5cfSKaran Tilak Kumar 13805efdd5cfSKaran Tilak Kumar fcid = FNIC_STD_GET_S_ID(fchdr); 13815efdd5cfSKaran Tilak Kumar tport_fcid = ntoh24(fcid); 13825efdd5cfSKaran Tilak Kumar 13835efdd5cfSKaran Tilak Kumar tport = fnic_find_tport_by_fcid(iport, tport_fcid); 13845efdd5cfSKaran Tilak Kumar if (!tport) { 13855efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 13865efdd5cfSKaran Tilak Kumar "tport: 0x%x not found\n", tport_fcid); 13875efdd5cfSKaran Tilak Kumar return; 13885efdd5cfSKaran Tilak Kumar } 13895efdd5cfSKaran Tilak Kumar 13905efdd5cfSKaran Tilak Kumar oxid = FNIC_STD_GET_OX_ID(fchdr); 13915efdd5cfSKaran Tilak Kumar nvfnic_ls_req = nvfnic_find_ls_req(tport, oxid); 13925efdd5cfSKaran Tilak Kumar if (!nvfnic_ls_req) { 13935efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 13945efdd5cfSKaran Tilak Kumar "tport: 0x%x no nvfnic_lsreq for oxid: 0x%x\n", 13955efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 13965efdd5cfSKaran Tilak Kumar return; 13975efdd5cfSKaran Tilak Kumar } 13985efdd5cfSKaran Tilak Kumar 13995efdd5cfSKaran Tilak Kumar lsreq = nvfnic_ls_req->ls_req; 14005efdd5cfSKaran Tilak Kumar if (!lsreq || (lsreq->private == NULL)) { 14015efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 14025efdd5cfSKaran Tilak Kumar "tport:0x%x lsreq:0x%x already done\n", 14035efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 14045efdd5cfSKaran Tilak Kumar return; 14055efdd5cfSKaran Tilak Kumar } 14065efdd5cfSKaran Tilak Kumar if (!lsreq->rspaddr) { 14075efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 14085efdd5cfSKaran Tilak Kumar "tport 0x%x lsreq 0x%x rspaddr NULL\n", 14095efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 14105efdd5cfSKaran Tilak Kumar return; 14115efdd5cfSKaran Tilak Kumar } 14125efdd5cfSKaran Tilak Kumar 14135efdd5cfSKaran Tilak Kumar if ((nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_PENDING) || 14145efdd5cfSKaran Tilak Kumar (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_STARTED)) { 14155efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 14165efdd5cfSKaran Tilak Kumar "tport 0x%x lsreq oxid: 0x%x abts pending\n", 14175efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 14185efdd5cfSKaran Tilak Kumar return; 14195efdd5cfSKaran Tilak Kumar } 14205efdd5cfSKaran Tilak Kumar 14215efdd5cfSKaran Tilak Kumar if (rsp_len > lsreq->rsplen) { 14225efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 14235efdd5cfSKaran Tilak Kumar "tport:0x%x lsreq:0x%x rsp %u > %u\n", 14245efdd5cfSKaran Tilak Kumar tport_fcid, oxid, rsp_len, lsreq->rsplen); 14255efdd5cfSKaran Tilak Kumar status = -EOVERFLOW; 14265efdd5cfSKaran Tilak Kumar } 14275efdd5cfSKaran Tilak Kumar 14285efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_COMPLETE; 1429d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_responses); 14305efdd5cfSKaran Tilak Kumar 14315efdd5cfSKaran Tilak Kumar list_del_init(&nvfnic_ls_req->list); 14325efdd5cfSKaran Tilak Kumar lsreq->private = NULL; 14335efdd5cfSKaran Tilak Kumar fdls_free_oxid(iport, oxid, &nvfnic_ls_req->oxid); 14345efdd5cfSKaran Tilak Kumar 14355efdd5cfSKaran Tilak Kumar if (status == 0) { 14365efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, fnic, 14375efdd5cfSKaran Tilak Kumar "tport:0x%x lsreq:0x%x completed\n", 14385efdd5cfSKaran Tilak Kumar tport_fcid, oxid); 14395efdd5cfSKaran Tilak Kumar 14405efdd5cfSKaran Tilak Kumar /* Copy the Response */ 14415efdd5cfSKaran Tilak Kumar memcpy(lsreq->rspaddr, (uint8_t *)fchdr + sizeof(*fchdr), 14425efdd5cfSKaran Tilak Kumar rsp_len); 14435efdd5cfSKaran Tilak Kumar } 14445efdd5cfSKaran Tilak Kumar 14455efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 14465efdd5cfSKaran Tilak Kumar timer_delete_sync(&nvfnic_ls_req->ls_req_timer); 14475efdd5cfSKaran Tilak Kumar lsreq->done(lsreq, status); 14485efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 14495efdd5cfSKaran Tilak Kumar } 14505efdd5cfSKaran Tilak Kumar 1451f06ee33dSKaran Tilak Kumar static bool nvfnic_ls_req_cleanup(struct fnic_iport_s *iport, 1452f06ee33dSKaran Tilak Kumar struct nvmefc_ls_req *lsreq, 1453f06ee33dSKaran Tilak Kumar uint16_t oxid) 1454f06ee33dSKaran Tilak Kumar { 1455f06ee33dSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req = lsreq->private; 1456f06ee33dSKaran Tilak Kumar 1457f06ee33dSKaran Tilak Kumar if (!nvfnic_ls_req) 1458f06ee33dSKaran Tilak Kumar return false; 1459f06ee33dSKaran Tilak Kumar 1460f06ee33dSKaran Tilak Kumar lsreq->private = NULL; 1461f06ee33dSKaran Tilak Kumar list_del(&nvfnic_ls_req->list); 1462f06ee33dSKaran Tilak Kumar fdls_free_oxid(iport, oxid, &nvfnic_ls_req->oxid); 1463f06ee33dSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_COMPLETE; 1464f06ee33dSKaran Tilak Kumar 1465f06ee33dSKaran Tilak Kumar return true; 1466f06ee33dSKaran Tilak Kumar } 1467f06ee33dSKaran Tilak Kumar 14685efdd5cfSKaran Tilak Kumar void nvfnic_ls_req_timeout(struct timer_list *t) 14695efdd5cfSKaran Tilak Kumar { 14705efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req = timer_container_of(nvfnic_ls_req, 14715efdd5cfSKaran Tilak Kumar t, ls_req_timer); 14725efdd5cfSKaran Tilak Kumar struct fnic *fnic = nvfnic_ls_req->fnic; 14735efdd5cfSKaran Tilak Kumar struct nvmefc_ls_req *ls_req = nvfnic_ls_req->ls_req; 14745efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport; 14755efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport = (struct fnic_tport_s *) nvfnic_ls_req->tport; 1476d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 14775efdd5cfSKaran Tilak Kumar uint16_t oxid = nvfnic_ls_req->oxid; 1478f06ee33dSKaran Tilak Kumar int timeout; 14795efdd5cfSKaran Tilak Kumar 14805efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 14815efdd5cfSKaran Tilak Kumar "tport: 0x%x lsreq: 0x%x state: %d timeout\n", 14825efdd5cfSKaran Tilak Kumar tport->fcid, nvfnic_ls_req->oxid, 14835efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state); 14845efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 14855efdd5cfSKaran Tilak Kumar 14865efdd5cfSKaran Tilak Kumar if ((ls_req->private == NULL) || 14875efdd5cfSKaran Tilak Kumar (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_STARTED)) { 14885efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 14895efdd5cfSKaran Tilak Kumar "tport: 0x%x lsreq: 0x%x already aborted\n", 14905efdd5cfSKaran Tilak Kumar tport->fcid, nvfnic_ls_req->oxid); 14915efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 14925efdd5cfSKaran Tilak Kumar return; 14935efdd5cfSKaran Tilak Kumar } 14945efdd5cfSKaran Tilak Kumar 14955efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_PENDING) { 14965efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 14975efdd5cfSKaran Tilak Kumar "tport: 0x%x lsreq: 0x%x abort timeout\n", 14985efdd5cfSKaran Tilak Kumar tport->fcid, nvfnic_ls_req->oxid); 14995efdd5cfSKaran Tilak Kumar 15005efdd5cfSKaran Tilak Kumar ls_req = nvfnic_ls_req->ls_req; 1501f06ee33dSKaran Tilak Kumar nvfnic_ls_req_cleanup(iport, ls_req, oxid); 15025efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 15035efdd5cfSKaran Tilak Kumar ls_req->done(ls_req, -ETIMEDOUT); 15045efdd5cfSKaran Tilak Kumar return; 15055efdd5cfSKaran Tilak Kumar } else if ((nvfnic_ls_req->state == FNIC_LS_REQ_CMD_PENDING) && 15065efdd5cfSKaran Tilak Kumar (nvfnic_transport_ready(iport, tport))) { 15075efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 15085efdd5cfSKaran Tilak Kumar "tport: 0x%x lsreq: 0x%x sending abort\n", 15095efdd5cfSKaran Tilak Kumar tport->fcid, nvfnic_ls_req->oxid); 1510f06ee33dSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_ABTS_PENDING; 1511d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_aborts); 1512f06ee33dSKaran Tilak Kumar 1513f06ee33dSKaran Tilak Kumar if (fdls_send_ls_req_abts(iport, tport, nvfnic_ls_req->oxid) == 0) { 1514f06ee33dSKaran Tilak Kumar timeout = FNIC_LS_REQ_TMO_MSECS(ls_req->timeout); 1515f06ee33dSKaran Tilak Kumar mod_timer(&nvfnic_ls_req->ls_req_timer, 1516f06ee33dSKaran Tilak Kumar round_jiffies(jiffies + msecs_to_jiffies(timeout))); 1517f06ee33dSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 1518f06ee33dSKaran Tilak Kumar return; 1519f06ee33dSKaran Tilak Kumar } 1520f06ee33dSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 1521f06ee33dSKaran Tilak Kumar "tport: 0x%x lsreq: 0x%x cannot send abort\n", 1522f06ee33dSKaran Tilak Kumar tport->fcid, oxid); 15235efdd5cfSKaran Tilak Kumar } 15245efdd5cfSKaran Tilak Kumar 15255efdd5cfSKaran Tilak Kumar if (ls_req->private == NULL) { 15265efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 15275efdd5cfSKaran Tilak Kumar return; 15285efdd5cfSKaran Tilak Kumar } 15295efdd5cfSKaran Tilak Kumar 15305efdd5cfSKaran Tilak Kumar ls_req = nvfnic_ls_req->ls_req; 1531f06ee33dSKaran Tilak Kumar nvfnic_ls_req_cleanup(iport, ls_req, oxid); 15325efdd5cfSKaran Tilak Kumar 15335efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 15345efdd5cfSKaran Tilak Kumar ls_req->done(ls_req, -ETIMEDOUT); 15355efdd5cfSKaran Tilak Kumar } 15365efdd5cfSKaran Tilak Kumar 153739bf0755SKaran Tilak Kumar /** 153839bf0755SKaran Tilak Kumar * nvfnic_ls_req_send - Send NVMe FC link service (LS) request 153939bf0755SKaran Tilak Kumar * @lport: Pointer to local NVMe FC port structure 154039bf0755SKaran Tilak Kumar * @rport: Pointer to remote NVMe FC port structure 154139bf0755SKaran Tilak Kumar * @ls_req: Pointer to the link service request structure 154239bf0755SKaran Tilak Kumar * 154339bf0755SKaran Tilak Kumar * This function is used to send link service (LS) commands to an NVMe 154439bf0755SKaran Tilak Kumar * Discovery Controller for discovery operations, as well as to regular 154539bf0755SKaran Tilak Kumar * NVMe subsystems during association. It encapsulates the logic for 154639bf0755SKaran Tilak Kumar * transmitting LS requests over the NVMe over Fabrics (NVMe-oF) FC 154739bf0755SKaran Tilak Kumar * transport. 154839bf0755SKaran Tilak Kumar * 154939bf0755SKaran Tilak Kumar * Returns: 0 on success, or a negative error code on failure. 155039bf0755SKaran Tilak Kumar */ 155139bf0755SKaran Tilak Kumar int nvfnic_ls_req_send(struct nvme_fc_local_port *lport, 155239bf0755SKaran Tilak Kumar struct nvme_fc_remote_port *rport, 155339bf0755SKaran Tilak Kumar struct nvmefc_ls_req *ls_req) 155439bf0755SKaran Tilak Kumar { 155539bf0755SKaran Tilak Kumar int timeout; 155639bf0755SKaran Tilak Kumar uint8_t *frame; 155739bf0755SKaran Tilak Kumar uint8_t fcid[3]; 155839bf0755SKaran Tilak Kumar unsigned long flags = 0; 155939bf0755SKaran Tilak Kumar struct fnic_iport_s *iport = lport->private; 156039bf0755SKaran Tilak Kumar uint8_t *ls_req_payload; 156139bf0755SKaran Tilak Kumar struct fnic *fnic = iport->fnic; 156239bf0755SKaran Tilak Kumar struct fc_frame_header *fchdr; 1563d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 156439bf0755SKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req = ls_req->private; 156539bf0755SKaran Tilak Kumar uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET + 156639bf0755SKaran Tilak Kumar sizeof(struct fc_frame_header) + ls_req->rqstlen; 156739bf0755SKaran Tilak Kumar struct fnic_tport_s *tport; 156839bf0755SKaran Tilak Kumar int ret; 156939bf0755SKaran Tilak Kumar 157039bf0755SKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 157139bf0755SKaran Tilak Kumar 157239bf0755SKaran Tilak Kumar tport = (struct fnic_tport_s *)rport->private; 157339bf0755SKaran Tilak Kumar INIT_LIST_HEAD(&nvfnic_ls_req->list); 157439bf0755SKaran Tilak Kumar 157539bf0755SKaran Tilak Kumar if (!nvfnic_transport_ready(iport, tport)) { 157639bf0755SKaran Tilak Kumar if (tport != NULL) 157739bf0755SKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 157839bf0755SKaran Tilak Kumar "iport: 0x%x tport: 0x%x transport not ready\n", 157939bf0755SKaran Tilak Kumar iport->fcid, tport->fcid); 158039bf0755SKaran Tilak Kumar else 158139bf0755SKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 158239bf0755SKaran Tilak Kumar "iport: 0x%x transport not ready\n", 158339bf0755SKaran Tilak Kumar iport->fcid); 158439bf0755SKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 158539bf0755SKaran Tilak Kumar return -ENOLINK; 158639bf0755SKaran Tilak Kumar } 158739bf0755SKaran Tilak Kumar 158839bf0755SKaran Tilak Kumar frame = fdls_alloc_frame(iport); 158939bf0755SKaran Tilak Kumar if (frame == NULL) { 159039bf0755SKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 159139bf0755SKaran Tilak Kumar "Failed to allocate frame to send NVME LS REQ"); 159239bf0755SKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 159339bf0755SKaran Tilak Kumar return -ENOMEM; 159439bf0755SKaran Tilak Kumar } 159539bf0755SKaran Tilak Kumar 159639bf0755SKaran Tilak Kumar if (fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_NVME_LS, 159739bf0755SKaran Tilak Kumar &nvfnic_ls_req->oxid) == FNIC_UNASSIGNED_OXID) { 159839bf0755SKaran Tilak Kumar FNIC_FCS_DBG(KERN_INFO, fnic, 159939bf0755SKaran Tilak Kumar "0x%x: Failed to allocate OXID to send NVME LS REQ", 160039bf0755SKaran Tilak Kumar iport->fcid); 160139bf0755SKaran Tilak Kumar mempool_free(frame, fnic->frame_pool); 160239bf0755SKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 160339bf0755SKaran Tilak Kumar return -EAGAIN; 160439bf0755SKaran Tilak Kumar } 160539bf0755SKaran Tilak Kumar 1606d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_requests); 160739bf0755SKaran Tilak Kumar timer_setup(&nvfnic_ls_req->ls_req_timer, nvfnic_ls_req_timeout, 160839bf0755SKaran Tilak Kumar 0UL); 160939bf0755SKaran Tilak Kumar 161039bf0755SKaran Tilak Kumar nvfnic_ls_req->fnic = fnic; 161139bf0755SKaran Tilak Kumar nvfnic_ls_req->tport = tport; 161239bf0755SKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_INIT; 161339bf0755SKaran Tilak Kumar nvfnic_ls_req->ls_req = ls_req; 161439bf0755SKaran Tilak Kumar 161539bf0755SKaran Tilak Kumar fchdr = (struct fc_frame_header *)(frame + FNIC_ETH_FCOE_HDRS_OFFSET); 161639bf0755SKaran Tilak Kumar *fchdr = (struct fc_frame_header) { 161739bf0755SKaran Tilak Kumar .fh_r_ctl = FC_RCTL_ELS4_REQ, 161839bf0755SKaran Tilak Kumar .fh_type = FC_TYPE_NVME, 161939bf0755SKaran Tilak Kumar .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0}, 162039bf0755SKaran Tilak Kumar .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID) 162139bf0755SKaran Tilak Kumar }; 162239bf0755SKaran Tilak Kumar 162339bf0755SKaran Tilak Kumar hton24(fcid, iport->fcid); 162439bf0755SKaran Tilak Kumar FNIC_STD_SET_S_ID(*fchdr, fcid); 162539bf0755SKaran Tilak Kumar 162639bf0755SKaran Tilak Kumar hton24(fcid, tport->fcid); 162739bf0755SKaran Tilak Kumar FNIC_STD_SET_D_ID(*fchdr, fcid); 162839bf0755SKaran Tilak Kumar 162939bf0755SKaran Tilak Kumar FNIC_STD_SET_OX_ID(*fchdr, nvfnic_ls_req->oxid); 163039bf0755SKaran Tilak Kumar 163139bf0755SKaran Tilak Kumar ls_req_payload = frame + FNIC_ETH_FCOE_HDRS_OFFSET + sizeof(*fchdr); 163239bf0755SKaran Tilak Kumar memcpy(ls_req_payload, ls_req->rqstaddr, ls_req->rqstlen); 163339bf0755SKaran Tilak Kumar 163439bf0755SKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 163539bf0755SKaran Tilak Kumar "0x%x: NVME send ls req with oxid: 0x%x type: 0x%02x len: %d", 163639bf0755SKaran Tilak Kumar iport->fcid, nvfnic_ls_req->oxid, *((uint8_t *) ls_req->rqstaddr), 163739bf0755SKaran Tilak Kumar ls_req->rqstlen); 163839bf0755SKaran Tilak Kumar 1639d25a557dSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 1640d25a557dSKaran Tilak Kumar "0x%x: ls_reqs count: %lld", 1641d25a557dSKaran Tilak Kumar iport->fcid, 1642d25a557dSKaran Tilak Kumar (u64) atomic64_read(&fnic_stats->nvme_stats.nvme_ls_requests)); 1643d25a557dSKaran Tilak Kumar 164439bf0755SKaran Tilak Kumar list_add_tail(&nvfnic_ls_req->list, &tport->ls_req_list); 164539bf0755SKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_PENDING; 164639bf0755SKaran Tilak Kumar 164739bf0755SKaran Tilak Kumar ret = fnic_send_fcoe_frame(iport, frame, frame_size); 164839bf0755SKaran Tilak Kumar if (ret) { 1649f06ee33dSKaran Tilak Kumar nvfnic_ls_req_cleanup(iport, ls_req, nvfnic_ls_req->oxid); 165039bf0755SKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 165139bf0755SKaran Tilak Kumar mempool_free(frame, fnic->frame_pool); 165239bf0755SKaran Tilak Kumar return ret; 165339bf0755SKaran Tilak Kumar } 165439bf0755SKaran Tilak Kumar 165539bf0755SKaran Tilak Kumar timeout = FNIC_LS_REQ_TMO_MSECS(ls_req->timeout); 165639bf0755SKaran Tilak Kumar mod_timer(&nvfnic_ls_req->ls_req_timer, 165739bf0755SKaran Tilak Kumar round_jiffies(jiffies + msecs_to_jiffies(timeout))); 165839bf0755SKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 165939bf0755SKaran Tilak Kumar 166039bf0755SKaran Tilak Kumar return 0; 166139bf0755SKaran Tilak Kumar } 166239bf0755SKaran Tilak Kumar 16635efdd5cfSKaran Tilak Kumar void nvfnic_local_port_delete(struct nvme_fc_local_port *lport) 16645efdd5cfSKaran Tilak Kumar { 16655efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = (struct fnic_iport_s *) lport->private; 16665efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 16675efdd5cfSKaran Tilak Kumar unsigned long flags = 0; 16685efdd5cfSKaran Tilak Kumar 16695efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, "lport delete 0x%x\n", 16705efdd5cfSKaran Tilak Kumar iport->fcid); 16715efdd5cfSKaran Tilak Kumar 16725efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 16735efdd5cfSKaran Tilak Kumar if (fnic->nvme_lport_unreg_done) 16745efdd5cfSKaran Tilak Kumar complete(fnic->nvme_lport_unreg_done); 16755efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 16765efdd5cfSKaran Tilak Kumar } 16775efdd5cfSKaran Tilak Kumar 16785efdd5cfSKaran Tilak Kumar void nvfnic_remote_port_delete(struct nvme_fc_remote_port *rport) 16795efdd5cfSKaran Tilak Kumar { 16805efdd5cfSKaran Tilak Kumar /* 16815efdd5cfSKaran Tilak Kumar * Read rport->private without the lock only to find fnic. 16825efdd5cfSKaran Tilak Kumar * Re-read it under fnic_lock to claim this delete callback, since 16835efdd5cfSKaran Tilak Kumar * another callback may already have cleared it. 16845efdd5cfSKaran Tilak Kumar */ 16855efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport = (struct fnic_tport_s *)rport->private; 16865efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport; 16875efdd5cfSKaran Tilak Kumar struct fnic *fnic = NULL; 16885efdd5cfSKaran Tilak Kumar unsigned long flags = 0; 16895efdd5cfSKaran Tilak Kumar 16905efdd5cfSKaran Tilak Kumar if (tport == NULL) { 16915efdd5cfSKaran Tilak Kumar pr_err("Attempt to delete already deleted tport\n"); 16925efdd5cfSKaran Tilak Kumar return; 16935efdd5cfSKaran Tilak Kumar } 16945efdd5cfSKaran Tilak Kumar 16955efdd5cfSKaran Tilak Kumar iport = tport->iport; 16965efdd5cfSKaran Tilak Kumar fnic = iport->fnic; 16975efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, "0x%x tport 0x%x\n", 16985efdd5cfSKaran Tilak Kumar iport->fcid, tport->fcid); 16995efdd5cfSKaran Tilak Kumar 17005efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 17015efdd5cfSKaran Tilak Kumar tport = (struct fnic_tport_s *)rport->private; 17025efdd5cfSKaran Tilak Kumar if (tport == NULL) { 17035efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 17045efdd5cfSKaran Tilak Kumar "NVMe tport callback after NULL set %p\n", 17055efdd5cfSKaran Tilak Kumar rport); 17065efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 17075efdd5cfSKaran Tilak Kumar return; 17085efdd5cfSKaran Tilak Kumar } 17095efdd5cfSKaran Tilak Kumar 17105efdd5cfSKaran Tilak Kumar iport = tport->iport; 17115efdd5cfSKaran Tilak Kumar rport->private = NULL; 17125efdd5cfSKaran Tilak Kumar 17135efdd5cfSKaran Tilak Kumar if (tport->timer_pending) { 17145efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 17155efdd5cfSKaran Tilak Kumar "tport: 0x%x canceling discovery timer\n", 17165efdd5cfSKaran Tilak Kumar tport->fcid); 17175efdd5cfSKaran Tilak Kumar /* 17185efdd5cfSKaran Tilak Kumar * The retry timer callback takes fnic_lock and dereferences 17195efdd5cfSKaran Tilak Kumar * this tport. Set del_timer_inprogress before dropping the 17205efdd5cfSKaran Tilak Kumar * lock so a callback that is already running observes teardown 17215efdd5cfSKaran Tilak Kumar * and exits. 17225efdd5cfSKaran Tilak Kumar * 17235efdd5cfSKaran Tilak Kumar * timer_delete_sync() then waits until no callback can still 17245efdd5cfSKaran Tilak Kumar * hold a reference before the remoteport-delete path completes 17255efdd5cfSKaran Tilak Kumar * or frees the target port. 17265efdd5cfSKaran Tilak Kumar */ 17275efdd5cfSKaran Tilak Kumar tport->del_timer_inprogress = 1; 17285efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 17295efdd5cfSKaran Tilak Kumar timer_delete_sync(&tport->retry_timer); 17305efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 17315efdd5cfSKaran Tilak Kumar tport->del_timer_inprogress = 0; 17325efdd5cfSKaran Tilak Kumar tport->timer_pending = 0; 17335efdd5cfSKaran Tilak Kumar } 17345efdd5cfSKaran Tilak Kumar 17355efdd5cfSKaran Tilak Kumar if (tport->flags & FNIC_FDLS_NVME_TPORT_CLEANUP_PENDING) { 17365efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 17375efdd5cfSKaran Tilak Kumar "tport %8x waiting on clean pending\n", 17385efdd5cfSKaran Tilak Kumar tport->fcid); 17395efdd5cfSKaran Tilak Kumar } 17405efdd5cfSKaran Tilak Kumar 17415efdd5cfSKaran Tilak Kumar while (tport->flags & FNIC_FDLS_NVME_TPORT_CLEANUP_PENDING) { 17425efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 17435efdd5cfSKaran Tilak Kumar msleep(2000); 17445efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 17455efdd5cfSKaran Tilak Kumar } 17465efdd5cfSKaran Tilak Kumar 17475efdd5cfSKaran Tilak Kumar list_del(&tport->links); 17485efdd5cfSKaran Tilak Kumar 17495efdd5cfSKaran Tilak Kumar if (tport->tport_del_done) { 17505efdd5cfSKaran Tilak Kumar tport->flags |= FNIC_TPORT_CAN_BE_FREED; 17515efdd5cfSKaran Tilak Kumar complete(tport->tport_del_done); 17525efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 17535efdd5cfSKaran Tilak Kumar return; 17545efdd5cfSKaran Tilak Kumar } 17555efdd5cfSKaran Tilak Kumar 17565efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 17575efdd5cfSKaran Tilak Kumar kfree(tport); 17585efdd5cfSKaran Tilak Kumar } 17595efdd5cfSKaran Tilak Kumar 17605efdd5cfSKaran Tilak Kumar int nvfnic_create_queue(struct nvme_fc_local_port *lport, 17615efdd5cfSKaran Tilak Kumar unsigned int idx, u16 size, void **handle) 17625efdd5cfSKaran Tilak Kumar { 17635efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = (struct fnic_iport_s *)lport->private; 17645efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 17655efdd5cfSKaran Tilak Kumar 17665efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, fnic, 17675efdd5cfSKaran Tilak Kumar "iport:0x%x queue:%d size:%d\n", iport->fcid, idx, size); 17685efdd5cfSKaran Tilak Kumar 17695efdd5cfSKaran Tilak Kumar if (idx > fnic->wq_copy_count) 17705efdd5cfSKaran Tilak Kumar return -EINVAL; 17715efdd5cfSKaran Tilak Kumar 17725efdd5cfSKaran Tilak Kumar if (idx == 0) { 17735efdd5cfSKaran Tilak Kumar /* Admin queue */ 17745efdd5cfSKaran Tilak Kumar *handle = &fnic->hw_copy_wq[0]; 17755efdd5cfSKaran Tilak Kumar } else { 17765efdd5cfSKaran Tilak Kumar /* IO queues */ 17775efdd5cfSKaran Tilak Kumar *handle = &fnic->hw_copy_wq[idx-1]; 17785efdd5cfSKaran Tilak Kumar } 17795efdd5cfSKaran Tilak Kumar 17805efdd5cfSKaran Tilak Kumar return 0; 17815efdd5cfSKaran Tilak Kumar } 17825efdd5cfSKaran Tilak Kumar 17835efdd5cfSKaran Tilak Kumar void nvfnic_ls_req_abort(struct nvme_fc_local_port *lport, 17845efdd5cfSKaran Tilak Kumar struct nvme_fc_remote_port *rport, 17855efdd5cfSKaran Tilak Kumar struct nvmefc_ls_req *lsreq) 17865efdd5cfSKaran Tilak Kumar { 17875efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = lport->private; 17885efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 17895efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport; 17905efdd5cfSKaran Tilak Kumar struct nvfnic_ls_req *nvfnic_ls_req; 1791d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 17925efdd5cfSKaran Tilak Kumar uint16_t oxid; 17935efdd5cfSKaran Tilak Kumar int timeout; 1794f06ee33dSKaran Tilak Kumar int ret; 17955efdd5cfSKaran Tilak Kumar 17965efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 17975efdd5cfSKaran Tilak Kumar 17985efdd5cfSKaran Tilak Kumar tport = (struct fnic_tport_s *) rport->private; 17995efdd5cfSKaran Tilak Kumar /* find the request */ 18005efdd5cfSKaran Tilak Kumar nvfnic_ls_req = lsreq->private; 18015efdd5cfSKaran Tilak Kumar 18025efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req == NULL) { 18035efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 18045efdd5cfSKaran Tilak Kumar "0x%x null lsreq already scheduled for abort\n", 18055efdd5cfSKaran Tilak Kumar iport->fcid); 18065efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 18075efdd5cfSKaran Tilak Kumar return; 18085efdd5cfSKaran Tilak Kumar } 18095efdd5cfSKaran Tilak Kumar 18105efdd5cfSKaran Tilak Kumar if (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_PENDING) { 18115efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 18125efdd5cfSKaran Tilak Kumar "0x%x lsreq 0x%x already scheduled for abort\n", 18135efdd5cfSKaran Tilak Kumar iport->fcid, nvfnic_ls_req->oxid); 18145efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 18155efdd5cfSKaran Tilak Kumar return; 18165efdd5cfSKaran Tilak Kumar } 18175efdd5cfSKaran Tilak Kumar 18185efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 18195efdd5cfSKaran Tilak Kumar "0x%x lsreq 0x%x abts\n", 18205efdd5cfSKaran Tilak Kumar iport->fcid, nvfnic_ls_req->oxid); 18215efdd5cfSKaran Tilak Kumar 18225efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_ABTS_STARTED; 18235efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 18245efdd5cfSKaran Tilak Kumar timer_delete_sync(&nvfnic_ls_req->ls_req_timer); 18255efdd5cfSKaran Tilak Kumar 18265efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); 18275efdd5cfSKaran Tilak Kumar nvfnic_ls_req = lsreq->private; 18285efdd5cfSKaran Tilak Kumar 18295efdd5cfSKaran Tilak Kumar if ((nvfnic_ls_req == NULL) || 18305efdd5cfSKaran Tilak Kumar (nvfnic_ls_req->state == FNIC_LS_REQ_CMD_ABTS_PENDING)) { 18315efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 18325efdd5cfSKaran Tilak Kumar "lsreq timeout raced with midlayer abort\n"); 18335efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 18345efdd5cfSKaran Tilak Kumar return; 18355efdd5cfSKaran Tilak Kumar } 18365efdd5cfSKaran Tilak Kumar 18375efdd5cfSKaran Tilak Kumar /* Basic validations of the state */ 18385efdd5cfSKaran Tilak Kumar if (!nvfnic_transport_ready(iport, tport)) { 18395efdd5cfSKaran Tilak Kumar /* If iport or tport offline, it will be handled from that event */ 18405efdd5cfSKaran Tilak Kumar oxid = nvfnic_ls_req->oxid; 18415efdd5cfSKaran Tilak Kumar lsreq->private = NULL; 18425efdd5cfSKaran Tilak Kumar list_del(&nvfnic_ls_req->list); 18435efdd5cfSKaran Tilak Kumar fdls_free_oxid(iport, oxid, &nvfnic_ls_req->oxid); 18445efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 18455efdd5cfSKaran Tilak Kumar lsreq->done(lsreq, -ENXIO); 18465efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 18475efdd5cfSKaran Tilak Kumar "nvfnic_lsreq_abort transport not ready\n"); 18485efdd5cfSKaran Tilak Kumar return; 18495efdd5cfSKaran Tilak Kumar } 18505efdd5cfSKaran Tilak Kumar 18515efdd5cfSKaran Tilak Kumar /* Mark the state and flags */ 18525efdd5cfSKaran Tilak Kumar nvfnic_ls_req->state = FNIC_LS_REQ_CMD_ABTS_PENDING; 1853d25a557dSKaran Tilak Kumar atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_aborts); 1854f06ee33dSKaran Tilak Kumar oxid = nvfnic_ls_req->oxid; 1855f06ee33dSKaran Tilak Kumar 1856f06ee33dSKaran Tilak Kumar ret = fdls_send_ls_req_abts(iport, tport, oxid); 1857f06ee33dSKaran Tilak Kumar if (!ret) { 18585efdd5cfSKaran Tilak Kumar timeout = FNIC_LS_REQ_TMO_MSECS(lsreq->timeout); 18595efdd5cfSKaran Tilak Kumar mod_timer(&nvfnic_ls_req->ls_req_timer, 18605efdd5cfSKaran Tilak Kumar round_jiffies(jiffies + msecs_to_jiffies(timeout))); 18615efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 1862f06ee33dSKaran Tilak Kumar return; 1863f06ee33dSKaran Tilak Kumar } 1864f06ee33dSKaran Tilak Kumar 1865f06ee33dSKaran Tilak Kumar if (!nvfnic_ls_req_cleanup(iport, lsreq, oxid)) { 1866f06ee33dSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 1867f06ee33dSKaran Tilak Kumar return; 1868f06ee33dSKaran Tilak Kumar } 1869f06ee33dSKaran Tilak Kumar 1870f06ee33dSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); 1871f06ee33dSKaran Tilak Kumar lsreq->done(lsreq, -EAGAIN); 18725efdd5cfSKaran Tilak Kumar } 18735efdd5cfSKaran Tilak Kumar 18745efdd5cfSKaran Tilak Kumar bool nvfnic_queue_abort_io_req(struct fnic *fnic, int tag, 18755efdd5cfSKaran Tilak Kumar u32 task_req, struct fnic_io_req *io_req) 18765efdd5cfSKaran Tilak Kumar { 18775efdd5cfSKaran Tilak Kumar int idx; 18785efdd5cfSKaran Tilak Kumar unsigned long flags; 1879d25a557dSKaran Tilak Kumar struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; 18805efdd5cfSKaran Tilak Kumar 18815efdd5cfSKaran Tilak Kumar idx = io_req->wq - &fnic->hw_copy_wq[0]; 18825efdd5cfSKaran Tilak Kumar 18835efdd5cfSKaran Tilak Kumar atomic_inc(&fnic->in_flight); 18845efdd5cfSKaran Tilak Kumar 18855efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->wq_copy_lock[idx], flags); 18865efdd5cfSKaran Tilak Kumar 18875efdd5cfSKaran Tilak Kumar if (vnic_wq_copy_desc_avail(io_req->wq) <= fnic->wq_copy_desc_low[idx]) 18885efdd5cfSKaran Tilak Kumar free_wq_copy_descs(fnic, io_req->wq, idx); 18895efdd5cfSKaran Tilak Kumar 18905efdd5cfSKaran Tilak Kumar if (!vnic_wq_copy_desc_avail(io_req->wq)) { 18915efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], flags); 18925efdd5cfSKaran Tilak Kumar atomic_dec(&fnic->in_flight); 18935efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 18945efdd5cfSKaran Tilak Kumar "tag 0x%x failure: no descriptors\n", tag); 1895d25a557dSKaran Tilak Kumar atomic64_inc(&misc_stats->abts_cpwq_alloc_failures); 18965efdd5cfSKaran Tilak Kumar return false; 18975efdd5cfSKaran Tilak Kumar } 18985efdd5cfSKaran Tilak Kumar fnic_queue_wq_copy_desc_itmf(io_req->wq, tag | FNIC_TAG_ABORT, 18995efdd5cfSKaran Tilak Kumar 0, task_req, tag, NULL, io_req->port_id, 19005efdd5cfSKaran Tilak Kumar fnic->config.ra_tov, fnic->config.ed_tov); 19015efdd5cfSKaran Tilak Kumar 1902d25a557dSKaran Tilak Kumar atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); 1903d25a557dSKaran Tilak Kumar if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > 1904d25a557dSKaran Tilak Kumar atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) 1905d25a557dSKaran Tilak Kumar atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, 1906d25a557dSKaran Tilak Kumar atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs)); 19075efdd5cfSKaran Tilak Kumar 19085efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], flags); 19095efdd5cfSKaran Tilak Kumar atomic_dec(&fnic->in_flight); 19105efdd5cfSKaran Tilak Kumar 19115efdd5cfSKaran Tilak Kumar return true; 19125efdd5cfSKaran Tilak Kumar } 19135efdd5cfSKaran Tilak Kumar 19145efdd5cfSKaran Tilak Kumar void nvfnic_fcpio_abort(struct nvme_fc_local_port *lport, 19155efdd5cfSKaran Tilak Kumar struct nvme_fc_remote_port *rport, 19165efdd5cfSKaran Tilak Kumar void *hw_queue_handle, struct nvmefc_fcp_req *fcp_req) 19175efdd5cfSKaran Tilak Kumar { 19185efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = lport->private; 19195efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 19205efdd5cfSKaran Tilak Kumar struct nvme_fc_cmd_iu *cmd_iu = fcp_req->cmdaddr; 19215efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req = (struct fnic_io_req *)fcp_req->private; 19225efdd5cfSKaran Tilak Kumar unsigned int tag = io_req->tag; 1923d25a557dSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats; 1924d25a557dSKaran Tilak Kumar struct abort_stats *abts_stats; 19255efdd5cfSKaran Tilak Kumar unsigned long flags = 0; 1926d25a557dSKaran Tilak Kumar unsigned long abt_issued_time; 19275efdd5cfSKaran Tilak Kumar unsigned int task_req; 19285efdd5cfSKaran Tilak Kumar enum fnic_ioreq_state old_ioreq_state; 1929d25a557dSKaran Tilak Kumar unsigned long num_ios_waitq, waitq_2sec, waitq_max_time; 19305efdd5cfSKaran Tilak Kumar 19315efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 19325efdd5cfSKaran Tilak Kumar 19335efdd5cfSKaran Tilak Kumar if (io_req->tag == FNIC_NVME_NO_FREE_TAG) { 19345efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 19355efdd5cfSKaran Tilak Kumar "tag: (0x%x) tport_fcid: 0x%x\n", 19365efdd5cfSKaran Tilak Kumar io_req->tag, io_req->tport->fcid); 19375efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 19385efdd5cfSKaran Tilak Kumar return; 19395efdd5cfSKaran Tilak Kumar } 19405efdd5cfSKaran Tilak Kumar 19415efdd5cfSKaran Tilak Kumar if (io_req != nvfnic_find_io_req_by_tag(fnic, io_req->tag)) { 19425efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 19435efdd5cfSKaran Tilak Kumar "cmd tag freed or not issued:0x%x sn:0x%08x\n", 19445efdd5cfSKaran Tilak Kumar io_req->tag, be32_to_cpu(cmd_iu->csn)); 1945d25a557dSKaran Tilak Kumar num_ios_waitq = 1946d25a557dSKaran Tilak Kumar atomic64_read(&fnic_stats->io_stats.nvme_num_ios_in_waitq); 1947d25a557dSKaran Tilak Kumar waitq_2sec = 1948d25a557dSKaran Tilak Kumar atomic64_read(&fnic_stats->io_stats.nvme_ios_in_waitq_3000_msec); 1949d25a557dSKaran Tilak Kumar waitq_max_time = 1950d25a557dSKaran Tilak Kumar atomic64_read(&fnic_stats->io_stats.nvme_ios_in_waitq_max_time); 1951d25a557dSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 1952d25a557dSKaran Tilak Kumar "waitq:%ld waitq_2sec:%ld max_wait:%ld\n", 1953d25a557dSKaran Tilak Kumar num_ios_waitq, waitq_2sec, waitq_max_time); 19545efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 19555efdd5cfSKaran Tilak Kumar return; 19565efdd5cfSKaran Tilak Kumar } 19575efdd5cfSKaran Tilak Kumar 19585efdd5cfSKaran Tilak Kumar if (io_req->cmd_state == FNIC_IOREQ_CMD_COMPLETE) { 19595efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 19605efdd5cfSKaran Tilak Kumar "IO already completed before abort: 0x%x\n", tag); 19615efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 19625efdd5cfSKaran Tilak Kumar return; 19635efdd5cfSKaran Tilak Kumar } 19645efdd5cfSKaran Tilak Kumar 19655efdd5cfSKaran Tilak Kumar if ((io_req->cmd_state == FNIC_IOREQ_ABTS_PENDING) || 19665efdd5cfSKaran Tilak Kumar (io_req->cmd_state == FNIC_DEV_RST_TERM_ISSUED)) { 19675efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, "abort already pending %d\n", 19685efdd5cfSKaran Tilak Kumar tag); 19695efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 19705efdd5cfSKaran Tilak Kumar return; 19715efdd5cfSKaran Tilak Kumar } 19725efdd5cfSKaran Tilak Kumar 19735efdd5cfSKaran Tilak Kumar if (io_req->cmd_state != FNIC_IOREQ_CMD_PENDING) { 19745efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 19755efdd5cfSKaran Tilak Kumar "io_req completed or aborted for tag:0x%x\n", 19765efdd5cfSKaran Tilak Kumar tag); 19775efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 19785efdd5cfSKaran Tilak Kumar return; 19795efdd5cfSKaran Tilak Kumar } 19805efdd5cfSKaran Tilak Kumar 19815efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, "in abort cmd_sn:%08x %llx tag: 0x%x\n", 19825efdd5cfSKaran Tilak Kumar be32_to_cpu(cmd_iu->csn), 19835efdd5cfSKaran Tilak Kumar le64_to_cpu(cmd_iu->sqe.rw.slba), io_req->tag); 19845efdd5cfSKaran Tilak Kumar 19855efdd5cfSKaran Tilak Kumar if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) { 19865efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 19875efdd5cfSKaran Tilak Kumar "abort tag:0x%x returned during fw reset\n", 19885efdd5cfSKaran Tilak Kumar io_req->tag); 19895efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 19905efdd5cfSKaran Tilak Kumar return; 19915efdd5cfSKaran Tilak Kumar } 19925efdd5cfSKaran Tilak Kumar atomic_inc(&fnic->in_flight); 19935efdd5cfSKaran Tilak Kumar 19945efdd5cfSKaran Tilak Kumar if (fdls_tport_is_offline(io_req->tport) || 19955efdd5cfSKaran Tilak Kumar (io_req->cmd_state == FNIC_IOREQ_RESET_TERM)) { 19965efdd5cfSKaran Tilak Kumar task_req = FCPIO_ITMF_ABT_TASK_TERM; 19975efdd5cfSKaran Tilak Kumar } else { 19985efdd5cfSKaran Tilak Kumar task_req = FCPIO_ITMF_ABT_TASK; 19995efdd5cfSKaran Tilak Kumar } 20005efdd5cfSKaran Tilak Kumar 2001d25a557dSKaran Tilak Kumar abts_stats = &fnic->fnic_stats.abts_stats; 2002d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->aborts); 20035efdd5cfSKaran Tilak Kumar 2004d25a557dSKaran Tilak Kumar abt_issued_time = jiffies_to_msecs(jiffies - io_req->start_time); 2005d25a557dSKaran Tilak Kumar if (abt_issued_time <= 6000) 2006d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_btw_0_to_6_sec); 2007d25a557dSKaran Tilak Kumar else if (abt_issued_time > 6000 && abt_issued_time <= 20000) 2008d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_btw_6_to_20_sec); 2009d25a557dSKaran Tilak Kumar else if (abt_issued_time > 20000 && abt_issued_time <= 30000) 2010d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_btw_20_to_30_sec); 2011d25a557dSKaran Tilak Kumar else if (abt_issued_time > 30000 && abt_issued_time <= 40000) 2012d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_btw_30_to_40_sec); 2013d25a557dSKaran Tilak Kumar else if (abt_issued_time > 40000 && abt_issued_time <= 50000) 2014d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_btw_40_to_50_sec); 2015d25a557dSKaran Tilak Kumar else if (abt_issued_time > 50000 && abt_issued_time <= 60000) 2016d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_btw_50_to_60_sec); 2017d25a557dSKaran Tilak Kumar else 2018d25a557dSKaran Tilak Kumar atomic64_inc(&abts_stats->abort_issued_greater_than_60_sec); 20195efdd5cfSKaran Tilak Kumar 20205efdd5cfSKaran Tilak Kumar old_ioreq_state = io_req->cmd_state; 20215efdd5cfSKaran Tilak Kumar io_req->cmd_state = FNIC_IOREQ_ABTS_PENDING; 20225efdd5cfSKaran Tilak Kumar io_req->abts_state = FCPIO_INVALID_CODE; 20235efdd5cfSKaran Tilak Kumar 20245efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 20255efdd5cfSKaran Tilak Kumar 20265efdd5cfSKaran Tilak Kumar if (!nvfnic_queue_abort_io_req(fnic, io_req->tag, task_req, io_req)) { 20275efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 20285efdd5cfSKaran Tilak Kumar "Abort io req queue failed\n"); 20295efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 20305efdd5cfSKaran Tilak Kumar io_req->cmd_state = old_ioreq_state; 20315efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 20325efdd5cfSKaran Tilak Kumar } 20335efdd5cfSKaran Tilak Kumar atomic_dec(&fnic->in_flight); 20345efdd5cfSKaran Tilak Kumar } 20355efdd5cfSKaran Tilak Kumar 20365efdd5cfSKaran Tilak Kumar struct 20375efdd5cfSKaran Tilak Kumar nvme_fc_port_template nvfnic_port = { 20385efdd5cfSKaran Tilak Kumar .localport_delete = nvfnic_local_port_delete, 20395efdd5cfSKaran Tilak Kumar .remoteport_delete = nvfnic_remote_port_delete, 20405efdd5cfSKaran Tilak Kumar .create_queue = nvfnic_create_queue, 20415efdd5cfSKaran Tilak Kumar .delete_queue = NULL, 204239bf0755SKaran Tilak Kumar .ls_req = nvfnic_ls_req_send, 20435efdd5cfSKaran Tilak Kumar .ls_abort = nvfnic_ls_req_abort, 20445efdd5cfSKaran Tilak Kumar .fcp_io = nvfnic_fcpio_send, 20455efdd5cfSKaran Tilak Kumar .fcp_abort = nvfnic_fcpio_abort, 20465efdd5cfSKaran Tilak Kumar .max_hw_queues = 1, 20475efdd5cfSKaran Tilak Kumar .max_sgl_segments = 256, 20485efdd5cfSKaran Tilak Kumar .max_dif_sgl_segments = 64, 20495efdd5cfSKaran Tilak Kumar .dma_boundary = 0xFFFFFFFF, 20505efdd5cfSKaran Tilak Kumar .local_priv_sz = sizeof(struct fnic_iport_s *), 20515efdd5cfSKaran Tilak Kumar .remote_priv_sz = sizeof(struct fnic_tport_s *), 20525efdd5cfSKaran Tilak Kumar .lsrqst_priv_sz = sizeof(struct nvfnic_ls_req), 20535efdd5cfSKaran Tilak Kumar .fcprqst_priv_sz = sizeof(struct fnic_io_req), 20545efdd5cfSKaran Tilak Kumar }; 20555efdd5cfSKaran Tilak Kumar 20565efdd5cfSKaran Tilak Kumar void nvfnic_flush_nvme_io_list(struct fnic *fnic) 20575efdd5cfSKaran Tilak Kumar { 20585efdd5cfSKaran Tilak Kumar queue_work(fnic_cmpl_queue, &fnic->nvme_io_cmpl_work); 20595efdd5cfSKaran Tilak Kumar flush_work(&fnic->nvme_io_cmpl_work); 20605efdd5cfSKaran Tilak Kumar } 20615efdd5cfSKaran Tilak Kumar 20625efdd5cfSKaran Tilak Kumar void nvfnic_nvme_iodone_work(struct work_struct *work) 20635efdd5cfSKaran Tilak Kumar { 20645efdd5cfSKaran Tilak Kumar struct fnic *fnic = container_of(work, struct fnic, nvme_io_cmpl_work); 20655efdd5cfSKaran Tilak Kumar struct llist_node *llnode; 20665efdd5cfSKaran Tilak Kumar struct fnic_io_req *io_req, *tmp; 20675efdd5cfSKaran Tilak Kumar 20685efdd5cfSKaran Tilak Kumar llnode = llist_del_all(&fnic->nvme_io_event_llist); 20695efdd5cfSKaran Tilak Kumar llist_for_each_entry_safe(io_req, tmp, llnode, nvfnic_io_cmpl) { 20705efdd5cfSKaran Tilak Kumar atomic_dec(&fnic->nvme_io_event_queued); 2071d25a557dSKaran Tilak Kumar atomic64_dec(&fnic->fnic_stats.io_stats.nvme_num_ios_in_waitq); 20725efdd5cfSKaran Tilak Kumar io_req->fcp_req->done(io_req->fcp_req); 20735efdd5cfSKaran Tilak Kumar } 20745efdd5cfSKaran Tilak Kumar } 20755efdd5cfSKaran Tilak Kumar 20765efdd5cfSKaran Tilak Kumar void nvfnic_exch_reset(struct fnic_iport_s *iport, struct fnic_tport_s *tport) 20775efdd5cfSKaran Tilak Kumar { 20785efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, iport->fnic, 20795efdd5cfSKaran Tilak Kumar "0x%x: Exchange reset scheduled for tport: 0x%x\n", 20805efdd5cfSKaran Tilak Kumar iport->fcid, tport->fcid); 20815efdd5cfSKaran Tilak Kumar 20825efdd5cfSKaran Tilak Kumar nvfnic_terminate_tport_ls_reqs(iport->fnic, tport); 20835efdd5cfSKaran Tilak Kumar nvfnic_terminate_tport_ios(iport->fnic, tport); 20845efdd5cfSKaran Tilak Kumar } 20855efdd5cfSKaran Tilak Kumar 20865efdd5cfSKaran Tilak Kumar void nvfnic_delete_tport(struct fnic_iport_s *iport, 20875efdd5cfSKaran Tilak Kumar struct fnic_tport_s *tport, 20885efdd5cfSKaran Tilak Kumar unsigned long flags) 20895efdd5cfSKaran Tilak Kumar { 20905efdd5cfSKaran Tilak Kumar struct fnic *fnic = iport->fnic; 20915efdd5cfSKaran Tilak Kumar int ret; 20925efdd5cfSKaran Tilak Kumar unsigned int time_wait = FNIC_NVME_TPORT_REMOVE_WAIT; 20935efdd5cfSKaran Tilak Kumar unsigned int time_remain; 20945efdd5cfSKaran Tilak Kumar DECLARE_COMPLETION_ONSTACK(tm_done); 20955efdd5cfSKaran Tilak Kumar unsigned int fcid; 20965efdd5cfSKaran Tilak Kumar int count = 0; 20975efdd5cfSKaran Tilak Kumar 20985efdd5cfSKaran Tilak Kumar if (!tport) 20995efdd5cfSKaran Tilak Kumar return; 21005efdd5cfSKaran Tilak Kumar 21015efdd5cfSKaran Tilak Kumar fcid = tport->fcid; 21025efdd5cfSKaran Tilak Kumar fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINE); 21035efdd5cfSKaran Tilak Kumar 21045efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, fnic, 21055efdd5cfSKaran Tilak Kumar "0x%x: scheduled deletion for tport: 0x%x\n", 21065efdd5cfSKaran Tilak Kumar iport->fcid, tport->fcid); 21075efdd5cfSKaran Tilak Kumar 21085efdd5cfSKaran Tilak Kumar if (!(tport->flags & FNIC_FDLS_NVME_REGISTERED)) { 21095efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 21105efdd5cfSKaran Tilak Kumar "0x%x: tport: 0x%x not registered. Freeing\n", 21115efdd5cfSKaran Tilak Kumar iport->fcid, tport->fcid); 21125efdd5cfSKaran Tilak Kumar list_del(&tport->links); 21135efdd5cfSKaran Tilak Kumar kfree(tport); 21145efdd5cfSKaran Tilak Kumar return; 21155efdd5cfSKaran Tilak Kumar } 21165efdd5cfSKaran Tilak Kumar 21175efdd5cfSKaran Tilak Kumar tport->tport_del_done = &tm_done; 21185efdd5cfSKaran Tilak Kumar 21195efdd5cfSKaran Tilak Kumar tport->flags |= FNIC_FDLS_TPORT_DELETED; 21205efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 21215efdd5cfSKaran Tilak Kumar ret = nvme_fc_unregister_remoteport(tport->nv_rport); 21225efdd5cfSKaran Tilak Kumar if (ret) { 21235efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 21245efdd5cfSKaran Tilak Kumar "tport: 0x%x unregister failed %d\n", 21255efdd5cfSKaran Tilak Kumar tport->fcid, ret); 21265efdd5cfSKaran Tilak Kumar 21275efdd5cfSKaran Tilak Kumar nvfnic_terminate_tport_ls_reqs(fnic, tport); 21285efdd5cfSKaran Tilak Kumar 21295efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 21305efdd5cfSKaran Tilak Kumar tport->tport_del_done = NULL; 21315efdd5cfSKaran Tilak Kumar if (tport->nv_rport && tport->nv_rport->private == tport) 21325efdd5cfSKaran Tilak Kumar tport->nv_rport->private = NULL; 21335efdd5cfSKaran Tilak Kumar list_del(&tport->links); 21345efdd5cfSKaran Tilak Kumar kfree(tport); 21355efdd5cfSKaran Tilak Kumar return; 21365efdd5cfSKaran Tilak Kumar } 21375efdd5cfSKaran Tilak Kumar time_remain = wait_for_completion_timeout(tport->tport_del_done, 21385efdd5cfSKaran Tilak Kumar msecs_to_jiffies(time_wait)); 21395efdd5cfSKaran Tilak Kumar 21405efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_DEBUG, fnic, 21415efdd5cfSKaran Tilak Kumar "tport: 0x%x wait for deletion done\n", 21425efdd5cfSKaran Tilak Kumar tport->fcid); 21435efdd5cfSKaran Tilak Kumar 21445efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 21455efdd5cfSKaran Tilak Kumar tport->tport_del_done = NULL; 21465efdd5cfSKaran Tilak Kumar 21475efdd5cfSKaran Tilak Kumar if (!time_remain) { 21485efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 21495efdd5cfSKaran Tilak Kumar "tport: 0x%x nvme midlayer completion timed out\n", 21505efdd5cfSKaran Tilak Kumar tport->fcid); 21515efdd5cfSKaran Tilak Kumar 21525efdd5cfSKaran Tilak Kumar if (tport->flags & FNIC_TPORT_CAN_BE_FREED) { 21535efdd5cfSKaran Tilak Kumar kfree(tport); 21545efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 21555efdd5cfSKaran Tilak Kumar "tport: 0x%x delete complete\n", fcid); 21565efdd5cfSKaran Tilak Kumar return; 21575efdd5cfSKaran Tilak Kumar } 21585efdd5cfSKaran Tilak Kumar 21595efdd5cfSKaran Tilak Kumar tport->flags |= FNIC_FDLS_NVME_TPORT_CLEANUP_PENDING; 21605efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 21615efdd5cfSKaran Tilak Kumar nvfnic_cleanup_tport_io(fnic, tport); 21625efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 21635efdd5cfSKaran Tilak Kumar tport->flags &= ~FNIC_FDLS_NVME_TPORT_CLEANUP_PENDING; 21645efdd5cfSKaran Tilak Kumar return; 21655efdd5cfSKaran Tilak Kumar } 21665efdd5cfSKaran Tilak Kumar while (!(tport->flags & FNIC_TPORT_CAN_BE_FREED) && 21675efdd5cfSKaran Tilak Kumar (count < FNIC_TPORT_CLEANUP_WAIT_COUNT)) { 21685efdd5cfSKaran Tilak Kumar count++; 21695efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 21705efdd5cfSKaran Tilak Kumar msleep(2000); 21715efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 21725efdd5cfSKaran Tilak Kumar } 21735efdd5cfSKaran Tilak Kumar if (tport->flags & FNIC_TPORT_CAN_BE_FREED) 21745efdd5cfSKaran Tilak Kumar kfree(tport); 21755efdd5cfSKaran Tilak Kumar 21765efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 21775efdd5cfSKaran Tilak Kumar "tport: 0x%x delete complete\n", fcid); 21785efdd5cfSKaran Tilak Kumar } 21795efdd5cfSKaran Tilak Kumar 21805efdd5cfSKaran Tilak Kumar int nvfnic_add_tport(struct fnic *fnic, struct fnic_tport_s *tport, 21815efdd5cfSKaran Tilak Kumar unsigned long flags) 21825efdd5cfSKaran Tilak Kumar { 21835efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport; 21845efdd5cfSKaran Tilak Kumar struct nvme_fc_port_info pinfo; 21855efdd5cfSKaran Tilak Kumar int ret = 0; 21865efdd5cfSKaran Tilak Kumar 21875efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 21885efdd5cfSKaran Tilak Kumar "Adding tport to nvme wwpn: 0x%llx\n", 21895efdd5cfSKaran Tilak Kumar tport->wwpn); 21905efdd5cfSKaran Tilak Kumar 21915efdd5cfSKaran Tilak Kumar memset(&pinfo, 0, sizeof(struct nvme_fc_port_info)); 21925efdd5cfSKaran Tilak Kumar 21935efdd5cfSKaran Tilak Kumar pinfo.port_name = tport->wwpn; 21945efdd5cfSKaran Tilak Kumar pinfo.node_name = tport->wwnn; 21955efdd5cfSKaran Tilak Kumar pinfo.port_role = FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET; 21965efdd5cfSKaran Tilak Kumar pinfo.port_id = tport->fcid; 21975efdd5cfSKaran Tilak Kumar pinfo.dev_loss_tmo = nvme_dev_loss_tmo; 21985efdd5cfSKaran Tilak Kumar 21995efdd5cfSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags); 22005efdd5cfSKaran Tilak Kumar ret = nvme_fc_register_remoteport(iport->nv_lport, &pinfo, 22015efdd5cfSKaran Tilak Kumar &tport->nv_rport); 22025efdd5cfSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags); 22035efdd5cfSKaran Tilak Kumar if (ret) { 22045efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 22055efdd5cfSKaran Tilak Kumar "Failed to register tport wwpn: 0x%llx ret: %d\n", 22065efdd5cfSKaran Tilak Kumar tport->wwpn, ret); 22075efdd5cfSKaran Tilak Kumar return ret; 22085efdd5cfSKaran Tilak Kumar } 22095efdd5cfSKaran Tilak Kumar tport->flags |= FNIC_FDLS_NVME_REGISTERED; 22105efdd5cfSKaran Tilak Kumar tport->nv_rport->private = tport; 22115efdd5cfSKaran Tilak Kumar 22125efdd5cfSKaran Tilak Kumar snprintf(tport->str_wwpn, sizeof(tport->str_wwpn), "0x%llx", tport->wwpn); 22135efdd5cfSKaran Tilak Kumar snprintf(tport->str_wwnn, sizeof(tport->str_wwnn), "0x%llx", tport->wwnn); 22145efdd5cfSKaran Tilak Kumar return ret; 22155efdd5cfSKaran Tilak Kumar } 22165efdd5cfSKaran Tilak Kumar 22175efdd5cfSKaran Tilak Kumar int nvfnic_add_lport(struct fnic *fnic) 22185efdd5cfSKaran Tilak Kumar { 22195efdd5cfSKaran Tilak Kumar struct nvme_fc_port_info pinfo; 22205efdd5cfSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport; 22215efdd5cfSKaran Tilak Kumar int ret = 0; 22225efdd5cfSKaran Tilak Kumar 22235efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 22245efdd5cfSKaran Tilak Kumar "Adding lport nvme wwpn: 0x%llx\n", 22255efdd5cfSKaran Tilak Kumar iport->wwpn); 22265efdd5cfSKaran Tilak Kumar 22275efdd5cfSKaran Tilak Kumar pinfo.node_name = iport->wwnn; 22285efdd5cfSKaran Tilak Kumar pinfo.port_name = iport->wwpn; 22295efdd5cfSKaran Tilak Kumar pinfo.port_role = FC_PORT_ROLE_NVME_INITIATOR; 22305efdd5cfSKaran Tilak Kumar pinfo.port_id = iport->fcid; 22315efdd5cfSKaran Tilak Kumar 22325efdd5cfSKaran Tilak Kumar nvfnic_reset_fcpio_tag_pool(iport); 22335efdd5cfSKaran Tilak Kumar 22345efdd5cfSKaran Tilak Kumar if (!(iport->flags & FNIC_LPORT_NVME_REGISTERED)) { 22355efdd5cfSKaran Tilak Kumar iport->nv_tmpl = kzalloc_obj(struct nvme_fc_port_template, GFP_ATOMIC); 22365efdd5cfSKaran Tilak Kumar if (!iport->nv_tmpl) { 22375efdd5cfSKaran Tilak Kumar FNIC_FCS_DBG(KERN_INFO, fnic, 22385efdd5cfSKaran Tilak Kumar "iport:0x%x NVMe tmpl alloc failed\n", 22395efdd5cfSKaran Tilak Kumar iport->fcid); 22405efdd5cfSKaran Tilak Kumar return -ENOMEM; 22415efdd5cfSKaran Tilak Kumar } 22425efdd5cfSKaran Tilak Kumar memcpy(iport->nv_tmpl, &nvfnic_port, 22435efdd5cfSKaran Tilak Kumar sizeof(struct nvme_fc_port_template)); 22445efdd5cfSKaran Tilak Kumar iport->nv_tmpl->max_hw_queues = fnic->wq_copy_count; 22455efdd5cfSKaran Tilak Kumar 22465efdd5cfSKaran Tilak Kumar ret = nvme_fc_register_localport(&pinfo, iport->nv_tmpl, 22475efdd5cfSKaran Tilak Kumar &fnic->pdev->dev, &iport->nv_lport); 22485efdd5cfSKaran Tilak Kumar if (ret) { 22495efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_ERR, fnic, 22505efdd5cfSKaran Tilak Kumar "Failed to add wwpn: 0x%llx ret: %d\n", 22515efdd5cfSKaran Tilak Kumar iport->wwpn, ret); 22525efdd5cfSKaran Tilak Kumar kfree(iport->nv_tmpl); 22535efdd5cfSKaran Tilak Kumar return ret; 22545efdd5cfSKaran Tilak Kumar } 22555efdd5cfSKaran Tilak Kumar iport->flags |= FNIC_LPORT_NVME_REGISTERED; 22565efdd5cfSKaran Tilak Kumar iport->nv_lport->private = iport; 22575efdd5cfSKaran Tilak Kumar } 22585efdd5cfSKaran Tilak Kumar 22595efdd5cfSKaran Tilak Kumar sprintf(iport->str_wwpn, "0x%llx", iport->wwpn); 22605efdd5cfSKaran Tilak Kumar sprintf(iport->str_wwnn, "0x%llx", iport->wwnn); 22615efdd5cfSKaran Tilak Kumar 22625efdd5cfSKaran Tilak Kumar FNIC_NVME_DBG(KERN_INFO, fnic, 22635efdd5cfSKaran Tilak Kumar "Successfully added lport wwpn: 0x%llx\n", 22645efdd5cfSKaran Tilak Kumar iport->wwpn); 22655efdd5cfSKaran Tilak Kumar return 0; 22665efdd5cfSKaran Tilak Kumar } 22675efdd5cfSKaran Tilak Kumar 22685efdd5cfSKaran Tilak Kumar #endif 2269