16733b39aSJayamohan Kallickal /** 265c5efa8SJayamohan Kallickal * Copyright (C) 2005 - 2014 Emulex 36733b39aSJayamohan Kallickal * All rights reserved. 46733b39aSJayamohan Kallickal * 56733b39aSJayamohan Kallickal * This program is free software; you can redistribute it and/or 66733b39aSJayamohan Kallickal * modify it under the terms of the GNU General Public License version 2 76733b39aSJayamohan Kallickal * as published by the Free Software Foundation. The full GNU General 86733b39aSJayamohan Kallickal * Public License is included in this distribution in the file called COPYING. 96733b39aSJayamohan Kallickal * 10255fa9a3SJayamohan Kallickal * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com) 116733b39aSJayamohan Kallickal * 126733b39aSJayamohan Kallickal * Contact Information: 13255fa9a3SJayamohan Kallickal * linux-drivers@emulex.com 146733b39aSJayamohan Kallickal * 15255fa9a3SJayamohan Kallickal * Emulex 16255fa9a3SJayamohan Kallickal * 3333 Susan Street 17255fa9a3SJayamohan Kallickal * Costa Mesa, CA 92626 186733b39aSJayamohan Kallickal */ 19255fa9a3SJayamohan Kallickal 206733b39aSJayamohan Kallickal #include <linux/reboot.h> 216733b39aSJayamohan Kallickal #include <linux/delay.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 236733b39aSJayamohan Kallickal #include <linux/interrupt.h> 246733b39aSJayamohan Kallickal #include <linux/blkdev.h> 256733b39aSJayamohan Kallickal #include <linux/pci.h> 266733b39aSJayamohan Kallickal #include <linux/string.h> 276733b39aSJayamohan Kallickal #include <linux/kernel.h> 286733b39aSJayamohan Kallickal #include <linux/semaphore.h> 29c7acc5b8SJayamohan Kallickal #include <linux/iscsi_boot_sysfs.h> 30acf3368fSPaul Gortmaker #include <linux/module.h> 31ffce3e2eSJayamohan Kallickal #include <linux/bsg-lib.h> 326733b39aSJayamohan Kallickal 336733b39aSJayamohan Kallickal #include <scsi/libiscsi.h> 34ffce3e2eSJayamohan Kallickal #include <scsi/scsi_bsg_iscsi.h> 35ffce3e2eSJayamohan Kallickal #include <scsi/scsi_netlink.h> 366733b39aSJayamohan Kallickal #include <scsi/scsi_transport_iscsi.h> 376733b39aSJayamohan Kallickal #include <scsi/scsi_transport.h> 386733b39aSJayamohan Kallickal #include <scsi/scsi_cmnd.h> 396733b39aSJayamohan Kallickal #include <scsi/scsi_device.h> 406733b39aSJayamohan Kallickal #include <scsi/scsi_host.h> 416733b39aSJayamohan Kallickal #include <scsi/scsi.h> 426733b39aSJayamohan Kallickal #include "be_main.h" 436733b39aSJayamohan Kallickal #include "be_iscsi.h" 446733b39aSJayamohan Kallickal #include "be_mgmt.h" 450a513dd8SJohn Soni Jose #include "be_cmds.h" 466733b39aSJayamohan Kallickal 476733b39aSJayamohan Kallickal static unsigned int be_iopoll_budget = 10; 486733b39aSJayamohan Kallickal static unsigned int be_max_phys_size = 64; 49bfead3b2SJayamohan Kallickal static unsigned int enable_msix = 1; 506733b39aSJayamohan Kallickal 516733b39aSJayamohan Kallickal MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); 526733b39aSJayamohan Kallickal MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); 5376d15dbdSJayamohan Kallickal MODULE_VERSION(BUILD_STR); 542f635883SJayamohan Kallickal MODULE_AUTHOR("Emulex Corporation"); 556733b39aSJayamohan Kallickal MODULE_LICENSE("GPL"); 566733b39aSJayamohan Kallickal module_param(be_iopoll_budget, int, 0); 576733b39aSJayamohan Kallickal module_param(enable_msix, int, 0); 586733b39aSJayamohan Kallickal module_param(be_max_phys_size, uint, S_IRUGO); 5999bc5d55SJohn Soni Jose MODULE_PARM_DESC(be_max_phys_size, 6099bc5d55SJohn Soni Jose "Maximum Size (In Kilobytes) of physically contiguous " 6199bc5d55SJohn Soni Jose "memory that can be allocated. Range is 16 - 128"); 6299bc5d55SJohn Soni Jose 6399bc5d55SJohn Soni Jose #define beiscsi_disp_param(_name)\ 6499bc5d55SJohn Soni Jose ssize_t \ 6599bc5d55SJohn Soni Jose beiscsi_##_name##_disp(struct device *dev,\ 6699bc5d55SJohn Soni Jose struct device_attribute *attrib, char *buf) \ 6799bc5d55SJohn Soni Jose { \ 6899bc5d55SJohn Soni Jose struct Scsi_Host *shost = class_to_shost(dev);\ 6999bc5d55SJohn Soni Jose struct beiscsi_hba *phba = iscsi_host_priv(shost); \ 7099bc5d55SJohn Soni Jose uint32_t param_val = 0; \ 7199bc5d55SJohn Soni Jose param_val = phba->attr_##_name;\ 7299bc5d55SJohn Soni Jose return snprintf(buf, PAGE_SIZE, "%d\n",\ 7399bc5d55SJohn Soni Jose phba->attr_##_name);\ 7499bc5d55SJohn Soni Jose } 7599bc5d55SJohn Soni Jose 7699bc5d55SJohn Soni Jose #define beiscsi_change_param(_name, _minval, _maxval, _defaval)\ 7799bc5d55SJohn Soni Jose int \ 7899bc5d55SJohn Soni Jose beiscsi_##_name##_change(struct beiscsi_hba *phba, uint32_t val)\ 7999bc5d55SJohn Soni Jose {\ 8099bc5d55SJohn Soni Jose if (val >= _minval && val <= _maxval) {\ 8199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,\ 8299bc5d55SJohn Soni Jose "BA_%d : beiscsi_"#_name" updated "\ 8399bc5d55SJohn Soni Jose "from 0x%x ==> 0x%x\n",\ 8499bc5d55SJohn Soni Jose phba->attr_##_name, val); \ 8599bc5d55SJohn Soni Jose phba->attr_##_name = val;\ 8699bc5d55SJohn Soni Jose return 0;\ 8799bc5d55SJohn Soni Jose } \ 8899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, \ 8999bc5d55SJohn Soni Jose "BA_%d beiscsi_"#_name" attribute "\ 9099bc5d55SJohn Soni Jose "cannot be updated to 0x%x, "\ 9199bc5d55SJohn Soni Jose "range allowed is ["#_minval" - "#_maxval"]\n", val);\ 9299bc5d55SJohn Soni Jose return -EINVAL;\ 9399bc5d55SJohn Soni Jose } 9499bc5d55SJohn Soni Jose 9599bc5d55SJohn Soni Jose #define beiscsi_store_param(_name) \ 9699bc5d55SJohn Soni Jose ssize_t \ 9799bc5d55SJohn Soni Jose beiscsi_##_name##_store(struct device *dev,\ 9899bc5d55SJohn Soni Jose struct device_attribute *attr, const char *buf,\ 9999bc5d55SJohn Soni Jose size_t count) \ 10099bc5d55SJohn Soni Jose { \ 10199bc5d55SJohn Soni Jose struct Scsi_Host *shost = class_to_shost(dev);\ 10299bc5d55SJohn Soni Jose struct beiscsi_hba *phba = iscsi_host_priv(shost);\ 10399bc5d55SJohn Soni Jose uint32_t param_val = 0;\ 10499bc5d55SJohn Soni Jose if (!isdigit(buf[0]))\ 10599bc5d55SJohn Soni Jose return -EINVAL;\ 10699bc5d55SJohn Soni Jose if (sscanf(buf, "%i", ¶m_val) != 1)\ 10799bc5d55SJohn Soni Jose return -EINVAL;\ 10899bc5d55SJohn Soni Jose if (beiscsi_##_name##_change(phba, param_val) == 0) \ 10999bc5d55SJohn Soni Jose return strlen(buf);\ 11099bc5d55SJohn Soni Jose else \ 11199bc5d55SJohn Soni Jose return -EINVAL;\ 11299bc5d55SJohn Soni Jose } 11399bc5d55SJohn Soni Jose 11499bc5d55SJohn Soni Jose #define beiscsi_init_param(_name, _minval, _maxval, _defval) \ 11599bc5d55SJohn Soni Jose int \ 11699bc5d55SJohn Soni Jose beiscsi_##_name##_init(struct beiscsi_hba *phba, uint32_t val) \ 11799bc5d55SJohn Soni Jose { \ 11899bc5d55SJohn Soni Jose if (val >= _minval && val <= _maxval) {\ 11999bc5d55SJohn Soni Jose phba->attr_##_name = val;\ 12099bc5d55SJohn Soni Jose return 0;\ 12199bc5d55SJohn Soni Jose } \ 12299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,\ 12399bc5d55SJohn Soni Jose "BA_%d beiscsi_"#_name" attribute " \ 12499bc5d55SJohn Soni Jose "cannot be updated to 0x%x, "\ 12599bc5d55SJohn Soni Jose "range allowed is ["#_minval" - "#_maxval"]\n", val);\ 12699bc5d55SJohn Soni Jose phba->attr_##_name = _defval;\ 12799bc5d55SJohn Soni Jose return -EINVAL;\ 12899bc5d55SJohn Soni Jose } 12999bc5d55SJohn Soni Jose 13099bc5d55SJohn Soni Jose #define BEISCSI_RW_ATTR(_name, _minval, _maxval, _defval, _descp) \ 13199bc5d55SJohn Soni Jose static uint beiscsi_##_name = _defval;\ 13299bc5d55SJohn Soni Jose module_param(beiscsi_##_name, uint, S_IRUGO);\ 13399bc5d55SJohn Soni Jose MODULE_PARM_DESC(beiscsi_##_name, _descp);\ 13499bc5d55SJohn Soni Jose beiscsi_disp_param(_name)\ 13599bc5d55SJohn Soni Jose beiscsi_change_param(_name, _minval, _maxval, _defval)\ 13699bc5d55SJohn Soni Jose beiscsi_store_param(_name)\ 13799bc5d55SJohn Soni Jose beiscsi_init_param(_name, _minval, _maxval, _defval)\ 13899bc5d55SJohn Soni Jose DEVICE_ATTR(beiscsi_##_name, S_IRUGO | S_IWUSR,\ 13999bc5d55SJohn Soni Jose beiscsi_##_name##_disp, beiscsi_##_name##_store) 14099bc5d55SJohn Soni Jose 14199bc5d55SJohn Soni Jose /* 14299bc5d55SJohn Soni Jose * When new log level added update the 14399bc5d55SJohn Soni Jose * the MAX allowed value for log_enable 14499bc5d55SJohn Soni Jose */ 14599bc5d55SJohn Soni Jose BEISCSI_RW_ATTR(log_enable, 0x00, 14699bc5d55SJohn Soni Jose 0xFF, 0x00, "Enable logging Bit Mask\n" 14799bc5d55SJohn Soni Jose "\t\t\t\tInitialization Events : 0x01\n" 14899bc5d55SJohn Soni Jose "\t\t\t\tMailbox Events : 0x02\n" 14999bc5d55SJohn Soni Jose "\t\t\t\tMiscellaneous Events : 0x04\n" 15099bc5d55SJohn Soni Jose "\t\t\t\tError Handling : 0x08\n" 15199bc5d55SJohn Soni Jose "\t\t\t\tIO Path Events : 0x10\n" 152afb96058SJayamohan Kallickal "\t\t\t\tConfiguration Path : 0x20\n" 153afb96058SJayamohan Kallickal "\t\t\t\tiSCSI Protocol : 0x40\n"); 15499bc5d55SJohn Soni Jose 1555cac7596SJohn Soni Jose DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); 15626000db7SJohn Soni Jose DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); 15722661e25SJayamohan Kallickal DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); 158d3fea9afSJayamohan Kallickal DEVICE_ATTR(beiscsi_phys_port, S_IRUGO, beiscsi_phys_port_disp, NULL); 1596103c1f7SJayamohan Kallickal DEVICE_ATTR(beiscsi_active_session_count, S_IRUGO, 1606103c1f7SJayamohan Kallickal beiscsi_active_session_disp, NULL); 1616103c1f7SJayamohan Kallickal DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, 1626103c1f7SJayamohan Kallickal beiscsi_free_session_disp, NULL); 16399bc5d55SJohn Soni Jose struct device_attribute *beiscsi_attrs[] = { 16499bc5d55SJohn Soni Jose &dev_attr_beiscsi_log_enable, 1655cac7596SJohn Soni Jose &dev_attr_beiscsi_drvr_ver, 16626000db7SJohn Soni Jose &dev_attr_beiscsi_adapter_family, 16722661e25SJayamohan Kallickal &dev_attr_beiscsi_fw_ver, 1686103c1f7SJayamohan Kallickal &dev_attr_beiscsi_active_session_count, 1696103c1f7SJayamohan Kallickal &dev_attr_beiscsi_free_session_count, 170d3fea9afSJayamohan Kallickal &dev_attr_beiscsi_phys_port, 17199bc5d55SJohn Soni Jose NULL, 17299bc5d55SJohn Soni Jose }; 1736733b39aSJayamohan Kallickal 1746763daaeSJohn Soni Jose static char const *cqe_desc[] = { 1756763daaeSJohn Soni Jose "RESERVED_DESC", 1766763daaeSJohn Soni Jose "SOL_CMD_COMPLETE", 1776763daaeSJohn Soni Jose "SOL_CMD_KILLED_DATA_DIGEST_ERR", 1786763daaeSJohn Soni Jose "CXN_KILLED_PDU_SIZE_EXCEEDS_DSL", 1796763daaeSJohn Soni Jose "CXN_KILLED_BURST_LEN_MISMATCH", 1806763daaeSJohn Soni Jose "CXN_KILLED_AHS_RCVD", 1816763daaeSJohn Soni Jose "CXN_KILLED_HDR_DIGEST_ERR", 1826763daaeSJohn Soni Jose "CXN_KILLED_UNKNOWN_HDR", 1836763daaeSJohn Soni Jose "CXN_KILLED_STALE_ITT_TTT_RCVD", 1846763daaeSJohn Soni Jose "CXN_KILLED_INVALID_ITT_TTT_RCVD", 1856763daaeSJohn Soni Jose "CXN_KILLED_RST_RCVD", 1866763daaeSJohn Soni Jose "CXN_KILLED_TIMED_OUT", 1876763daaeSJohn Soni Jose "CXN_KILLED_RST_SENT", 1886763daaeSJohn Soni Jose "CXN_KILLED_FIN_RCVD", 1896763daaeSJohn Soni Jose "CXN_KILLED_BAD_UNSOL_PDU_RCVD", 1906763daaeSJohn Soni Jose "CXN_KILLED_BAD_WRB_INDEX_ERROR", 1916763daaeSJohn Soni Jose "CXN_KILLED_OVER_RUN_RESIDUAL", 1926763daaeSJohn Soni Jose "CXN_KILLED_UNDER_RUN_RESIDUAL", 1936763daaeSJohn Soni Jose "CMD_KILLED_INVALID_STATSN_RCVD", 1946763daaeSJohn Soni Jose "CMD_KILLED_INVALID_R2T_RCVD", 1956763daaeSJohn Soni Jose "CMD_CXN_KILLED_LUN_INVALID", 1966763daaeSJohn Soni Jose "CMD_CXN_KILLED_ICD_INVALID", 1976763daaeSJohn Soni Jose "CMD_CXN_KILLED_ITT_INVALID", 1986763daaeSJohn Soni Jose "CMD_CXN_KILLED_SEQ_OUTOFORDER", 1996763daaeSJohn Soni Jose "CMD_CXN_KILLED_INVALID_DATASN_RCVD", 2006763daaeSJohn Soni Jose "CXN_INVALIDATE_NOTIFY", 2016763daaeSJohn Soni Jose "CXN_INVALIDATE_INDEX_NOTIFY", 2026763daaeSJohn Soni Jose "CMD_INVALIDATED_NOTIFY", 2036763daaeSJohn Soni Jose "UNSOL_HDR_NOTIFY", 2046763daaeSJohn Soni Jose "UNSOL_DATA_NOTIFY", 2056763daaeSJohn Soni Jose "UNSOL_DATA_DIGEST_ERROR_NOTIFY", 2066763daaeSJohn Soni Jose "DRIVERMSG_NOTIFY", 2076763daaeSJohn Soni Jose "CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN", 2086763daaeSJohn Soni Jose "SOL_CMD_KILLED_DIF_ERR", 2096763daaeSJohn Soni Jose "CXN_KILLED_SYN_RCVD", 2106763daaeSJohn Soni Jose "CXN_KILLED_IMM_DATA_RCVD" 2116763daaeSJohn Soni Jose }; 2126763daaeSJohn Soni Jose 2136733b39aSJayamohan Kallickal static int beiscsi_slave_configure(struct scsi_device *sdev) 2146733b39aSJayamohan Kallickal { 2156733b39aSJayamohan Kallickal blk_queue_max_segment_size(sdev->request_queue, 65536); 2166733b39aSJayamohan Kallickal return 0; 2176733b39aSJayamohan Kallickal } 2186733b39aSJayamohan Kallickal 2194183122dSJayamohan Kallickal static int beiscsi_eh_abort(struct scsi_cmnd *sc) 2204183122dSJayamohan Kallickal { 2214183122dSJayamohan Kallickal struct iscsi_cls_session *cls_session; 2224183122dSJayamohan Kallickal struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; 2234183122dSJayamohan Kallickal struct beiscsi_io_task *aborted_io_task; 2244183122dSJayamohan Kallickal struct iscsi_conn *conn; 2254183122dSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn; 2264183122dSJayamohan Kallickal struct beiscsi_hba *phba; 2274183122dSJayamohan Kallickal struct iscsi_session *session; 2284183122dSJayamohan Kallickal struct invalidate_command_table *inv_tbl; 2293cbb7a74SJayamohan Kallickal struct be_dma_mem nonemb_cmd; 2304183122dSJayamohan Kallickal unsigned int cid, tag, num_invalidate; 2311957aa7fSJayamohan Kallickal int rc; 2324183122dSJayamohan Kallickal 2334183122dSJayamohan Kallickal cls_session = starget_to_session(scsi_target(sc->device)); 2344183122dSJayamohan Kallickal session = cls_session->dd_data; 2354183122dSJayamohan Kallickal 236659743b0SShlomo Pongratz spin_lock_bh(&session->frwd_lock); 2374183122dSJayamohan Kallickal if (!aborted_task || !aborted_task->sc) { 2384183122dSJayamohan Kallickal /* we raced */ 239659743b0SShlomo Pongratz spin_unlock_bh(&session->frwd_lock); 2404183122dSJayamohan Kallickal return SUCCESS; 2414183122dSJayamohan Kallickal } 2424183122dSJayamohan Kallickal 2434183122dSJayamohan Kallickal aborted_io_task = aborted_task->dd_data; 2444183122dSJayamohan Kallickal if (!aborted_io_task->scsi_cmnd) { 2454183122dSJayamohan Kallickal /* raced or invalid command */ 246659743b0SShlomo Pongratz spin_unlock_bh(&session->frwd_lock); 2474183122dSJayamohan Kallickal return SUCCESS; 2484183122dSJayamohan Kallickal } 249659743b0SShlomo Pongratz spin_unlock_bh(&session->frwd_lock); 2507626c06bSJayamohan Kallickal /* Invalidate WRB Posted for this Task */ 2517626c06bSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, invld, 2527626c06bSJayamohan Kallickal aborted_io_task->pwrb_handle->pwrb, 2537626c06bSJayamohan Kallickal 1); 2547626c06bSJayamohan Kallickal 2554183122dSJayamohan Kallickal conn = aborted_task->conn; 2564183122dSJayamohan Kallickal beiscsi_conn = conn->dd_data; 2574183122dSJayamohan Kallickal phba = beiscsi_conn->phba; 2584183122dSJayamohan Kallickal 2594183122dSJayamohan Kallickal /* invalidate iocb */ 2604183122dSJayamohan Kallickal cid = beiscsi_conn->beiscsi_conn_cid; 2614183122dSJayamohan Kallickal inv_tbl = phba->inv_tbl; 2624183122dSJayamohan Kallickal memset(inv_tbl, 0x0, sizeof(*inv_tbl)); 2634183122dSJayamohan Kallickal inv_tbl->cid = cid; 2644183122dSJayamohan Kallickal inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; 2654183122dSJayamohan Kallickal num_invalidate = 1; 2663cbb7a74SJayamohan Kallickal nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, 2673cbb7a74SJayamohan Kallickal sizeof(struct invalidate_commands_params_in), 2683cbb7a74SJayamohan Kallickal &nonemb_cmd.dma); 2693cbb7a74SJayamohan Kallickal if (nonemb_cmd.va == NULL) { 27099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, 27199bc5d55SJohn Soni Jose "BM_%d : Failed to allocate memory for" 2723cbb7a74SJayamohan Kallickal "mgmt_invalidate_icds\n"); 2733cbb7a74SJayamohan Kallickal return FAILED; 2743cbb7a74SJayamohan Kallickal } 2753cbb7a74SJayamohan Kallickal nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); 2763cbb7a74SJayamohan Kallickal 2773cbb7a74SJayamohan Kallickal tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, 2783cbb7a74SJayamohan Kallickal cid, &nonemb_cmd); 2794183122dSJayamohan Kallickal if (!tag) { 28099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, 28199bc5d55SJohn Soni Jose "BM_%d : mgmt_invalidate_icds could not be" 2824183122dSJayamohan Kallickal "submitted\n"); 2833cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 2843cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 2853cbb7a74SJayamohan Kallickal 2864183122dSJayamohan Kallickal return FAILED; 2874183122dSJayamohan Kallickal } 288e175defeSJohn Soni Jose 2891957aa7fSJayamohan Kallickal rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); 2901957aa7fSJayamohan Kallickal if (rc != -EBUSY) 2913cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 2923cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 2931957aa7fSJayamohan Kallickal 2944183122dSJayamohan Kallickal return iscsi_eh_abort(sc); 2954183122dSJayamohan Kallickal } 2964183122dSJayamohan Kallickal 2974183122dSJayamohan Kallickal static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) 2984183122dSJayamohan Kallickal { 2994183122dSJayamohan Kallickal struct iscsi_task *abrt_task; 3004183122dSJayamohan Kallickal struct beiscsi_io_task *abrt_io_task; 3014183122dSJayamohan Kallickal struct iscsi_conn *conn; 3024183122dSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn; 3034183122dSJayamohan Kallickal struct beiscsi_hba *phba; 3044183122dSJayamohan Kallickal struct iscsi_session *session; 3054183122dSJayamohan Kallickal struct iscsi_cls_session *cls_session; 3064183122dSJayamohan Kallickal struct invalidate_command_table *inv_tbl; 3073cbb7a74SJayamohan Kallickal struct be_dma_mem nonemb_cmd; 3084183122dSJayamohan Kallickal unsigned int cid, tag, i, num_invalidate; 3091957aa7fSJayamohan Kallickal int rc; 3104183122dSJayamohan Kallickal 3114183122dSJayamohan Kallickal /* invalidate iocbs */ 3124183122dSJayamohan Kallickal cls_session = starget_to_session(scsi_target(sc->device)); 3134183122dSJayamohan Kallickal session = cls_session->dd_data; 314659743b0SShlomo Pongratz spin_lock_bh(&session->frwd_lock); 315db7f7709SJayamohan Kallickal if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) { 316659743b0SShlomo Pongratz spin_unlock_bh(&session->frwd_lock); 317db7f7709SJayamohan Kallickal return FAILED; 318db7f7709SJayamohan Kallickal } 3194183122dSJayamohan Kallickal conn = session->leadconn; 3204183122dSJayamohan Kallickal beiscsi_conn = conn->dd_data; 3214183122dSJayamohan Kallickal phba = beiscsi_conn->phba; 3224183122dSJayamohan Kallickal cid = beiscsi_conn->beiscsi_conn_cid; 3234183122dSJayamohan Kallickal inv_tbl = phba->inv_tbl; 3244183122dSJayamohan Kallickal memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); 3254183122dSJayamohan Kallickal num_invalidate = 0; 3264183122dSJayamohan Kallickal for (i = 0; i < conn->session->cmds_max; i++) { 3274183122dSJayamohan Kallickal abrt_task = conn->session->cmds[i]; 3284183122dSJayamohan Kallickal abrt_io_task = abrt_task->dd_data; 3294183122dSJayamohan Kallickal if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) 3304183122dSJayamohan Kallickal continue; 3314183122dSJayamohan Kallickal 332126e964aSMike Christie if (sc->device->lun != abrt_task->sc->device->lun) 3334183122dSJayamohan Kallickal continue; 3344183122dSJayamohan Kallickal 3357626c06bSJayamohan Kallickal /* Invalidate WRB Posted for this Task */ 3367626c06bSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, invld, 3377626c06bSJayamohan Kallickal abrt_io_task->pwrb_handle->pwrb, 3387626c06bSJayamohan Kallickal 1); 3397626c06bSJayamohan Kallickal 3404183122dSJayamohan Kallickal inv_tbl->cid = cid; 3414183122dSJayamohan Kallickal inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; 3424183122dSJayamohan Kallickal num_invalidate++; 3434183122dSJayamohan Kallickal inv_tbl++; 3444183122dSJayamohan Kallickal } 345659743b0SShlomo Pongratz spin_unlock_bh(&session->frwd_lock); 3464183122dSJayamohan Kallickal inv_tbl = phba->inv_tbl; 3474183122dSJayamohan Kallickal 3483cbb7a74SJayamohan Kallickal nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, 3493cbb7a74SJayamohan Kallickal sizeof(struct invalidate_commands_params_in), 3503cbb7a74SJayamohan Kallickal &nonemb_cmd.dma); 3513cbb7a74SJayamohan Kallickal if (nonemb_cmd.va == NULL) { 35299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, 35399bc5d55SJohn Soni Jose "BM_%d : Failed to allocate memory for" 3543cbb7a74SJayamohan Kallickal "mgmt_invalidate_icds\n"); 3553cbb7a74SJayamohan Kallickal return FAILED; 3563cbb7a74SJayamohan Kallickal } 3573cbb7a74SJayamohan Kallickal nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); 3583cbb7a74SJayamohan Kallickal memset(nonemb_cmd.va, 0, nonemb_cmd.size); 3593cbb7a74SJayamohan Kallickal tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, 3603cbb7a74SJayamohan Kallickal cid, &nonemb_cmd); 3614183122dSJayamohan Kallickal if (!tag) { 36299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, 36399bc5d55SJohn Soni Jose "BM_%d : mgmt_invalidate_icds could not be" 3644183122dSJayamohan Kallickal " submitted\n"); 3653cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 3663cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 3674183122dSJayamohan Kallickal return FAILED; 3684183122dSJayamohan Kallickal } 369e175defeSJohn Soni Jose 3701957aa7fSJayamohan Kallickal rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); 3711957aa7fSJayamohan Kallickal if (rc != -EBUSY) 3723cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 3733cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 3744183122dSJayamohan Kallickal return iscsi_eh_device_reset(sc); 3754183122dSJayamohan Kallickal } 3764183122dSJayamohan Kallickal 377c7acc5b8SJayamohan Kallickal static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) 378c7acc5b8SJayamohan Kallickal { 379c7acc5b8SJayamohan Kallickal struct beiscsi_hba *phba = data; 380f457a46fSMike Christie struct mgmt_session_info *boot_sess = &phba->boot_sess; 381f457a46fSMike Christie struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0]; 382c7acc5b8SJayamohan Kallickal char *str = buf; 383c7acc5b8SJayamohan Kallickal int rc; 384c7acc5b8SJayamohan Kallickal 385c7acc5b8SJayamohan Kallickal switch (type) { 386c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_NAME: 387c7acc5b8SJayamohan Kallickal rc = sprintf(buf, "%.*s\n", 388f457a46fSMike Christie (int)strlen(boot_sess->target_name), 389f457a46fSMike Christie (char *)&boot_sess->target_name); 390c7acc5b8SJayamohan Kallickal break; 391c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_IP_ADDR: 392f457a46fSMike Christie if (boot_conn->dest_ipaddr.ip_type == 0x1) 393c7acc5b8SJayamohan Kallickal rc = sprintf(buf, "%pI4\n", 3940e43895eSMike Christie (char *)&boot_conn->dest_ipaddr.addr); 395c7acc5b8SJayamohan Kallickal else 396c7acc5b8SJayamohan Kallickal rc = sprintf(str, "%pI6\n", 3970e43895eSMike Christie (char *)&boot_conn->dest_ipaddr.addr); 398c7acc5b8SJayamohan Kallickal break; 399c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_PORT: 400f457a46fSMike Christie rc = sprintf(str, "%d\n", boot_conn->dest_port); 401c7acc5b8SJayamohan Kallickal break; 402c7acc5b8SJayamohan Kallickal 403c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_CHAP_NAME: 404c7acc5b8SJayamohan Kallickal rc = sprintf(str, "%.*s\n", 405f457a46fSMike Christie boot_conn->negotiated_login_options.auth_data.chap. 406c7acc5b8SJayamohan Kallickal target_chap_name_length, 407f457a46fSMike Christie (char *)&boot_conn->negotiated_login_options. 408f457a46fSMike Christie auth_data.chap.target_chap_name); 409c7acc5b8SJayamohan Kallickal break; 410c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_CHAP_SECRET: 411c7acc5b8SJayamohan Kallickal rc = sprintf(str, "%.*s\n", 412f457a46fSMike Christie boot_conn->negotiated_login_options.auth_data.chap. 413c7acc5b8SJayamohan Kallickal target_secret_length, 414f457a46fSMike Christie (char *)&boot_conn->negotiated_login_options. 415f457a46fSMike Christie auth_data.chap.target_secret); 416c7acc5b8SJayamohan Kallickal break; 417c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_REV_CHAP_NAME: 418c7acc5b8SJayamohan Kallickal rc = sprintf(str, "%.*s\n", 419f457a46fSMike Christie boot_conn->negotiated_login_options.auth_data.chap. 420c7acc5b8SJayamohan Kallickal intr_chap_name_length, 421f457a46fSMike Christie (char *)&boot_conn->negotiated_login_options. 422f457a46fSMike Christie auth_data.chap.intr_chap_name); 423c7acc5b8SJayamohan Kallickal break; 424c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_REV_CHAP_SECRET: 425c7acc5b8SJayamohan Kallickal rc = sprintf(str, "%.*s\n", 426f457a46fSMike Christie boot_conn->negotiated_login_options.auth_data.chap. 427c7acc5b8SJayamohan Kallickal intr_secret_length, 428f457a46fSMike Christie (char *)&boot_conn->negotiated_login_options. 429f457a46fSMike Christie auth_data.chap.intr_secret); 430c7acc5b8SJayamohan Kallickal break; 431c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_FLAGS: 432c7acc5b8SJayamohan Kallickal rc = sprintf(str, "2\n"); 433c7acc5b8SJayamohan Kallickal break; 434c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_NIC_ASSOC: 435c7acc5b8SJayamohan Kallickal rc = sprintf(str, "0\n"); 436c7acc5b8SJayamohan Kallickal break; 437c7acc5b8SJayamohan Kallickal default: 438c7acc5b8SJayamohan Kallickal rc = -ENOSYS; 439c7acc5b8SJayamohan Kallickal break; 440c7acc5b8SJayamohan Kallickal } 441c7acc5b8SJayamohan Kallickal return rc; 442c7acc5b8SJayamohan Kallickal } 443c7acc5b8SJayamohan Kallickal 444c7acc5b8SJayamohan Kallickal static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) 445c7acc5b8SJayamohan Kallickal { 446c7acc5b8SJayamohan Kallickal struct beiscsi_hba *phba = data; 447c7acc5b8SJayamohan Kallickal char *str = buf; 448c7acc5b8SJayamohan Kallickal int rc; 449c7acc5b8SJayamohan Kallickal 450c7acc5b8SJayamohan Kallickal switch (type) { 451c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_INI_INITIATOR_NAME: 452c7acc5b8SJayamohan Kallickal rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); 453c7acc5b8SJayamohan Kallickal break; 454c7acc5b8SJayamohan Kallickal default: 455c7acc5b8SJayamohan Kallickal rc = -ENOSYS; 456c7acc5b8SJayamohan Kallickal break; 457c7acc5b8SJayamohan Kallickal } 458c7acc5b8SJayamohan Kallickal return rc; 459c7acc5b8SJayamohan Kallickal } 460c7acc5b8SJayamohan Kallickal 461c7acc5b8SJayamohan Kallickal static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) 462c7acc5b8SJayamohan Kallickal { 463c7acc5b8SJayamohan Kallickal struct beiscsi_hba *phba = data; 464c7acc5b8SJayamohan Kallickal char *str = buf; 465c7acc5b8SJayamohan Kallickal int rc; 466c7acc5b8SJayamohan Kallickal 467c7acc5b8SJayamohan Kallickal switch (type) { 468c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_ETH_FLAGS: 469c7acc5b8SJayamohan Kallickal rc = sprintf(str, "2\n"); 470c7acc5b8SJayamohan Kallickal break; 471c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_ETH_INDEX: 472c7acc5b8SJayamohan Kallickal rc = sprintf(str, "0\n"); 473c7acc5b8SJayamohan Kallickal break; 474c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_ETH_MAC: 4750e43895eSMike Christie rc = beiscsi_get_macaddr(str, phba); 476c7acc5b8SJayamohan Kallickal break; 477c7acc5b8SJayamohan Kallickal default: 478c7acc5b8SJayamohan Kallickal rc = -ENOSYS; 479c7acc5b8SJayamohan Kallickal break; 480c7acc5b8SJayamohan Kallickal } 481c7acc5b8SJayamohan Kallickal return rc; 482c7acc5b8SJayamohan Kallickal } 483c7acc5b8SJayamohan Kallickal 484c7acc5b8SJayamohan Kallickal 485587a1f16SAl Viro static umode_t beiscsi_tgt_get_attr_visibility(void *data, int type) 486c7acc5b8SJayamohan Kallickal { 487587a1f16SAl Viro umode_t rc; 488c7acc5b8SJayamohan Kallickal 489c7acc5b8SJayamohan Kallickal switch (type) { 490c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_NAME: 491c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_IP_ADDR: 492c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_PORT: 493c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_CHAP_NAME: 494c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_CHAP_SECRET: 495c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_REV_CHAP_NAME: 496c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_REV_CHAP_SECRET: 497c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_NIC_ASSOC: 498c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_TGT_FLAGS: 499c7acc5b8SJayamohan Kallickal rc = S_IRUGO; 500c7acc5b8SJayamohan Kallickal break; 501c7acc5b8SJayamohan Kallickal default: 502c7acc5b8SJayamohan Kallickal rc = 0; 503c7acc5b8SJayamohan Kallickal break; 504c7acc5b8SJayamohan Kallickal } 505c7acc5b8SJayamohan Kallickal return rc; 506c7acc5b8SJayamohan Kallickal } 507c7acc5b8SJayamohan Kallickal 508587a1f16SAl Viro static umode_t beiscsi_ini_get_attr_visibility(void *data, int type) 509c7acc5b8SJayamohan Kallickal { 510587a1f16SAl Viro umode_t rc; 511c7acc5b8SJayamohan Kallickal 512c7acc5b8SJayamohan Kallickal switch (type) { 513c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_INI_INITIATOR_NAME: 514c7acc5b8SJayamohan Kallickal rc = S_IRUGO; 515c7acc5b8SJayamohan Kallickal break; 516c7acc5b8SJayamohan Kallickal default: 517c7acc5b8SJayamohan Kallickal rc = 0; 518c7acc5b8SJayamohan Kallickal break; 519c7acc5b8SJayamohan Kallickal } 520c7acc5b8SJayamohan Kallickal return rc; 521c7acc5b8SJayamohan Kallickal } 522c7acc5b8SJayamohan Kallickal 523c7acc5b8SJayamohan Kallickal 524587a1f16SAl Viro static umode_t beiscsi_eth_get_attr_visibility(void *data, int type) 525c7acc5b8SJayamohan Kallickal { 526587a1f16SAl Viro umode_t rc; 527c7acc5b8SJayamohan Kallickal 528c7acc5b8SJayamohan Kallickal switch (type) { 529c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_ETH_FLAGS: 530c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_ETH_MAC: 531c7acc5b8SJayamohan Kallickal case ISCSI_BOOT_ETH_INDEX: 532c7acc5b8SJayamohan Kallickal rc = S_IRUGO; 533c7acc5b8SJayamohan Kallickal break; 534c7acc5b8SJayamohan Kallickal default: 535c7acc5b8SJayamohan Kallickal rc = 0; 536c7acc5b8SJayamohan Kallickal break; 537c7acc5b8SJayamohan Kallickal } 538c7acc5b8SJayamohan Kallickal return rc; 539c7acc5b8SJayamohan Kallickal } 540c7acc5b8SJayamohan Kallickal 541bfead3b2SJayamohan Kallickal /*------------------- PCI Driver operations and data ----------------- */ 5429baa3c34SBenoit Taine static const struct pci_device_id beiscsi_pci_id_table[] = { 543bfead3b2SJayamohan Kallickal { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, 544f98c96b0SJayamohan Kallickal { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, 545bfead3b2SJayamohan Kallickal { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, 546bfead3b2SJayamohan Kallickal { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, 547bfead3b2SJayamohan Kallickal { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, 548139a1b1eSJohn Soni Jose { PCI_DEVICE(ELX_VENDOR_ID, OC_SKH_ID1) }, 549bfead3b2SJayamohan Kallickal { 0 } 550bfead3b2SJayamohan Kallickal }; 551bfead3b2SJayamohan Kallickal MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); 552bfead3b2SJayamohan Kallickal 55399bc5d55SJohn Soni Jose 5546733b39aSJayamohan Kallickal static struct scsi_host_template beiscsi_sht = { 5556733b39aSJayamohan Kallickal .module = THIS_MODULE, 5562f635883SJayamohan Kallickal .name = "Emulex 10Gbe open-iscsi Initiator Driver", 5576733b39aSJayamohan Kallickal .proc_name = DRV_NAME, 5586733b39aSJayamohan Kallickal .queuecommand = iscsi_queuecommand, 5596733b39aSJayamohan Kallickal .change_queue_depth = iscsi_change_queue_depth, 5606733b39aSJayamohan Kallickal .slave_configure = beiscsi_slave_configure, 5616733b39aSJayamohan Kallickal .target_alloc = iscsi_target_alloc, 5624183122dSJayamohan Kallickal .eh_abort_handler = beiscsi_eh_abort, 5634183122dSJayamohan Kallickal .eh_device_reset_handler = beiscsi_eh_device_reset, 564309ce156SJayamohan Kallickal .eh_target_reset_handler = iscsi_eh_session_reset, 56599bc5d55SJohn Soni Jose .shost_attrs = beiscsi_attrs, 5666733b39aSJayamohan Kallickal .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, 5676733b39aSJayamohan Kallickal .can_queue = BE2_IO_DEPTH, 5686733b39aSJayamohan Kallickal .this_id = -1, 5696733b39aSJayamohan Kallickal .max_sectors = BEISCSI_MAX_SECTORS, 5706733b39aSJayamohan Kallickal .cmd_per_lun = BEISCSI_CMD_PER_LUN, 5716733b39aSJayamohan Kallickal .use_clustering = ENABLE_CLUSTERING, 572ffce3e2eSJayamohan Kallickal .vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID, 573ffce3e2eSJayamohan Kallickal 5746733b39aSJayamohan Kallickal }; 5756733b39aSJayamohan Kallickal 576bfead3b2SJayamohan Kallickal static struct scsi_transport_template *beiscsi_scsi_transport; 5776733b39aSJayamohan Kallickal 5786733b39aSJayamohan Kallickal static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) 5796733b39aSJayamohan Kallickal { 5806733b39aSJayamohan Kallickal struct beiscsi_hba *phba; 5816733b39aSJayamohan Kallickal struct Scsi_Host *shost; 5826733b39aSJayamohan Kallickal 5836733b39aSJayamohan Kallickal shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0); 5846733b39aSJayamohan Kallickal if (!shost) { 58599bc5d55SJohn Soni Jose dev_err(&pcidev->dev, 58699bc5d55SJohn Soni Jose "beiscsi_hba_alloc - iscsi_host_alloc failed\n"); 5876733b39aSJayamohan Kallickal return NULL; 5886733b39aSJayamohan Kallickal } 5896733b39aSJayamohan Kallickal shost->dma_boundary = pcidev->dma_mask; 5906733b39aSJayamohan Kallickal shost->max_id = BE2_MAX_SESSIONS; 5916733b39aSJayamohan Kallickal shost->max_channel = 0; 5926733b39aSJayamohan Kallickal shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; 5936733b39aSJayamohan Kallickal shost->max_lun = BEISCSI_NUM_MAX_LUN; 5946733b39aSJayamohan Kallickal shost->transportt = beiscsi_scsi_transport; 5956733b39aSJayamohan Kallickal phba = iscsi_host_priv(shost); 5966733b39aSJayamohan Kallickal memset(phba, 0, sizeof(*phba)); 5976733b39aSJayamohan Kallickal phba->shost = shost; 5986733b39aSJayamohan Kallickal phba->pcidev = pci_dev_get(pcidev); 5992807afb7SJayamohan Kallickal pci_set_drvdata(pcidev, phba); 6000e43895eSMike Christie phba->interface_handle = 0xFFFFFFFF; 6016733b39aSJayamohan Kallickal 6026733b39aSJayamohan Kallickal return phba; 6036733b39aSJayamohan Kallickal } 6046733b39aSJayamohan Kallickal 6056733b39aSJayamohan Kallickal static void beiscsi_unmap_pci_function(struct beiscsi_hba *phba) 6066733b39aSJayamohan Kallickal { 6076733b39aSJayamohan Kallickal if (phba->csr_va) { 6086733b39aSJayamohan Kallickal iounmap(phba->csr_va); 6096733b39aSJayamohan Kallickal phba->csr_va = NULL; 6106733b39aSJayamohan Kallickal } 6116733b39aSJayamohan Kallickal if (phba->db_va) { 6126733b39aSJayamohan Kallickal iounmap(phba->db_va); 6136733b39aSJayamohan Kallickal phba->db_va = NULL; 6146733b39aSJayamohan Kallickal } 6156733b39aSJayamohan Kallickal if (phba->pci_va) { 6166733b39aSJayamohan Kallickal iounmap(phba->pci_va); 6176733b39aSJayamohan Kallickal phba->pci_va = NULL; 6186733b39aSJayamohan Kallickal } 6196733b39aSJayamohan Kallickal } 6206733b39aSJayamohan Kallickal 6216733b39aSJayamohan Kallickal static int beiscsi_map_pci_bars(struct beiscsi_hba *phba, 6226733b39aSJayamohan Kallickal struct pci_dev *pcidev) 6236733b39aSJayamohan Kallickal { 6246733b39aSJayamohan Kallickal u8 __iomem *addr; 625f98c96b0SJayamohan Kallickal int pcicfg_reg; 6266733b39aSJayamohan Kallickal 6276733b39aSJayamohan Kallickal addr = ioremap_nocache(pci_resource_start(pcidev, 2), 6286733b39aSJayamohan Kallickal pci_resource_len(pcidev, 2)); 6296733b39aSJayamohan Kallickal if (addr == NULL) 6306733b39aSJayamohan Kallickal return -ENOMEM; 6316733b39aSJayamohan Kallickal phba->ctrl.csr = addr; 6326733b39aSJayamohan Kallickal phba->csr_va = addr; 6336733b39aSJayamohan Kallickal phba->csr_pa.u.a64.address = pci_resource_start(pcidev, 2); 6346733b39aSJayamohan Kallickal 6356733b39aSJayamohan Kallickal addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024); 6366733b39aSJayamohan Kallickal if (addr == NULL) 6376733b39aSJayamohan Kallickal goto pci_map_err; 6386733b39aSJayamohan Kallickal phba->ctrl.db = addr; 6396733b39aSJayamohan Kallickal phba->db_va = addr; 6406733b39aSJayamohan Kallickal phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4); 6416733b39aSJayamohan Kallickal 642f98c96b0SJayamohan Kallickal if (phba->generation == BE_GEN2) 643f98c96b0SJayamohan Kallickal pcicfg_reg = 1; 644f98c96b0SJayamohan Kallickal else 645f98c96b0SJayamohan Kallickal pcicfg_reg = 0; 646f98c96b0SJayamohan Kallickal 647f98c96b0SJayamohan Kallickal addr = ioremap_nocache(pci_resource_start(pcidev, pcicfg_reg), 648f98c96b0SJayamohan Kallickal pci_resource_len(pcidev, pcicfg_reg)); 649f98c96b0SJayamohan Kallickal 6506733b39aSJayamohan Kallickal if (addr == NULL) 6516733b39aSJayamohan Kallickal goto pci_map_err; 6526733b39aSJayamohan Kallickal phba->ctrl.pcicfg = addr; 6536733b39aSJayamohan Kallickal phba->pci_va = addr; 654f98c96b0SJayamohan Kallickal phba->pci_pa.u.a64.address = pci_resource_start(pcidev, pcicfg_reg); 6556733b39aSJayamohan Kallickal return 0; 6566733b39aSJayamohan Kallickal 6576733b39aSJayamohan Kallickal pci_map_err: 6586733b39aSJayamohan Kallickal beiscsi_unmap_pci_function(phba); 6596733b39aSJayamohan Kallickal return -ENOMEM; 6606733b39aSJayamohan Kallickal } 6616733b39aSJayamohan Kallickal 6626733b39aSJayamohan Kallickal static int beiscsi_enable_pci(struct pci_dev *pcidev) 6636733b39aSJayamohan Kallickal { 6646733b39aSJayamohan Kallickal int ret; 6656733b39aSJayamohan Kallickal 6666733b39aSJayamohan Kallickal ret = pci_enable_device(pcidev); 6676733b39aSJayamohan Kallickal if (ret) { 66899bc5d55SJohn Soni Jose dev_err(&pcidev->dev, 66999bc5d55SJohn Soni Jose "beiscsi_enable_pci - enable device failed\n"); 6706733b39aSJayamohan Kallickal return ret; 6716733b39aSJayamohan Kallickal } 6726733b39aSJayamohan Kallickal 673bfead3b2SJayamohan Kallickal pci_set_master(pcidev); 6746c57625bSJayamohan Kallickal ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64)); 6756c57625bSJayamohan Kallickal if (ret) { 6766c57625bSJayamohan Kallickal ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)); 6776c57625bSJayamohan Kallickal if (ret) { 6786c57625bSJayamohan Kallickal dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n"); 6796c57625bSJayamohan Kallickal pci_disable_device(pcidev); 6806c57625bSJayamohan Kallickal return ret; 6816c57625bSJayamohan Kallickal } else { 6826c57625bSJayamohan Kallickal ret = pci_set_consistent_dma_mask(pcidev, 6836c57625bSJayamohan Kallickal DMA_BIT_MASK(32)); 6846c57625bSJayamohan Kallickal } 6856c57625bSJayamohan Kallickal } else { 6866c57625bSJayamohan Kallickal ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64)); 6876733b39aSJayamohan Kallickal if (ret) { 6886733b39aSJayamohan Kallickal dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n"); 6896733b39aSJayamohan Kallickal pci_disable_device(pcidev); 6906733b39aSJayamohan Kallickal return ret; 6916733b39aSJayamohan Kallickal } 6926733b39aSJayamohan Kallickal } 6936733b39aSJayamohan Kallickal return 0; 6946733b39aSJayamohan Kallickal } 6956733b39aSJayamohan Kallickal 6966733b39aSJayamohan Kallickal static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) 6976733b39aSJayamohan Kallickal { 6986733b39aSJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 6996733b39aSJayamohan Kallickal struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced; 7006733b39aSJayamohan Kallickal struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem; 7016733b39aSJayamohan Kallickal int status = 0; 7026733b39aSJayamohan Kallickal 7036733b39aSJayamohan Kallickal ctrl->pdev = pdev; 7046733b39aSJayamohan Kallickal status = beiscsi_map_pci_bars(phba, pdev); 7056733b39aSJayamohan Kallickal if (status) 7066733b39aSJayamohan Kallickal return status; 7076733b39aSJayamohan Kallickal mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; 7086733b39aSJayamohan Kallickal mbox_mem_alloc->va = pci_alloc_consistent(pdev, 7096733b39aSJayamohan Kallickal mbox_mem_alloc->size, 7106733b39aSJayamohan Kallickal &mbox_mem_alloc->dma); 7116733b39aSJayamohan Kallickal if (!mbox_mem_alloc->va) { 7126733b39aSJayamohan Kallickal beiscsi_unmap_pci_function(phba); 713a49e06d5SJayamohan Kallickal return -ENOMEM; 7146733b39aSJayamohan Kallickal } 7156733b39aSJayamohan Kallickal 7166733b39aSJayamohan Kallickal mbox_mem_align->size = sizeof(struct be_mcc_mailbox); 7176733b39aSJayamohan Kallickal mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); 7186733b39aSJayamohan Kallickal mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); 7196733b39aSJayamohan Kallickal memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); 7206733b39aSJayamohan Kallickal spin_lock_init(&ctrl->mbox_lock); 721bfead3b2SJayamohan Kallickal spin_lock_init(&phba->ctrl.mcc_lock); 722bfead3b2SJayamohan Kallickal spin_lock_init(&phba->ctrl.mcc_cq_lock); 723bfead3b2SJayamohan Kallickal 7246733b39aSJayamohan Kallickal return status; 7256733b39aSJayamohan Kallickal } 7266733b39aSJayamohan Kallickal 727843ae752SJayamohan Kallickal /** 728843ae752SJayamohan Kallickal * beiscsi_get_params()- Set the config paramters 729843ae752SJayamohan Kallickal * @phba: ptr device priv structure 730843ae752SJayamohan Kallickal **/ 7316733b39aSJayamohan Kallickal static void beiscsi_get_params(struct beiscsi_hba *phba) 7326733b39aSJayamohan Kallickal { 733843ae752SJayamohan Kallickal uint32_t total_cid_count = 0; 734843ae752SJayamohan Kallickal uint32_t total_icd_count = 0; 735843ae752SJayamohan Kallickal uint8_t ulp_num = 0; 736843ae752SJayamohan Kallickal 737843ae752SJayamohan Kallickal total_cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) + 738843ae752SJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1); 739843ae752SJayamohan Kallickal 740cf987b79SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 741cf987b79SJayamohan Kallickal uint32_t align_mask = 0; 742cf987b79SJayamohan Kallickal uint32_t icd_post_per_page = 0; 743cf987b79SJayamohan Kallickal uint32_t icd_count_unavailable = 0; 744cf987b79SJayamohan Kallickal uint32_t icd_start = 0, icd_count = 0; 745cf987b79SJayamohan Kallickal uint32_t icd_start_align = 0, icd_count_align = 0; 746cf987b79SJayamohan Kallickal 747843ae752SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 748cf987b79SJayamohan Kallickal icd_start = phba->fw_config.iscsi_icd_start[ulp_num]; 749cf987b79SJayamohan Kallickal icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; 750cf987b79SJayamohan Kallickal 751cf987b79SJayamohan Kallickal /* Get ICD count that can be posted on each page */ 752cf987b79SJayamohan Kallickal icd_post_per_page = (PAGE_SIZE / (BE2_SGE * 753cf987b79SJayamohan Kallickal sizeof(struct iscsi_sge))); 754cf987b79SJayamohan Kallickal align_mask = (icd_post_per_page - 1); 755cf987b79SJayamohan Kallickal 756cf987b79SJayamohan Kallickal /* Check if icd_start is aligned ICD per page posting */ 757cf987b79SJayamohan Kallickal if (icd_start % icd_post_per_page) { 758cf987b79SJayamohan Kallickal icd_start_align = ((icd_start + 759cf987b79SJayamohan Kallickal icd_post_per_page) & 760cf987b79SJayamohan Kallickal ~(align_mask)); 761cf987b79SJayamohan Kallickal phba->fw_config. 762cf987b79SJayamohan Kallickal iscsi_icd_start[ulp_num] = 763cf987b79SJayamohan Kallickal icd_start_align; 764843ae752SJayamohan Kallickal } 765843ae752SJayamohan Kallickal 766cf987b79SJayamohan Kallickal icd_count_align = (icd_count & ~align_mask); 767cf987b79SJayamohan Kallickal 768cf987b79SJayamohan Kallickal /* ICD discarded in the process of alignment */ 769cf987b79SJayamohan Kallickal if (icd_start_align) 770cf987b79SJayamohan Kallickal icd_count_unavailable = ((icd_start_align - 771cf987b79SJayamohan Kallickal icd_start) + 772cf987b79SJayamohan Kallickal (icd_count - 773cf987b79SJayamohan Kallickal icd_count_align)); 774cf987b79SJayamohan Kallickal 775cf987b79SJayamohan Kallickal /* Updated ICD count available */ 776cf987b79SJayamohan Kallickal phba->fw_config.iscsi_icd_count[ulp_num] = (icd_count - 777cf987b79SJayamohan Kallickal icd_count_unavailable); 778cf987b79SJayamohan Kallickal 779cf987b79SJayamohan Kallickal beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 780cf987b79SJayamohan Kallickal "BM_%d : Aligned ICD values\n" 781cf987b79SJayamohan Kallickal "\t ICD Start : %d\n" 782cf987b79SJayamohan Kallickal "\t ICD Count : %d\n" 783cf987b79SJayamohan Kallickal "\t ICD Discarded : %d\n", 784cf987b79SJayamohan Kallickal phba->fw_config. 785cf987b79SJayamohan Kallickal iscsi_icd_start[ulp_num], 786cf987b79SJayamohan Kallickal phba->fw_config. 787cf987b79SJayamohan Kallickal iscsi_icd_count[ulp_num], 788cf987b79SJayamohan Kallickal icd_count_unavailable); 789cf987b79SJayamohan Kallickal break; 790cf987b79SJayamohan Kallickal } 791cf987b79SJayamohan Kallickal } 792cf987b79SJayamohan Kallickal 793cf987b79SJayamohan Kallickal total_icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; 794843ae752SJayamohan Kallickal phba->params.ios_per_ctrl = (total_icd_count - 795843ae752SJayamohan Kallickal (total_cid_count + 796843ae752SJayamohan Kallickal BE2_TMFS + BE2_NOPOUT_REQ)); 797843ae752SJayamohan Kallickal phba->params.cxns_per_ctrl = total_cid_count; 798843ae752SJayamohan Kallickal phba->params.asyncpdus_per_ctrl = total_cid_count; 799843ae752SJayamohan Kallickal phba->params.icds_per_ctrl = total_icd_count; 8006733b39aSJayamohan Kallickal phba->params.num_sge_per_io = BE2_SGE; 8016733b39aSJayamohan Kallickal phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; 8026733b39aSJayamohan Kallickal phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; 8036733b39aSJayamohan Kallickal phba->params.eq_timer = 64; 804843ae752SJayamohan Kallickal phba->params.num_eq_entries = 1024; 805843ae752SJayamohan Kallickal phba->params.num_cq_entries = 1024; 8066733b39aSJayamohan Kallickal phba->params.wrbs_per_cxn = 256; 8076733b39aSJayamohan Kallickal } 8086733b39aSJayamohan Kallickal 8096733b39aSJayamohan Kallickal static void hwi_ring_eq_db(struct beiscsi_hba *phba, 8106733b39aSJayamohan Kallickal unsigned int id, unsigned int clr_interrupt, 8116733b39aSJayamohan Kallickal unsigned int num_processed, 8126733b39aSJayamohan Kallickal unsigned char rearm, unsigned char event) 8136733b39aSJayamohan Kallickal { 8146733b39aSJayamohan Kallickal u32 val = 0; 815e08b3c8bSJayamohan Kallickal 8166733b39aSJayamohan Kallickal if (rearm) 8176733b39aSJayamohan Kallickal val |= 1 << DB_EQ_REARM_SHIFT; 8186733b39aSJayamohan Kallickal if (clr_interrupt) 8196733b39aSJayamohan Kallickal val |= 1 << DB_EQ_CLR_SHIFT; 8206733b39aSJayamohan Kallickal if (event) 8216733b39aSJayamohan Kallickal val |= 1 << DB_EQ_EVNT_SHIFT; 822e08b3c8bSJayamohan Kallickal 8236733b39aSJayamohan Kallickal val |= num_processed << DB_EQ_NUM_POPPED_SHIFT; 824e08b3c8bSJayamohan Kallickal /* Setting lower order EQ_ID Bits */ 825e08b3c8bSJayamohan Kallickal val |= (id & DB_EQ_RING_ID_LOW_MASK); 826e08b3c8bSJayamohan Kallickal 827e08b3c8bSJayamohan Kallickal /* Setting Higher order EQ_ID Bits */ 828e08b3c8bSJayamohan Kallickal val |= (((id >> DB_EQ_HIGH_FEILD_SHIFT) & 829e08b3c8bSJayamohan Kallickal DB_EQ_RING_ID_HIGH_MASK) 830e08b3c8bSJayamohan Kallickal << DB_EQ_HIGH_SET_SHIFT); 831e08b3c8bSJayamohan Kallickal 8326733b39aSJayamohan Kallickal iowrite32(val, phba->db_va + DB_EQ_OFFSET); 8336733b39aSJayamohan Kallickal } 8346733b39aSJayamohan Kallickal 8356733b39aSJayamohan Kallickal /** 836bfead3b2SJayamohan Kallickal * be_isr_mcc - The isr routine of the driver. 837bfead3b2SJayamohan Kallickal * @irq: Not used 838bfead3b2SJayamohan Kallickal * @dev_id: Pointer to host adapter structure 839bfead3b2SJayamohan Kallickal */ 840bfead3b2SJayamohan Kallickal static irqreturn_t be_isr_mcc(int irq, void *dev_id) 841bfead3b2SJayamohan Kallickal { 842bfead3b2SJayamohan Kallickal struct beiscsi_hba *phba; 843bfead3b2SJayamohan Kallickal struct be_eq_entry *eqe = NULL; 844bfead3b2SJayamohan Kallickal struct be_queue_info *eq; 845bfead3b2SJayamohan Kallickal struct be_queue_info *mcc; 846bfead3b2SJayamohan Kallickal unsigned int num_eq_processed; 847bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 848bfead3b2SJayamohan Kallickal unsigned long flags; 849bfead3b2SJayamohan Kallickal 850bfead3b2SJayamohan Kallickal pbe_eq = dev_id; 851bfead3b2SJayamohan Kallickal eq = &pbe_eq->q; 852bfead3b2SJayamohan Kallickal phba = pbe_eq->phba; 853bfead3b2SJayamohan Kallickal mcc = &phba->ctrl.mcc_obj.cq; 854bfead3b2SJayamohan Kallickal eqe = queue_tail_node(eq); 855bfead3b2SJayamohan Kallickal 856bfead3b2SJayamohan Kallickal num_eq_processed = 0; 857bfead3b2SJayamohan Kallickal 858bfead3b2SJayamohan Kallickal while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] 859bfead3b2SJayamohan Kallickal & EQE_VALID_MASK) { 860bfead3b2SJayamohan Kallickal if (((eqe->dw[offsetof(struct amap_eq_entry, 861bfead3b2SJayamohan Kallickal resource_id) / 32] & 862bfead3b2SJayamohan Kallickal EQE_RESID_MASK) >> 16) == mcc->id) { 863bfead3b2SJayamohan Kallickal spin_lock_irqsave(&phba->isr_lock, flags); 86472fb46a9SJohn Soni Jose pbe_eq->todo_mcc_cq = true; 865bfead3b2SJayamohan Kallickal spin_unlock_irqrestore(&phba->isr_lock, flags); 866bfead3b2SJayamohan Kallickal } 867bfead3b2SJayamohan Kallickal AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 868bfead3b2SJayamohan Kallickal queue_tail_inc(eq); 869bfead3b2SJayamohan Kallickal eqe = queue_tail_node(eq); 870bfead3b2SJayamohan Kallickal num_eq_processed++; 871bfead3b2SJayamohan Kallickal } 87272fb46a9SJohn Soni Jose if (pbe_eq->todo_mcc_cq) 87372fb46a9SJohn Soni Jose queue_work(phba->wq, &pbe_eq->work_cqs); 874bfead3b2SJayamohan Kallickal if (num_eq_processed) 875bfead3b2SJayamohan Kallickal hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); 876bfead3b2SJayamohan Kallickal 877bfead3b2SJayamohan Kallickal return IRQ_HANDLED; 878bfead3b2SJayamohan Kallickal } 879bfead3b2SJayamohan Kallickal 880bfead3b2SJayamohan Kallickal /** 881bfead3b2SJayamohan Kallickal * be_isr_msix - The isr routine of the driver. 882bfead3b2SJayamohan Kallickal * @irq: Not used 883bfead3b2SJayamohan Kallickal * @dev_id: Pointer to host adapter structure 884bfead3b2SJayamohan Kallickal */ 885bfead3b2SJayamohan Kallickal static irqreturn_t be_isr_msix(int irq, void *dev_id) 886bfead3b2SJayamohan Kallickal { 887bfead3b2SJayamohan Kallickal struct beiscsi_hba *phba; 888bfead3b2SJayamohan Kallickal struct be_eq_entry *eqe = NULL; 889bfead3b2SJayamohan Kallickal struct be_queue_info *eq; 890bfead3b2SJayamohan Kallickal struct be_queue_info *cq; 891bfead3b2SJayamohan Kallickal unsigned int num_eq_processed; 892bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 893bfead3b2SJayamohan Kallickal 894bfead3b2SJayamohan Kallickal pbe_eq = dev_id; 895bfead3b2SJayamohan Kallickal eq = &pbe_eq->q; 896bfead3b2SJayamohan Kallickal cq = pbe_eq->cq; 897bfead3b2SJayamohan Kallickal eqe = queue_tail_node(eq); 898bfead3b2SJayamohan Kallickal 899bfead3b2SJayamohan Kallickal phba = pbe_eq->phba; 900bfead3b2SJayamohan Kallickal num_eq_processed = 0; 901bfead3b2SJayamohan Kallickal while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] 902bfead3b2SJayamohan Kallickal & EQE_VALID_MASK) { 903bfead3b2SJayamohan Kallickal if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) 904bfead3b2SJayamohan Kallickal blk_iopoll_sched(&pbe_eq->iopoll); 905bfead3b2SJayamohan Kallickal 906bfead3b2SJayamohan Kallickal AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 907bfead3b2SJayamohan Kallickal queue_tail_inc(eq); 908bfead3b2SJayamohan Kallickal eqe = queue_tail_node(eq); 909bfead3b2SJayamohan Kallickal num_eq_processed++; 910bfead3b2SJayamohan Kallickal } 911bfead3b2SJayamohan Kallickal 912bfead3b2SJayamohan Kallickal if (num_eq_processed) 91372fb46a9SJohn Soni Jose hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); 914bfead3b2SJayamohan Kallickal 915bfead3b2SJayamohan Kallickal return IRQ_HANDLED; 916bfead3b2SJayamohan Kallickal } 917bfead3b2SJayamohan Kallickal 918bfead3b2SJayamohan Kallickal /** 9196733b39aSJayamohan Kallickal * be_isr - The isr routine of the driver. 9206733b39aSJayamohan Kallickal * @irq: Not used 9216733b39aSJayamohan Kallickal * @dev_id: Pointer to host adapter structure 9226733b39aSJayamohan Kallickal */ 9236733b39aSJayamohan Kallickal static irqreturn_t be_isr(int irq, void *dev_id) 9246733b39aSJayamohan Kallickal { 9256733b39aSJayamohan Kallickal struct beiscsi_hba *phba; 9266733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 9276733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context; 9286733b39aSJayamohan Kallickal struct be_eq_entry *eqe = NULL; 9296733b39aSJayamohan Kallickal struct be_queue_info *eq; 930bfead3b2SJayamohan Kallickal struct be_queue_info *mcc; 9316733b39aSJayamohan Kallickal unsigned long flags, index; 932bfead3b2SJayamohan Kallickal unsigned int num_mcceq_processed, num_ioeq_processed; 9336733b39aSJayamohan Kallickal struct be_ctrl_info *ctrl; 934bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 9356733b39aSJayamohan Kallickal int isr; 9366733b39aSJayamohan Kallickal 9376733b39aSJayamohan Kallickal phba = dev_id; 9386eab04a8SJustin P. Mattock ctrl = &phba->ctrl; 9396733b39aSJayamohan Kallickal isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + 9406733b39aSJayamohan Kallickal (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE)); 9416733b39aSJayamohan Kallickal if (!isr) 9426733b39aSJayamohan Kallickal return IRQ_NONE; 9436733b39aSJayamohan Kallickal 9446733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 9456733b39aSJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 946bfead3b2SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[0]; 947bfead3b2SJayamohan Kallickal 948bfead3b2SJayamohan Kallickal eq = &phwi_context->be_eq[0].q; 949bfead3b2SJayamohan Kallickal mcc = &phba->ctrl.mcc_obj.cq; 9506733b39aSJayamohan Kallickal index = 0; 9516733b39aSJayamohan Kallickal eqe = queue_tail_node(eq); 9526733b39aSJayamohan Kallickal 953bfead3b2SJayamohan Kallickal num_ioeq_processed = 0; 954bfead3b2SJayamohan Kallickal num_mcceq_processed = 0; 9556733b39aSJayamohan Kallickal while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] 9566733b39aSJayamohan Kallickal & EQE_VALID_MASK) { 957bfead3b2SJayamohan Kallickal if (((eqe->dw[offsetof(struct amap_eq_entry, 958bfead3b2SJayamohan Kallickal resource_id) / 32] & 959bfead3b2SJayamohan Kallickal EQE_RESID_MASK) >> 16) == mcc->id) { 960bfead3b2SJayamohan Kallickal spin_lock_irqsave(&phba->isr_lock, flags); 96172fb46a9SJohn Soni Jose pbe_eq->todo_mcc_cq = true; 962bfead3b2SJayamohan Kallickal spin_unlock_irqrestore(&phba->isr_lock, flags); 963bfead3b2SJayamohan Kallickal num_mcceq_processed++; 964bfead3b2SJayamohan Kallickal } else { 965bfead3b2SJayamohan Kallickal if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) 966bfead3b2SJayamohan Kallickal blk_iopoll_sched(&pbe_eq->iopoll); 967bfead3b2SJayamohan Kallickal num_ioeq_processed++; 968bfead3b2SJayamohan Kallickal } 9696733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 9706733b39aSJayamohan Kallickal queue_tail_inc(eq); 9716733b39aSJayamohan Kallickal eqe = queue_tail_node(eq); 9726733b39aSJayamohan Kallickal } 973bfead3b2SJayamohan Kallickal if (num_ioeq_processed || num_mcceq_processed) { 97472fb46a9SJohn Soni Jose if (pbe_eq->todo_mcc_cq) 97572fb46a9SJohn Soni Jose queue_work(phba->wq, &pbe_eq->work_cqs); 976bfead3b2SJayamohan Kallickal 977bfead3b2SJayamohan Kallickal if ((num_mcceq_processed) && (!num_ioeq_processed)) 978bfead3b2SJayamohan Kallickal hwi_ring_eq_db(phba, eq->id, 0, 979bfead3b2SJayamohan Kallickal (num_ioeq_processed + 980bfead3b2SJayamohan Kallickal num_mcceq_processed) , 1, 1); 981bfead3b2SJayamohan Kallickal else 982bfead3b2SJayamohan Kallickal hwi_ring_eq_db(phba, eq->id, 0, 983bfead3b2SJayamohan Kallickal (num_ioeq_processed + 984bfead3b2SJayamohan Kallickal num_mcceq_processed), 0, 1); 985bfead3b2SJayamohan Kallickal 9866733b39aSJayamohan Kallickal return IRQ_HANDLED; 9876733b39aSJayamohan Kallickal } else 9886733b39aSJayamohan Kallickal return IRQ_NONE; 9896733b39aSJayamohan Kallickal } 9906733b39aSJayamohan Kallickal 9916733b39aSJayamohan Kallickal static int beiscsi_init_irqs(struct beiscsi_hba *phba) 9926733b39aSJayamohan Kallickal { 9936733b39aSJayamohan Kallickal struct pci_dev *pcidev = phba->pcidev; 994bfead3b2SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 995bfead3b2SJayamohan Kallickal struct hwi_context_memory *phwi_context; 9964f5af07eSJayamohan Kallickal int ret, msix_vec, i, j; 9976733b39aSJayamohan Kallickal 998bfead3b2SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 999bfead3b2SJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 1000bfead3b2SJayamohan Kallickal 1001bfead3b2SJayamohan Kallickal if (phba->msix_enabled) { 1002bfead3b2SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 10038fcfb210SJayamohan Kallickal phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, 10048fcfb210SJayamohan Kallickal GFP_KERNEL); 10058fcfb210SJayamohan Kallickal if (!phba->msi_name[i]) { 10068fcfb210SJayamohan Kallickal ret = -ENOMEM; 10078fcfb210SJayamohan Kallickal goto free_msix_irqs; 10088fcfb210SJayamohan Kallickal } 10098fcfb210SJayamohan Kallickal 10108fcfb210SJayamohan Kallickal sprintf(phba->msi_name[i], "beiscsi_%02x_%02x", 10118fcfb210SJayamohan Kallickal phba->shost->host_no, i); 1012bfead3b2SJayamohan Kallickal msix_vec = phba->msix_entries[i].vector; 10138fcfb210SJayamohan Kallickal ret = request_irq(msix_vec, be_isr_msix, 0, 10148fcfb210SJayamohan Kallickal phba->msi_name[i], 1015bfead3b2SJayamohan Kallickal &phwi_context->be_eq[i]); 10164f5af07eSJayamohan Kallickal if (ret) { 101799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 101899bc5d55SJohn Soni Jose "BM_%d : beiscsi_init_irqs-Failed to" 101999bc5d55SJohn Soni Jose "register msix for i = %d\n", 102099bc5d55SJohn Soni Jose i); 10218fcfb210SJayamohan Kallickal kfree(phba->msi_name[i]); 10224f5af07eSJayamohan Kallickal goto free_msix_irqs; 10234f5af07eSJayamohan Kallickal } 1024bfead3b2SJayamohan Kallickal } 10258fcfb210SJayamohan Kallickal phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL); 10268fcfb210SJayamohan Kallickal if (!phba->msi_name[i]) { 10278fcfb210SJayamohan Kallickal ret = -ENOMEM; 10288fcfb210SJayamohan Kallickal goto free_msix_irqs; 10298fcfb210SJayamohan Kallickal } 10308fcfb210SJayamohan Kallickal sprintf(phba->msi_name[i], "beiscsi_mcc_%02x", 10318fcfb210SJayamohan Kallickal phba->shost->host_no); 1032bfead3b2SJayamohan Kallickal msix_vec = phba->msix_entries[i].vector; 10338fcfb210SJayamohan Kallickal ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i], 1034bfead3b2SJayamohan Kallickal &phwi_context->be_eq[i]); 10354f5af07eSJayamohan Kallickal if (ret) { 103699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT , 103799bc5d55SJohn Soni Jose "BM_%d : beiscsi_init_irqs-" 10384f5af07eSJayamohan Kallickal "Failed to register beiscsi_msix_mcc\n"); 10398fcfb210SJayamohan Kallickal kfree(phba->msi_name[i]); 10404f5af07eSJayamohan Kallickal goto free_msix_irqs; 10414f5af07eSJayamohan Kallickal } 10424f5af07eSJayamohan Kallickal 1043bfead3b2SJayamohan Kallickal } else { 1044bfead3b2SJayamohan Kallickal ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, 1045bfead3b2SJayamohan Kallickal "beiscsi", phba); 10466733b39aSJayamohan Kallickal if (ret) { 104799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 104899bc5d55SJohn Soni Jose "BM_%d : beiscsi_init_irqs-" 10496733b39aSJayamohan Kallickal "Failed to register irq\\n"); 10506733b39aSJayamohan Kallickal return ret; 10516733b39aSJayamohan Kallickal } 1052bfead3b2SJayamohan Kallickal } 10536733b39aSJayamohan Kallickal return 0; 10544f5af07eSJayamohan Kallickal free_msix_irqs: 10558fcfb210SJayamohan Kallickal for (j = i - 1; j >= 0; j--) { 10568fcfb210SJayamohan Kallickal kfree(phba->msi_name[j]); 10578fcfb210SJayamohan Kallickal msix_vec = phba->msix_entries[j].vector; 10584f5af07eSJayamohan Kallickal free_irq(msix_vec, &phwi_context->be_eq[j]); 10598fcfb210SJayamohan Kallickal } 10604f5af07eSJayamohan Kallickal return ret; 10616733b39aSJayamohan Kallickal } 10626733b39aSJayamohan Kallickal 1063e08b3c8bSJayamohan Kallickal void hwi_ring_cq_db(struct beiscsi_hba *phba, 10646733b39aSJayamohan Kallickal unsigned int id, unsigned int num_processed, 10656733b39aSJayamohan Kallickal unsigned char rearm, unsigned char event) 10666733b39aSJayamohan Kallickal { 10676733b39aSJayamohan Kallickal u32 val = 0; 1068e08b3c8bSJayamohan Kallickal 10696733b39aSJayamohan Kallickal if (rearm) 10706733b39aSJayamohan Kallickal val |= 1 << DB_CQ_REARM_SHIFT; 1071e08b3c8bSJayamohan Kallickal 10726733b39aSJayamohan Kallickal val |= num_processed << DB_CQ_NUM_POPPED_SHIFT; 1073e08b3c8bSJayamohan Kallickal 1074e08b3c8bSJayamohan Kallickal /* Setting lower order CQ_ID Bits */ 1075e08b3c8bSJayamohan Kallickal val |= (id & DB_CQ_RING_ID_LOW_MASK); 1076e08b3c8bSJayamohan Kallickal 1077e08b3c8bSJayamohan Kallickal /* Setting Higher order CQ_ID Bits */ 1078e08b3c8bSJayamohan Kallickal val |= (((id >> DB_CQ_HIGH_FEILD_SHIFT) & 1079e08b3c8bSJayamohan Kallickal DB_CQ_RING_ID_HIGH_MASK) 1080e08b3c8bSJayamohan Kallickal << DB_CQ_HIGH_SET_SHIFT); 1081e08b3c8bSJayamohan Kallickal 10826733b39aSJayamohan Kallickal iowrite32(val, phba->db_va + DB_CQ_OFFSET); 10836733b39aSJayamohan Kallickal } 10846733b39aSJayamohan Kallickal 10856733b39aSJayamohan Kallickal static unsigned int 10866733b39aSJayamohan Kallickal beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, 10876733b39aSJayamohan Kallickal struct beiscsi_hba *phba, 10886733b39aSJayamohan Kallickal struct pdu_base *ppdu, 10896733b39aSJayamohan Kallickal unsigned long pdu_len, 10906733b39aSJayamohan Kallickal void *pbuffer, unsigned long buf_len) 10916733b39aSJayamohan Kallickal { 10926733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 10936733b39aSJayamohan Kallickal struct iscsi_session *session = conn->session; 1094bfead3b2SJayamohan Kallickal struct iscsi_task *task; 1095bfead3b2SJayamohan Kallickal struct beiscsi_io_task *io_task; 1096bfead3b2SJayamohan Kallickal struct iscsi_hdr *login_hdr; 10976733b39aSJayamohan Kallickal 10986733b39aSJayamohan Kallickal switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] & 10996733b39aSJayamohan Kallickal PDUBASE_OPCODE_MASK) { 11006733b39aSJayamohan Kallickal case ISCSI_OP_NOOP_IN: 11016733b39aSJayamohan Kallickal pbuffer = NULL; 11026733b39aSJayamohan Kallickal buf_len = 0; 11036733b39aSJayamohan Kallickal break; 11046733b39aSJayamohan Kallickal case ISCSI_OP_ASYNC_EVENT: 11056733b39aSJayamohan Kallickal break; 11066733b39aSJayamohan Kallickal case ISCSI_OP_REJECT: 11076733b39aSJayamohan Kallickal WARN_ON(!pbuffer); 11086733b39aSJayamohan Kallickal WARN_ON(!(buf_len == 48)); 110999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 111099bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 111199bc5d55SJohn Soni Jose "BM_%d : In ISCSI_OP_REJECT\n"); 11126733b39aSJayamohan Kallickal break; 11136733b39aSJayamohan Kallickal case ISCSI_OP_LOGIN_RSP: 11147bd6e25cSJayamohan Kallickal case ISCSI_OP_TEXT_RSP: 1115bfead3b2SJayamohan Kallickal task = conn->login_task; 1116bfead3b2SJayamohan Kallickal io_task = task->dd_data; 1117bfead3b2SJayamohan Kallickal login_hdr = (struct iscsi_hdr *)ppdu; 1118bfead3b2SJayamohan Kallickal login_hdr->itt = io_task->libiscsi_itt; 11196733b39aSJayamohan Kallickal break; 11206733b39aSJayamohan Kallickal default: 112199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, 112299bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 112399bc5d55SJohn Soni Jose "BM_%d : Unrecognized opcode 0x%x in async msg\n", 11246733b39aSJayamohan Kallickal (ppdu-> 11256733b39aSJayamohan Kallickal dw[offsetof(struct amap_pdu_base, opcode) / 32] 11266733b39aSJayamohan Kallickal & PDUBASE_OPCODE_MASK)); 11276733b39aSJayamohan Kallickal return 1; 11286733b39aSJayamohan Kallickal } 11296733b39aSJayamohan Kallickal 1130659743b0SShlomo Pongratz spin_lock_bh(&session->back_lock); 11316733b39aSJayamohan Kallickal __iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len); 1132659743b0SShlomo Pongratz spin_unlock_bh(&session->back_lock); 11336733b39aSJayamohan Kallickal return 0; 11346733b39aSJayamohan Kallickal } 11356733b39aSJayamohan Kallickal 11366733b39aSJayamohan Kallickal static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) 11376733b39aSJayamohan Kallickal { 11386733b39aSJayamohan Kallickal struct sgl_handle *psgl_handle; 11396733b39aSJayamohan Kallickal 11406733b39aSJayamohan Kallickal if (phba->io_sgl_hndl_avbl) { 114199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, 114299bc5d55SJohn Soni Jose "BM_%d : In alloc_io_sgl_handle," 114399bc5d55SJohn Soni Jose " io_sgl_alloc_index=%d\n", 11446733b39aSJayamohan Kallickal phba->io_sgl_alloc_index); 114599bc5d55SJohn Soni Jose 11466733b39aSJayamohan Kallickal psgl_handle = phba->io_sgl_hndl_base[phba-> 11476733b39aSJayamohan Kallickal io_sgl_alloc_index]; 11486733b39aSJayamohan Kallickal phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL; 11496733b39aSJayamohan Kallickal phba->io_sgl_hndl_avbl--; 1150bfead3b2SJayamohan Kallickal if (phba->io_sgl_alloc_index == (phba->params. 1151bfead3b2SJayamohan Kallickal ios_per_ctrl - 1)) 11526733b39aSJayamohan Kallickal phba->io_sgl_alloc_index = 0; 11536733b39aSJayamohan Kallickal else 11546733b39aSJayamohan Kallickal phba->io_sgl_alloc_index++; 11556733b39aSJayamohan Kallickal } else 11566733b39aSJayamohan Kallickal psgl_handle = NULL; 11576733b39aSJayamohan Kallickal return psgl_handle; 11586733b39aSJayamohan Kallickal } 11596733b39aSJayamohan Kallickal 11606733b39aSJayamohan Kallickal static void 11616733b39aSJayamohan Kallickal free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) 11626733b39aSJayamohan Kallickal { 116399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, 116499bc5d55SJohn Soni Jose "BM_%d : In free_,io_sgl_free_index=%d\n", 11656733b39aSJayamohan Kallickal phba->io_sgl_free_index); 116699bc5d55SJohn Soni Jose 11676733b39aSJayamohan Kallickal if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) { 11686733b39aSJayamohan Kallickal /* 11696733b39aSJayamohan Kallickal * this can happen if clean_task is called on a task that 11706733b39aSJayamohan Kallickal * failed in xmit_task or alloc_pdu. 11716733b39aSJayamohan Kallickal */ 117299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, 117399bc5d55SJohn Soni Jose "BM_%d : Double Free in IO SGL io_sgl_free_index=%d," 11746733b39aSJayamohan Kallickal "value there=%p\n", phba->io_sgl_free_index, 117599bc5d55SJohn Soni Jose phba->io_sgl_hndl_base 117699bc5d55SJohn Soni Jose [phba->io_sgl_free_index]); 11776733b39aSJayamohan Kallickal return; 11786733b39aSJayamohan Kallickal } 11796733b39aSJayamohan Kallickal phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle; 11806733b39aSJayamohan Kallickal phba->io_sgl_hndl_avbl++; 11816733b39aSJayamohan Kallickal if (phba->io_sgl_free_index == (phba->params.ios_per_ctrl - 1)) 11826733b39aSJayamohan Kallickal phba->io_sgl_free_index = 0; 11836733b39aSJayamohan Kallickal else 11846733b39aSJayamohan Kallickal phba->io_sgl_free_index++; 11856733b39aSJayamohan Kallickal } 11866733b39aSJayamohan Kallickal 11876733b39aSJayamohan Kallickal /** 11886733b39aSJayamohan Kallickal * alloc_wrb_handle - To allocate a wrb handle 11896733b39aSJayamohan Kallickal * @phba: The hba pointer 11906733b39aSJayamohan Kallickal * @cid: The cid to use for allocation 11916733b39aSJayamohan Kallickal * 11926733b39aSJayamohan Kallickal * This happens under session_lock until submission to chip 11936733b39aSJayamohan Kallickal */ 1194d5431488SJayamohan Kallickal struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid) 11956733b39aSJayamohan Kallickal { 11966733b39aSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 11976733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 1198d5431488SJayamohan Kallickal struct wrb_handle *pwrb_handle, *pwrb_handle_tmp; 1199a7909b39SJayamohan Kallickal uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); 12006733b39aSJayamohan Kallickal 12016733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 1202a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 1203d5431488SJayamohan Kallickal if (pwrb_context->wrb_handles_available >= 2) { 1204bfead3b2SJayamohan Kallickal pwrb_handle = pwrb_context->pwrb_handle_base[ 1205bfead3b2SJayamohan Kallickal pwrb_context->alloc_index]; 1206bfead3b2SJayamohan Kallickal pwrb_context->wrb_handles_available--; 1207bfead3b2SJayamohan Kallickal if (pwrb_context->alloc_index == 1208bfead3b2SJayamohan Kallickal (phba->params.wrbs_per_cxn - 1)) 1209bfead3b2SJayamohan Kallickal pwrb_context->alloc_index = 0; 1210bfead3b2SJayamohan Kallickal else 1211bfead3b2SJayamohan Kallickal pwrb_context->alloc_index++; 1212d5431488SJayamohan Kallickal pwrb_handle_tmp = pwrb_context->pwrb_handle_base[ 1213d5431488SJayamohan Kallickal pwrb_context->alloc_index]; 1214d5431488SJayamohan Kallickal pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index; 1215bfead3b2SJayamohan Kallickal } else 1216bfead3b2SJayamohan Kallickal pwrb_handle = NULL; 12176733b39aSJayamohan Kallickal return pwrb_handle; 12186733b39aSJayamohan Kallickal } 12196733b39aSJayamohan Kallickal 12206733b39aSJayamohan Kallickal /** 12216733b39aSJayamohan Kallickal * free_wrb_handle - To free the wrb handle back to pool 12226733b39aSJayamohan Kallickal * @phba: The hba pointer 12236733b39aSJayamohan Kallickal * @pwrb_context: The context to free from 12246733b39aSJayamohan Kallickal * @pwrb_handle: The wrb_handle to free 12256733b39aSJayamohan Kallickal * 12266733b39aSJayamohan Kallickal * This happens under session_lock until submission to chip 12276733b39aSJayamohan Kallickal */ 12286733b39aSJayamohan Kallickal static void 12296733b39aSJayamohan Kallickal free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, 12306733b39aSJayamohan Kallickal struct wrb_handle *pwrb_handle) 12316733b39aSJayamohan Kallickal { 123232951dd8SJayamohan Kallickal pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; 1233bfead3b2SJayamohan Kallickal pwrb_context->wrb_handles_available++; 1234bfead3b2SJayamohan Kallickal if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1)) 1235bfead3b2SJayamohan Kallickal pwrb_context->free_index = 0; 1236bfead3b2SJayamohan Kallickal else 1237bfead3b2SJayamohan Kallickal pwrb_context->free_index++; 1238bfead3b2SJayamohan Kallickal 123999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, 124099bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 124199bc5d55SJohn Soni Jose "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x" 12426733b39aSJayamohan Kallickal "wrb_handles_available=%d\n", 12436733b39aSJayamohan Kallickal pwrb_handle, pwrb_context->free_index, 1244bfead3b2SJayamohan Kallickal pwrb_context->wrb_handles_available); 12456733b39aSJayamohan Kallickal } 12466733b39aSJayamohan Kallickal 12476733b39aSJayamohan Kallickal static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) 12486733b39aSJayamohan Kallickal { 12496733b39aSJayamohan Kallickal struct sgl_handle *psgl_handle; 12506733b39aSJayamohan Kallickal 12516733b39aSJayamohan Kallickal if (phba->eh_sgl_hndl_avbl) { 12526733b39aSJayamohan Kallickal psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index]; 12536733b39aSJayamohan Kallickal phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; 125499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 125599bc5d55SJohn Soni Jose "BM_%d : mgmt_sgl_alloc_index=%d=0x%x\n", 125699bc5d55SJohn Soni Jose phba->eh_sgl_alloc_index, 125799bc5d55SJohn Soni Jose phba->eh_sgl_alloc_index); 125899bc5d55SJohn Soni Jose 12596733b39aSJayamohan Kallickal phba->eh_sgl_hndl_avbl--; 12606733b39aSJayamohan Kallickal if (phba->eh_sgl_alloc_index == 12616733b39aSJayamohan Kallickal (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - 12626733b39aSJayamohan Kallickal 1)) 12636733b39aSJayamohan Kallickal phba->eh_sgl_alloc_index = 0; 12646733b39aSJayamohan Kallickal else 12656733b39aSJayamohan Kallickal phba->eh_sgl_alloc_index++; 12666733b39aSJayamohan Kallickal } else 12676733b39aSJayamohan Kallickal psgl_handle = NULL; 12686733b39aSJayamohan Kallickal return psgl_handle; 12696733b39aSJayamohan Kallickal } 12706733b39aSJayamohan Kallickal 12716733b39aSJayamohan Kallickal void 12726733b39aSJayamohan Kallickal free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) 12736733b39aSJayamohan Kallickal { 12746733b39aSJayamohan Kallickal 127599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 127699bc5d55SJohn Soni Jose "BM_%d : In free_mgmt_sgl_handle," 127799bc5d55SJohn Soni Jose "eh_sgl_free_index=%d\n", 1278bfead3b2SJayamohan Kallickal phba->eh_sgl_free_index); 127999bc5d55SJohn Soni Jose 12806733b39aSJayamohan Kallickal if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) { 12816733b39aSJayamohan Kallickal /* 12826733b39aSJayamohan Kallickal * this can happen if clean_task is called on a task that 12836733b39aSJayamohan Kallickal * failed in xmit_task or alloc_pdu. 12846733b39aSJayamohan Kallickal */ 128599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 128699bc5d55SJohn Soni Jose "BM_%d : Double Free in eh SGL ," 128799bc5d55SJohn Soni Jose "eh_sgl_free_index=%d\n", 12886733b39aSJayamohan Kallickal phba->eh_sgl_free_index); 12896733b39aSJayamohan Kallickal return; 12906733b39aSJayamohan Kallickal } 12916733b39aSJayamohan Kallickal phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle; 12926733b39aSJayamohan Kallickal phba->eh_sgl_hndl_avbl++; 12936733b39aSJayamohan Kallickal if (phba->eh_sgl_free_index == 12946733b39aSJayamohan Kallickal (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - 1)) 12956733b39aSJayamohan Kallickal phba->eh_sgl_free_index = 0; 12966733b39aSJayamohan Kallickal else 12976733b39aSJayamohan Kallickal phba->eh_sgl_free_index++; 12986733b39aSJayamohan Kallickal } 12996733b39aSJayamohan Kallickal 13006733b39aSJayamohan Kallickal static void 13016733b39aSJayamohan Kallickal be_complete_io(struct beiscsi_conn *beiscsi_conn, 130273133261SJohn Soni Jose struct iscsi_task *task, 130373133261SJohn Soni Jose struct common_sol_cqe *csol_cqe) 13046733b39aSJayamohan Kallickal { 13056733b39aSJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 13066733b39aSJayamohan Kallickal struct be_status_bhs *sts_bhs = 13076733b39aSJayamohan Kallickal (struct be_status_bhs *)io_task->cmd_bhs; 13086733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 13096733b39aSJayamohan Kallickal unsigned char *sense; 13106733b39aSJayamohan Kallickal u32 resid = 0, exp_cmdsn, max_cmdsn; 13116733b39aSJayamohan Kallickal u8 rsp, status, flags; 13126733b39aSJayamohan Kallickal 131373133261SJohn Soni Jose exp_cmdsn = csol_cqe->exp_cmdsn; 131473133261SJohn Soni Jose max_cmdsn = (csol_cqe->exp_cmdsn + 131573133261SJohn Soni Jose csol_cqe->cmd_wnd - 1); 131673133261SJohn Soni Jose rsp = csol_cqe->i_resp; 131773133261SJohn Soni Jose status = csol_cqe->i_sts; 131873133261SJohn Soni Jose flags = csol_cqe->i_flags; 131973133261SJohn Soni Jose resid = csol_cqe->res_cnt; 132073133261SJohn Soni Jose 1321bd535451SJayamohan Kallickal if (!task->sc) { 1322da334977SJayamohan Kallickal if (io_task->scsi_cmnd) { 1323bd535451SJayamohan Kallickal scsi_dma_unmap(io_task->scsi_cmnd); 1324da334977SJayamohan Kallickal io_task->scsi_cmnd = NULL; 1325da334977SJayamohan Kallickal } 13266733b39aSJayamohan Kallickal 1327bd535451SJayamohan Kallickal return; 1328bd535451SJayamohan Kallickal } 13296733b39aSJayamohan Kallickal task->sc->result = (DID_OK << 16) | status; 13306733b39aSJayamohan Kallickal if (rsp != ISCSI_STATUS_CMD_COMPLETED) { 13316733b39aSJayamohan Kallickal task->sc->result = DID_ERROR << 16; 13326733b39aSJayamohan Kallickal goto unmap; 13336733b39aSJayamohan Kallickal } 13346733b39aSJayamohan Kallickal 13356733b39aSJayamohan Kallickal /* bidi not initially supported */ 13366733b39aSJayamohan Kallickal if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) { 13376733b39aSJayamohan Kallickal if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW)) 13386733b39aSJayamohan Kallickal task->sc->result = DID_ERROR << 16; 13396733b39aSJayamohan Kallickal 13406733b39aSJayamohan Kallickal if (flags & ISCSI_FLAG_CMD_UNDERFLOW) { 13416733b39aSJayamohan Kallickal scsi_set_resid(task->sc, resid); 13426733b39aSJayamohan Kallickal if (!status && (scsi_bufflen(task->sc) - resid < 13436733b39aSJayamohan Kallickal task->sc->underflow)) 13446733b39aSJayamohan Kallickal task->sc->result = DID_ERROR << 16; 13456733b39aSJayamohan Kallickal } 13466733b39aSJayamohan Kallickal } 13476733b39aSJayamohan Kallickal 13486733b39aSJayamohan Kallickal if (status == SAM_STAT_CHECK_CONDITION) { 13494053a4beSDan Carpenter u16 sense_len; 1350bfead3b2SJayamohan Kallickal unsigned short *slen = (unsigned short *)sts_bhs->sense_info; 13514053a4beSDan Carpenter 13526733b39aSJayamohan Kallickal sense = sts_bhs->sense_info + sizeof(unsigned short); 13534053a4beSDan Carpenter sense_len = be16_to_cpu(*slen); 13546733b39aSJayamohan Kallickal memcpy(task->sc->sense_buffer, sense, 13556733b39aSJayamohan Kallickal min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); 13566733b39aSJayamohan Kallickal } 1357756d29c8SJayamohan Kallickal 135873133261SJohn Soni Jose if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) 135973133261SJohn Soni Jose conn->rxdata_octets += resid; 13606733b39aSJayamohan Kallickal unmap: 13616733b39aSJayamohan Kallickal scsi_dma_unmap(io_task->scsi_cmnd); 1362da334977SJayamohan Kallickal io_task->scsi_cmnd = NULL; 13636733b39aSJayamohan Kallickal iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn); 13646733b39aSJayamohan Kallickal } 13656733b39aSJayamohan Kallickal 13666733b39aSJayamohan Kallickal static void 13676733b39aSJayamohan Kallickal be_complete_logout(struct beiscsi_conn *beiscsi_conn, 136873133261SJohn Soni Jose struct iscsi_task *task, 136973133261SJohn Soni Jose struct common_sol_cqe *csol_cqe) 13706733b39aSJayamohan Kallickal { 13716733b39aSJayamohan Kallickal struct iscsi_logout_rsp *hdr; 1372bfead3b2SJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 13736733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 13746733b39aSJayamohan Kallickal 13756733b39aSJayamohan Kallickal hdr = (struct iscsi_logout_rsp *)task->hdr; 13767bd6e25cSJayamohan Kallickal hdr->opcode = ISCSI_OP_LOGOUT_RSP; 13776733b39aSJayamohan Kallickal hdr->t2wait = 5; 13786733b39aSJayamohan Kallickal hdr->t2retain = 0; 137973133261SJohn Soni Jose hdr->flags = csol_cqe->i_flags; 138073133261SJohn Soni Jose hdr->response = csol_cqe->i_resp; 1381702dc5e8SJayamohan Kallickal hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); 1382702dc5e8SJayamohan Kallickal hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + 1383702dc5e8SJayamohan Kallickal csol_cqe->cmd_wnd - 1); 138473133261SJohn Soni Jose 13857bd6e25cSJayamohan Kallickal hdr->dlength[0] = 0; 13867bd6e25cSJayamohan Kallickal hdr->dlength[1] = 0; 13877bd6e25cSJayamohan Kallickal hdr->dlength[2] = 0; 13886733b39aSJayamohan Kallickal hdr->hlength = 0; 1389bfead3b2SJayamohan Kallickal hdr->itt = io_task->libiscsi_itt; 13906733b39aSJayamohan Kallickal __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); 13916733b39aSJayamohan Kallickal } 13926733b39aSJayamohan Kallickal 13936733b39aSJayamohan Kallickal static void 13946733b39aSJayamohan Kallickal be_complete_tmf(struct beiscsi_conn *beiscsi_conn, 139573133261SJohn Soni Jose struct iscsi_task *task, 139673133261SJohn Soni Jose struct common_sol_cqe *csol_cqe) 13976733b39aSJayamohan Kallickal { 13986733b39aSJayamohan Kallickal struct iscsi_tm_rsp *hdr; 13996733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 1400bfead3b2SJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 14016733b39aSJayamohan Kallickal 14026733b39aSJayamohan Kallickal hdr = (struct iscsi_tm_rsp *)task->hdr; 14037bd6e25cSJayamohan Kallickal hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; 140473133261SJohn Soni Jose hdr->flags = csol_cqe->i_flags; 140573133261SJohn Soni Jose hdr->response = csol_cqe->i_resp; 1406702dc5e8SJayamohan Kallickal hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); 1407702dc5e8SJayamohan Kallickal hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + 140873133261SJohn Soni Jose csol_cqe->cmd_wnd - 1); 140973133261SJohn Soni Jose 1410bfead3b2SJayamohan Kallickal hdr->itt = io_task->libiscsi_itt; 14116733b39aSJayamohan Kallickal __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); 14126733b39aSJayamohan Kallickal } 14136733b39aSJayamohan Kallickal 14146733b39aSJayamohan Kallickal static void 14156733b39aSJayamohan Kallickal hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, 14166733b39aSJayamohan Kallickal struct beiscsi_hba *phba, struct sol_cqe *psol) 14176733b39aSJayamohan Kallickal { 14186733b39aSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 1419bfead3b2SJayamohan Kallickal struct wrb_handle *pwrb_handle = NULL; 14206733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 1421bfead3b2SJayamohan Kallickal struct iscsi_task *task; 1422bfead3b2SJayamohan Kallickal struct beiscsi_io_task *io_task; 1423a7909b39SJayamohan Kallickal uint16_t wrb_index, cid, cri_index; 14246733b39aSJayamohan Kallickal 14256733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 14262c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) { 142773133261SJohn Soni Jose wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe, 142873133261SJohn Soni Jose wrb_idx, psol); 142973133261SJohn Soni Jose cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe, 143073133261SJohn Soni Jose cid, psol); 14312c9dfd36SJayamohan Kallickal } else { 14322c9dfd36SJayamohan Kallickal wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, 14332c9dfd36SJayamohan Kallickal wrb_idx, psol); 14342c9dfd36SJayamohan Kallickal cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, 14352c9dfd36SJayamohan Kallickal cid, psol); 143673133261SJohn Soni Jose } 143773133261SJohn Soni Jose 1438a7909b39SJayamohan Kallickal cri_index = BE_GET_CRI_FROM_CID(cid); 1439a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 144073133261SJohn Soni Jose pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; 1441bfead3b2SJayamohan Kallickal task = pwrb_handle->pio_handle; 144235e66019SJayamohan Kallickal 1443bfead3b2SJayamohan Kallickal io_task = task->dd_data; 14444a4a11b9SJayamohan Kallickal memset(io_task->pwrb_handle->pwrb, 0, sizeof(struct iscsi_wrb)); 14454a4a11b9SJayamohan Kallickal iscsi_put_task(task); 14466733b39aSJayamohan Kallickal } 14476733b39aSJayamohan Kallickal 14486733b39aSJayamohan Kallickal static void 14496733b39aSJayamohan Kallickal be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, 145073133261SJohn Soni Jose struct iscsi_task *task, 145173133261SJohn Soni Jose struct common_sol_cqe *csol_cqe) 14526733b39aSJayamohan Kallickal { 14536733b39aSJayamohan Kallickal struct iscsi_nopin *hdr; 14546733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 1455bfead3b2SJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 14566733b39aSJayamohan Kallickal 14576733b39aSJayamohan Kallickal hdr = (struct iscsi_nopin *)task->hdr; 145873133261SJohn Soni Jose hdr->flags = csol_cqe->i_flags; 145973133261SJohn Soni Jose hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); 1460702dc5e8SJayamohan Kallickal hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + 146173133261SJohn Soni Jose csol_cqe->cmd_wnd - 1); 146273133261SJohn Soni Jose 14636733b39aSJayamohan Kallickal hdr->opcode = ISCSI_OP_NOOP_IN; 1464bfead3b2SJayamohan Kallickal hdr->itt = io_task->libiscsi_itt; 14656733b39aSJayamohan Kallickal __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); 14666733b39aSJayamohan Kallickal } 14676733b39aSJayamohan Kallickal 146873133261SJohn Soni Jose static void adapter_get_sol_cqe(struct beiscsi_hba *phba, 146973133261SJohn Soni Jose struct sol_cqe *psol, 147073133261SJohn Soni Jose struct common_sol_cqe *csol_cqe) 147173133261SJohn Soni Jose { 14722c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) { 14732c9dfd36SJayamohan Kallickal csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe, 14742c9dfd36SJayamohan Kallickal i_exp_cmd_sn, psol); 14752c9dfd36SJayamohan Kallickal csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe, 14762c9dfd36SJayamohan Kallickal i_res_cnt, psol); 14772c9dfd36SJayamohan Kallickal csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, 14782c9dfd36SJayamohan Kallickal i_cmd_wnd, psol); 14792c9dfd36SJayamohan Kallickal csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe, 14802c9dfd36SJayamohan Kallickal wrb_index, psol); 14812c9dfd36SJayamohan Kallickal csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe, 14822c9dfd36SJayamohan Kallickal cid, psol); 14832c9dfd36SJayamohan Kallickal csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe, 14842c9dfd36SJayamohan Kallickal hw_sts, psol); 14852c9dfd36SJayamohan Kallickal csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe, 14862c9dfd36SJayamohan Kallickal i_resp, psol); 14872c9dfd36SJayamohan Kallickal csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe, 14882c9dfd36SJayamohan Kallickal i_sts, psol); 14892c9dfd36SJayamohan Kallickal csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe, 14902c9dfd36SJayamohan Kallickal i_flags, psol); 14912c9dfd36SJayamohan Kallickal } else { 149273133261SJohn Soni Jose csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2, 149373133261SJohn Soni Jose i_exp_cmd_sn, psol); 149473133261SJohn Soni Jose csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2, 149573133261SJohn Soni Jose i_res_cnt, psol); 149673133261SJohn Soni Jose csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe_v2, 149773133261SJohn Soni Jose wrb_index, psol); 149873133261SJohn Soni Jose csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, 149973133261SJohn Soni Jose cid, psol); 150073133261SJohn Soni Jose csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, 150173133261SJohn Soni Jose hw_sts, psol); 1502702dc5e8SJayamohan Kallickal csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe_v2, 150373133261SJohn Soni Jose i_cmd_wnd, psol); 150473133261SJohn Soni Jose if (AMAP_GET_BITS(struct amap_sol_cqe_v2, 150573133261SJohn Soni Jose cmd_cmpl, psol)) 150673133261SJohn Soni Jose csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, 150773133261SJohn Soni Jose i_sts, psol); 150873133261SJohn Soni Jose else 150973133261SJohn Soni Jose csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe_v2, 151073133261SJohn Soni Jose i_sts, psol); 151173133261SJohn Soni Jose if (AMAP_GET_BITS(struct amap_sol_cqe_v2, 151273133261SJohn Soni Jose u, psol)) 151373133261SJohn Soni Jose csol_cqe->i_flags = ISCSI_FLAG_CMD_UNDERFLOW; 151473133261SJohn Soni Jose 151573133261SJohn Soni Jose if (AMAP_GET_BITS(struct amap_sol_cqe_v2, 151673133261SJohn Soni Jose o, psol)) 151773133261SJohn Soni Jose csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW; 151873133261SJohn Soni Jose } 151973133261SJohn Soni Jose } 152073133261SJohn Soni Jose 152173133261SJohn Soni Jose 15226733b39aSJayamohan Kallickal static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, 15236733b39aSJayamohan Kallickal struct beiscsi_hba *phba, struct sol_cqe *psol) 15246733b39aSJayamohan Kallickal { 15256733b39aSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 15266733b39aSJayamohan Kallickal struct wrb_handle *pwrb_handle; 15276733b39aSJayamohan Kallickal struct iscsi_wrb *pwrb = NULL; 15286733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 15296733b39aSJayamohan Kallickal struct iscsi_task *task; 1530bfead3b2SJayamohan Kallickal unsigned int type; 15316733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 15326733b39aSJayamohan Kallickal struct iscsi_session *session = conn->session; 153373133261SJohn Soni Jose struct common_sol_cqe csol_cqe = {0}; 1534a7909b39SJayamohan Kallickal uint16_t cri_index = 0; 15356733b39aSJayamohan Kallickal 15366733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 153773133261SJohn Soni Jose 153873133261SJohn Soni Jose /* Copy the elements to a common structure */ 153973133261SJohn Soni Jose adapter_get_sol_cqe(phba, psol, &csol_cqe); 154073133261SJohn Soni Jose 1541a7909b39SJayamohan Kallickal cri_index = BE_GET_CRI_FROM_CID(csol_cqe.cid); 1542a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 154373133261SJohn Soni Jose 154473133261SJohn Soni Jose pwrb_handle = pwrb_context->pwrb_handle_basestd[ 154573133261SJohn Soni Jose csol_cqe.wrb_index]; 154673133261SJohn Soni Jose 15476733b39aSJayamohan Kallickal task = pwrb_handle->pio_handle; 15486733b39aSJayamohan Kallickal pwrb = pwrb_handle->pwrb; 154973133261SJohn Soni Jose type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type; 155032951dd8SJayamohan Kallickal 1551659743b0SShlomo Pongratz spin_lock_bh(&session->back_lock); 1552bfead3b2SJayamohan Kallickal switch (type) { 15536733b39aSJayamohan Kallickal case HWH_TYPE_IO: 15546733b39aSJayamohan Kallickal case HWH_TYPE_IO_RD: 15556733b39aSJayamohan Kallickal if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == 1556dafab8e0SJayamohan Kallickal ISCSI_OP_NOOP_OUT) 155773133261SJohn Soni Jose be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe); 1558dafab8e0SJayamohan Kallickal else 155973133261SJohn Soni Jose be_complete_io(beiscsi_conn, task, &csol_cqe); 15606733b39aSJayamohan Kallickal break; 15616733b39aSJayamohan Kallickal 15626733b39aSJayamohan Kallickal case HWH_TYPE_LOGOUT: 1563dafab8e0SJayamohan Kallickal if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) 156473133261SJohn Soni Jose be_complete_logout(beiscsi_conn, task, &csol_cqe); 1565dafab8e0SJayamohan Kallickal else 156673133261SJohn Soni Jose be_complete_tmf(beiscsi_conn, task, &csol_cqe); 15676733b39aSJayamohan Kallickal break; 15686733b39aSJayamohan Kallickal 15696733b39aSJayamohan Kallickal case HWH_TYPE_LOGIN: 157099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 157199bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 157299bc5d55SJohn Soni Jose "BM_%d :\t\t No HWH_TYPE_LOGIN Expected in" 157399bc5d55SJohn Soni Jose " hwi_complete_cmd- Solicited path\n"); 15746733b39aSJayamohan Kallickal break; 15756733b39aSJayamohan Kallickal 15766733b39aSJayamohan Kallickal case HWH_TYPE_NOP: 157773133261SJohn Soni Jose be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe); 15786733b39aSJayamohan Kallickal break; 15796733b39aSJayamohan Kallickal 15806733b39aSJayamohan Kallickal default: 158199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, 158299bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 158399bc5d55SJohn Soni Jose "BM_%d : In hwi_complete_cmd, unknown type = %d" 1584bfead3b2SJayamohan Kallickal "wrb_index 0x%x CID 0x%x\n", type, 158573133261SJohn Soni Jose csol_cqe.wrb_index, 158673133261SJohn Soni Jose csol_cqe.cid); 15876733b39aSJayamohan Kallickal break; 15886733b39aSJayamohan Kallickal } 158935e66019SJayamohan Kallickal 1590659743b0SShlomo Pongratz spin_unlock_bh(&session->back_lock); 15916733b39aSJayamohan Kallickal } 15926733b39aSJayamohan Kallickal 15936733b39aSJayamohan Kallickal static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context 15946733b39aSJayamohan Kallickal *pasync_ctx, unsigned int is_header, 15956733b39aSJayamohan Kallickal unsigned int host_write_ptr) 15966733b39aSJayamohan Kallickal { 15976733b39aSJayamohan Kallickal if (is_header) 15986733b39aSJayamohan Kallickal return &pasync_ctx->async_entry[host_write_ptr]. 15996733b39aSJayamohan Kallickal header_busy_list; 16006733b39aSJayamohan Kallickal else 16016733b39aSJayamohan Kallickal return &pasync_ctx->async_entry[host_write_ptr].data_busy_list; 16026733b39aSJayamohan Kallickal } 16036733b39aSJayamohan Kallickal 16046733b39aSJayamohan Kallickal static struct async_pdu_handle * 16056733b39aSJayamohan Kallickal hwi_get_async_handle(struct beiscsi_hba *phba, 16066733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn, 16076733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx, 16086733b39aSJayamohan Kallickal struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index) 16096733b39aSJayamohan Kallickal { 16106733b39aSJayamohan Kallickal struct be_bus_address phys_addr; 16116733b39aSJayamohan Kallickal struct list_head *pbusy_list; 16126733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle = NULL; 16136733b39aSJayamohan Kallickal unsigned char is_header = 0; 161473133261SJohn Soni Jose unsigned int index, dpl; 161573133261SJohn Soni Jose 16162c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) { 161773133261SJohn Soni Jose dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, 161873133261SJohn Soni Jose dpl, pdpdu_cqe); 161973133261SJohn Soni Jose index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, 162073133261SJohn Soni Jose index, pdpdu_cqe); 16212c9dfd36SJayamohan Kallickal } else { 16222c9dfd36SJayamohan Kallickal dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, 16232c9dfd36SJayamohan Kallickal dpl, pdpdu_cqe); 16242c9dfd36SJayamohan Kallickal index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, 16252c9dfd36SJayamohan Kallickal index, pdpdu_cqe); 162673133261SJohn Soni Jose } 16276733b39aSJayamohan Kallickal 16286733b39aSJayamohan Kallickal phys_addr.u.a32.address_lo = 162973133261SJohn Soni Jose (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, 163073133261SJohn Soni Jose db_addr_lo) / 32] - dpl); 16316733b39aSJayamohan Kallickal phys_addr.u.a32.address_hi = 163273133261SJohn Soni Jose pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, 163373133261SJohn Soni Jose db_addr_hi) / 32]; 16346733b39aSJayamohan Kallickal 16356733b39aSJayamohan Kallickal phys_addr.u.a64.address = 16366733b39aSJayamohan Kallickal *((unsigned long long *)(&phys_addr.u.a64.address)); 16376733b39aSJayamohan Kallickal 16386733b39aSJayamohan Kallickal switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32] 16396733b39aSJayamohan Kallickal & PDUCQE_CODE_MASK) { 16406733b39aSJayamohan Kallickal case UNSOL_HDR_NOTIFY: 16416733b39aSJayamohan Kallickal is_header = 1; 16426733b39aSJayamohan Kallickal 164373133261SJohn Soni Jose pbusy_list = hwi_get_async_busy_list(pasync_ctx, 164473133261SJohn Soni Jose is_header, index); 16456733b39aSJayamohan Kallickal break; 16466733b39aSJayamohan Kallickal case UNSOL_DATA_NOTIFY: 164773133261SJohn Soni Jose pbusy_list = hwi_get_async_busy_list(pasync_ctx, 164873133261SJohn Soni Jose is_header, index); 16496733b39aSJayamohan Kallickal break; 16506733b39aSJayamohan Kallickal default: 16516733b39aSJayamohan Kallickal pbusy_list = NULL; 165299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, 165399bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 165499bc5d55SJohn Soni Jose "BM_%d : Unexpected code=%d\n", 16556733b39aSJayamohan Kallickal pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, 16566733b39aSJayamohan Kallickal code) / 32] & PDUCQE_CODE_MASK); 16576733b39aSJayamohan Kallickal return NULL; 16586733b39aSJayamohan Kallickal } 16596733b39aSJayamohan Kallickal 16606733b39aSJayamohan Kallickal WARN_ON(list_empty(pbusy_list)); 16616733b39aSJayamohan Kallickal list_for_each_entry(pasync_handle, pbusy_list, link) { 1662dc63aac6SJayamohan Kallickal if (pasync_handle->pa.u.a64.address == phys_addr.u.a64.address) 16636733b39aSJayamohan Kallickal break; 16646733b39aSJayamohan Kallickal } 16656733b39aSJayamohan Kallickal 16666733b39aSJayamohan Kallickal WARN_ON(!pasync_handle); 16676733b39aSJayamohan Kallickal 16688a86e833SJayamohan Kallickal pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID( 16698a86e833SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 16706733b39aSJayamohan Kallickal pasync_handle->is_header = is_header; 167173133261SJohn Soni Jose pasync_handle->buffer_len = dpl; 167273133261SJohn Soni Jose *pcq_index = index; 16736733b39aSJayamohan Kallickal 16746733b39aSJayamohan Kallickal return pasync_handle; 16756733b39aSJayamohan Kallickal } 16766733b39aSJayamohan Kallickal 16776733b39aSJayamohan Kallickal static unsigned int 167899bc5d55SJohn Soni Jose hwi_update_async_writables(struct beiscsi_hba *phba, 167999bc5d55SJohn Soni Jose struct hwi_async_pdu_context *pasync_ctx, 16806733b39aSJayamohan Kallickal unsigned int is_header, unsigned int cq_index) 16816733b39aSJayamohan Kallickal { 16826733b39aSJayamohan Kallickal struct list_head *pbusy_list; 16836733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle; 16846733b39aSJayamohan Kallickal unsigned int num_entries, writables = 0; 16856733b39aSJayamohan Kallickal unsigned int *pep_read_ptr, *pwritables; 16866733b39aSJayamohan Kallickal 1687dc63aac6SJayamohan Kallickal num_entries = pasync_ctx->num_entries; 16886733b39aSJayamohan Kallickal if (is_header) { 16896733b39aSJayamohan Kallickal pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr; 16906733b39aSJayamohan Kallickal pwritables = &pasync_ctx->async_header.writables; 16916733b39aSJayamohan Kallickal } else { 16926733b39aSJayamohan Kallickal pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr; 16936733b39aSJayamohan Kallickal pwritables = &pasync_ctx->async_data.writables; 16946733b39aSJayamohan Kallickal } 16956733b39aSJayamohan Kallickal 16966733b39aSJayamohan Kallickal while ((*pep_read_ptr) != cq_index) { 16976733b39aSJayamohan Kallickal (*pep_read_ptr)++; 16986733b39aSJayamohan Kallickal *pep_read_ptr = (*pep_read_ptr) % num_entries; 16996733b39aSJayamohan Kallickal 17006733b39aSJayamohan Kallickal pbusy_list = hwi_get_async_busy_list(pasync_ctx, is_header, 17016733b39aSJayamohan Kallickal *pep_read_ptr); 17026733b39aSJayamohan Kallickal if (writables == 0) 17036733b39aSJayamohan Kallickal WARN_ON(list_empty(pbusy_list)); 17046733b39aSJayamohan Kallickal 17056733b39aSJayamohan Kallickal if (!list_empty(pbusy_list)) { 17066733b39aSJayamohan Kallickal pasync_handle = list_entry(pbusy_list->next, 17076733b39aSJayamohan Kallickal struct async_pdu_handle, 17086733b39aSJayamohan Kallickal link); 17096733b39aSJayamohan Kallickal WARN_ON(!pasync_handle); 17106733b39aSJayamohan Kallickal pasync_handle->consumed = 1; 17116733b39aSJayamohan Kallickal } 17126733b39aSJayamohan Kallickal 17136733b39aSJayamohan Kallickal writables++; 17146733b39aSJayamohan Kallickal } 17156733b39aSJayamohan Kallickal 17166733b39aSJayamohan Kallickal if (!writables) { 171799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 171899bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 171999bc5d55SJohn Soni Jose "BM_%d : Duplicate notification received - index 0x%x!!\n", 17206733b39aSJayamohan Kallickal cq_index); 17216733b39aSJayamohan Kallickal WARN_ON(1); 17226733b39aSJayamohan Kallickal } 17236733b39aSJayamohan Kallickal 17246733b39aSJayamohan Kallickal *pwritables = *pwritables + writables; 17256733b39aSJayamohan Kallickal return 0; 17266733b39aSJayamohan Kallickal } 17276733b39aSJayamohan Kallickal 17289728d8d0SJayamohan Kallickal static void hwi_free_async_msg(struct beiscsi_hba *phba, 17298a86e833SJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx, 17306733b39aSJayamohan Kallickal unsigned int cri) 17316733b39aSJayamohan Kallickal { 17326733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle, *tmp_handle; 17336733b39aSJayamohan Kallickal struct list_head *plist; 17346733b39aSJayamohan Kallickal 17356733b39aSJayamohan Kallickal plist = &pasync_ctx->async_entry[cri].wait_queue.list; 17366733b39aSJayamohan Kallickal list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { 17376733b39aSJayamohan Kallickal list_del(&pasync_handle->link); 17386733b39aSJayamohan Kallickal 17399728d8d0SJayamohan Kallickal if (pasync_handle->is_header) { 17406733b39aSJayamohan Kallickal list_add_tail(&pasync_handle->link, 17416733b39aSJayamohan Kallickal &pasync_ctx->async_header.free_list); 17426733b39aSJayamohan Kallickal pasync_ctx->async_header.free_entries++; 17436733b39aSJayamohan Kallickal } else { 17446733b39aSJayamohan Kallickal list_add_tail(&pasync_handle->link, 17456733b39aSJayamohan Kallickal &pasync_ctx->async_data.free_list); 17466733b39aSJayamohan Kallickal pasync_ctx->async_data.free_entries++; 17476733b39aSJayamohan Kallickal } 17486733b39aSJayamohan Kallickal } 17496733b39aSJayamohan Kallickal 17506733b39aSJayamohan Kallickal INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list); 17516733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0; 17526733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; 17536733b39aSJayamohan Kallickal } 17546733b39aSJayamohan Kallickal 17556733b39aSJayamohan Kallickal static struct phys_addr * 17566733b39aSJayamohan Kallickal hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx, 17576733b39aSJayamohan Kallickal unsigned int is_header, unsigned int host_write_ptr) 17586733b39aSJayamohan Kallickal { 17596733b39aSJayamohan Kallickal struct phys_addr *pasync_sge = NULL; 17606733b39aSJayamohan Kallickal 17616733b39aSJayamohan Kallickal if (is_header) 17626733b39aSJayamohan Kallickal pasync_sge = pasync_ctx->async_header.ring_base; 17636733b39aSJayamohan Kallickal else 17646733b39aSJayamohan Kallickal pasync_sge = pasync_ctx->async_data.ring_base; 17656733b39aSJayamohan Kallickal 17666733b39aSJayamohan Kallickal return pasync_sge + host_write_ptr; 17676733b39aSJayamohan Kallickal } 17686733b39aSJayamohan Kallickal 17696733b39aSJayamohan Kallickal static void hwi_post_async_buffers(struct beiscsi_hba *phba, 17708a86e833SJayamohan Kallickal unsigned int is_header, uint8_t ulp_num) 17716733b39aSJayamohan Kallickal { 17726733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 17736733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 17746733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle; 17756733b39aSJayamohan Kallickal struct list_head *pfree_link, *pbusy_list; 17766733b39aSJayamohan Kallickal struct phys_addr *pasync_sge; 17776733b39aSJayamohan Kallickal unsigned int ring_id, num_entries; 17788a86e833SJayamohan Kallickal unsigned int host_write_num, doorbell_offset; 17796733b39aSJayamohan Kallickal unsigned int writables; 17806733b39aSJayamohan Kallickal unsigned int i = 0; 17816733b39aSJayamohan Kallickal u32 doorbell = 0; 17826733b39aSJayamohan Kallickal 17836733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 17848a86e833SJayamohan Kallickal pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); 1785dc63aac6SJayamohan Kallickal num_entries = pasync_ctx->num_entries; 17866733b39aSJayamohan Kallickal 17876733b39aSJayamohan Kallickal if (is_header) { 17886733b39aSJayamohan Kallickal writables = min(pasync_ctx->async_header.writables, 17896733b39aSJayamohan Kallickal pasync_ctx->async_header.free_entries); 17906733b39aSJayamohan Kallickal pfree_link = pasync_ctx->async_header.free_list.next; 17916733b39aSJayamohan Kallickal host_write_num = pasync_ctx->async_header.host_write_ptr; 17928a86e833SJayamohan Kallickal ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; 17938a86e833SJayamohan Kallickal doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. 17948a86e833SJayamohan Kallickal doorbell_offset; 17956733b39aSJayamohan Kallickal } else { 17966733b39aSJayamohan Kallickal writables = min(pasync_ctx->async_data.writables, 17976733b39aSJayamohan Kallickal pasync_ctx->async_data.free_entries); 17986733b39aSJayamohan Kallickal pfree_link = pasync_ctx->async_data.free_list.next; 17996733b39aSJayamohan Kallickal host_write_num = pasync_ctx->async_data.host_write_ptr; 18008a86e833SJayamohan Kallickal ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; 18018a86e833SJayamohan Kallickal doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num]. 18028a86e833SJayamohan Kallickal doorbell_offset; 18036733b39aSJayamohan Kallickal } 18046733b39aSJayamohan Kallickal 18056733b39aSJayamohan Kallickal writables = (writables / 8) * 8; 18066733b39aSJayamohan Kallickal if (writables) { 18076733b39aSJayamohan Kallickal for (i = 0; i < writables; i++) { 18086733b39aSJayamohan Kallickal pbusy_list = 18096733b39aSJayamohan Kallickal hwi_get_async_busy_list(pasync_ctx, is_header, 18106733b39aSJayamohan Kallickal host_write_num); 18116733b39aSJayamohan Kallickal pasync_handle = 18126733b39aSJayamohan Kallickal list_entry(pfree_link, struct async_pdu_handle, 18136733b39aSJayamohan Kallickal link); 18146733b39aSJayamohan Kallickal WARN_ON(!pasync_handle); 18156733b39aSJayamohan Kallickal pasync_handle->consumed = 0; 18166733b39aSJayamohan Kallickal 18176733b39aSJayamohan Kallickal pfree_link = pfree_link->next; 18186733b39aSJayamohan Kallickal 18196733b39aSJayamohan Kallickal pasync_sge = hwi_get_ring_address(pasync_ctx, 18206733b39aSJayamohan Kallickal is_header, host_write_num); 18216733b39aSJayamohan Kallickal 18226733b39aSJayamohan Kallickal pasync_sge->hi = pasync_handle->pa.u.a32.address_lo; 18236733b39aSJayamohan Kallickal pasync_sge->lo = pasync_handle->pa.u.a32.address_hi; 18246733b39aSJayamohan Kallickal 18256733b39aSJayamohan Kallickal list_move(&pasync_handle->link, pbusy_list); 18266733b39aSJayamohan Kallickal 18276733b39aSJayamohan Kallickal host_write_num++; 18286733b39aSJayamohan Kallickal host_write_num = host_write_num % num_entries; 18296733b39aSJayamohan Kallickal } 18306733b39aSJayamohan Kallickal 18316733b39aSJayamohan Kallickal if (is_header) { 18326733b39aSJayamohan Kallickal pasync_ctx->async_header.host_write_ptr = 18336733b39aSJayamohan Kallickal host_write_num; 18346733b39aSJayamohan Kallickal pasync_ctx->async_header.free_entries -= writables; 18356733b39aSJayamohan Kallickal pasync_ctx->async_header.writables -= writables; 18366733b39aSJayamohan Kallickal pasync_ctx->async_header.busy_entries += writables; 18376733b39aSJayamohan Kallickal } else { 18386733b39aSJayamohan Kallickal pasync_ctx->async_data.host_write_ptr = host_write_num; 18396733b39aSJayamohan Kallickal pasync_ctx->async_data.free_entries -= writables; 18406733b39aSJayamohan Kallickal pasync_ctx->async_data.writables -= writables; 18416733b39aSJayamohan Kallickal pasync_ctx->async_data.busy_entries += writables; 18426733b39aSJayamohan Kallickal } 18436733b39aSJayamohan Kallickal 18446733b39aSJayamohan Kallickal doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK; 18456733b39aSJayamohan Kallickal doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT; 18466733b39aSJayamohan Kallickal doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT; 18476733b39aSJayamohan Kallickal doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK) 18486733b39aSJayamohan Kallickal << DB_DEF_PDU_CQPROC_SHIFT; 18496733b39aSJayamohan Kallickal 18508a86e833SJayamohan Kallickal iowrite32(doorbell, phba->db_va + doorbell_offset); 18516733b39aSJayamohan Kallickal } 18526733b39aSJayamohan Kallickal } 18536733b39aSJayamohan Kallickal 18546733b39aSJayamohan Kallickal static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba, 18556733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn, 18566733b39aSJayamohan Kallickal struct i_t_dpdu_cqe *pdpdu_cqe) 18576733b39aSJayamohan Kallickal { 18586733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 18596733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 18606733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle = NULL; 18616733b39aSJayamohan Kallickal unsigned int cq_index = -1; 18628a86e833SJayamohan Kallickal uint16_t cri_index = BE_GET_CRI_FROM_CID( 18638a86e833SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 18646733b39aSJayamohan Kallickal 18656733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 18668a86e833SJayamohan Kallickal pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, 18678a86e833SJayamohan Kallickal BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, 18688a86e833SJayamohan Kallickal cri_index)); 18696733b39aSJayamohan Kallickal 18706733b39aSJayamohan Kallickal pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, 18716733b39aSJayamohan Kallickal pdpdu_cqe, &cq_index); 18726733b39aSJayamohan Kallickal BUG_ON(pasync_handle->is_header != 0); 18736733b39aSJayamohan Kallickal if (pasync_handle->consumed == 0) 187499bc5d55SJohn Soni Jose hwi_update_async_writables(phba, pasync_ctx, 187599bc5d55SJohn Soni Jose pasync_handle->is_header, cq_index); 18766733b39aSJayamohan Kallickal 18778a86e833SJayamohan Kallickal hwi_free_async_msg(phba, pasync_ctx, pasync_handle->cri); 18788a86e833SJayamohan Kallickal hwi_post_async_buffers(phba, pasync_handle->is_header, 18798a86e833SJayamohan Kallickal BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, 18808a86e833SJayamohan Kallickal cri_index)); 18816733b39aSJayamohan Kallickal } 18826733b39aSJayamohan Kallickal 18836733b39aSJayamohan Kallickal static unsigned int 18846733b39aSJayamohan Kallickal hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn, 18856733b39aSJayamohan Kallickal struct beiscsi_hba *phba, 18866733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx, unsigned short cri) 18876733b39aSJayamohan Kallickal { 18886733b39aSJayamohan Kallickal struct list_head *plist; 18896733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle; 18906733b39aSJayamohan Kallickal void *phdr = NULL; 18916733b39aSJayamohan Kallickal unsigned int hdr_len = 0, buf_len = 0; 18926733b39aSJayamohan Kallickal unsigned int status, index = 0, offset = 0; 18936733b39aSJayamohan Kallickal void *pfirst_buffer = NULL; 18946733b39aSJayamohan Kallickal unsigned int num_buf = 0; 18956733b39aSJayamohan Kallickal 18966733b39aSJayamohan Kallickal plist = &pasync_ctx->async_entry[cri].wait_queue.list; 18976733b39aSJayamohan Kallickal 18986733b39aSJayamohan Kallickal list_for_each_entry(pasync_handle, plist, link) { 18996733b39aSJayamohan Kallickal if (index == 0) { 19006733b39aSJayamohan Kallickal phdr = pasync_handle->pbuffer; 19016733b39aSJayamohan Kallickal hdr_len = pasync_handle->buffer_len; 19026733b39aSJayamohan Kallickal } else { 19036733b39aSJayamohan Kallickal buf_len = pasync_handle->buffer_len; 19046733b39aSJayamohan Kallickal if (!num_buf) { 19056733b39aSJayamohan Kallickal pfirst_buffer = pasync_handle->pbuffer; 19066733b39aSJayamohan Kallickal num_buf++; 19076733b39aSJayamohan Kallickal } 19086733b39aSJayamohan Kallickal memcpy(pfirst_buffer + offset, 19096733b39aSJayamohan Kallickal pasync_handle->pbuffer, buf_len); 1910f2ba02b8SJayamohan Kallickal offset += buf_len; 19116733b39aSJayamohan Kallickal } 19126733b39aSJayamohan Kallickal index++; 19136733b39aSJayamohan Kallickal } 19146733b39aSJayamohan Kallickal 19156733b39aSJayamohan Kallickal status = beiscsi_process_async_pdu(beiscsi_conn, phba, 19166733b39aSJayamohan Kallickal phdr, hdr_len, pfirst_buffer, 1917f2ba02b8SJayamohan Kallickal offset); 19186733b39aSJayamohan Kallickal 19198a86e833SJayamohan Kallickal hwi_free_async_msg(phba, pasync_ctx, cri); 19206733b39aSJayamohan Kallickal return 0; 19216733b39aSJayamohan Kallickal } 19226733b39aSJayamohan Kallickal 19236733b39aSJayamohan Kallickal static unsigned int 19246733b39aSJayamohan Kallickal hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn, 19256733b39aSJayamohan Kallickal struct beiscsi_hba *phba, 19266733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle) 19276733b39aSJayamohan Kallickal { 19286733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 19296733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 19306733b39aSJayamohan Kallickal unsigned int bytes_needed = 0, status = 0; 19316733b39aSJayamohan Kallickal unsigned short cri = pasync_handle->cri; 19326733b39aSJayamohan Kallickal struct pdu_base *ppdu; 19336733b39aSJayamohan Kallickal 19346733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 19358a86e833SJayamohan Kallickal pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, 19368a86e833SJayamohan Kallickal BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, 19378a86e833SJayamohan Kallickal BE_GET_CRI_FROM_CID(beiscsi_conn-> 19388a86e833SJayamohan Kallickal beiscsi_conn_cid))); 19396733b39aSJayamohan Kallickal 19406733b39aSJayamohan Kallickal list_del(&pasync_handle->link); 19416733b39aSJayamohan Kallickal if (pasync_handle->is_header) { 19426733b39aSJayamohan Kallickal pasync_ctx->async_header.busy_entries--; 19436733b39aSJayamohan Kallickal if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { 19448a86e833SJayamohan Kallickal hwi_free_async_msg(phba, pasync_ctx, cri); 19456733b39aSJayamohan Kallickal BUG(); 19466733b39aSJayamohan Kallickal } 19476733b39aSJayamohan Kallickal 19486733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; 19496733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue.hdr_received = 1; 19506733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue.hdr_len = 19516733b39aSJayamohan Kallickal (unsigned short)pasync_handle->buffer_len; 19526733b39aSJayamohan Kallickal list_add_tail(&pasync_handle->link, 19536733b39aSJayamohan Kallickal &pasync_ctx->async_entry[cri].wait_queue.list); 19546733b39aSJayamohan Kallickal 19556733b39aSJayamohan Kallickal ppdu = pasync_handle->pbuffer; 19566733b39aSJayamohan Kallickal bytes_needed = ((((ppdu->dw[offsetof(struct amap_pdu_base, 19576733b39aSJayamohan Kallickal data_len_hi) / 32] & PDUBASE_DATALENHI_MASK) << 8) & 19586733b39aSJayamohan Kallickal 0xFFFF0000) | ((be16_to_cpu((ppdu-> 19596733b39aSJayamohan Kallickal dw[offsetof(struct amap_pdu_base, data_len_lo) / 32] 19606733b39aSJayamohan Kallickal & PDUBASE_DATALENLO_MASK) >> 16)) & 0x0000FFFF)); 19616733b39aSJayamohan Kallickal 19626733b39aSJayamohan Kallickal if (status == 0) { 19636733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue.bytes_needed = 19646733b39aSJayamohan Kallickal bytes_needed; 19656733b39aSJayamohan Kallickal 19666733b39aSJayamohan Kallickal if (bytes_needed == 0) 19676733b39aSJayamohan Kallickal status = hwi_fwd_async_msg(beiscsi_conn, phba, 19686733b39aSJayamohan Kallickal pasync_ctx, cri); 19696733b39aSJayamohan Kallickal } 19706733b39aSJayamohan Kallickal } else { 19716733b39aSJayamohan Kallickal pasync_ctx->async_data.busy_entries--; 19726733b39aSJayamohan Kallickal if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { 19736733b39aSJayamohan Kallickal list_add_tail(&pasync_handle->link, 19746733b39aSJayamohan Kallickal &pasync_ctx->async_entry[cri].wait_queue. 19756733b39aSJayamohan Kallickal list); 19766733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue. 19776733b39aSJayamohan Kallickal bytes_received += 19786733b39aSJayamohan Kallickal (unsigned short)pasync_handle->buffer_len; 19796733b39aSJayamohan Kallickal 19806733b39aSJayamohan Kallickal if (pasync_ctx->async_entry[cri].wait_queue. 19816733b39aSJayamohan Kallickal bytes_received >= 19826733b39aSJayamohan Kallickal pasync_ctx->async_entry[cri].wait_queue. 19836733b39aSJayamohan Kallickal bytes_needed) 19846733b39aSJayamohan Kallickal status = hwi_fwd_async_msg(beiscsi_conn, phba, 19856733b39aSJayamohan Kallickal pasync_ctx, cri); 19866733b39aSJayamohan Kallickal } 19876733b39aSJayamohan Kallickal } 19886733b39aSJayamohan Kallickal return status; 19896733b39aSJayamohan Kallickal } 19906733b39aSJayamohan Kallickal 19916733b39aSJayamohan Kallickal static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, 19926733b39aSJayamohan Kallickal struct beiscsi_hba *phba, 19936733b39aSJayamohan Kallickal struct i_t_dpdu_cqe *pdpdu_cqe) 19946733b39aSJayamohan Kallickal { 19956733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 19966733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 19976733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_handle = NULL; 19986733b39aSJayamohan Kallickal unsigned int cq_index = -1; 19998a86e833SJayamohan Kallickal uint16_t cri_index = BE_GET_CRI_FROM_CID( 20008a86e833SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 20016733b39aSJayamohan Kallickal 20026733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 20038a86e833SJayamohan Kallickal pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, 20048a86e833SJayamohan Kallickal BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, 20058a86e833SJayamohan Kallickal cri_index)); 20068a86e833SJayamohan Kallickal 20076733b39aSJayamohan Kallickal pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, 20086733b39aSJayamohan Kallickal pdpdu_cqe, &cq_index); 20096733b39aSJayamohan Kallickal 20106733b39aSJayamohan Kallickal if (pasync_handle->consumed == 0) 201199bc5d55SJohn Soni Jose hwi_update_async_writables(phba, pasync_ctx, 201299bc5d55SJohn Soni Jose pasync_handle->is_header, cq_index); 201399bc5d55SJohn Soni Jose 20146733b39aSJayamohan Kallickal hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); 20158a86e833SJayamohan Kallickal hwi_post_async_buffers(phba, pasync_handle->is_header, 20168a86e833SJayamohan Kallickal BEISCSI_GET_ULP_FROM_CRI( 20178a86e833SJayamohan Kallickal phwi_ctrlr, cri_index)); 20186733b39aSJayamohan Kallickal } 20196733b39aSJayamohan Kallickal 2020756d29c8SJayamohan Kallickal static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) 2021756d29c8SJayamohan Kallickal { 2022756d29c8SJayamohan Kallickal struct be_queue_info *mcc_cq; 2023756d29c8SJayamohan Kallickal struct be_mcc_compl *mcc_compl; 2024756d29c8SJayamohan Kallickal unsigned int num_processed = 0; 2025756d29c8SJayamohan Kallickal 2026756d29c8SJayamohan Kallickal mcc_cq = &phba->ctrl.mcc_obj.cq; 2027756d29c8SJayamohan Kallickal mcc_compl = queue_tail_node(mcc_cq); 2028756d29c8SJayamohan Kallickal mcc_compl->flags = le32_to_cpu(mcc_compl->flags); 2029756d29c8SJayamohan Kallickal while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) { 2030756d29c8SJayamohan Kallickal 2031756d29c8SJayamohan Kallickal if (num_processed >= 32) { 2032756d29c8SJayamohan Kallickal hwi_ring_cq_db(phba, mcc_cq->id, 2033756d29c8SJayamohan Kallickal num_processed, 0, 0); 2034756d29c8SJayamohan Kallickal num_processed = 0; 2035756d29c8SJayamohan Kallickal } 2036756d29c8SJayamohan Kallickal if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { 2037756d29c8SJayamohan Kallickal /* Interpret flags as an async trailer */ 2038756d29c8SJayamohan Kallickal if (is_link_state_evt(mcc_compl->flags)) 2039756d29c8SJayamohan Kallickal /* Interpret compl as a async link evt */ 2040756d29c8SJayamohan Kallickal beiscsi_async_link_state_process(phba, 2041756d29c8SJayamohan Kallickal (struct be_async_event_link_state *) mcc_compl); 2042756d29c8SJayamohan Kallickal else 204399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX, 204499bc5d55SJohn Soni Jose "BM_%d : Unsupported Async Event, flags" 204599bc5d55SJohn Soni Jose " = 0x%08x\n", 204699bc5d55SJohn Soni Jose mcc_compl->flags); 2047756d29c8SJayamohan Kallickal } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) { 2048756d29c8SJayamohan Kallickal be_mcc_compl_process_isr(&phba->ctrl, mcc_compl); 2049756d29c8SJayamohan Kallickal atomic_dec(&phba->ctrl.mcc_obj.q.used); 2050756d29c8SJayamohan Kallickal } 2051756d29c8SJayamohan Kallickal 2052756d29c8SJayamohan Kallickal mcc_compl->flags = 0; 2053756d29c8SJayamohan Kallickal queue_tail_inc(mcc_cq); 2054756d29c8SJayamohan Kallickal mcc_compl = queue_tail_node(mcc_cq); 2055756d29c8SJayamohan Kallickal mcc_compl->flags = le32_to_cpu(mcc_compl->flags); 2056756d29c8SJayamohan Kallickal num_processed++; 2057756d29c8SJayamohan Kallickal } 2058756d29c8SJayamohan Kallickal 2059756d29c8SJayamohan Kallickal if (num_processed > 0) 2060756d29c8SJayamohan Kallickal hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); 2061756d29c8SJayamohan Kallickal 2062756d29c8SJayamohan Kallickal } 2063bfead3b2SJayamohan Kallickal 20646763daaeSJohn Soni Jose /** 20656763daaeSJohn Soni Jose * beiscsi_process_cq()- Process the Completion Queue 20666763daaeSJohn Soni Jose * @pbe_eq: Event Q on which the Completion has come 20676763daaeSJohn Soni Jose * 20686763daaeSJohn Soni Jose * return 20696763daaeSJohn Soni Jose * Number of Completion Entries processed. 20706763daaeSJohn Soni Jose **/ 2071bfead3b2SJayamohan Kallickal static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) 20726733b39aSJayamohan Kallickal { 20736733b39aSJayamohan Kallickal struct be_queue_info *cq; 20746733b39aSJayamohan Kallickal struct sol_cqe *sol; 20756733b39aSJayamohan Kallickal struct dmsg_cqe *dmsg; 20766733b39aSJayamohan Kallickal unsigned int num_processed = 0; 20776733b39aSJayamohan Kallickal unsigned int tot_nump = 0; 20780a513dd8SJohn Soni Jose unsigned short code = 0, cid = 0; 2079a7909b39SJayamohan Kallickal uint16_t cri_index = 0; 20806733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn; 2081c2462288SJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep; 2082c2462288SJayamohan Kallickal struct iscsi_endpoint *ep; 2083bfead3b2SJayamohan Kallickal struct beiscsi_hba *phba; 20846733b39aSJayamohan Kallickal 2085bfead3b2SJayamohan Kallickal cq = pbe_eq->cq; 20866733b39aSJayamohan Kallickal sol = queue_tail_node(cq); 2087bfead3b2SJayamohan Kallickal phba = pbe_eq->phba; 20886733b39aSJayamohan Kallickal 20896733b39aSJayamohan Kallickal while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & 20906733b39aSJayamohan Kallickal CQE_VALID_MASK) { 20916733b39aSJayamohan Kallickal be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); 20926733b39aSJayamohan Kallickal 209373133261SJohn Soni Jose code = (sol->dw[offsetof(struct amap_sol_cqe, code) / 209473133261SJohn Soni Jose 32] & CQE_CODE_MASK); 209532951dd8SJayamohan Kallickal 209673133261SJohn Soni Jose /* Get the CID */ 20972c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) { 20982c9dfd36SJayamohan Kallickal cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol); 20992c9dfd36SJayamohan Kallickal } else { 210073133261SJohn Soni Jose if ((code == DRIVERMSG_NOTIFY) || 210173133261SJohn Soni Jose (code == UNSOL_HDR_NOTIFY) || 210273133261SJohn Soni Jose (code == UNSOL_DATA_NOTIFY)) 210373133261SJohn Soni Jose cid = AMAP_GET_BITS( 210473133261SJohn Soni Jose struct amap_i_t_dpdu_cqe_v2, 210573133261SJohn Soni Jose cid, sol); 210673133261SJohn Soni Jose else 210773133261SJohn Soni Jose cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, 210873133261SJohn Soni Jose cid, sol); 21092c9dfd36SJayamohan Kallickal } 211073133261SJohn Soni Jose 2111a7909b39SJayamohan Kallickal cri_index = BE_GET_CRI_FROM_CID(cid); 2112a7909b39SJayamohan Kallickal ep = phba->ep_array[cri_index]; 2113c2462288SJayamohan Kallickal beiscsi_ep = ep->dd_data; 2114c2462288SJayamohan Kallickal beiscsi_conn = beiscsi_ep->conn; 2115756d29c8SJayamohan Kallickal 21166733b39aSJayamohan Kallickal if (num_processed >= 32) { 2117bfead3b2SJayamohan Kallickal hwi_ring_cq_db(phba, cq->id, 21186733b39aSJayamohan Kallickal num_processed, 0, 0); 21196733b39aSJayamohan Kallickal tot_nump += num_processed; 21206733b39aSJayamohan Kallickal num_processed = 0; 21216733b39aSJayamohan Kallickal } 21226733b39aSJayamohan Kallickal 21230a513dd8SJohn Soni Jose switch (code) { 21246733b39aSJayamohan Kallickal case SOL_CMD_COMPLETE: 21256733b39aSJayamohan Kallickal hwi_complete_cmd(beiscsi_conn, phba, sol); 21266733b39aSJayamohan Kallickal break; 21276733b39aSJayamohan Kallickal case DRIVERMSG_NOTIFY: 212899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, 212999bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 21306763daaeSJohn Soni Jose "BM_%d : Received %s[%d] on CID : %d\n", 21316763daaeSJohn Soni Jose cqe_desc[code], code, cid); 213299bc5d55SJohn Soni Jose 21336733b39aSJayamohan Kallickal dmsg = (struct dmsg_cqe *)sol; 21346733b39aSJayamohan Kallickal hwi_complete_drvr_msgs(beiscsi_conn, phba, sol); 21356733b39aSJayamohan Kallickal break; 21366733b39aSJayamohan Kallickal case UNSOL_HDR_NOTIFY: 213799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, 213899bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 21396763daaeSJohn Soni Jose "BM_%d : Received %s[%d] on CID : %d\n", 21406763daaeSJohn Soni Jose cqe_desc[code], code, cid); 214199bc5d55SJohn Soni Jose 21428f09a3b9SJayamohan Kallickal spin_lock_bh(&phba->async_pdu_lock); 2143bfead3b2SJayamohan Kallickal hwi_process_default_pdu_ring(beiscsi_conn, phba, 2144bfead3b2SJayamohan Kallickal (struct i_t_dpdu_cqe *)sol); 21458f09a3b9SJayamohan Kallickal spin_unlock_bh(&phba->async_pdu_lock); 2146bfead3b2SJayamohan Kallickal break; 21476733b39aSJayamohan Kallickal case UNSOL_DATA_NOTIFY: 214899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, 214999bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 21506763daaeSJohn Soni Jose "BM_%d : Received %s[%d] on CID : %d\n", 21516763daaeSJohn Soni Jose cqe_desc[code], code, cid); 215299bc5d55SJohn Soni Jose 21538f09a3b9SJayamohan Kallickal spin_lock_bh(&phba->async_pdu_lock); 21546733b39aSJayamohan Kallickal hwi_process_default_pdu_ring(beiscsi_conn, phba, 21556733b39aSJayamohan Kallickal (struct i_t_dpdu_cqe *)sol); 21568f09a3b9SJayamohan Kallickal spin_unlock_bh(&phba->async_pdu_lock); 21576733b39aSJayamohan Kallickal break; 21586733b39aSJayamohan Kallickal case CXN_INVALIDATE_INDEX_NOTIFY: 21596733b39aSJayamohan Kallickal case CMD_INVALIDATED_NOTIFY: 21606733b39aSJayamohan Kallickal case CXN_INVALIDATE_NOTIFY: 216199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 216299bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 21636763daaeSJohn Soni Jose "BM_%d : Ignoring %s[%d] on CID : %d\n", 21646763daaeSJohn Soni Jose cqe_desc[code], code, cid); 21656733b39aSJayamohan Kallickal break; 21666733b39aSJayamohan Kallickal case SOL_CMD_KILLED_DATA_DIGEST_ERR: 21676733b39aSJayamohan Kallickal case CMD_KILLED_INVALID_STATSN_RCVD: 21686733b39aSJayamohan Kallickal case CMD_KILLED_INVALID_R2T_RCVD: 21696733b39aSJayamohan Kallickal case CMD_CXN_KILLED_LUN_INVALID: 21706733b39aSJayamohan Kallickal case CMD_CXN_KILLED_ICD_INVALID: 21716733b39aSJayamohan Kallickal case CMD_CXN_KILLED_ITT_INVALID: 21726733b39aSJayamohan Kallickal case CMD_CXN_KILLED_SEQ_OUTOFORDER: 21736733b39aSJayamohan Kallickal case CMD_CXN_KILLED_INVALID_DATASN_RCVD: 217499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 217599bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 21766763daaeSJohn Soni Jose "BM_%d : Cmd Notification %s[%d] on CID : %d\n", 21776763daaeSJohn Soni Jose cqe_desc[code], code, cid); 21786733b39aSJayamohan Kallickal break; 21796733b39aSJayamohan Kallickal case UNSOL_DATA_DIGEST_ERROR_NOTIFY: 218099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 218199bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 21826763daaeSJohn Soni Jose "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", 21836763daaeSJohn Soni Jose cqe_desc[code], code, cid); 21848f09a3b9SJayamohan Kallickal spin_lock_bh(&phba->async_pdu_lock); 21856733b39aSJayamohan Kallickal hwi_flush_default_pdu_buffer(phba, beiscsi_conn, 21866733b39aSJayamohan Kallickal (struct i_t_dpdu_cqe *) sol); 21878f09a3b9SJayamohan Kallickal spin_unlock_bh(&phba->async_pdu_lock); 21886733b39aSJayamohan Kallickal break; 21896733b39aSJayamohan Kallickal case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: 21906733b39aSJayamohan Kallickal case CXN_KILLED_BURST_LEN_MISMATCH: 21916733b39aSJayamohan Kallickal case CXN_KILLED_AHS_RCVD: 21926733b39aSJayamohan Kallickal case CXN_KILLED_HDR_DIGEST_ERR: 21936733b39aSJayamohan Kallickal case CXN_KILLED_UNKNOWN_HDR: 21946733b39aSJayamohan Kallickal case CXN_KILLED_STALE_ITT_TTT_RCVD: 21956733b39aSJayamohan Kallickal case CXN_KILLED_INVALID_ITT_TTT_RCVD: 21966733b39aSJayamohan Kallickal case CXN_KILLED_TIMED_OUT: 21976733b39aSJayamohan Kallickal case CXN_KILLED_FIN_RCVD: 21986763daaeSJohn Soni Jose case CXN_KILLED_RST_SENT: 21996763daaeSJohn Soni Jose case CXN_KILLED_RST_RCVD: 22006733b39aSJayamohan Kallickal case CXN_KILLED_BAD_UNSOL_PDU_RCVD: 22016733b39aSJayamohan Kallickal case CXN_KILLED_BAD_WRB_INDEX_ERROR: 22026733b39aSJayamohan Kallickal case CXN_KILLED_OVER_RUN_RESIDUAL: 22036733b39aSJayamohan Kallickal case CXN_KILLED_UNDER_RUN_RESIDUAL: 22046733b39aSJayamohan Kallickal case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN: 220599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 220699bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 22076763daaeSJohn Soni Jose "BM_%d : Event %s[%d] received on CID : %d\n", 22086763daaeSJohn Soni Jose cqe_desc[code], code, cid); 22090a513dd8SJohn Soni Jose if (beiscsi_conn) 22106733b39aSJayamohan Kallickal iscsi_conn_failure(beiscsi_conn->conn, 22116733b39aSJayamohan Kallickal ISCSI_ERR_CONN_FAILED); 22126733b39aSJayamohan Kallickal break; 22136733b39aSJayamohan Kallickal default: 221499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 221599bc5d55SJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 22166763daaeSJohn Soni Jose "BM_%d : Invalid CQE Event Received Code : %d" 22176763daaeSJohn Soni Jose "CID 0x%x...\n", 22180a513dd8SJohn Soni Jose code, cid); 22196733b39aSJayamohan Kallickal break; 22206733b39aSJayamohan Kallickal } 22216733b39aSJayamohan Kallickal 22226733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_sol_cqe, valid, sol, 0); 22236733b39aSJayamohan Kallickal queue_tail_inc(cq); 22246733b39aSJayamohan Kallickal sol = queue_tail_node(cq); 22256733b39aSJayamohan Kallickal num_processed++; 22266733b39aSJayamohan Kallickal } 22276733b39aSJayamohan Kallickal 22286733b39aSJayamohan Kallickal if (num_processed > 0) { 22296733b39aSJayamohan Kallickal tot_nump += num_processed; 2230bfead3b2SJayamohan Kallickal hwi_ring_cq_db(phba, cq->id, num_processed, 1, 0); 22316733b39aSJayamohan Kallickal } 22326733b39aSJayamohan Kallickal return tot_nump; 22336733b39aSJayamohan Kallickal } 22346733b39aSJayamohan Kallickal 2235756d29c8SJayamohan Kallickal void beiscsi_process_all_cqs(struct work_struct *work) 22366733b39aSJayamohan Kallickal { 22376733b39aSJayamohan Kallickal unsigned long flags; 2238bfead3b2SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 2239bfead3b2SJayamohan Kallickal struct hwi_context_memory *phwi_context; 224072fb46a9SJohn Soni Jose struct beiscsi_hba *phba; 224172fb46a9SJohn Soni Jose struct be_eq_obj *pbe_eq = 224272fb46a9SJohn Soni Jose container_of(work, struct be_eq_obj, work_cqs); 22436733b39aSJayamohan Kallickal 224472fb46a9SJohn Soni Jose phba = pbe_eq->phba; 2245bfead3b2SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 2246bfead3b2SJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 2247bfead3b2SJayamohan Kallickal 224872fb46a9SJohn Soni Jose if (pbe_eq->todo_mcc_cq) { 22496733b39aSJayamohan Kallickal spin_lock_irqsave(&phba->isr_lock, flags); 225072fb46a9SJohn Soni Jose pbe_eq->todo_mcc_cq = false; 22516733b39aSJayamohan Kallickal spin_unlock_irqrestore(&phba->isr_lock, flags); 2252756d29c8SJayamohan Kallickal beiscsi_process_mcc_isr(phba); 22536733b39aSJayamohan Kallickal } 22546733b39aSJayamohan Kallickal 225572fb46a9SJohn Soni Jose if (pbe_eq->todo_cq) { 22566733b39aSJayamohan Kallickal spin_lock_irqsave(&phba->isr_lock, flags); 225772fb46a9SJohn Soni Jose pbe_eq->todo_cq = false; 22586733b39aSJayamohan Kallickal spin_unlock_irqrestore(&phba->isr_lock, flags); 2259bfead3b2SJayamohan Kallickal beiscsi_process_cq(pbe_eq); 22606733b39aSJayamohan Kallickal } 226172fb46a9SJohn Soni Jose 226272fb46a9SJohn Soni Jose /* rearm EQ for further interrupts */ 226372fb46a9SJohn Soni Jose hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); 22646733b39aSJayamohan Kallickal } 22656733b39aSJayamohan Kallickal 22666733b39aSJayamohan Kallickal static int be_iopoll(struct blk_iopoll *iop, int budget) 22676733b39aSJayamohan Kallickal { 2268ad3f428eSShlomo Pongratz unsigned int ret; 22696733b39aSJayamohan Kallickal struct beiscsi_hba *phba; 2270bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 22716733b39aSJayamohan Kallickal 2272bfead3b2SJayamohan Kallickal pbe_eq = container_of(iop, struct be_eq_obj, iopoll); 2273bfead3b2SJayamohan Kallickal ret = beiscsi_process_cq(pbe_eq); 227473af08e1SJayamohan Kallickal pbe_eq->cq_count += ret; 22756733b39aSJayamohan Kallickal if (ret < budget) { 2276bfead3b2SJayamohan Kallickal phba = pbe_eq->phba; 22776733b39aSJayamohan Kallickal blk_iopoll_complete(iop); 227899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, 227999bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, 228099bc5d55SJohn Soni Jose "BM_%d : rearm pbe_eq->q.id =%d\n", 228199bc5d55SJohn Soni Jose pbe_eq->q.id); 2282bfead3b2SJayamohan Kallickal hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); 22836733b39aSJayamohan Kallickal } 22846733b39aSJayamohan Kallickal return ret; 22856733b39aSJayamohan Kallickal } 22866733b39aSJayamohan Kallickal 22876733b39aSJayamohan Kallickal static void 228809a1093aSJohn Soni Jose hwi_write_sgl_v2(struct iscsi_wrb *pwrb, struct scatterlist *sg, 228909a1093aSJohn Soni Jose unsigned int num_sg, struct beiscsi_io_task *io_task) 229009a1093aSJohn Soni Jose { 229109a1093aSJohn Soni Jose struct iscsi_sge *psgl; 229209a1093aSJohn Soni Jose unsigned int sg_len, index; 229309a1093aSJohn Soni Jose unsigned int sge_len = 0; 229409a1093aSJohn Soni Jose unsigned long long addr; 229509a1093aSJohn Soni Jose struct scatterlist *l_sg; 229609a1093aSJohn Soni Jose unsigned int offset; 229709a1093aSJohn Soni Jose 229809a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_lo, pwrb, 229909a1093aSJohn Soni Jose io_task->bhs_pa.u.a32.address_lo); 230009a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_hi, pwrb, 230109a1093aSJohn Soni Jose io_task->bhs_pa.u.a32.address_hi); 230209a1093aSJohn Soni Jose 230309a1093aSJohn Soni Jose l_sg = sg; 230409a1093aSJohn Soni Jose for (index = 0; (index < num_sg) && (index < 2); index++, 230509a1093aSJohn Soni Jose sg = sg_next(sg)) { 230609a1093aSJohn Soni Jose if (index == 0) { 230709a1093aSJohn Soni Jose sg_len = sg_dma_len(sg); 230809a1093aSJohn Soni Jose addr = (u64) sg_dma_address(sg); 230909a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 231009a1093aSJohn Soni Jose sge0_addr_lo, pwrb, 231109a1093aSJohn Soni Jose lower_32_bits(addr)); 231209a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 231309a1093aSJohn Soni Jose sge0_addr_hi, pwrb, 231409a1093aSJohn Soni Jose upper_32_bits(addr)); 231509a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 231609a1093aSJohn Soni Jose sge0_len, pwrb, 231709a1093aSJohn Soni Jose sg_len); 231809a1093aSJohn Soni Jose sge_len = sg_len; 231909a1093aSJohn Soni Jose } else { 232009a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_r2t_offset, 232109a1093aSJohn Soni Jose pwrb, sge_len); 232209a1093aSJohn Soni Jose sg_len = sg_dma_len(sg); 232309a1093aSJohn Soni Jose addr = (u64) sg_dma_address(sg); 232409a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 232509a1093aSJohn Soni Jose sge1_addr_lo, pwrb, 232609a1093aSJohn Soni Jose lower_32_bits(addr)); 232709a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 232809a1093aSJohn Soni Jose sge1_addr_hi, pwrb, 232909a1093aSJohn Soni Jose upper_32_bits(addr)); 233009a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 233109a1093aSJohn Soni Jose sge1_len, pwrb, 233209a1093aSJohn Soni Jose sg_len); 233309a1093aSJohn Soni Jose } 233409a1093aSJohn Soni Jose } 233509a1093aSJohn Soni Jose psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; 233609a1093aSJohn Soni Jose memset(psgl, 0, sizeof(*psgl) * BE2_SGE); 233709a1093aSJohn Soni Jose 233809a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2); 233909a1093aSJohn Soni Jose 234009a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 234109a1093aSJohn Soni Jose io_task->bhs_pa.u.a32.address_hi); 234209a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 234309a1093aSJohn Soni Jose io_task->bhs_pa.u.a32.address_lo); 234409a1093aSJohn Soni Jose 234509a1093aSJohn Soni Jose if (num_sg == 1) { 234609a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, 234709a1093aSJohn Soni Jose 1); 234809a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, 234909a1093aSJohn Soni Jose 0); 235009a1093aSJohn Soni Jose } else if (num_sg == 2) { 235109a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, 235209a1093aSJohn Soni Jose 0); 235309a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, 235409a1093aSJohn Soni Jose 1); 235509a1093aSJohn Soni Jose } else { 235609a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, 235709a1093aSJohn Soni Jose 0); 235809a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, 235909a1093aSJohn Soni Jose 0); 236009a1093aSJohn Soni Jose } 236109a1093aSJohn Soni Jose 236209a1093aSJohn Soni Jose sg = l_sg; 236309a1093aSJohn Soni Jose psgl++; 236409a1093aSJohn Soni Jose psgl++; 236509a1093aSJohn Soni Jose offset = 0; 236609a1093aSJohn Soni Jose for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) { 236709a1093aSJohn Soni Jose sg_len = sg_dma_len(sg); 236809a1093aSJohn Soni Jose addr = (u64) sg_dma_address(sg); 236909a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 237009a1093aSJohn Soni Jose lower_32_bits(addr)); 237109a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 237209a1093aSJohn Soni Jose upper_32_bits(addr)); 237309a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len); 237409a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset); 237509a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); 237609a1093aSJohn Soni Jose offset += sg_len; 237709a1093aSJohn Soni Jose } 237809a1093aSJohn Soni Jose psgl--; 237909a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); 238009a1093aSJohn Soni Jose } 238109a1093aSJohn Soni Jose 238209a1093aSJohn Soni Jose static void 23836733b39aSJayamohan Kallickal hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, 23846733b39aSJayamohan Kallickal unsigned int num_sg, struct beiscsi_io_task *io_task) 23856733b39aSJayamohan Kallickal { 23866733b39aSJayamohan Kallickal struct iscsi_sge *psgl; 238758ff4bd0SJayamohan Kallickal unsigned int sg_len, index; 23886733b39aSJayamohan Kallickal unsigned int sge_len = 0; 23896733b39aSJayamohan Kallickal unsigned long long addr; 23906733b39aSJayamohan Kallickal struct scatterlist *l_sg; 23916733b39aSJayamohan Kallickal unsigned int offset; 23926733b39aSJayamohan Kallickal 23936733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb, 23946733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_lo); 23956733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb, 23966733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_hi); 23976733b39aSJayamohan Kallickal 23986733b39aSJayamohan Kallickal l_sg = sg; 239948bd86cfSJayamohan Kallickal for (index = 0; (index < num_sg) && (index < 2); index++, 240048bd86cfSJayamohan Kallickal sg = sg_next(sg)) { 24016733b39aSJayamohan Kallickal if (index == 0) { 24026733b39aSJayamohan Kallickal sg_len = sg_dma_len(sg); 24036733b39aSJayamohan Kallickal addr = (u64) sg_dma_address(sg); 24046733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, 2405457ff3b7SJayamohan Kallickal ((u32)(addr & 0xFFFFFFFF))); 24066733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, 2407457ff3b7SJayamohan Kallickal ((u32)(addr >> 32))); 24086733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, 24096733b39aSJayamohan Kallickal sg_len); 24106733b39aSJayamohan Kallickal sge_len = sg_len; 24116733b39aSJayamohan Kallickal } else { 24126733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset, 24136733b39aSJayamohan Kallickal pwrb, sge_len); 24146733b39aSJayamohan Kallickal sg_len = sg_dma_len(sg); 24156733b39aSJayamohan Kallickal addr = (u64) sg_dma_address(sg); 24166733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb, 2417457ff3b7SJayamohan Kallickal ((u32)(addr & 0xFFFFFFFF))); 24186733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb, 2419457ff3b7SJayamohan Kallickal ((u32)(addr >> 32))); 24206733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb, 24216733b39aSJayamohan Kallickal sg_len); 24226733b39aSJayamohan Kallickal } 24236733b39aSJayamohan Kallickal } 24246733b39aSJayamohan Kallickal psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; 24256733b39aSJayamohan Kallickal memset(psgl, 0, sizeof(*psgl) * BE2_SGE); 24266733b39aSJayamohan Kallickal 24276733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2); 24286733b39aSJayamohan Kallickal 24296733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 24306733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_hi); 24316733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 24326733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_lo); 24336733b39aSJayamohan Kallickal 2434caf818f1SJayamohan Kallickal if (num_sg == 1) { 2435caf818f1SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 2436caf818f1SJayamohan Kallickal 1); 2437caf818f1SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 2438caf818f1SJayamohan Kallickal 0); 2439caf818f1SJayamohan Kallickal } else if (num_sg == 2) { 2440caf818f1SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 2441caf818f1SJayamohan Kallickal 0); 2442caf818f1SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 2443caf818f1SJayamohan Kallickal 1); 2444caf818f1SJayamohan Kallickal } else { 2445caf818f1SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 2446caf818f1SJayamohan Kallickal 0); 2447caf818f1SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 2448caf818f1SJayamohan Kallickal 0); 2449caf818f1SJayamohan Kallickal } 24506733b39aSJayamohan Kallickal sg = l_sg; 24516733b39aSJayamohan Kallickal psgl++; 24526733b39aSJayamohan Kallickal psgl++; 24536733b39aSJayamohan Kallickal offset = 0; 245448bd86cfSJayamohan Kallickal for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) { 24556733b39aSJayamohan Kallickal sg_len = sg_dma_len(sg); 24566733b39aSJayamohan Kallickal addr = (u64) sg_dma_address(sg); 24576733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 24586733b39aSJayamohan Kallickal (addr & 0xFFFFFFFF)); 24596733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 24606733b39aSJayamohan Kallickal (addr >> 32)); 24616733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len); 24626733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset); 24636733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); 24646733b39aSJayamohan Kallickal offset += sg_len; 24656733b39aSJayamohan Kallickal } 24666733b39aSJayamohan Kallickal psgl--; 24676733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); 24686733b39aSJayamohan Kallickal } 24696733b39aSJayamohan Kallickal 2470d629c471SJohn Soni Jose /** 2471d629c471SJohn Soni Jose * hwi_write_buffer()- Populate the WRB with task info 2472d629c471SJohn Soni Jose * @pwrb: ptr to the WRB entry 2473d629c471SJohn Soni Jose * @task: iscsi task which is to be executed 2474d629c471SJohn Soni Jose **/ 24756733b39aSJayamohan Kallickal static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) 24766733b39aSJayamohan Kallickal { 24776733b39aSJayamohan Kallickal struct iscsi_sge *psgl; 24786733b39aSJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 24796733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn = io_task->conn; 24806733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_conn->phba; 248109a1093aSJohn Soni Jose uint8_t dsp_value = 0; 24826733b39aSJayamohan Kallickal 24836733b39aSJayamohan Kallickal io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2; 24846733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb, 24856733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_lo); 24866733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb, 24876733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_hi); 24886733b39aSJayamohan Kallickal 24896733b39aSJayamohan Kallickal if (task->data) { 249009a1093aSJohn Soni Jose 249109a1093aSJohn Soni Jose /* Check for the data_count */ 249209a1093aSJohn Soni Jose dsp_value = (task->data_count) ? 1 : 0; 249309a1093aSJohn Soni Jose 24942c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) 24952c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, 249609a1093aSJohn Soni Jose pwrb, dsp_value); 249709a1093aSJohn Soni Jose else 24982c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, 249909a1093aSJohn Soni Jose pwrb, dsp_value); 250009a1093aSJohn Soni Jose 250109a1093aSJohn Soni Jose /* Map addr only if there is data_count */ 250209a1093aSJohn Soni Jose if (dsp_value) { 2503d629c471SJohn Soni Jose io_task->mtask_addr = pci_map_single(phba->pcidev, 25046733b39aSJayamohan Kallickal task->data, 2505d629c471SJohn Soni Jose task->data_count, 2506d629c471SJohn Soni Jose PCI_DMA_TODEVICE); 2507d629c471SJohn Soni Jose io_task->mtask_data_count = task->data_count; 250809a1093aSJohn Soni Jose } else 2509d629c471SJohn Soni Jose io_task->mtask_addr = 0; 251009a1093aSJohn Soni Jose 25116733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, 2512d629c471SJohn Soni Jose lower_32_bits(io_task->mtask_addr)); 25136733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, 2514d629c471SJohn Soni Jose upper_32_bits(io_task->mtask_addr)); 25156733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, 25166733b39aSJayamohan Kallickal task->data_count); 25176733b39aSJayamohan Kallickal 25186733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1); 25196733b39aSJayamohan Kallickal } else { 25206733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); 2521d629c471SJohn Soni Jose io_task->mtask_addr = 0; 25226733b39aSJayamohan Kallickal } 25236733b39aSJayamohan Kallickal 25246733b39aSJayamohan Kallickal psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; 25256733b39aSJayamohan Kallickal 25266733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len); 25276733b39aSJayamohan Kallickal 25286733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 25296733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_hi); 25306733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 25316733b39aSJayamohan Kallickal io_task->bhs_pa.u.a32.address_lo); 25326733b39aSJayamohan Kallickal if (task->data) { 25336733b39aSJayamohan Kallickal psgl++; 25346733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 0); 25356733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 0); 25366733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0); 25376733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, 0); 25386733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, rsvd0, psgl, 0); 25396733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); 25406733b39aSJayamohan Kallickal 25416733b39aSJayamohan Kallickal psgl++; 25426733b39aSJayamohan Kallickal if (task->data) { 25436733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 2544d629c471SJohn Soni Jose lower_32_bits(io_task->mtask_addr)); 25456733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 2546d629c471SJohn Soni Jose upper_32_bits(io_task->mtask_addr)); 25476733b39aSJayamohan Kallickal } 25486733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106); 25496733b39aSJayamohan Kallickal } 25506733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); 25516733b39aSJayamohan Kallickal } 25526733b39aSJayamohan Kallickal 2553843ae752SJayamohan Kallickal /** 2554843ae752SJayamohan Kallickal * beiscsi_find_mem_req()- Find mem needed 2555843ae752SJayamohan Kallickal * @phba: ptr to HBA struct 2556843ae752SJayamohan Kallickal **/ 25576733b39aSJayamohan Kallickal static void beiscsi_find_mem_req(struct beiscsi_hba *phba) 25586733b39aSJayamohan Kallickal { 25598a86e833SJayamohan Kallickal uint8_t mem_descr_index, ulp_num; 2560bfead3b2SJayamohan Kallickal unsigned int num_cq_pages, num_async_pdu_buf_pages; 25616733b39aSJayamohan Kallickal unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; 25626733b39aSJayamohan Kallickal unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; 25636733b39aSJayamohan Kallickal 25646733b39aSJayamohan Kallickal num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ 25656733b39aSJayamohan Kallickal sizeof(struct sol_cqe)); 25666733b39aSJayamohan Kallickal 25676733b39aSJayamohan Kallickal phba->params.hwi_ws_sz = sizeof(struct hwi_controller); 25686733b39aSJayamohan Kallickal 25696733b39aSJayamohan Kallickal phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 * 25706733b39aSJayamohan Kallickal BE_ISCSI_PDU_HEADER_SIZE; 25716733b39aSJayamohan Kallickal phba->mem_req[HWI_MEM_ADDN_CONTEXT] = 25726733b39aSJayamohan Kallickal sizeof(struct hwi_context_memory); 25736733b39aSJayamohan Kallickal 25746733b39aSJayamohan Kallickal 25756733b39aSJayamohan Kallickal phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb) 25766733b39aSJayamohan Kallickal * (phba->params.wrbs_per_cxn) 25776733b39aSJayamohan Kallickal * phba->params.cxns_per_ctrl; 25786733b39aSJayamohan Kallickal wrb_sz_per_cxn = sizeof(struct wrb_handle) * 25796733b39aSJayamohan Kallickal (phba->params.wrbs_per_cxn); 25806733b39aSJayamohan Kallickal phba->mem_req[HWI_MEM_WRBH] = roundup_pow_of_two((wrb_sz_per_cxn) * 25816733b39aSJayamohan Kallickal phba->params.cxns_per_ctrl); 25826733b39aSJayamohan Kallickal 25836733b39aSJayamohan Kallickal phba->mem_req[HWI_MEM_SGLH] = sizeof(struct sgl_handle) * 25846733b39aSJayamohan Kallickal phba->params.icds_per_ctrl; 25856733b39aSJayamohan Kallickal phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) * 25866733b39aSJayamohan Kallickal phba->params.num_sge_per_io * phba->params.icds_per_ctrl; 25878a86e833SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 25888a86e833SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 25896733b39aSJayamohan Kallickal 25908a86e833SJayamohan Kallickal num_async_pdu_buf_sgl_pages = 25918a86e833SJayamohan Kallickal PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( 25928a86e833SJayamohan Kallickal phba, ulp_num) * 25938a86e833SJayamohan Kallickal sizeof(struct phys_addr)); 25948a86e833SJayamohan Kallickal 25958a86e833SJayamohan Kallickal num_async_pdu_buf_pages = 25968a86e833SJayamohan Kallickal PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( 25978a86e833SJayamohan Kallickal phba, ulp_num) * 25988a86e833SJayamohan Kallickal phba->params.defpdu_hdr_sz); 25998a86e833SJayamohan Kallickal 26008a86e833SJayamohan Kallickal num_async_pdu_data_pages = 26018a86e833SJayamohan Kallickal PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( 26028a86e833SJayamohan Kallickal phba, ulp_num) * 26038a86e833SJayamohan Kallickal phba->params.defpdu_data_sz); 26048a86e833SJayamohan Kallickal 26058a86e833SJayamohan Kallickal num_async_pdu_data_sgl_pages = 26068a86e833SJayamohan Kallickal PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( 26078a86e833SJayamohan Kallickal phba, ulp_num) * 26088a86e833SJayamohan Kallickal sizeof(struct phys_addr)); 26098a86e833SJayamohan Kallickal 2610a129d92fSJayamohan Kallickal mem_descr_index = (HWI_MEM_TEMPLATE_HDR_ULP0 + 2611a129d92fSJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 2612a129d92fSJayamohan Kallickal phba->mem_req[mem_descr_index] = 2613a129d92fSJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, ulp_num) * 2614a129d92fSJayamohan Kallickal BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE; 2615a129d92fSJayamohan Kallickal 26168a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_HEADER_BUF_ULP0 + 26178a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26188a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26198a86e833SJayamohan Kallickal num_async_pdu_buf_pages * 26208a86e833SJayamohan Kallickal PAGE_SIZE; 26218a86e833SJayamohan Kallickal 26228a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_DATA_BUF_ULP0 + 26238a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26248a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26258a86e833SJayamohan Kallickal num_async_pdu_data_pages * 26268a86e833SJayamohan Kallickal PAGE_SIZE; 26278a86e833SJayamohan Kallickal 26288a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_HEADER_RING_ULP0 + 26298a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26308a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26318a86e833SJayamohan Kallickal num_async_pdu_buf_sgl_pages * 26328a86e833SJayamohan Kallickal PAGE_SIZE; 26338a86e833SJayamohan Kallickal 26348a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_DATA_RING_ULP0 + 26358a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26368a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26378a86e833SJayamohan Kallickal num_async_pdu_data_sgl_pages * 26388a86e833SJayamohan Kallickal PAGE_SIZE; 26398a86e833SJayamohan Kallickal 26408a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + 26418a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26428a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26438a86e833SJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, ulp_num) * 26446733b39aSJayamohan Kallickal sizeof(struct async_pdu_handle); 26458a86e833SJayamohan Kallickal 26468a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + 26478a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26488a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26498a86e833SJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, ulp_num) * 26506733b39aSJayamohan Kallickal sizeof(struct async_pdu_handle); 26518a86e833SJayamohan Kallickal 26528a86e833SJayamohan Kallickal mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + 26538a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 26548a86e833SJayamohan Kallickal phba->mem_req[mem_descr_index] = 26556733b39aSJayamohan Kallickal sizeof(struct hwi_async_pdu_context) + 26568a86e833SJayamohan Kallickal (BEISCSI_GET_CID_COUNT(phba, ulp_num) * 26578a86e833SJayamohan Kallickal sizeof(struct hwi_async_entry)); 26588a86e833SJayamohan Kallickal } 26598a86e833SJayamohan Kallickal } 26606733b39aSJayamohan Kallickal } 26616733b39aSJayamohan Kallickal 26626733b39aSJayamohan Kallickal static int beiscsi_alloc_mem(struct beiscsi_hba *phba) 26636733b39aSJayamohan Kallickal { 26646733b39aSJayamohan Kallickal dma_addr_t bus_add; 2665a7909b39SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 2666a7909b39SJayamohan Kallickal struct be_mem_descriptor *mem_descr; 26676733b39aSJayamohan Kallickal struct mem_array *mem_arr, *mem_arr_orig; 26686733b39aSJayamohan Kallickal unsigned int i, j, alloc_size, curr_alloc_size; 26696733b39aSJayamohan Kallickal 26703ec78271SJayamohan Kallickal phba->phwi_ctrlr = kzalloc(phba->params.hwi_ws_sz, GFP_KERNEL); 26716733b39aSJayamohan Kallickal if (!phba->phwi_ctrlr) 26726733b39aSJayamohan Kallickal return -ENOMEM; 26736733b39aSJayamohan Kallickal 2674a7909b39SJayamohan Kallickal /* Allocate memory for wrb_context */ 2675a7909b39SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 2676a7909b39SJayamohan Kallickal phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) * 2677a7909b39SJayamohan Kallickal phba->params.cxns_per_ctrl, 2678a7909b39SJayamohan Kallickal GFP_KERNEL); 2679a7909b39SJayamohan Kallickal if (!phwi_ctrlr->wrb_context) 2680a7909b39SJayamohan Kallickal return -ENOMEM; 2681a7909b39SJayamohan Kallickal 26826733b39aSJayamohan Kallickal phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr), 26836733b39aSJayamohan Kallickal GFP_KERNEL); 26846733b39aSJayamohan Kallickal if (!phba->init_mem) { 2685a7909b39SJayamohan Kallickal kfree(phwi_ctrlr->wrb_context); 26866733b39aSJayamohan Kallickal kfree(phba->phwi_ctrlr); 26876733b39aSJayamohan Kallickal return -ENOMEM; 26886733b39aSJayamohan Kallickal } 26896733b39aSJayamohan Kallickal 26906733b39aSJayamohan Kallickal mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT, 26916733b39aSJayamohan Kallickal GFP_KERNEL); 26926733b39aSJayamohan Kallickal if (!mem_arr_orig) { 26936733b39aSJayamohan Kallickal kfree(phba->init_mem); 2694a7909b39SJayamohan Kallickal kfree(phwi_ctrlr->wrb_context); 26956733b39aSJayamohan Kallickal kfree(phba->phwi_ctrlr); 26966733b39aSJayamohan Kallickal return -ENOMEM; 26976733b39aSJayamohan Kallickal } 26986733b39aSJayamohan Kallickal 26996733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 27006733b39aSJayamohan Kallickal for (i = 0; i < SE_MEM_MAX; i++) { 27018a86e833SJayamohan Kallickal if (!phba->mem_req[i]) { 27028a86e833SJayamohan Kallickal mem_descr->mem_array = NULL; 27038a86e833SJayamohan Kallickal mem_descr++; 27048a86e833SJayamohan Kallickal continue; 27058a86e833SJayamohan Kallickal } 27068a86e833SJayamohan Kallickal 27076733b39aSJayamohan Kallickal j = 0; 27086733b39aSJayamohan Kallickal mem_arr = mem_arr_orig; 27096733b39aSJayamohan Kallickal alloc_size = phba->mem_req[i]; 27106733b39aSJayamohan Kallickal memset(mem_arr, 0, sizeof(struct mem_array) * 27116733b39aSJayamohan Kallickal BEISCSI_MAX_FRAGS_INIT); 27126733b39aSJayamohan Kallickal curr_alloc_size = min(be_max_phys_size * 1024, alloc_size); 27136733b39aSJayamohan Kallickal do { 27146733b39aSJayamohan Kallickal mem_arr->virtual_address = pci_alloc_consistent( 27156733b39aSJayamohan Kallickal phba->pcidev, 27166733b39aSJayamohan Kallickal curr_alloc_size, 27176733b39aSJayamohan Kallickal &bus_add); 27186733b39aSJayamohan Kallickal if (!mem_arr->virtual_address) { 27196733b39aSJayamohan Kallickal if (curr_alloc_size <= BE_MIN_MEM_SIZE) 27206733b39aSJayamohan Kallickal goto free_mem; 27216733b39aSJayamohan Kallickal if (curr_alloc_size - 27226733b39aSJayamohan Kallickal rounddown_pow_of_two(curr_alloc_size)) 27236733b39aSJayamohan Kallickal curr_alloc_size = rounddown_pow_of_two 27246733b39aSJayamohan Kallickal (curr_alloc_size); 27256733b39aSJayamohan Kallickal else 27266733b39aSJayamohan Kallickal curr_alloc_size = curr_alloc_size / 2; 27276733b39aSJayamohan Kallickal } else { 27286733b39aSJayamohan Kallickal mem_arr->bus_address.u. 27296733b39aSJayamohan Kallickal a64.address = (__u64) bus_add; 27306733b39aSJayamohan Kallickal mem_arr->size = curr_alloc_size; 27316733b39aSJayamohan Kallickal alloc_size -= curr_alloc_size; 27326733b39aSJayamohan Kallickal curr_alloc_size = min(be_max_phys_size * 27336733b39aSJayamohan Kallickal 1024, alloc_size); 27346733b39aSJayamohan Kallickal j++; 27356733b39aSJayamohan Kallickal mem_arr++; 27366733b39aSJayamohan Kallickal } 27376733b39aSJayamohan Kallickal } while (alloc_size); 27386733b39aSJayamohan Kallickal mem_descr->num_elements = j; 27396733b39aSJayamohan Kallickal mem_descr->size_in_bytes = phba->mem_req[i]; 27406733b39aSJayamohan Kallickal mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j, 27416733b39aSJayamohan Kallickal GFP_KERNEL); 27426733b39aSJayamohan Kallickal if (!mem_descr->mem_array) 27436733b39aSJayamohan Kallickal goto free_mem; 27446733b39aSJayamohan Kallickal 27456733b39aSJayamohan Kallickal memcpy(mem_descr->mem_array, mem_arr_orig, 27466733b39aSJayamohan Kallickal sizeof(struct mem_array) * j); 27476733b39aSJayamohan Kallickal mem_descr++; 27486733b39aSJayamohan Kallickal } 27496733b39aSJayamohan Kallickal kfree(mem_arr_orig); 27506733b39aSJayamohan Kallickal return 0; 27516733b39aSJayamohan Kallickal free_mem: 27526733b39aSJayamohan Kallickal mem_descr->num_elements = j; 27536733b39aSJayamohan Kallickal while ((i) || (j)) { 27546733b39aSJayamohan Kallickal for (j = mem_descr->num_elements; j > 0; j--) { 27556733b39aSJayamohan Kallickal pci_free_consistent(phba->pcidev, 27566733b39aSJayamohan Kallickal mem_descr->mem_array[j - 1].size, 27576733b39aSJayamohan Kallickal mem_descr->mem_array[j - 1]. 27586733b39aSJayamohan Kallickal virtual_address, 2759457ff3b7SJayamohan Kallickal (unsigned long)mem_descr-> 2760457ff3b7SJayamohan Kallickal mem_array[j - 1]. 27616733b39aSJayamohan Kallickal bus_address.u.a64.address); 27626733b39aSJayamohan Kallickal } 27636733b39aSJayamohan Kallickal if (i) { 27646733b39aSJayamohan Kallickal i--; 27656733b39aSJayamohan Kallickal kfree(mem_descr->mem_array); 27666733b39aSJayamohan Kallickal mem_descr--; 27676733b39aSJayamohan Kallickal } 27686733b39aSJayamohan Kallickal } 27696733b39aSJayamohan Kallickal kfree(mem_arr_orig); 27706733b39aSJayamohan Kallickal kfree(phba->init_mem); 2771a7909b39SJayamohan Kallickal kfree(phba->phwi_ctrlr->wrb_context); 27726733b39aSJayamohan Kallickal kfree(phba->phwi_ctrlr); 27736733b39aSJayamohan Kallickal return -ENOMEM; 27746733b39aSJayamohan Kallickal } 27756733b39aSJayamohan Kallickal 27766733b39aSJayamohan Kallickal static int beiscsi_get_memory(struct beiscsi_hba *phba) 27776733b39aSJayamohan Kallickal { 27786733b39aSJayamohan Kallickal beiscsi_find_mem_req(phba); 27796733b39aSJayamohan Kallickal return beiscsi_alloc_mem(phba); 27806733b39aSJayamohan Kallickal } 27816733b39aSJayamohan Kallickal 27826733b39aSJayamohan Kallickal static void iscsi_init_global_templates(struct beiscsi_hba *phba) 27836733b39aSJayamohan Kallickal { 27846733b39aSJayamohan Kallickal struct pdu_data_out *pdata_out; 27856733b39aSJayamohan Kallickal struct pdu_nop_out *pnop_out; 27866733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 27876733b39aSJayamohan Kallickal 27886733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 27896733b39aSJayamohan Kallickal mem_descr += ISCSI_MEM_GLOBAL_HEADER; 27906733b39aSJayamohan Kallickal pdata_out = 27916733b39aSJayamohan Kallickal (struct pdu_data_out *)mem_descr->mem_array[0].virtual_address; 27926733b39aSJayamohan Kallickal memset(pdata_out, 0, BE_ISCSI_PDU_HEADER_SIZE); 27936733b39aSJayamohan Kallickal 27946733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_pdu_data_out, opcode, pdata_out, 27956733b39aSJayamohan Kallickal IIOC_SCSI_DATA); 27966733b39aSJayamohan Kallickal 27976733b39aSJayamohan Kallickal pnop_out = 27986733b39aSJayamohan Kallickal (struct pdu_nop_out *)((unsigned char *)mem_descr->mem_array[0]. 27996733b39aSJayamohan Kallickal virtual_address + BE_ISCSI_PDU_HEADER_SIZE); 28006733b39aSJayamohan Kallickal 28016733b39aSJayamohan Kallickal memset(pnop_out, 0, BE_ISCSI_PDU_HEADER_SIZE); 28026733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_pdu_nop_out, ttt, pnop_out, 0xFFFFFFFF); 28036733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_pdu_nop_out, f_bit, pnop_out, 1); 28046733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0); 28056733b39aSJayamohan Kallickal } 28066733b39aSJayamohan Kallickal 28073ec78271SJayamohan Kallickal static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) 28086733b39aSJayamohan Kallickal { 28096733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb; 2810a7909b39SJayamohan Kallickal struct hwi_context_memory *phwi_ctxt; 28113ec78271SJayamohan Kallickal struct wrb_handle *pwrb_handle = NULL; 28126733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 28136733b39aSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 28143ec78271SJayamohan Kallickal struct iscsi_wrb *pwrb = NULL; 28153ec78271SJayamohan Kallickal unsigned int num_cxn_wrbh = 0; 28163ec78271SJayamohan Kallickal unsigned int num_cxn_wrb = 0, j, idx = 0, index; 28176733b39aSJayamohan Kallickal 28186733b39aSJayamohan Kallickal mem_descr_wrbh = phba->init_mem; 28196733b39aSJayamohan Kallickal mem_descr_wrbh += HWI_MEM_WRBH; 28206733b39aSJayamohan Kallickal 28216733b39aSJayamohan Kallickal mem_descr_wrb = phba->init_mem; 28226733b39aSJayamohan Kallickal mem_descr_wrb += HWI_MEM_WRB; 28236733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 28246733b39aSJayamohan Kallickal 2825a7909b39SJayamohan Kallickal /* Allocate memory for WRBQ */ 2826a7909b39SJayamohan Kallickal phwi_ctxt = phwi_ctrlr->phwi_ctxt; 2827a7909b39SJayamohan Kallickal phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) * 2828843ae752SJayamohan Kallickal phba->params.cxns_per_ctrl, 2829a7909b39SJayamohan Kallickal GFP_KERNEL); 2830a7909b39SJayamohan Kallickal if (!phwi_ctxt->be_wrbq) { 2831a7909b39SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 2832a7909b39SJayamohan Kallickal "BM_%d : WRBQ Mem Alloc Failed\n"); 2833a7909b39SJayamohan Kallickal return -ENOMEM; 2834a7909b39SJayamohan Kallickal } 2835a7909b39SJayamohan Kallickal 2836a7909b39SJayamohan Kallickal for (index = 0; index < phba->params.cxns_per_ctrl; index++) { 28376733b39aSJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[index]; 28386733b39aSJayamohan Kallickal pwrb_context->pwrb_handle_base = 28396733b39aSJayamohan Kallickal kzalloc(sizeof(struct wrb_handle *) * 28406733b39aSJayamohan Kallickal phba->params.wrbs_per_cxn, GFP_KERNEL); 28413ec78271SJayamohan Kallickal if (!pwrb_context->pwrb_handle_base) { 284299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 284399bc5d55SJohn Soni Jose "BM_%d : Mem Alloc Failed. Failing to load\n"); 28443ec78271SJayamohan Kallickal goto init_wrb_hndl_failed; 28453ec78271SJayamohan Kallickal } 28466733b39aSJayamohan Kallickal pwrb_context->pwrb_handle_basestd = 28476733b39aSJayamohan Kallickal kzalloc(sizeof(struct wrb_handle *) * 28486733b39aSJayamohan Kallickal phba->params.wrbs_per_cxn, GFP_KERNEL); 28493ec78271SJayamohan Kallickal if (!pwrb_context->pwrb_handle_basestd) { 285099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 285199bc5d55SJohn Soni Jose "BM_%d : Mem Alloc Failed. Failing to load\n"); 28523ec78271SJayamohan Kallickal goto init_wrb_hndl_failed; 28536733b39aSJayamohan Kallickal } 28543ec78271SJayamohan Kallickal if (!num_cxn_wrbh) { 28556733b39aSJayamohan Kallickal pwrb_handle = 28566733b39aSJayamohan Kallickal mem_descr_wrbh->mem_array[idx].virtual_address; 28573ec78271SJayamohan Kallickal num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) / 28586733b39aSJayamohan Kallickal ((sizeof(struct wrb_handle)) * 28596733b39aSJayamohan Kallickal phba->params.wrbs_per_cxn)); 28603ec78271SJayamohan Kallickal idx++; 28613ec78271SJayamohan Kallickal } 28626733b39aSJayamohan Kallickal pwrb_context->alloc_index = 0; 28633ec78271SJayamohan Kallickal pwrb_context->wrb_handles_available = 0; 28643ec78271SJayamohan Kallickal pwrb_context->free_index = 0; 28653ec78271SJayamohan Kallickal 28663ec78271SJayamohan Kallickal if (num_cxn_wrbh) { 28676733b39aSJayamohan Kallickal for (j = 0; j < phba->params.wrbs_per_cxn; j++) { 28686733b39aSJayamohan Kallickal pwrb_context->pwrb_handle_base[j] = pwrb_handle; 28696733b39aSJayamohan Kallickal pwrb_context->pwrb_handle_basestd[j] = 28706733b39aSJayamohan Kallickal pwrb_handle; 28716733b39aSJayamohan Kallickal pwrb_context->wrb_handles_available++; 2872bfead3b2SJayamohan Kallickal pwrb_handle->wrb_index = j; 28736733b39aSJayamohan Kallickal pwrb_handle++; 28746733b39aSJayamohan Kallickal } 28756733b39aSJayamohan Kallickal num_cxn_wrbh--; 28766733b39aSJayamohan Kallickal } 28776733b39aSJayamohan Kallickal } 28786733b39aSJayamohan Kallickal idx = 0; 2879a7909b39SJayamohan Kallickal for (index = 0; index < phba->params.cxns_per_ctrl; index++) { 28803ec78271SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[index]; 28813ec78271SJayamohan Kallickal if (!num_cxn_wrb) { 28826733b39aSJayamohan Kallickal pwrb = mem_descr_wrb->mem_array[idx].virtual_address; 28837c56533cSJayamohan Kallickal num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / 28847c56533cSJayamohan Kallickal ((sizeof(struct iscsi_wrb) * 28857c56533cSJayamohan Kallickal phba->params.wrbs_per_cxn)); 28863ec78271SJayamohan Kallickal idx++; 28873ec78271SJayamohan Kallickal } 28883ec78271SJayamohan Kallickal 28896733b39aSJayamohan Kallickal if (num_cxn_wrb) { 28906733b39aSJayamohan Kallickal for (j = 0; j < phba->params.wrbs_per_cxn; j++) { 28916733b39aSJayamohan Kallickal pwrb_handle = pwrb_context->pwrb_handle_base[j]; 28926733b39aSJayamohan Kallickal pwrb_handle->pwrb = pwrb; 28936733b39aSJayamohan Kallickal pwrb++; 28946733b39aSJayamohan Kallickal } 28956733b39aSJayamohan Kallickal num_cxn_wrb--; 28966733b39aSJayamohan Kallickal } 28976733b39aSJayamohan Kallickal } 28983ec78271SJayamohan Kallickal return 0; 28993ec78271SJayamohan Kallickal init_wrb_hndl_failed: 29003ec78271SJayamohan Kallickal for (j = index; j > 0; j--) { 29013ec78271SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[j]; 29023ec78271SJayamohan Kallickal kfree(pwrb_context->pwrb_handle_base); 29033ec78271SJayamohan Kallickal kfree(pwrb_context->pwrb_handle_basestd); 29043ec78271SJayamohan Kallickal } 29053ec78271SJayamohan Kallickal return -ENOMEM; 29066733b39aSJayamohan Kallickal } 29076733b39aSJayamohan Kallickal 2908a7909b39SJayamohan Kallickal static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) 29096733b39aSJayamohan Kallickal { 29108a86e833SJayamohan Kallickal uint8_t ulp_num; 29116733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 29126733b39aSJayamohan Kallickal struct hba_parameters *p = &phba->params; 29136733b39aSJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 29146733b39aSJayamohan Kallickal struct async_pdu_handle *pasync_header_h, *pasync_data_h; 2915dc63aac6SJayamohan Kallickal unsigned int index, idx, num_per_mem, num_async_data; 29166733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 29176733b39aSJayamohan Kallickal 29188a86e833SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 29198a86e833SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 29208a86e833SJayamohan Kallickal 29216733b39aSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 29228a86e833SJayamohan Kallickal mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + 29238a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET)); 29246733b39aSJayamohan Kallickal 29256733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 29268a86e833SJayamohan Kallickal phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num] = 29278a86e833SJayamohan Kallickal (struct hwi_async_pdu_context *) 29286733b39aSJayamohan Kallickal mem_descr->mem_array[0].virtual_address; 29298a86e833SJayamohan Kallickal 29308a86e833SJayamohan Kallickal pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; 29316733b39aSJayamohan Kallickal memset(pasync_ctx, 0, sizeof(*pasync_ctx)); 29326733b39aSJayamohan Kallickal 29338a86e833SJayamohan Kallickal pasync_ctx->async_entry = 29348a86e833SJayamohan Kallickal (struct hwi_async_entry *) 29358a86e833SJayamohan Kallickal ((long unsigned int)pasync_ctx + 29368a86e833SJayamohan Kallickal sizeof(struct hwi_async_pdu_context)); 2937a7909b39SJayamohan Kallickal 29388a86e833SJayamohan Kallickal pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, 29398a86e833SJayamohan Kallickal ulp_num); 2940dc63aac6SJayamohan Kallickal pasync_ctx->buffer_size = p->defpdu_hdr_sz; 29416733b39aSJayamohan Kallickal 29426733b39aSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 29438a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_HEADER_BUF_ULP0 + 29448a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 29456733b39aSJayamohan Kallickal if (mem_descr->mem_array[0].virtual_address) { 294699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 294799bc5d55SJohn Soni Jose "BM_%d : hwi_init_async_pdu_ctx" 29488a86e833SJayamohan Kallickal " HWI_MEM_ASYNC_HEADER_BUF_ULP%d va=%p\n", 29498a86e833SJayamohan Kallickal ulp_num, 29508a86e833SJayamohan Kallickal mem_descr->mem_array[0]. 29518a86e833SJayamohan Kallickal virtual_address); 29526733b39aSJayamohan Kallickal } else 29538a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 29548a86e833SJayamohan Kallickal BEISCSI_LOG_INIT, 29558a86e833SJayamohan Kallickal "BM_%d : No Virtual address for ULP : %d\n", 29568a86e833SJayamohan Kallickal ulp_num); 29576733b39aSJayamohan Kallickal 29586733b39aSJayamohan Kallickal pasync_ctx->async_header.va_base = 29596733b39aSJayamohan Kallickal mem_descr->mem_array[0].virtual_address; 29606733b39aSJayamohan Kallickal 29616733b39aSJayamohan Kallickal pasync_ctx->async_header.pa_base.u.a64.address = 29628a86e833SJayamohan Kallickal mem_descr->mem_array[0]. 29638a86e833SJayamohan Kallickal bus_address.u.a64.address; 29646733b39aSJayamohan Kallickal 29656733b39aSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 29668a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + 29678a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 29686733b39aSJayamohan Kallickal if (mem_descr->mem_array[0].virtual_address) { 296999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 297099bc5d55SJohn Soni Jose "BM_%d : hwi_init_async_pdu_ctx" 29718a86e833SJayamohan Kallickal " HWI_MEM_ASYNC_HEADER_RING_ULP%d va=%p\n", 29728a86e833SJayamohan Kallickal ulp_num, 29738a86e833SJayamohan Kallickal mem_descr->mem_array[0]. 29748a86e833SJayamohan Kallickal virtual_address); 29756733b39aSJayamohan Kallickal } else 29768a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 29778a86e833SJayamohan Kallickal BEISCSI_LOG_INIT, 29788a86e833SJayamohan Kallickal "BM_%d : No Virtual address for ULP : %d\n", 29798a86e833SJayamohan Kallickal ulp_num); 298099bc5d55SJohn Soni Jose 29816733b39aSJayamohan Kallickal pasync_ctx->async_header.ring_base = 29826733b39aSJayamohan Kallickal mem_descr->mem_array[0].virtual_address; 29836733b39aSJayamohan Kallickal 29846733b39aSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 29858a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + 29868a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 29876733b39aSJayamohan Kallickal if (mem_descr->mem_array[0].virtual_address) { 298899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 298999bc5d55SJohn Soni Jose "BM_%d : hwi_init_async_pdu_ctx" 29908a86e833SJayamohan Kallickal " HWI_MEM_ASYNC_HEADER_HANDLE_ULP%d va=%p\n", 29918a86e833SJayamohan Kallickal ulp_num, 29928a86e833SJayamohan Kallickal mem_descr->mem_array[0]. 29938a86e833SJayamohan Kallickal virtual_address); 29946733b39aSJayamohan Kallickal } else 29958a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 29968a86e833SJayamohan Kallickal BEISCSI_LOG_INIT, 29978a86e833SJayamohan Kallickal "BM_%d : No Virtual address for ULP : %d\n", 29988a86e833SJayamohan Kallickal ulp_num); 29996733b39aSJayamohan Kallickal 30006733b39aSJayamohan Kallickal pasync_ctx->async_header.handle_base = 30016733b39aSJayamohan Kallickal mem_descr->mem_array[0].virtual_address; 30026733b39aSJayamohan Kallickal pasync_ctx->async_header.writables = 0; 30036733b39aSJayamohan Kallickal INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); 30046733b39aSJayamohan Kallickal 30056733b39aSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 30068a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + 30078a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 30086733b39aSJayamohan Kallickal if (mem_descr->mem_array[0].virtual_address) { 300999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 301099bc5d55SJohn Soni Jose "BM_%d : hwi_init_async_pdu_ctx" 30118a86e833SJayamohan Kallickal " HWI_MEM_ASYNC_DATA_RING_ULP%d va=%p\n", 30128a86e833SJayamohan Kallickal ulp_num, 30138a86e833SJayamohan Kallickal mem_descr->mem_array[0]. 30148a86e833SJayamohan Kallickal virtual_address); 30156733b39aSJayamohan Kallickal } else 30168a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 30178a86e833SJayamohan Kallickal BEISCSI_LOG_INIT, 30188a86e833SJayamohan Kallickal "BM_%d : No Virtual address for ULP : %d\n", 30198a86e833SJayamohan Kallickal ulp_num); 30206733b39aSJayamohan Kallickal 30216733b39aSJayamohan Kallickal pasync_ctx->async_data.ring_base = 30226733b39aSJayamohan Kallickal mem_descr->mem_array[0].virtual_address; 30236733b39aSJayamohan Kallickal 30246733b39aSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 30258a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + 30268a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 30276733b39aSJayamohan Kallickal if (!mem_descr->mem_array[0].virtual_address) 30288a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 30298a86e833SJayamohan Kallickal BEISCSI_LOG_INIT, 30308a86e833SJayamohan Kallickal "BM_%d : No Virtual address for ULP : %d\n", 30318a86e833SJayamohan Kallickal ulp_num); 30326733b39aSJayamohan Kallickal 30336733b39aSJayamohan Kallickal pasync_ctx->async_data.handle_base = 30346733b39aSJayamohan Kallickal mem_descr->mem_array[0].virtual_address; 30356733b39aSJayamohan Kallickal pasync_ctx->async_data.writables = 0; 30366733b39aSJayamohan Kallickal INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); 30376733b39aSJayamohan Kallickal 30386733b39aSJayamohan Kallickal pasync_header_h = 30398a86e833SJayamohan Kallickal (struct async_pdu_handle *) 30408a86e833SJayamohan Kallickal pasync_ctx->async_header.handle_base; 30416733b39aSJayamohan Kallickal pasync_data_h = 30428a86e833SJayamohan Kallickal (struct async_pdu_handle *) 30438a86e833SJayamohan Kallickal pasync_ctx->async_data.handle_base; 30446733b39aSJayamohan Kallickal 3045dc63aac6SJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 30468a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_DATA_BUF_ULP0 + 30478a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 3048dc63aac6SJayamohan Kallickal if (mem_descr->mem_array[0].virtual_address) { 304999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 305099bc5d55SJohn Soni Jose "BM_%d : hwi_init_async_pdu_ctx" 30518a86e833SJayamohan Kallickal " HWI_MEM_ASYNC_DATA_BUF_ULP%d va=%p\n", 30528a86e833SJayamohan Kallickal ulp_num, 30538a86e833SJayamohan Kallickal mem_descr->mem_array[0]. 30548a86e833SJayamohan Kallickal virtual_address); 3055dc63aac6SJayamohan Kallickal } else 30568a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 30578a86e833SJayamohan Kallickal BEISCSI_LOG_INIT, 30588a86e833SJayamohan Kallickal "BM_%d : No Virtual address for ULP : %d\n", 30598a86e833SJayamohan Kallickal ulp_num); 306099bc5d55SJohn Soni Jose 3061dc63aac6SJayamohan Kallickal idx = 0; 3062dc63aac6SJayamohan Kallickal pasync_ctx->async_data.va_base = 3063dc63aac6SJayamohan Kallickal mem_descr->mem_array[idx].virtual_address; 3064dc63aac6SJayamohan Kallickal pasync_ctx->async_data.pa_base.u.a64.address = 30658a86e833SJayamohan Kallickal mem_descr->mem_array[idx]. 30668a86e833SJayamohan Kallickal bus_address.u.a64.address; 3067dc63aac6SJayamohan Kallickal 3068dc63aac6SJayamohan Kallickal num_async_data = ((mem_descr->mem_array[idx].size) / 3069dc63aac6SJayamohan Kallickal phba->params.defpdu_data_sz); 3070dc63aac6SJayamohan Kallickal num_per_mem = 0; 3071dc63aac6SJayamohan Kallickal 30728a86e833SJayamohan Kallickal for (index = 0; index < BEISCSI_GET_CID_COUNT 30738a86e833SJayamohan Kallickal (phba, ulp_num); index++) { 30746733b39aSJayamohan Kallickal pasync_header_h->cri = -1; 30756733b39aSJayamohan Kallickal pasync_header_h->index = (char)index; 30766733b39aSJayamohan Kallickal INIT_LIST_HEAD(&pasync_header_h->link); 30776733b39aSJayamohan Kallickal pasync_header_h->pbuffer = 30786733b39aSJayamohan Kallickal (void *)((unsigned long) 30798a86e833SJayamohan Kallickal (pasync_ctx-> 30808a86e833SJayamohan Kallickal async_header.va_base) + 30816733b39aSJayamohan Kallickal (p->defpdu_hdr_sz * index)); 30826733b39aSJayamohan Kallickal 30836733b39aSJayamohan Kallickal pasync_header_h->pa.u.a64.address = 30848a86e833SJayamohan Kallickal pasync_ctx->async_header.pa_base.u.a64. 30858a86e833SJayamohan Kallickal address + (p->defpdu_hdr_sz * index); 30866733b39aSJayamohan Kallickal 30876733b39aSJayamohan Kallickal list_add_tail(&pasync_header_h->link, 30888a86e833SJayamohan Kallickal &pasync_ctx->async_header. 30898a86e833SJayamohan Kallickal free_list); 30906733b39aSJayamohan Kallickal pasync_header_h++; 30916733b39aSJayamohan Kallickal pasync_ctx->async_header.free_entries++; 30926733b39aSJayamohan Kallickal pasync_ctx->async_header.writables++; 30936733b39aSJayamohan Kallickal 30948a86e833SJayamohan Kallickal INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. 30958a86e833SJayamohan Kallickal wait_queue.list); 30966733b39aSJayamohan Kallickal INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. 30976733b39aSJayamohan Kallickal header_busy_list); 30986733b39aSJayamohan Kallickal pasync_data_h->cri = -1; 30996733b39aSJayamohan Kallickal pasync_data_h->index = (char)index; 31006733b39aSJayamohan Kallickal INIT_LIST_HEAD(&pasync_data_h->link); 3101dc63aac6SJayamohan Kallickal 3102dc63aac6SJayamohan Kallickal if (!num_async_data) { 3103dc63aac6SJayamohan Kallickal num_per_mem = 0; 3104dc63aac6SJayamohan Kallickal idx++; 3105dc63aac6SJayamohan Kallickal pasync_ctx->async_data.va_base = 31068a86e833SJayamohan Kallickal mem_descr->mem_array[idx]. 31078a86e833SJayamohan Kallickal virtual_address; 31088a86e833SJayamohan Kallickal pasync_ctx->async_data.pa_base.u. 31098a86e833SJayamohan Kallickal a64.address = 3110dc63aac6SJayamohan Kallickal mem_descr->mem_array[idx]. 3111dc63aac6SJayamohan Kallickal bus_address.u.a64.address; 31128a86e833SJayamohan Kallickal num_async_data = 31138a86e833SJayamohan Kallickal ((mem_descr->mem_array[idx]. 31148a86e833SJayamohan Kallickal size) / 3115dc63aac6SJayamohan Kallickal phba->params.defpdu_data_sz); 3116dc63aac6SJayamohan Kallickal } 31176733b39aSJayamohan Kallickal pasync_data_h->pbuffer = 31186733b39aSJayamohan Kallickal (void *)((unsigned long) 31196733b39aSJayamohan Kallickal (pasync_ctx->async_data.va_base) + 3120dc63aac6SJayamohan Kallickal (p->defpdu_data_sz * num_per_mem)); 31216733b39aSJayamohan Kallickal 31226733b39aSJayamohan Kallickal pasync_data_h->pa.u.a64.address = 31238a86e833SJayamohan Kallickal pasync_ctx->async_data.pa_base.u.a64. 31248a86e833SJayamohan Kallickal address + (p->defpdu_data_sz * 31258a86e833SJayamohan Kallickal num_per_mem); 3126dc63aac6SJayamohan Kallickal num_per_mem++; 3127dc63aac6SJayamohan Kallickal num_async_data--; 31286733b39aSJayamohan Kallickal 31296733b39aSJayamohan Kallickal list_add_tail(&pasync_data_h->link, 31308a86e833SJayamohan Kallickal &pasync_ctx->async_data. 31318a86e833SJayamohan Kallickal free_list); 31326733b39aSJayamohan Kallickal pasync_data_h++; 31336733b39aSJayamohan Kallickal pasync_ctx->async_data.free_entries++; 31346733b39aSJayamohan Kallickal pasync_ctx->async_data.writables++; 31356733b39aSJayamohan Kallickal 31368a86e833SJayamohan Kallickal INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. 31378a86e833SJayamohan Kallickal data_busy_list); 31386733b39aSJayamohan Kallickal } 31396733b39aSJayamohan Kallickal 31406733b39aSJayamohan Kallickal pasync_ctx->async_header.host_write_ptr = 0; 31416733b39aSJayamohan Kallickal pasync_ctx->async_header.ep_read_ptr = -1; 31426733b39aSJayamohan Kallickal pasync_ctx->async_data.host_write_ptr = 0; 31436733b39aSJayamohan Kallickal pasync_ctx->async_data.ep_read_ptr = -1; 31448a86e833SJayamohan Kallickal } 31458a86e833SJayamohan Kallickal } 3146a7909b39SJayamohan Kallickal 3147a7909b39SJayamohan Kallickal return 0; 31486733b39aSJayamohan Kallickal } 31496733b39aSJayamohan Kallickal 31506733b39aSJayamohan Kallickal static int 31516733b39aSJayamohan Kallickal be_sgl_create_contiguous(void *virtual_address, 31526733b39aSJayamohan Kallickal u64 physical_address, u32 length, 31536733b39aSJayamohan Kallickal struct be_dma_mem *sgl) 31546733b39aSJayamohan Kallickal { 31556733b39aSJayamohan Kallickal WARN_ON(!virtual_address); 31566733b39aSJayamohan Kallickal WARN_ON(!physical_address); 31576733b39aSJayamohan Kallickal WARN_ON(!length > 0); 31586733b39aSJayamohan Kallickal WARN_ON(!sgl); 31596733b39aSJayamohan Kallickal 31606733b39aSJayamohan Kallickal sgl->va = virtual_address; 3161457ff3b7SJayamohan Kallickal sgl->dma = (unsigned long)physical_address; 31626733b39aSJayamohan Kallickal sgl->size = length; 31636733b39aSJayamohan Kallickal 31646733b39aSJayamohan Kallickal return 0; 31656733b39aSJayamohan Kallickal } 31666733b39aSJayamohan Kallickal 31676733b39aSJayamohan Kallickal static void be_sgl_destroy_contiguous(struct be_dma_mem *sgl) 31686733b39aSJayamohan Kallickal { 31696733b39aSJayamohan Kallickal memset(sgl, 0, sizeof(*sgl)); 31706733b39aSJayamohan Kallickal } 31716733b39aSJayamohan Kallickal 31726733b39aSJayamohan Kallickal static void 31736733b39aSJayamohan Kallickal hwi_build_be_sgl_arr(struct beiscsi_hba *phba, 31746733b39aSJayamohan Kallickal struct mem_array *pmem, struct be_dma_mem *sgl) 31756733b39aSJayamohan Kallickal { 31766733b39aSJayamohan Kallickal if (sgl->va) 31776733b39aSJayamohan Kallickal be_sgl_destroy_contiguous(sgl); 31786733b39aSJayamohan Kallickal 31796733b39aSJayamohan Kallickal be_sgl_create_contiguous(pmem->virtual_address, 31806733b39aSJayamohan Kallickal pmem->bus_address.u.a64.address, 31816733b39aSJayamohan Kallickal pmem->size, sgl); 31826733b39aSJayamohan Kallickal } 31836733b39aSJayamohan Kallickal 31846733b39aSJayamohan Kallickal static void 31856733b39aSJayamohan Kallickal hwi_build_be_sgl_by_offset(struct beiscsi_hba *phba, 31866733b39aSJayamohan Kallickal struct mem_array *pmem, struct be_dma_mem *sgl) 31876733b39aSJayamohan Kallickal { 31886733b39aSJayamohan Kallickal if (sgl->va) 31896733b39aSJayamohan Kallickal be_sgl_destroy_contiguous(sgl); 31906733b39aSJayamohan Kallickal 31916733b39aSJayamohan Kallickal be_sgl_create_contiguous((unsigned char *)pmem->virtual_address, 31926733b39aSJayamohan Kallickal pmem->bus_address.u.a64.address, 31936733b39aSJayamohan Kallickal pmem->size, sgl); 31946733b39aSJayamohan Kallickal } 31956733b39aSJayamohan Kallickal 31966733b39aSJayamohan Kallickal static int be_fill_queue(struct be_queue_info *q, 31976733b39aSJayamohan Kallickal u16 len, u16 entry_size, void *vaddress) 31986733b39aSJayamohan Kallickal { 31996733b39aSJayamohan Kallickal struct be_dma_mem *mem = &q->dma_mem; 32006733b39aSJayamohan Kallickal 32016733b39aSJayamohan Kallickal memset(q, 0, sizeof(*q)); 32026733b39aSJayamohan Kallickal q->len = len; 32036733b39aSJayamohan Kallickal q->entry_size = entry_size; 32046733b39aSJayamohan Kallickal mem->size = len * entry_size; 32056733b39aSJayamohan Kallickal mem->va = vaddress; 32066733b39aSJayamohan Kallickal if (!mem->va) 32076733b39aSJayamohan Kallickal return -ENOMEM; 32086733b39aSJayamohan Kallickal memset(mem->va, 0, mem->size); 32096733b39aSJayamohan Kallickal return 0; 32106733b39aSJayamohan Kallickal } 32116733b39aSJayamohan Kallickal 3212bfead3b2SJayamohan Kallickal static int beiscsi_create_eqs(struct beiscsi_hba *phba, 32136733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context) 32146733b39aSJayamohan Kallickal { 3215bfead3b2SJayamohan Kallickal unsigned int i, num_eq_pages; 321699bc5d55SJohn Soni Jose int ret = 0, eq_for_mcc; 32176733b39aSJayamohan Kallickal struct be_queue_info *eq; 32186733b39aSJayamohan Kallickal struct be_dma_mem *mem; 32196733b39aSJayamohan Kallickal void *eq_vaddress; 3220bfead3b2SJayamohan Kallickal dma_addr_t paddr; 32216733b39aSJayamohan Kallickal 3222bfead3b2SJayamohan Kallickal num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \ 3223bfead3b2SJayamohan Kallickal sizeof(struct be_eq_entry)); 3224bfead3b2SJayamohan Kallickal 3225bfead3b2SJayamohan Kallickal if (phba->msix_enabled) 3226bfead3b2SJayamohan Kallickal eq_for_mcc = 1; 3227bfead3b2SJayamohan Kallickal else 3228bfead3b2SJayamohan Kallickal eq_for_mcc = 0; 3229bfead3b2SJayamohan Kallickal for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { 3230bfead3b2SJayamohan Kallickal eq = &phwi_context->be_eq[i].q; 32316733b39aSJayamohan Kallickal mem = &eq->dma_mem; 3232bfead3b2SJayamohan Kallickal phwi_context->be_eq[i].phba = phba; 3233bfead3b2SJayamohan Kallickal eq_vaddress = pci_alloc_consistent(phba->pcidev, 3234bfead3b2SJayamohan Kallickal num_eq_pages * PAGE_SIZE, 3235bfead3b2SJayamohan Kallickal &paddr); 3236bfead3b2SJayamohan Kallickal if (!eq_vaddress) 3237bfead3b2SJayamohan Kallickal goto create_eq_error; 32386733b39aSJayamohan Kallickal 3239bfead3b2SJayamohan Kallickal mem->va = eq_vaddress; 32406733b39aSJayamohan Kallickal ret = be_fill_queue(eq, phba->params.num_eq_entries, 32416733b39aSJayamohan Kallickal sizeof(struct be_eq_entry), eq_vaddress); 32426733b39aSJayamohan Kallickal if (ret) { 324399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 324499bc5d55SJohn Soni Jose "BM_%d : be_fill_queue Failed for EQ\n"); 3245bfead3b2SJayamohan Kallickal goto create_eq_error; 32466733b39aSJayamohan Kallickal } 32476733b39aSJayamohan Kallickal 3248bfead3b2SJayamohan Kallickal mem->dma = paddr; 32496733b39aSJayamohan Kallickal ret = beiscsi_cmd_eq_create(&phba->ctrl, eq, 3250bfead3b2SJayamohan Kallickal phwi_context->cur_eqd); 32516733b39aSJayamohan Kallickal if (ret) { 325299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 325399bc5d55SJohn Soni Jose "BM_%d : beiscsi_cmd_eq_create" 32546733b39aSJayamohan Kallickal "Failed for EQ\n"); 3255bfead3b2SJayamohan Kallickal goto create_eq_error; 3256bfead3b2SJayamohan Kallickal } 325799bc5d55SJohn Soni Jose 325899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 325999bc5d55SJohn Soni Jose "BM_%d : eqid = %d\n", 326099bc5d55SJohn Soni Jose phwi_context->be_eq[i].q.id); 3261bfead3b2SJayamohan Kallickal } 3262bfead3b2SJayamohan Kallickal return 0; 3263bfead3b2SJayamohan Kallickal create_eq_error: 3264107dfcbaSJohn Soni Jose for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { 3265bfead3b2SJayamohan Kallickal eq = &phwi_context->be_eq[i].q; 3266bfead3b2SJayamohan Kallickal mem = &eq->dma_mem; 3267bfead3b2SJayamohan Kallickal if (mem->va) 3268bfead3b2SJayamohan Kallickal pci_free_consistent(phba->pcidev, num_eq_pages 3269bfead3b2SJayamohan Kallickal * PAGE_SIZE, 3270bfead3b2SJayamohan Kallickal mem->va, mem->dma); 3271bfead3b2SJayamohan Kallickal } 32726733b39aSJayamohan Kallickal return ret; 32736733b39aSJayamohan Kallickal } 32746733b39aSJayamohan Kallickal 3275bfead3b2SJayamohan Kallickal static int beiscsi_create_cqs(struct beiscsi_hba *phba, 32766733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context) 32776733b39aSJayamohan Kallickal { 3278bfead3b2SJayamohan Kallickal unsigned int i, num_cq_pages; 327999bc5d55SJohn Soni Jose int ret = 0; 32806733b39aSJayamohan Kallickal struct be_queue_info *cq, *eq; 32816733b39aSJayamohan Kallickal struct be_dma_mem *mem; 3282bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 32836733b39aSJayamohan Kallickal void *cq_vaddress; 3284bfead3b2SJayamohan Kallickal dma_addr_t paddr; 32856733b39aSJayamohan Kallickal 3286bfead3b2SJayamohan Kallickal num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ 3287bfead3b2SJayamohan Kallickal sizeof(struct sol_cqe)); 3288bfead3b2SJayamohan Kallickal 3289bfead3b2SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 3290bfead3b2SJayamohan Kallickal cq = &phwi_context->be_cq[i]; 3291bfead3b2SJayamohan Kallickal eq = &phwi_context->be_eq[i].q; 3292bfead3b2SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 3293bfead3b2SJayamohan Kallickal pbe_eq->cq = cq; 3294bfead3b2SJayamohan Kallickal pbe_eq->phba = phba; 32956733b39aSJayamohan Kallickal mem = &cq->dma_mem; 3296bfead3b2SJayamohan Kallickal cq_vaddress = pci_alloc_consistent(phba->pcidev, 3297bfead3b2SJayamohan Kallickal num_cq_pages * PAGE_SIZE, 3298bfead3b2SJayamohan Kallickal &paddr); 3299bfead3b2SJayamohan Kallickal if (!cq_vaddress) 3300bfead3b2SJayamohan Kallickal goto create_cq_error; 33017da50879SJayamohan Kallickal ret = be_fill_queue(cq, phba->params.num_cq_entries, 33026733b39aSJayamohan Kallickal sizeof(struct sol_cqe), cq_vaddress); 33036733b39aSJayamohan Kallickal if (ret) { 330499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 330599bc5d55SJohn Soni Jose "BM_%d : be_fill_queue Failed " 330699bc5d55SJohn Soni Jose "for ISCSI CQ\n"); 3307bfead3b2SJayamohan Kallickal goto create_cq_error; 33086733b39aSJayamohan Kallickal } 33096733b39aSJayamohan Kallickal 3310bfead3b2SJayamohan Kallickal mem->dma = paddr; 3311bfead3b2SJayamohan Kallickal ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, 3312bfead3b2SJayamohan Kallickal false, 0); 33136733b39aSJayamohan Kallickal if (ret) { 331499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 331599bc5d55SJohn Soni Jose "BM_%d : beiscsi_cmd_eq_create" 3316bfead3b2SJayamohan Kallickal "Failed for ISCSI CQ\n"); 3317bfead3b2SJayamohan Kallickal goto create_cq_error; 33186733b39aSJayamohan Kallickal } 331999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 332099bc5d55SJohn Soni Jose "BM_%d : iscsi cq_id is %d for eq_id %d\n" 332199bc5d55SJohn Soni Jose "iSCSI CQ CREATED\n", cq->id, eq->id); 3322bfead3b2SJayamohan Kallickal } 33236733b39aSJayamohan Kallickal return 0; 3324bfead3b2SJayamohan Kallickal 3325bfead3b2SJayamohan Kallickal create_cq_error: 3326bfead3b2SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 3327bfead3b2SJayamohan Kallickal cq = &phwi_context->be_cq[i]; 3328bfead3b2SJayamohan Kallickal mem = &cq->dma_mem; 3329bfead3b2SJayamohan Kallickal if (mem->va) 3330bfead3b2SJayamohan Kallickal pci_free_consistent(phba->pcidev, num_cq_pages 3331bfead3b2SJayamohan Kallickal * PAGE_SIZE, 3332bfead3b2SJayamohan Kallickal mem->va, mem->dma); 3333bfead3b2SJayamohan Kallickal } 3334bfead3b2SJayamohan Kallickal return ret; 3335bfead3b2SJayamohan Kallickal 33366733b39aSJayamohan Kallickal } 33376733b39aSJayamohan Kallickal 33386733b39aSJayamohan Kallickal static int 33396733b39aSJayamohan Kallickal beiscsi_create_def_hdr(struct beiscsi_hba *phba, 33406733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context, 33416733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr, 33428a86e833SJayamohan Kallickal unsigned int def_pdu_ring_sz, uint8_t ulp_num) 33436733b39aSJayamohan Kallickal { 33446733b39aSJayamohan Kallickal unsigned int idx; 33456733b39aSJayamohan Kallickal int ret; 33466733b39aSJayamohan Kallickal struct be_queue_info *dq, *cq; 33476733b39aSJayamohan Kallickal struct be_dma_mem *mem; 33486733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 33496733b39aSJayamohan Kallickal void *dq_vaddress; 33506733b39aSJayamohan Kallickal 33516733b39aSJayamohan Kallickal idx = 0; 33528a86e833SJayamohan Kallickal dq = &phwi_context->be_def_hdrq[ulp_num]; 3353bfead3b2SJayamohan Kallickal cq = &phwi_context->be_cq[0]; 33546733b39aSJayamohan Kallickal mem = &dq->dma_mem; 33556733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 33568a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + 33578a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 33586733b39aSJayamohan Kallickal dq_vaddress = mem_descr->mem_array[idx].virtual_address; 33596733b39aSJayamohan Kallickal ret = be_fill_queue(dq, mem_descr->mem_array[0].size / 33606733b39aSJayamohan Kallickal sizeof(struct phys_addr), 33616733b39aSJayamohan Kallickal sizeof(struct phys_addr), dq_vaddress); 33626733b39aSJayamohan Kallickal if (ret) { 336399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 33648a86e833SJayamohan Kallickal "BM_%d : be_fill_queue Failed for DEF PDU HDR on ULP : %d\n", 33658a86e833SJayamohan Kallickal ulp_num); 33668a86e833SJayamohan Kallickal 33676733b39aSJayamohan Kallickal return ret; 33686733b39aSJayamohan Kallickal } 3369457ff3b7SJayamohan Kallickal mem->dma = (unsigned long)mem_descr->mem_array[idx]. 3370457ff3b7SJayamohan Kallickal bus_address.u.a64.address; 33716733b39aSJayamohan Kallickal ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq, 33726733b39aSJayamohan Kallickal def_pdu_ring_sz, 33738a86e833SJayamohan Kallickal phba->params.defpdu_hdr_sz, 33748a86e833SJayamohan Kallickal BEISCSI_DEFQ_HDR, ulp_num); 33756733b39aSJayamohan Kallickal if (ret) { 337699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 33778a86e833SJayamohan Kallickal "BM_%d : be_cmd_create_default_pdu_queue Failed DEFHDR on ULP : %d\n", 33788a86e833SJayamohan Kallickal ulp_num); 33798a86e833SJayamohan Kallickal 33806733b39aSJayamohan Kallickal return ret; 33816733b39aSJayamohan Kallickal } 338299bc5d55SJohn Soni Jose 33838a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 33848a86e833SJayamohan Kallickal "BM_%d : iscsi hdr def pdu id for ULP : %d is %d\n", 33858a86e833SJayamohan Kallickal ulp_num, 33868a86e833SJayamohan Kallickal phwi_context->be_def_hdrq[ulp_num].id); 33878a86e833SJayamohan Kallickal hwi_post_async_buffers(phba, BEISCSI_DEFQ_HDR, ulp_num); 33886733b39aSJayamohan Kallickal return 0; 33896733b39aSJayamohan Kallickal } 33906733b39aSJayamohan Kallickal 33916733b39aSJayamohan Kallickal static int 33926733b39aSJayamohan Kallickal beiscsi_create_def_data(struct beiscsi_hba *phba, 33936733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context, 33946733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr, 33958a86e833SJayamohan Kallickal unsigned int def_pdu_ring_sz, uint8_t ulp_num) 33966733b39aSJayamohan Kallickal { 33976733b39aSJayamohan Kallickal unsigned int idx; 33986733b39aSJayamohan Kallickal int ret; 33996733b39aSJayamohan Kallickal struct be_queue_info *dataq, *cq; 34006733b39aSJayamohan Kallickal struct be_dma_mem *mem; 34016733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 34026733b39aSJayamohan Kallickal void *dq_vaddress; 34036733b39aSJayamohan Kallickal 34046733b39aSJayamohan Kallickal idx = 0; 34058a86e833SJayamohan Kallickal dataq = &phwi_context->be_def_dataq[ulp_num]; 3406bfead3b2SJayamohan Kallickal cq = &phwi_context->be_cq[0]; 34076733b39aSJayamohan Kallickal mem = &dataq->dma_mem; 34086733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 34098a86e833SJayamohan Kallickal mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + 34108a86e833SJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 34116733b39aSJayamohan Kallickal dq_vaddress = mem_descr->mem_array[idx].virtual_address; 34126733b39aSJayamohan Kallickal ret = be_fill_queue(dataq, mem_descr->mem_array[0].size / 34136733b39aSJayamohan Kallickal sizeof(struct phys_addr), 34146733b39aSJayamohan Kallickal sizeof(struct phys_addr), dq_vaddress); 34156733b39aSJayamohan Kallickal if (ret) { 341699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 34178a86e833SJayamohan Kallickal "BM_%d : be_fill_queue Failed for DEF PDU " 34188a86e833SJayamohan Kallickal "DATA on ULP : %d\n", 34198a86e833SJayamohan Kallickal ulp_num); 34208a86e833SJayamohan Kallickal 34216733b39aSJayamohan Kallickal return ret; 34226733b39aSJayamohan Kallickal } 3423457ff3b7SJayamohan Kallickal mem->dma = (unsigned long)mem_descr->mem_array[idx]. 3424457ff3b7SJayamohan Kallickal bus_address.u.a64.address; 34256733b39aSJayamohan Kallickal ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq, 34266733b39aSJayamohan Kallickal def_pdu_ring_sz, 34278a86e833SJayamohan Kallickal phba->params.defpdu_data_sz, 34288a86e833SJayamohan Kallickal BEISCSI_DEFQ_DATA, ulp_num); 34296733b39aSJayamohan Kallickal if (ret) { 343099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 343199bc5d55SJohn Soni Jose "BM_%d be_cmd_create_default_pdu_queue" 34328a86e833SJayamohan Kallickal " Failed for DEF PDU DATA on ULP : %d\n", 34338a86e833SJayamohan Kallickal ulp_num); 34346733b39aSJayamohan Kallickal return ret; 34356733b39aSJayamohan Kallickal } 343699bc5d55SJohn Soni Jose 343799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 34388a86e833SJayamohan Kallickal "BM_%d : iscsi def data id on ULP : %d is %d\n", 34398a86e833SJayamohan Kallickal ulp_num, 34408a86e833SJayamohan Kallickal phwi_context->be_def_dataq[ulp_num].id); 34418a86e833SJayamohan Kallickal 34428a86e833SJayamohan Kallickal hwi_post_async_buffers(phba, BEISCSI_DEFQ_DATA, ulp_num); 34438a86e833SJayamohan Kallickal beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 34448a86e833SJayamohan Kallickal "BM_%d : DEFAULT PDU DATA RING CREATED" 34458a86e833SJayamohan Kallickal "on ULP : %d\n", ulp_num); 344699bc5d55SJohn Soni Jose 34476733b39aSJayamohan Kallickal return 0; 34486733b39aSJayamohan Kallickal } 34496733b39aSJayamohan Kallickal 345015a90fe0SJayamohan Kallickal 345115a90fe0SJayamohan Kallickal static int 345215a90fe0SJayamohan Kallickal beiscsi_post_template_hdr(struct beiscsi_hba *phba) 345315a90fe0SJayamohan Kallickal { 345415a90fe0SJayamohan Kallickal struct be_mem_descriptor *mem_descr; 345515a90fe0SJayamohan Kallickal struct mem_array *pm_arr; 345615a90fe0SJayamohan Kallickal struct be_dma_mem sgl; 3457a129d92fSJayamohan Kallickal int status, ulp_num; 345815a90fe0SJayamohan Kallickal 3459a129d92fSJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 3460a129d92fSJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 3461a129d92fSJayamohan Kallickal mem_descr = (struct be_mem_descriptor *)phba->init_mem; 3462a129d92fSJayamohan Kallickal mem_descr += HWI_MEM_TEMPLATE_HDR_ULP0 + 3463a129d92fSJayamohan Kallickal (ulp_num * MEM_DESCR_OFFSET); 346415a90fe0SJayamohan Kallickal pm_arr = mem_descr->mem_array; 346515a90fe0SJayamohan Kallickal 346615a90fe0SJayamohan Kallickal hwi_build_be_sgl_arr(phba, pm_arr, &sgl); 3467a129d92fSJayamohan Kallickal status = be_cmd_iscsi_post_template_hdr( 3468a129d92fSJayamohan Kallickal &phba->ctrl, &sgl); 346915a90fe0SJayamohan Kallickal 347015a90fe0SJayamohan Kallickal if (status != 0) { 347115a90fe0SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 3472a129d92fSJayamohan Kallickal "BM_%d : Post Template HDR Failed for" 3473a129d92fSJayamohan Kallickal "ULP_%d\n", ulp_num); 347415a90fe0SJayamohan Kallickal return status; 347515a90fe0SJayamohan Kallickal } 347615a90fe0SJayamohan Kallickal 347715a90fe0SJayamohan Kallickal beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 3478a129d92fSJayamohan Kallickal "BM_%d : Template HDR Pages Posted for" 3479a129d92fSJayamohan Kallickal "ULP_%d\n", ulp_num); 3480a129d92fSJayamohan Kallickal } 3481a129d92fSJayamohan Kallickal } 348215a90fe0SJayamohan Kallickal return 0; 348315a90fe0SJayamohan Kallickal } 348415a90fe0SJayamohan Kallickal 34856733b39aSJayamohan Kallickal static int 34866733b39aSJayamohan Kallickal beiscsi_post_pages(struct beiscsi_hba *phba) 34876733b39aSJayamohan Kallickal { 34886733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 34896733b39aSJayamohan Kallickal struct mem_array *pm_arr; 34906733b39aSJayamohan Kallickal unsigned int page_offset, i; 34916733b39aSJayamohan Kallickal struct be_dma_mem sgl; 3492843ae752SJayamohan Kallickal int status, ulp_num = 0; 34936733b39aSJayamohan Kallickal 34946733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 34956733b39aSJayamohan Kallickal mem_descr += HWI_MEM_SGE; 34966733b39aSJayamohan Kallickal pm_arr = mem_descr->mem_array; 34976733b39aSJayamohan Kallickal 349890622db3SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) 349990622db3SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) 350090622db3SJayamohan Kallickal break; 350190622db3SJayamohan Kallickal 35026733b39aSJayamohan Kallickal page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io * 3503843ae752SJayamohan Kallickal phba->fw_config.iscsi_icd_start[ulp_num]) / PAGE_SIZE; 35046733b39aSJayamohan Kallickal for (i = 0; i < mem_descr->num_elements; i++) { 35056733b39aSJayamohan Kallickal hwi_build_be_sgl_arr(phba, pm_arr, &sgl); 35066733b39aSJayamohan Kallickal status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl, 35076733b39aSJayamohan Kallickal page_offset, 35086733b39aSJayamohan Kallickal (pm_arr->size / PAGE_SIZE)); 35096733b39aSJayamohan Kallickal page_offset += pm_arr->size / PAGE_SIZE; 35106733b39aSJayamohan Kallickal if (status != 0) { 351199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 351299bc5d55SJohn Soni Jose "BM_%d : post sgl failed.\n"); 35136733b39aSJayamohan Kallickal return status; 35146733b39aSJayamohan Kallickal } 35156733b39aSJayamohan Kallickal pm_arr++; 35166733b39aSJayamohan Kallickal } 351799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 351899bc5d55SJohn Soni Jose "BM_%d : POSTED PAGES\n"); 35196733b39aSJayamohan Kallickal return 0; 35206733b39aSJayamohan Kallickal } 35216733b39aSJayamohan Kallickal 3522bfead3b2SJayamohan Kallickal static void be_queue_free(struct beiscsi_hba *phba, struct be_queue_info *q) 3523bfead3b2SJayamohan Kallickal { 3524bfead3b2SJayamohan Kallickal struct be_dma_mem *mem = &q->dma_mem; 3525c8b25598SJayamohan Kallickal if (mem->va) { 3526bfead3b2SJayamohan Kallickal pci_free_consistent(phba->pcidev, mem->size, 3527bfead3b2SJayamohan Kallickal mem->va, mem->dma); 3528c8b25598SJayamohan Kallickal mem->va = NULL; 3529c8b25598SJayamohan Kallickal } 3530bfead3b2SJayamohan Kallickal } 3531bfead3b2SJayamohan Kallickal 3532bfead3b2SJayamohan Kallickal static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q, 3533bfead3b2SJayamohan Kallickal u16 len, u16 entry_size) 3534bfead3b2SJayamohan Kallickal { 3535bfead3b2SJayamohan Kallickal struct be_dma_mem *mem = &q->dma_mem; 3536bfead3b2SJayamohan Kallickal 3537bfead3b2SJayamohan Kallickal memset(q, 0, sizeof(*q)); 3538bfead3b2SJayamohan Kallickal q->len = len; 3539bfead3b2SJayamohan Kallickal q->entry_size = entry_size; 3540bfead3b2SJayamohan Kallickal mem->size = len * entry_size; 35417c845eb5SJoe Perches mem->va = pci_zalloc_consistent(phba->pcidev, mem->size, &mem->dma); 3542bfead3b2SJayamohan Kallickal if (!mem->va) 3543d3ad2bb3SJayamohan Kallickal return -ENOMEM; 3544bfead3b2SJayamohan Kallickal return 0; 3545bfead3b2SJayamohan Kallickal } 3546bfead3b2SJayamohan Kallickal 35476733b39aSJayamohan Kallickal static int 35486733b39aSJayamohan Kallickal beiscsi_create_wrb_rings(struct beiscsi_hba *phba, 35496733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context, 35506733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr) 35516733b39aSJayamohan Kallickal { 35526733b39aSJayamohan Kallickal unsigned int wrb_mem_index, offset, size, num_wrb_rings; 35536733b39aSJayamohan Kallickal u64 pa_addr_lo; 35544eea99d5SJayamohan Kallickal unsigned int idx, num, i, ulp_num; 35556733b39aSJayamohan Kallickal struct mem_array *pwrb_arr; 35566733b39aSJayamohan Kallickal void *wrb_vaddr; 35576733b39aSJayamohan Kallickal struct be_dma_mem sgl; 35586733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 3559a7909b39SJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 35606733b39aSJayamohan Kallickal int status; 35614eea99d5SJayamohan Kallickal uint8_t ulp_count = 0, ulp_base_num = 0; 35624eea99d5SJayamohan Kallickal uint16_t cid_count_ulp[BEISCSI_ULP_COUNT] = { 0 }; 35636733b39aSJayamohan Kallickal 35646733b39aSJayamohan Kallickal idx = 0; 35656733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 35666733b39aSJayamohan Kallickal mem_descr += HWI_MEM_WRB; 35676733b39aSJayamohan Kallickal pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl, 35686733b39aSJayamohan Kallickal GFP_KERNEL); 35696733b39aSJayamohan Kallickal if (!pwrb_arr) { 357099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 357199bc5d55SJohn Soni Jose "BM_%d : Memory alloc failed in create wrb ring.\n"); 35726733b39aSJayamohan Kallickal return -ENOMEM; 35736733b39aSJayamohan Kallickal } 35746733b39aSJayamohan Kallickal wrb_vaddr = mem_descr->mem_array[idx].virtual_address; 35756733b39aSJayamohan Kallickal pa_addr_lo = mem_descr->mem_array[idx].bus_address.u.a64.address; 35766733b39aSJayamohan Kallickal num_wrb_rings = mem_descr->mem_array[idx].size / 35776733b39aSJayamohan Kallickal (phba->params.wrbs_per_cxn * sizeof(struct iscsi_wrb)); 35786733b39aSJayamohan Kallickal 35796733b39aSJayamohan Kallickal for (num = 0; num < phba->params.cxns_per_ctrl; num++) { 35806733b39aSJayamohan Kallickal if (num_wrb_rings) { 35816733b39aSJayamohan Kallickal pwrb_arr[num].virtual_address = wrb_vaddr; 35826733b39aSJayamohan Kallickal pwrb_arr[num].bus_address.u.a64.address = pa_addr_lo; 35836733b39aSJayamohan Kallickal pwrb_arr[num].size = phba->params.wrbs_per_cxn * 35846733b39aSJayamohan Kallickal sizeof(struct iscsi_wrb); 35856733b39aSJayamohan Kallickal wrb_vaddr += pwrb_arr[num].size; 35866733b39aSJayamohan Kallickal pa_addr_lo += pwrb_arr[num].size; 35876733b39aSJayamohan Kallickal num_wrb_rings--; 35886733b39aSJayamohan Kallickal } else { 35896733b39aSJayamohan Kallickal idx++; 35906733b39aSJayamohan Kallickal wrb_vaddr = mem_descr->mem_array[idx].virtual_address; 35916733b39aSJayamohan Kallickal pa_addr_lo = mem_descr->mem_array[idx].\ 35926733b39aSJayamohan Kallickal bus_address.u.a64.address; 35936733b39aSJayamohan Kallickal num_wrb_rings = mem_descr->mem_array[idx].size / 35946733b39aSJayamohan Kallickal (phba->params.wrbs_per_cxn * 35956733b39aSJayamohan Kallickal sizeof(struct iscsi_wrb)); 35966733b39aSJayamohan Kallickal pwrb_arr[num].virtual_address = wrb_vaddr; 35976733b39aSJayamohan Kallickal pwrb_arr[num].bus_address.u.a64.address\ 35986733b39aSJayamohan Kallickal = pa_addr_lo; 35996733b39aSJayamohan Kallickal pwrb_arr[num].size = phba->params.wrbs_per_cxn * 36006733b39aSJayamohan Kallickal sizeof(struct iscsi_wrb); 36016733b39aSJayamohan Kallickal wrb_vaddr += pwrb_arr[num].size; 36026733b39aSJayamohan Kallickal pa_addr_lo += pwrb_arr[num].size; 36036733b39aSJayamohan Kallickal num_wrb_rings--; 36046733b39aSJayamohan Kallickal } 36056733b39aSJayamohan Kallickal } 36064eea99d5SJayamohan Kallickal 36074eea99d5SJayamohan Kallickal /* Get the ULP Count */ 36084eea99d5SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) 36094eea99d5SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 36104eea99d5SJayamohan Kallickal ulp_count++; 36114eea99d5SJayamohan Kallickal ulp_base_num = ulp_num; 36124eea99d5SJayamohan Kallickal cid_count_ulp[ulp_num] = 36134eea99d5SJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, ulp_num); 36144eea99d5SJayamohan Kallickal } 36154eea99d5SJayamohan Kallickal 36166733b39aSJayamohan Kallickal for (i = 0; i < phba->params.cxns_per_ctrl; i++) { 36176733b39aSJayamohan Kallickal wrb_mem_index = 0; 36186733b39aSJayamohan Kallickal offset = 0; 36196733b39aSJayamohan Kallickal size = 0; 36206733b39aSJayamohan Kallickal 36214eea99d5SJayamohan Kallickal if (ulp_count > 1) { 36224eea99d5SJayamohan Kallickal ulp_base_num = (ulp_base_num + 1) % BEISCSI_ULP_COUNT; 36234eea99d5SJayamohan Kallickal 36244eea99d5SJayamohan Kallickal if (!cid_count_ulp[ulp_base_num]) 36254eea99d5SJayamohan Kallickal ulp_base_num = (ulp_base_num + 1) % 36264eea99d5SJayamohan Kallickal BEISCSI_ULP_COUNT; 36274eea99d5SJayamohan Kallickal 36284eea99d5SJayamohan Kallickal cid_count_ulp[ulp_base_num]--; 36294eea99d5SJayamohan Kallickal } 36304eea99d5SJayamohan Kallickal 36314eea99d5SJayamohan Kallickal 36326733b39aSJayamohan Kallickal hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl); 36336733b39aSJayamohan Kallickal status = be_cmd_wrbq_create(&phba->ctrl, &sgl, 36344eea99d5SJayamohan Kallickal &phwi_context->be_wrbq[i], 36354eea99d5SJayamohan Kallickal &phwi_ctrlr->wrb_context[i], 36364eea99d5SJayamohan Kallickal ulp_base_num); 36376733b39aSJayamohan Kallickal if (status != 0) { 363899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 363999bc5d55SJohn Soni Jose "BM_%d : wrbq create failed."); 36401462b8ffSDan Carpenter kfree(pwrb_arr); 36416733b39aSJayamohan Kallickal return status; 36426733b39aSJayamohan Kallickal } 3643a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[i]; 3644a7909b39SJayamohan Kallickal BE_SET_CID_TO_CRI(i, pwrb_context->cid); 36456733b39aSJayamohan Kallickal } 36466733b39aSJayamohan Kallickal kfree(pwrb_arr); 36476733b39aSJayamohan Kallickal return 0; 36486733b39aSJayamohan Kallickal } 36496733b39aSJayamohan Kallickal 36506733b39aSJayamohan Kallickal static void free_wrb_handles(struct beiscsi_hba *phba) 36516733b39aSJayamohan Kallickal { 36526733b39aSJayamohan Kallickal unsigned int index; 36536733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 36546733b39aSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 36556733b39aSJayamohan Kallickal 36566733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 3657a7909b39SJayamohan Kallickal for (index = 0; index < phba->params.cxns_per_ctrl; index++) { 36586733b39aSJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[index]; 36596733b39aSJayamohan Kallickal kfree(pwrb_context->pwrb_handle_base); 36606733b39aSJayamohan Kallickal kfree(pwrb_context->pwrb_handle_basestd); 36616733b39aSJayamohan Kallickal } 36626733b39aSJayamohan Kallickal } 36636733b39aSJayamohan Kallickal 3664bfead3b2SJayamohan Kallickal static void be_mcc_queues_destroy(struct beiscsi_hba *phba) 3665bfead3b2SJayamohan Kallickal { 3666bfead3b2SJayamohan Kallickal struct be_queue_info *q; 3667bfead3b2SJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 3668bfead3b2SJayamohan Kallickal 3669bfead3b2SJayamohan Kallickal q = &phba->ctrl.mcc_obj.q; 3670bfead3b2SJayamohan Kallickal if (q->created) 3671bfead3b2SJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); 3672bfead3b2SJayamohan Kallickal be_queue_free(phba, q); 3673bfead3b2SJayamohan Kallickal 3674bfead3b2SJayamohan Kallickal q = &phba->ctrl.mcc_obj.cq; 3675bfead3b2SJayamohan Kallickal if (q->created) 3676bfead3b2SJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); 3677bfead3b2SJayamohan Kallickal be_queue_free(phba, q); 3678bfead3b2SJayamohan Kallickal } 3679bfead3b2SJayamohan Kallickal 36806733b39aSJayamohan Kallickal static void hwi_cleanup(struct beiscsi_hba *phba) 36816733b39aSJayamohan Kallickal { 36826733b39aSJayamohan Kallickal struct be_queue_info *q; 36836733b39aSJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 36846733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 36856733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context; 3686a7909b39SJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 368723188167SJayamohan Kallickal int i, eq_for_mcc, ulp_num; 36886733b39aSJayamohan Kallickal 36896733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 36906733b39aSJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 369115a90fe0SJayamohan Kallickal 369215a90fe0SJayamohan Kallickal be_cmd_iscsi_remove_template_hdr(ctrl); 369315a90fe0SJayamohan Kallickal 36946733b39aSJayamohan Kallickal for (i = 0; i < phba->params.cxns_per_ctrl; i++) { 36956733b39aSJayamohan Kallickal q = &phwi_context->be_wrbq[i]; 36966733b39aSJayamohan Kallickal if (q->created) 36976733b39aSJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); 36986733b39aSJayamohan Kallickal } 3699a7909b39SJayamohan Kallickal kfree(phwi_context->be_wrbq); 37006733b39aSJayamohan Kallickal free_wrb_handles(phba); 37016733b39aSJayamohan Kallickal 37028a86e833SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 37038a86e833SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 37048a86e833SJayamohan Kallickal 37058a86e833SJayamohan Kallickal q = &phwi_context->be_def_hdrq[ulp_num]; 37066733b39aSJayamohan Kallickal if (q->created) 37076733b39aSJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); 37086733b39aSJayamohan Kallickal 37098a86e833SJayamohan Kallickal q = &phwi_context->be_def_dataq[ulp_num]; 37106733b39aSJayamohan Kallickal if (q->created) 37116733b39aSJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); 37126733b39aSJayamohan Kallickal 37138a86e833SJayamohan Kallickal pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; 37148a86e833SJayamohan Kallickal } 37158a86e833SJayamohan Kallickal } 37168a86e833SJayamohan Kallickal 37176733b39aSJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); 37186733b39aSJayamohan Kallickal 3719bfead3b2SJayamohan Kallickal for (i = 0; i < (phba->num_cpus); i++) { 3720bfead3b2SJayamohan Kallickal q = &phwi_context->be_cq[i]; 37216733b39aSJayamohan Kallickal if (q->created) 37226733b39aSJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); 3723bfead3b2SJayamohan Kallickal } 372423188167SJayamohan Kallickal 372523188167SJayamohan Kallickal be_mcc_queues_destroy(phba); 3726bfead3b2SJayamohan Kallickal if (phba->msix_enabled) 372723188167SJayamohan Kallickal eq_for_mcc = 1; 3728bfead3b2SJayamohan Kallickal else 372923188167SJayamohan Kallickal eq_for_mcc = 0; 373023188167SJayamohan Kallickal for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { 3731bfead3b2SJayamohan Kallickal q = &phwi_context->be_eq[i].q; 37326733b39aSJayamohan Kallickal if (q->created) 37336733b39aSJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); 37346733b39aSJayamohan Kallickal } 37350283fbb1SJayamohan Kallickal be_cmd_fw_uninit(ctrl); 3736bfead3b2SJayamohan Kallickal } 3737bfead3b2SJayamohan Kallickal 3738bfead3b2SJayamohan Kallickal static int be_mcc_queues_create(struct beiscsi_hba *phba, 3739bfead3b2SJayamohan Kallickal struct hwi_context_memory *phwi_context) 3740bfead3b2SJayamohan Kallickal { 3741bfead3b2SJayamohan Kallickal struct be_queue_info *q, *cq; 3742bfead3b2SJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 3743bfead3b2SJayamohan Kallickal 3744bfead3b2SJayamohan Kallickal /* Alloc MCC compl queue */ 3745bfead3b2SJayamohan Kallickal cq = &phba->ctrl.mcc_obj.cq; 3746bfead3b2SJayamohan Kallickal if (be_queue_alloc(phba, cq, MCC_CQ_LEN, 3747bfead3b2SJayamohan Kallickal sizeof(struct be_mcc_compl))) 3748bfead3b2SJayamohan Kallickal goto err; 3749bfead3b2SJayamohan Kallickal /* Ask BE to create MCC compl queue; */ 3750bfead3b2SJayamohan Kallickal if (phba->msix_enabled) { 3751bfead3b2SJayamohan Kallickal if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq 3752bfead3b2SJayamohan Kallickal [phba->num_cpus].q, false, true, 0)) 3753bfead3b2SJayamohan Kallickal goto mcc_cq_free; 3754bfead3b2SJayamohan Kallickal } else { 3755bfead3b2SJayamohan Kallickal if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq[0].q, 3756bfead3b2SJayamohan Kallickal false, true, 0)) 3757bfead3b2SJayamohan Kallickal goto mcc_cq_free; 3758bfead3b2SJayamohan Kallickal } 3759bfead3b2SJayamohan Kallickal 3760bfead3b2SJayamohan Kallickal /* Alloc MCC queue */ 3761bfead3b2SJayamohan Kallickal q = &phba->ctrl.mcc_obj.q; 3762bfead3b2SJayamohan Kallickal if (be_queue_alloc(phba, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb))) 3763bfead3b2SJayamohan Kallickal goto mcc_cq_destroy; 3764bfead3b2SJayamohan Kallickal 3765bfead3b2SJayamohan Kallickal /* Ask BE to create MCC queue */ 376635e66019SJayamohan Kallickal if (beiscsi_cmd_mccq_create(phba, q, cq)) 3767bfead3b2SJayamohan Kallickal goto mcc_q_free; 3768bfead3b2SJayamohan Kallickal 3769bfead3b2SJayamohan Kallickal return 0; 3770bfead3b2SJayamohan Kallickal 3771bfead3b2SJayamohan Kallickal mcc_q_free: 3772bfead3b2SJayamohan Kallickal be_queue_free(phba, q); 3773bfead3b2SJayamohan Kallickal mcc_cq_destroy: 3774bfead3b2SJayamohan Kallickal beiscsi_cmd_q_destroy(ctrl, cq, QTYPE_CQ); 3775bfead3b2SJayamohan Kallickal mcc_cq_free: 3776bfead3b2SJayamohan Kallickal be_queue_free(phba, cq); 3777bfead3b2SJayamohan Kallickal err: 3778d3ad2bb3SJayamohan Kallickal return -ENOMEM; 3779bfead3b2SJayamohan Kallickal } 3780bfead3b2SJayamohan Kallickal 3781107dfcbaSJohn Soni Jose /** 3782107dfcbaSJohn Soni Jose * find_num_cpus()- Get the CPU online count 3783107dfcbaSJohn Soni Jose * @phba: ptr to priv structure 3784107dfcbaSJohn Soni Jose * 3785107dfcbaSJohn Soni Jose * CPU count is used for creating EQ. 3786107dfcbaSJohn Soni Jose **/ 3787107dfcbaSJohn Soni Jose static void find_num_cpus(struct beiscsi_hba *phba) 3788bfead3b2SJayamohan Kallickal { 3789bfead3b2SJayamohan Kallickal int num_cpus = 0; 3790bfead3b2SJayamohan Kallickal 3791bfead3b2SJayamohan Kallickal num_cpus = num_online_cpus(); 3792bfead3b2SJayamohan Kallickal 379322abeef0SJohn Soni Jose switch (phba->generation) { 379422abeef0SJohn Soni Jose case BE_GEN2: 379522abeef0SJohn Soni Jose case BE_GEN3: 379622abeef0SJohn Soni Jose phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ? 379722abeef0SJohn Soni Jose BEISCSI_MAX_NUM_CPUS : num_cpus; 379822abeef0SJohn Soni Jose break; 379922abeef0SJohn Soni Jose case BE_GEN4: 380068c26a3aSJayamohan Kallickal /* 380168c26a3aSJayamohan Kallickal * If eqid_count == 1 fall back to 380268c26a3aSJayamohan Kallickal * INTX mechanism 380368c26a3aSJayamohan Kallickal **/ 380468c26a3aSJayamohan Kallickal if (phba->fw_config.eqid_count == 1) { 380568c26a3aSJayamohan Kallickal enable_msix = 0; 380668c26a3aSJayamohan Kallickal phba->num_cpus = 1; 380768c26a3aSJayamohan Kallickal return; 380868c26a3aSJayamohan Kallickal } 380968c26a3aSJayamohan Kallickal 381068c26a3aSJayamohan Kallickal phba->num_cpus = 381168c26a3aSJayamohan Kallickal (num_cpus > (phba->fw_config.eqid_count - 1)) ? 381268c26a3aSJayamohan Kallickal (phba->fw_config.eqid_count - 1) : num_cpus; 381322abeef0SJohn Soni Jose break; 381422abeef0SJohn Soni Jose default: 381522abeef0SJohn Soni Jose phba->num_cpus = 1; 381622abeef0SJohn Soni Jose } 3817bfead3b2SJayamohan Kallickal } 38186733b39aSJayamohan Kallickal 38196733b39aSJayamohan Kallickal static int hwi_init_port(struct beiscsi_hba *phba) 38206733b39aSJayamohan Kallickal { 38216733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 38226733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context; 38236733b39aSJayamohan Kallickal unsigned int def_pdu_ring_sz; 38246733b39aSJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 38258a86e833SJayamohan Kallickal int status, ulp_num; 38266733b39aSJayamohan Kallickal 38276733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 38286733b39aSJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 382973af08e1SJayamohan Kallickal phwi_context->max_eqd = 128; 3830bfead3b2SJayamohan Kallickal phwi_context->min_eqd = 0; 383173af08e1SJayamohan Kallickal phwi_context->cur_eqd = 0; 38326733b39aSJayamohan Kallickal be_cmd_fw_initialize(&phba->ctrl); 3833bfead3b2SJayamohan Kallickal 3834bfead3b2SJayamohan Kallickal status = beiscsi_create_eqs(phba, phwi_context); 38356733b39aSJayamohan Kallickal if (status != 0) { 383699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 383799bc5d55SJohn Soni Jose "BM_%d : EQ not created\n"); 38386733b39aSJayamohan Kallickal goto error; 38396733b39aSJayamohan Kallickal } 38406733b39aSJayamohan Kallickal 3841bfead3b2SJayamohan Kallickal status = be_mcc_queues_create(phba, phwi_context); 3842bfead3b2SJayamohan Kallickal if (status != 0) 3843bfead3b2SJayamohan Kallickal goto error; 3844bfead3b2SJayamohan Kallickal 3845bfead3b2SJayamohan Kallickal status = mgmt_check_supported_fw(ctrl, phba); 38466733b39aSJayamohan Kallickal if (status != 0) { 384799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 384899bc5d55SJohn Soni Jose "BM_%d : Unsupported fw version\n"); 38496733b39aSJayamohan Kallickal goto error; 38506733b39aSJayamohan Kallickal } 38516733b39aSJayamohan Kallickal 3852bfead3b2SJayamohan Kallickal status = beiscsi_create_cqs(phba, phwi_context); 38536733b39aSJayamohan Kallickal if (status != 0) { 385499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 385599bc5d55SJohn Soni Jose "BM_%d : CQ not created\n"); 38566733b39aSJayamohan Kallickal goto error; 38576733b39aSJayamohan Kallickal } 38586733b39aSJayamohan Kallickal 38598a86e833SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 38608a86e833SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 38618a86e833SJayamohan Kallickal 38628a86e833SJayamohan Kallickal def_pdu_ring_sz = 38638a86e833SJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, ulp_num) * 38648a86e833SJayamohan Kallickal sizeof(struct phys_addr); 38658a86e833SJayamohan Kallickal 38668a86e833SJayamohan Kallickal status = beiscsi_create_def_hdr(phba, phwi_context, 38678a86e833SJayamohan Kallickal phwi_ctrlr, 38688a86e833SJayamohan Kallickal def_pdu_ring_sz, 38698a86e833SJayamohan Kallickal ulp_num); 38706733b39aSJayamohan Kallickal if (status != 0) { 387199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 38728a86e833SJayamohan Kallickal "BM_%d : Default Header not created for ULP : %d\n", 38738a86e833SJayamohan Kallickal ulp_num); 38746733b39aSJayamohan Kallickal goto error; 38756733b39aSJayamohan Kallickal } 38766733b39aSJayamohan Kallickal 38776733b39aSJayamohan Kallickal status = beiscsi_create_def_data(phba, phwi_context, 38788a86e833SJayamohan Kallickal phwi_ctrlr, 38798a86e833SJayamohan Kallickal def_pdu_ring_sz, 38808a86e833SJayamohan Kallickal ulp_num); 38816733b39aSJayamohan Kallickal if (status != 0) { 388299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 38838a86e833SJayamohan Kallickal "BM_%d : Default Data not created for ULP : %d\n", 38848a86e833SJayamohan Kallickal ulp_num); 38856733b39aSJayamohan Kallickal goto error; 38866733b39aSJayamohan Kallickal } 38878a86e833SJayamohan Kallickal } 38888a86e833SJayamohan Kallickal } 38896733b39aSJayamohan Kallickal 38906733b39aSJayamohan Kallickal status = beiscsi_post_pages(phba); 38916733b39aSJayamohan Kallickal if (status != 0) { 389299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 389399bc5d55SJohn Soni Jose "BM_%d : Post SGL Pages Failed\n"); 38946733b39aSJayamohan Kallickal goto error; 38956733b39aSJayamohan Kallickal } 38966733b39aSJayamohan Kallickal 389715a90fe0SJayamohan Kallickal status = beiscsi_post_template_hdr(phba); 389815a90fe0SJayamohan Kallickal if (status != 0) { 389915a90fe0SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 390015a90fe0SJayamohan Kallickal "BM_%d : Template HDR Posting for CXN Failed\n"); 390115a90fe0SJayamohan Kallickal } 390215a90fe0SJayamohan Kallickal 39036733b39aSJayamohan Kallickal status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr); 39046733b39aSJayamohan Kallickal if (status != 0) { 390599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 390699bc5d55SJohn Soni Jose "BM_%d : WRB Rings not created\n"); 39076733b39aSJayamohan Kallickal goto error; 39086733b39aSJayamohan Kallickal } 39096733b39aSJayamohan Kallickal 39108a86e833SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 39118a86e833SJayamohan Kallickal uint16_t async_arr_idx = 0; 39128a86e833SJayamohan Kallickal 39138a86e833SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { 39148a86e833SJayamohan Kallickal uint16_t cri = 0; 39158a86e833SJayamohan Kallickal struct hwi_async_pdu_context *pasync_ctx; 39168a86e833SJayamohan Kallickal 39178a86e833SJayamohan Kallickal pasync_ctx = HWI_GET_ASYNC_PDU_CTX( 39188a86e833SJayamohan Kallickal phwi_ctrlr, ulp_num); 39198a86e833SJayamohan Kallickal for (cri = 0; cri < 39208a86e833SJayamohan Kallickal phba->params.cxns_per_ctrl; cri++) { 39218a86e833SJayamohan Kallickal if (ulp_num == BEISCSI_GET_ULP_FROM_CRI 39228a86e833SJayamohan Kallickal (phwi_ctrlr, cri)) 39238a86e833SJayamohan Kallickal pasync_ctx->cid_to_async_cri_map[ 39248a86e833SJayamohan Kallickal phwi_ctrlr->wrb_context[cri].cid] = 39258a86e833SJayamohan Kallickal async_arr_idx++; 39268a86e833SJayamohan Kallickal } 39278a86e833SJayamohan Kallickal } 39288a86e833SJayamohan Kallickal } 39298a86e833SJayamohan Kallickal 393099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 393199bc5d55SJohn Soni Jose "BM_%d : hwi_init_port success\n"); 39326733b39aSJayamohan Kallickal return 0; 39336733b39aSJayamohan Kallickal 39346733b39aSJayamohan Kallickal error: 393599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 393699bc5d55SJohn Soni Jose "BM_%d : hwi_init_port failed"); 39376733b39aSJayamohan Kallickal hwi_cleanup(phba); 3938a49e06d5SJayamohan Kallickal return status; 39396733b39aSJayamohan Kallickal } 39406733b39aSJayamohan Kallickal 39416733b39aSJayamohan Kallickal static int hwi_init_controller(struct beiscsi_hba *phba) 39426733b39aSJayamohan Kallickal { 39436733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 39446733b39aSJayamohan Kallickal 39456733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 39466733b39aSJayamohan Kallickal if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) { 39476733b39aSJayamohan Kallickal phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba-> 39486733b39aSJayamohan Kallickal init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address; 394999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 395099bc5d55SJohn Soni Jose "BM_%d : phwi_ctrlr->phwi_ctxt=%p\n", 39516733b39aSJayamohan Kallickal phwi_ctrlr->phwi_ctxt); 39526733b39aSJayamohan Kallickal } else { 395399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 395499bc5d55SJohn Soni Jose "BM_%d : HWI_MEM_ADDN_CONTEXT is more " 395599bc5d55SJohn Soni Jose "than one element.Failing to load\n"); 39566733b39aSJayamohan Kallickal return -ENOMEM; 39576733b39aSJayamohan Kallickal } 39586733b39aSJayamohan Kallickal 39596733b39aSJayamohan Kallickal iscsi_init_global_templates(phba); 39603ec78271SJayamohan Kallickal if (beiscsi_init_wrb_handle(phba)) 39613ec78271SJayamohan Kallickal return -ENOMEM; 39623ec78271SJayamohan Kallickal 3963a7909b39SJayamohan Kallickal if (hwi_init_async_pdu_ctx(phba)) { 3964a7909b39SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 3965a7909b39SJayamohan Kallickal "BM_%d : hwi_init_async_pdu_ctx failed\n"); 3966a7909b39SJayamohan Kallickal return -ENOMEM; 3967a7909b39SJayamohan Kallickal } 3968a7909b39SJayamohan Kallickal 39696733b39aSJayamohan Kallickal if (hwi_init_port(phba) != 0) { 397099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 397199bc5d55SJohn Soni Jose "BM_%d : hwi_init_controller failed\n"); 397299bc5d55SJohn Soni Jose 39736733b39aSJayamohan Kallickal return -ENOMEM; 39746733b39aSJayamohan Kallickal } 39756733b39aSJayamohan Kallickal return 0; 39766733b39aSJayamohan Kallickal } 39776733b39aSJayamohan Kallickal 39786733b39aSJayamohan Kallickal static void beiscsi_free_mem(struct beiscsi_hba *phba) 39796733b39aSJayamohan Kallickal { 39806733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr; 39816733b39aSJayamohan Kallickal int i, j; 39826733b39aSJayamohan Kallickal 39836733b39aSJayamohan Kallickal mem_descr = phba->init_mem; 39846733b39aSJayamohan Kallickal i = 0; 39856733b39aSJayamohan Kallickal j = 0; 39866733b39aSJayamohan Kallickal for (i = 0; i < SE_MEM_MAX; i++) { 39876733b39aSJayamohan Kallickal for (j = mem_descr->num_elements; j > 0; j--) { 39886733b39aSJayamohan Kallickal pci_free_consistent(phba->pcidev, 39896733b39aSJayamohan Kallickal mem_descr->mem_array[j - 1].size, 39906733b39aSJayamohan Kallickal mem_descr->mem_array[j - 1].virtual_address, 3991457ff3b7SJayamohan Kallickal (unsigned long)mem_descr->mem_array[j - 1]. 3992457ff3b7SJayamohan Kallickal bus_address.u.a64.address); 39936733b39aSJayamohan Kallickal } 39948a86e833SJayamohan Kallickal 39956733b39aSJayamohan Kallickal kfree(mem_descr->mem_array); 39966733b39aSJayamohan Kallickal mem_descr++; 39976733b39aSJayamohan Kallickal } 39986733b39aSJayamohan Kallickal kfree(phba->init_mem); 3999a7909b39SJayamohan Kallickal kfree(phba->phwi_ctrlr->wrb_context); 40006733b39aSJayamohan Kallickal kfree(phba->phwi_ctrlr); 40016733b39aSJayamohan Kallickal } 40026733b39aSJayamohan Kallickal 40036733b39aSJayamohan Kallickal static int beiscsi_init_controller(struct beiscsi_hba *phba) 40046733b39aSJayamohan Kallickal { 40056733b39aSJayamohan Kallickal int ret = -ENOMEM; 40066733b39aSJayamohan Kallickal 40076733b39aSJayamohan Kallickal ret = beiscsi_get_memory(phba); 40086733b39aSJayamohan Kallickal if (ret < 0) { 400999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 401099bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe -" 40116733b39aSJayamohan Kallickal "Failed in beiscsi_alloc_memory\n"); 40126733b39aSJayamohan Kallickal return ret; 40136733b39aSJayamohan Kallickal } 40146733b39aSJayamohan Kallickal 40156733b39aSJayamohan Kallickal ret = hwi_init_controller(phba); 40166733b39aSJayamohan Kallickal if (ret) 40176733b39aSJayamohan Kallickal goto free_init; 401899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 401999bc5d55SJohn Soni Jose "BM_%d : Return success from beiscsi_init_controller"); 402099bc5d55SJohn Soni Jose 40216733b39aSJayamohan Kallickal return 0; 40226733b39aSJayamohan Kallickal 40236733b39aSJayamohan Kallickal free_init: 40246733b39aSJayamohan Kallickal beiscsi_free_mem(phba); 4025a49e06d5SJayamohan Kallickal return ret; 40266733b39aSJayamohan Kallickal } 40276733b39aSJayamohan Kallickal 40286733b39aSJayamohan Kallickal static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) 40296733b39aSJayamohan Kallickal { 40306733b39aSJayamohan Kallickal struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg; 40316733b39aSJayamohan Kallickal struct sgl_handle *psgl_handle; 40326733b39aSJayamohan Kallickal struct iscsi_sge *pfrag; 403390622db3SJayamohan Kallickal unsigned int arr_index, i, idx; 403490622db3SJayamohan Kallickal unsigned int ulp_icd_start, ulp_num = 0; 40356733b39aSJayamohan Kallickal 40366733b39aSJayamohan Kallickal phba->io_sgl_hndl_avbl = 0; 40376733b39aSJayamohan Kallickal phba->eh_sgl_hndl_avbl = 0; 4038bfead3b2SJayamohan Kallickal 40396733b39aSJayamohan Kallickal mem_descr_sglh = phba->init_mem; 40406733b39aSJayamohan Kallickal mem_descr_sglh += HWI_MEM_SGLH; 40416733b39aSJayamohan Kallickal if (1 == mem_descr_sglh->num_elements) { 40426733b39aSJayamohan Kallickal phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * 40436733b39aSJayamohan Kallickal phba->params.ios_per_ctrl, 40446733b39aSJayamohan Kallickal GFP_KERNEL); 40456733b39aSJayamohan Kallickal if (!phba->io_sgl_hndl_base) { 404699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 404799bc5d55SJohn Soni Jose "BM_%d : Mem Alloc Failed. Failing to load\n"); 40486733b39aSJayamohan Kallickal return -ENOMEM; 40496733b39aSJayamohan Kallickal } 40506733b39aSJayamohan Kallickal phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * 40516733b39aSJayamohan Kallickal (phba->params.icds_per_ctrl - 40526733b39aSJayamohan Kallickal phba->params.ios_per_ctrl), 40536733b39aSJayamohan Kallickal GFP_KERNEL); 40546733b39aSJayamohan Kallickal if (!phba->eh_sgl_hndl_base) { 40556733b39aSJayamohan Kallickal kfree(phba->io_sgl_hndl_base); 405699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 405799bc5d55SJohn Soni Jose "BM_%d : Mem Alloc Failed. Failing to load\n"); 40586733b39aSJayamohan Kallickal return -ENOMEM; 40596733b39aSJayamohan Kallickal } 40606733b39aSJayamohan Kallickal } else { 406199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 406299bc5d55SJohn Soni Jose "BM_%d : HWI_MEM_SGLH is more than one element." 40636733b39aSJayamohan Kallickal "Failing to load\n"); 40646733b39aSJayamohan Kallickal return -ENOMEM; 40656733b39aSJayamohan Kallickal } 40666733b39aSJayamohan Kallickal 40676733b39aSJayamohan Kallickal arr_index = 0; 40686733b39aSJayamohan Kallickal idx = 0; 40696733b39aSJayamohan Kallickal while (idx < mem_descr_sglh->num_elements) { 40706733b39aSJayamohan Kallickal psgl_handle = mem_descr_sglh->mem_array[idx].virtual_address; 40716733b39aSJayamohan Kallickal 40726733b39aSJayamohan Kallickal for (i = 0; i < (mem_descr_sglh->mem_array[idx].size / 40736733b39aSJayamohan Kallickal sizeof(struct sgl_handle)); i++) { 40746733b39aSJayamohan Kallickal if (arr_index < phba->params.ios_per_ctrl) { 40756733b39aSJayamohan Kallickal phba->io_sgl_hndl_base[arr_index] = psgl_handle; 40766733b39aSJayamohan Kallickal phba->io_sgl_hndl_avbl++; 40776733b39aSJayamohan Kallickal arr_index++; 40786733b39aSJayamohan Kallickal } else { 40796733b39aSJayamohan Kallickal phba->eh_sgl_hndl_base[arr_index - 40806733b39aSJayamohan Kallickal phba->params.ios_per_ctrl] = 40816733b39aSJayamohan Kallickal psgl_handle; 40826733b39aSJayamohan Kallickal arr_index++; 40836733b39aSJayamohan Kallickal phba->eh_sgl_hndl_avbl++; 40846733b39aSJayamohan Kallickal } 40856733b39aSJayamohan Kallickal psgl_handle++; 40866733b39aSJayamohan Kallickal } 40876733b39aSJayamohan Kallickal idx++; 40886733b39aSJayamohan Kallickal } 408999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 409099bc5d55SJohn Soni Jose "BM_%d : phba->io_sgl_hndl_avbl=%d" 40916733b39aSJayamohan Kallickal "phba->eh_sgl_hndl_avbl=%d\n", 40926733b39aSJayamohan Kallickal phba->io_sgl_hndl_avbl, 40936733b39aSJayamohan Kallickal phba->eh_sgl_hndl_avbl); 409499bc5d55SJohn Soni Jose 40956733b39aSJayamohan Kallickal mem_descr_sg = phba->init_mem; 40966733b39aSJayamohan Kallickal mem_descr_sg += HWI_MEM_SGE; 409799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 409899bc5d55SJohn Soni Jose "\n BM_%d : mem_descr_sg->num_elements=%d\n", 40996733b39aSJayamohan Kallickal mem_descr_sg->num_elements); 410099bc5d55SJohn Soni Jose 410190622db3SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) 410290622db3SJayamohan Kallickal if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) 410390622db3SJayamohan Kallickal break; 410490622db3SJayamohan Kallickal 410590622db3SJayamohan Kallickal ulp_icd_start = phba->fw_config.iscsi_icd_start[ulp_num]; 410690622db3SJayamohan Kallickal 41076733b39aSJayamohan Kallickal arr_index = 0; 41086733b39aSJayamohan Kallickal idx = 0; 41096733b39aSJayamohan Kallickal while (idx < mem_descr_sg->num_elements) { 41106733b39aSJayamohan Kallickal pfrag = mem_descr_sg->mem_array[idx].virtual_address; 41116733b39aSJayamohan Kallickal 41126733b39aSJayamohan Kallickal for (i = 0; 41136733b39aSJayamohan Kallickal i < (mem_descr_sg->mem_array[idx].size) / 41146733b39aSJayamohan Kallickal (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io); 41156733b39aSJayamohan Kallickal i++) { 41166733b39aSJayamohan Kallickal if (arr_index < phba->params.ios_per_ctrl) 41176733b39aSJayamohan Kallickal psgl_handle = phba->io_sgl_hndl_base[arr_index]; 41186733b39aSJayamohan Kallickal else 41196733b39aSJayamohan Kallickal psgl_handle = phba->eh_sgl_hndl_base[arr_index - 41206733b39aSJayamohan Kallickal phba->params.ios_per_ctrl]; 41216733b39aSJayamohan Kallickal psgl_handle->pfrag = pfrag; 41226733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0); 41236733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0); 41246733b39aSJayamohan Kallickal pfrag += phba->params.num_sge_per_io; 412590622db3SJayamohan Kallickal psgl_handle->sgl_index = ulp_icd_start + arr_index++; 41266733b39aSJayamohan Kallickal } 41276733b39aSJayamohan Kallickal idx++; 41286733b39aSJayamohan Kallickal } 41296733b39aSJayamohan Kallickal phba->io_sgl_free_index = 0; 41306733b39aSJayamohan Kallickal phba->io_sgl_alloc_index = 0; 41316733b39aSJayamohan Kallickal phba->eh_sgl_free_index = 0; 41326733b39aSJayamohan Kallickal phba->eh_sgl_alloc_index = 0; 41336733b39aSJayamohan Kallickal return 0; 41346733b39aSJayamohan Kallickal } 41356733b39aSJayamohan Kallickal 41366733b39aSJayamohan Kallickal static int hba_setup_cid_tbls(struct beiscsi_hba *phba) 41376733b39aSJayamohan Kallickal { 41380a3db7c0SJayamohan Kallickal int ret; 41390a3db7c0SJayamohan Kallickal uint16_t i, ulp_num; 41400a3db7c0SJayamohan Kallickal struct ulp_cid_info *ptr_cid_info = NULL; 41416733b39aSJayamohan Kallickal 41420a3db7c0SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 41430a3db7c0SJayamohan Kallickal if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { 41440a3db7c0SJayamohan Kallickal ptr_cid_info = kzalloc(sizeof(struct ulp_cid_info), 41456733b39aSJayamohan Kallickal GFP_KERNEL); 41460a3db7c0SJayamohan Kallickal 41470a3db7c0SJayamohan Kallickal if (!ptr_cid_info) { 414899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 41490a3db7c0SJayamohan Kallickal "BM_%d : Failed to allocate memory" 41500a3db7c0SJayamohan Kallickal "for ULP_CID_INFO for ULP : %d\n", 41510a3db7c0SJayamohan Kallickal ulp_num); 41520a3db7c0SJayamohan Kallickal ret = -ENOMEM; 41530a3db7c0SJayamohan Kallickal goto free_memory; 41540a3db7c0SJayamohan Kallickal 41550a3db7c0SJayamohan Kallickal } 41560a3db7c0SJayamohan Kallickal 41570a3db7c0SJayamohan Kallickal /* Allocate memory for CID array */ 41580a3db7c0SJayamohan Kallickal ptr_cid_info->cid_array = kzalloc(sizeof(void *) * 41590a3db7c0SJayamohan Kallickal BEISCSI_GET_CID_COUNT(phba, 41600a3db7c0SJayamohan Kallickal ulp_num), GFP_KERNEL); 41610a3db7c0SJayamohan Kallickal if (!ptr_cid_info->cid_array) { 41620a3db7c0SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 41630a3db7c0SJayamohan Kallickal "BM_%d : Failed to allocate memory" 41640a3db7c0SJayamohan Kallickal "for CID_ARRAY for ULP : %d\n", 41650a3db7c0SJayamohan Kallickal ulp_num); 41660a3db7c0SJayamohan Kallickal kfree(ptr_cid_info); 41670a3db7c0SJayamohan Kallickal ptr_cid_info = NULL; 41680a3db7c0SJayamohan Kallickal ret = -ENOMEM; 41690a3db7c0SJayamohan Kallickal 41700a3db7c0SJayamohan Kallickal goto free_memory; 41710a3db7c0SJayamohan Kallickal } 41720a3db7c0SJayamohan Kallickal ptr_cid_info->avlbl_cids = BEISCSI_GET_CID_COUNT( 41730a3db7c0SJayamohan Kallickal phba, ulp_num); 41740a3db7c0SJayamohan Kallickal 41750a3db7c0SJayamohan Kallickal /* Save the cid_info_array ptr */ 41760a3db7c0SJayamohan Kallickal phba->cid_array_info[ulp_num] = ptr_cid_info; 41770a3db7c0SJayamohan Kallickal } 41786733b39aSJayamohan Kallickal } 4179c2462288SJayamohan Kallickal phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * 4180a7909b39SJayamohan Kallickal phba->params.cxns_per_ctrl, GFP_KERNEL); 41816733b39aSJayamohan Kallickal if (!phba->ep_array) { 418299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 418399bc5d55SJohn Soni Jose "BM_%d : Failed to allocate memory in " 41846733b39aSJayamohan Kallickal "hba_setup_cid_tbls\n"); 41850a3db7c0SJayamohan Kallickal ret = -ENOMEM; 41860a3db7c0SJayamohan Kallickal 41870a3db7c0SJayamohan Kallickal goto free_memory; 41886733b39aSJayamohan Kallickal } 4189a7909b39SJayamohan Kallickal 4190a7909b39SJayamohan Kallickal phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * 4191a7909b39SJayamohan Kallickal phba->params.cxns_per_ctrl, GFP_KERNEL); 4192a7909b39SJayamohan Kallickal if (!phba->conn_table) { 4193a7909b39SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 4194a7909b39SJayamohan Kallickal "BM_%d : Failed to allocate memory in" 4195a7909b39SJayamohan Kallickal "hba_setup_cid_tbls\n"); 4196a7909b39SJayamohan Kallickal 4197a7909b39SJayamohan Kallickal kfree(phba->ep_array); 4198a7909b39SJayamohan Kallickal phba->ep_array = NULL; 41990a3db7c0SJayamohan Kallickal ret = -ENOMEM; 42005f2d25efSTomas Henzl 42015f2d25efSTomas Henzl goto free_memory; 42026733b39aSJayamohan Kallickal } 4203a7909b39SJayamohan Kallickal 42040a3db7c0SJayamohan Kallickal for (i = 0; i < phba->params.cxns_per_ctrl; i++) { 42050a3db7c0SJayamohan Kallickal ulp_num = phba->phwi_ctrlr->wrb_context[i].ulp_num; 4206a7909b39SJayamohan Kallickal 42070a3db7c0SJayamohan Kallickal ptr_cid_info = phba->cid_array_info[ulp_num]; 42080a3db7c0SJayamohan Kallickal ptr_cid_info->cid_array[ptr_cid_info->cid_alloc++] = 42090a3db7c0SJayamohan Kallickal phba->phwi_ctrlr->wrb_context[i].cid; 42100a3db7c0SJayamohan Kallickal 42110a3db7c0SJayamohan Kallickal } 42120a3db7c0SJayamohan Kallickal 42130a3db7c0SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 42140a3db7c0SJayamohan Kallickal if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { 42150a3db7c0SJayamohan Kallickal ptr_cid_info = phba->cid_array_info[ulp_num]; 42160a3db7c0SJayamohan Kallickal 42170a3db7c0SJayamohan Kallickal ptr_cid_info->cid_alloc = 0; 42180a3db7c0SJayamohan Kallickal ptr_cid_info->cid_free = 0; 42190a3db7c0SJayamohan Kallickal } 42200a3db7c0SJayamohan Kallickal } 42216733b39aSJayamohan Kallickal return 0; 42220a3db7c0SJayamohan Kallickal 42230a3db7c0SJayamohan Kallickal free_memory: 42240a3db7c0SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 42250a3db7c0SJayamohan Kallickal if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { 42260a3db7c0SJayamohan Kallickal ptr_cid_info = phba->cid_array_info[ulp_num]; 42270a3db7c0SJayamohan Kallickal 42280a3db7c0SJayamohan Kallickal if (ptr_cid_info) { 42290a3db7c0SJayamohan Kallickal kfree(ptr_cid_info->cid_array); 42300a3db7c0SJayamohan Kallickal kfree(ptr_cid_info); 42310a3db7c0SJayamohan Kallickal phba->cid_array_info[ulp_num] = NULL; 42320a3db7c0SJayamohan Kallickal } 42330a3db7c0SJayamohan Kallickal } 42340a3db7c0SJayamohan Kallickal } 42350a3db7c0SJayamohan Kallickal 42360a3db7c0SJayamohan Kallickal return ret; 42376733b39aSJayamohan Kallickal } 42386733b39aSJayamohan Kallickal 4239238f6b72SJayamohan Kallickal static void hwi_enable_intr(struct beiscsi_hba *phba) 42406733b39aSJayamohan Kallickal { 42416733b39aSJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 42426733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 42436733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context; 42446733b39aSJayamohan Kallickal struct be_queue_info *eq; 42456733b39aSJayamohan Kallickal u8 __iomem *addr; 4246bfead3b2SJayamohan Kallickal u32 reg, i; 42476733b39aSJayamohan Kallickal u32 enabled; 42486733b39aSJayamohan Kallickal 42496733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 42506733b39aSJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 42516733b39aSJayamohan Kallickal 42526733b39aSJayamohan Kallickal addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg + 42536733b39aSJayamohan Kallickal PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); 42546733b39aSJayamohan Kallickal reg = ioread32(addr); 42556733b39aSJayamohan Kallickal 42566733b39aSJayamohan Kallickal enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; 42576733b39aSJayamohan Kallickal if (!enabled) { 42586733b39aSJayamohan Kallickal reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; 425999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 426099bc5d55SJohn Soni Jose "BM_%d : reg =x%08x addr=%p\n", reg, addr); 42616733b39aSJayamohan Kallickal iowrite32(reg, addr); 4262665d6d94SJayamohan Kallickal } 4263665d6d94SJayamohan Kallickal 4264c03af1aeSJayamohan Kallickal if (!phba->msix_enabled) { 4265c03af1aeSJayamohan Kallickal eq = &phwi_context->be_eq[0].q; 426699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 426799bc5d55SJohn Soni Jose "BM_%d : eq->id=%d\n", eq->id); 426899bc5d55SJohn Soni Jose 4269c03af1aeSJayamohan Kallickal hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); 4270c03af1aeSJayamohan Kallickal } else { 4271bfead3b2SJayamohan Kallickal for (i = 0; i <= phba->num_cpus; i++) { 4272bfead3b2SJayamohan Kallickal eq = &phwi_context->be_eq[i].q; 427399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 427499bc5d55SJohn Soni Jose "BM_%d : eq->id=%d\n", eq->id); 42756733b39aSJayamohan Kallickal hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); 4276bfead3b2SJayamohan Kallickal } 4277c03af1aeSJayamohan Kallickal } 4278c03af1aeSJayamohan Kallickal } 42796733b39aSJayamohan Kallickal 42806733b39aSJayamohan Kallickal static void hwi_disable_intr(struct beiscsi_hba *phba) 42816733b39aSJayamohan Kallickal { 42826733b39aSJayamohan Kallickal struct be_ctrl_info *ctrl = &phba->ctrl; 42836733b39aSJayamohan Kallickal 42846733b39aSJayamohan Kallickal u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; 42856733b39aSJayamohan Kallickal u32 reg = ioread32(addr); 42866733b39aSJayamohan Kallickal 42876733b39aSJayamohan Kallickal u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; 42886733b39aSJayamohan Kallickal if (enabled) { 42896733b39aSJayamohan Kallickal reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; 42906733b39aSJayamohan Kallickal iowrite32(reg, addr); 42916733b39aSJayamohan Kallickal } else 429299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, 429399bc5d55SJohn Soni Jose "BM_%d : In hwi_disable_intr, Already Disabled\n"); 42946733b39aSJayamohan Kallickal } 42956733b39aSJayamohan Kallickal 42969aef4200SJohn Soni Jose /** 42979aef4200SJohn Soni Jose * beiscsi_get_boot_info()- Get the boot session info 42989aef4200SJohn Soni Jose * @phba: The device priv structure instance 42999aef4200SJohn Soni Jose * 43009aef4200SJohn Soni Jose * Get the boot target info and store in driver priv structure 43019aef4200SJohn Soni Jose * 43029aef4200SJohn Soni Jose * return values 43039aef4200SJohn Soni Jose * Success: 0 43049aef4200SJohn Soni Jose * Failure: Non-Zero Value 43059aef4200SJohn Soni Jose **/ 4306c7acc5b8SJayamohan Kallickal static int beiscsi_get_boot_info(struct beiscsi_hba *phba) 4307c7acc5b8SJayamohan Kallickal { 43080e43895eSMike Christie struct be_cmd_get_session_resp *session_resp; 4309c7acc5b8SJayamohan Kallickal struct be_dma_mem nonemb_cmd; 4310e175defeSJohn Soni Jose unsigned int tag; 43119aef4200SJohn Soni Jose unsigned int s_handle; 4312f457a46fSMike Christie int ret = -ENOMEM; 4313c7acc5b8SJayamohan Kallickal 43149aef4200SJohn Soni Jose /* Get the session handle of the boot target */ 43159aef4200SJohn Soni Jose ret = be_mgmt_get_boot_shandle(phba, &s_handle); 43169aef4200SJohn Soni Jose if (ret) { 431799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 431899bc5d55SJohn Soni Jose BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 431999bc5d55SJohn Soni Jose "BM_%d : No boot session\n"); 43209aef4200SJohn Soni Jose return ret; 4321c7acc5b8SJayamohan Kallickal } 43227c845eb5SJoe Perches nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, 4323c7acc5b8SJayamohan Kallickal sizeof(*session_resp), 4324c7acc5b8SJayamohan Kallickal &nonemb_cmd.dma); 4325c7acc5b8SJayamohan Kallickal if (nonemb_cmd.va == NULL) { 432699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 432799bc5d55SJohn Soni Jose BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 432899bc5d55SJohn Soni Jose "BM_%d : Failed to allocate memory for" 4329c7acc5b8SJayamohan Kallickal "beiscsi_get_session_info\n"); 433099bc5d55SJohn Soni Jose 4331c7acc5b8SJayamohan Kallickal return -ENOMEM; 4332c7acc5b8SJayamohan Kallickal } 4333c7acc5b8SJayamohan Kallickal 43349aef4200SJohn Soni Jose tag = mgmt_get_session_info(phba, s_handle, 43350e43895eSMike Christie &nonemb_cmd); 4336c7acc5b8SJayamohan Kallickal if (!tag) { 433799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 433899bc5d55SJohn Soni Jose BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 433999bc5d55SJohn Soni Jose "BM_%d : beiscsi_get_session_info" 4340c7acc5b8SJayamohan Kallickal " Failed\n"); 434199bc5d55SJohn Soni Jose 4342c7acc5b8SJayamohan Kallickal goto boot_freemem; 4343e175defeSJohn Soni Jose } 4344c7acc5b8SJayamohan Kallickal 43451957aa7fSJayamohan Kallickal ret = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); 4346e175defeSJohn Soni Jose if (ret) { 434799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 434899bc5d55SJohn Soni Jose BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 4349e175defeSJohn Soni Jose "BM_%d : beiscsi_get_session_info Failed"); 43501957aa7fSJayamohan Kallickal 43511957aa7fSJayamohan Kallickal if (ret != -EBUSY) 4352c7acc5b8SJayamohan Kallickal goto boot_freemem; 43531957aa7fSJayamohan Kallickal else 43541957aa7fSJayamohan Kallickal return ret; 4355c7acc5b8SJayamohan Kallickal } 4356e175defeSJohn Soni Jose 4357c7acc5b8SJayamohan Kallickal session_resp = nonemb_cmd.va ; 4358f457a46fSMike Christie 4359c7acc5b8SJayamohan Kallickal memcpy(&phba->boot_sess, &session_resp->session_info, 4360c7acc5b8SJayamohan Kallickal sizeof(struct mgmt_session_info)); 4361f457a46fSMike Christie ret = 0; 4362f457a46fSMike Christie 4363c7acc5b8SJayamohan Kallickal boot_freemem: 4364c7acc5b8SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 4365c7acc5b8SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 4366f457a46fSMike Christie return ret; 4367f457a46fSMike Christie } 4368f457a46fSMike Christie 4369f457a46fSMike Christie static void beiscsi_boot_release(void *data) 4370f457a46fSMike Christie { 4371f457a46fSMike Christie struct beiscsi_hba *phba = data; 4372f457a46fSMike Christie 4373f457a46fSMike Christie scsi_host_put(phba->shost); 4374f457a46fSMike Christie } 4375f457a46fSMike Christie 4376f457a46fSMike Christie static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) 4377f457a46fSMike Christie { 4378f457a46fSMike Christie struct iscsi_boot_kobj *boot_kobj; 4379f457a46fSMike Christie 4380f457a46fSMike Christie /* get boot info using mgmt cmd */ 4381f457a46fSMike Christie if (beiscsi_get_boot_info(phba)) 4382f457a46fSMike Christie /* Try to see if we can carry on without this */ 4383f457a46fSMike Christie return 0; 4384f457a46fSMike Christie 4385f457a46fSMike Christie phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); 4386f457a46fSMike Christie if (!phba->boot_kset) 4387f457a46fSMike Christie return -ENOMEM; 4388f457a46fSMike Christie 4389f457a46fSMike Christie /* get a ref because the show function will ref the phba */ 4390f457a46fSMike Christie if (!scsi_host_get(phba->shost)) 4391f457a46fSMike Christie goto free_kset; 4392f457a46fSMike Christie boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, 4393f457a46fSMike Christie beiscsi_show_boot_tgt_info, 4394f457a46fSMike Christie beiscsi_tgt_get_attr_visibility, 4395f457a46fSMike Christie beiscsi_boot_release); 4396f457a46fSMike Christie if (!boot_kobj) 4397f457a46fSMike Christie goto put_shost; 4398f457a46fSMike Christie 4399f457a46fSMike Christie if (!scsi_host_get(phba->shost)) 4400f457a46fSMike Christie goto free_kset; 4401f457a46fSMike Christie boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, 4402f457a46fSMike Christie beiscsi_show_boot_ini_info, 4403f457a46fSMike Christie beiscsi_ini_get_attr_visibility, 4404f457a46fSMike Christie beiscsi_boot_release); 4405f457a46fSMike Christie if (!boot_kobj) 4406f457a46fSMike Christie goto put_shost; 4407f457a46fSMike Christie 4408f457a46fSMike Christie if (!scsi_host_get(phba->shost)) 4409f457a46fSMike Christie goto free_kset; 4410f457a46fSMike Christie boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, 4411f457a46fSMike Christie beiscsi_show_boot_eth_info, 4412f457a46fSMike Christie beiscsi_eth_get_attr_visibility, 4413f457a46fSMike Christie beiscsi_boot_release); 4414f457a46fSMike Christie if (!boot_kobj) 4415f457a46fSMike Christie goto put_shost; 4416f457a46fSMike Christie return 0; 4417f457a46fSMike Christie 4418f457a46fSMike Christie put_shost: 4419f457a46fSMike Christie scsi_host_put(phba->shost); 4420f457a46fSMike Christie free_kset: 4421f457a46fSMike Christie iscsi_boot_destroy_kset(phba->boot_kset); 4422c7acc5b8SJayamohan Kallickal return -ENOMEM; 4423c7acc5b8SJayamohan Kallickal } 4424c7acc5b8SJayamohan Kallickal 44256733b39aSJayamohan Kallickal static int beiscsi_init_port(struct beiscsi_hba *phba) 44266733b39aSJayamohan Kallickal { 44276733b39aSJayamohan Kallickal int ret; 44286733b39aSJayamohan Kallickal 44296733b39aSJayamohan Kallickal ret = beiscsi_init_controller(phba); 44306733b39aSJayamohan Kallickal if (ret < 0) { 443199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 443299bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe - Failed in" 44336733b39aSJayamohan Kallickal "beiscsi_init_controller\n"); 44346733b39aSJayamohan Kallickal return ret; 44356733b39aSJayamohan Kallickal } 44366733b39aSJayamohan Kallickal ret = beiscsi_init_sgl_handle(phba); 44376733b39aSJayamohan Kallickal if (ret < 0) { 443899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 443999bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe - Failed in" 44406733b39aSJayamohan Kallickal "beiscsi_init_sgl_handle\n"); 44416733b39aSJayamohan Kallickal goto do_cleanup_ctrlr; 44426733b39aSJayamohan Kallickal } 44436733b39aSJayamohan Kallickal 44446733b39aSJayamohan Kallickal if (hba_setup_cid_tbls(phba)) { 444599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 444699bc5d55SJohn Soni Jose "BM_%d : Failed in hba_setup_cid_tbls\n"); 44476733b39aSJayamohan Kallickal kfree(phba->io_sgl_hndl_base); 44486733b39aSJayamohan Kallickal kfree(phba->eh_sgl_hndl_base); 44496733b39aSJayamohan Kallickal goto do_cleanup_ctrlr; 44506733b39aSJayamohan Kallickal } 44516733b39aSJayamohan Kallickal 44526733b39aSJayamohan Kallickal return ret; 44536733b39aSJayamohan Kallickal 44546733b39aSJayamohan Kallickal do_cleanup_ctrlr: 44556733b39aSJayamohan Kallickal hwi_cleanup(phba); 44566733b39aSJayamohan Kallickal return ret; 44576733b39aSJayamohan Kallickal } 44586733b39aSJayamohan Kallickal 44596733b39aSJayamohan Kallickal static void hwi_purge_eq(struct beiscsi_hba *phba) 44606733b39aSJayamohan Kallickal { 44616733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 44626733b39aSJayamohan Kallickal struct hwi_context_memory *phwi_context; 44636733b39aSJayamohan Kallickal struct be_queue_info *eq; 44646733b39aSJayamohan Kallickal struct be_eq_entry *eqe = NULL; 4465bfead3b2SJayamohan Kallickal int i, eq_msix; 4466756d29c8SJayamohan Kallickal unsigned int num_processed; 44676733b39aSJayamohan Kallickal 44686733b39aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 44696733b39aSJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 4470bfead3b2SJayamohan Kallickal if (phba->msix_enabled) 4471bfead3b2SJayamohan Kallickal eq_msix = 1; 4472bfead3b2SJayamohan Kallickal else 4473bfead3b2SJayamohan Kallickal eq_msix = 0; 4474bfead3b2SJayamohan Kallickal 4475bfead3b2SJayamohan Kallickal for (i = 0; i < (phba->num_cpus + eq_msix); i++) { 4476bfead3b2SJayamohan Kallickal eq = &phwi_context->be_eq[i].q; 44776733b39aSJayamohan Kallickal eqe = queue_tail_node(eq); 4478756d29c8SJayamohan Kallickal num_processed = 0; 44796733b39aSJayamohan Kallickal while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] 44806733b39aSJayamohan Kallickal & EQE_VALID_MASK) { 44816733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); 44826733b39aSJayamohan Kallickal queue_tail_inc(eq); 44836733b39aSJayamohan Kallickal eqe = queue_tail_node(eq); 4484756d29c8SJayamohan Kallickal num_processed++; 44856733b39aSJayamohan Kallickal } 4486756d29c8SJayamohan Kallickal 4487756d29c8SJayamohan Kallickal if (num_processed) 4488756d29c8SJayamohan Kallickal hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1); 44896733b39aSJayamohan Kallickal } 4490bfead3b2SJayamohan Kallickal } 44916733b39aSJayamohan Kallickal 44926733b39aSJayamohan Kallickal static void beiscsi_clean_port(struct beiscsi_hba *phba) 44936733b39aSJayamohan Kallickal { 44940a3db7c0SJayamohan Kallickal int mgmt_status, ulp_num; 44950a3db7c0SJayamohan Kallickal struct ulp_cid_info *ptr_cid_info = NULL; 44966733b39aSJayamohan Kallickal 4497bd41c2bdSJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 4498bd41c2bdSJayamohan Kallickal if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { 4499bd41c2bdSJayamohan Kallickal mgmt_status = mgmt_epfw_cleanup(phba, ulp_num); 45006733b39aSJayamohan Kallickal if (mgmt_status) 4501bd41c2bdSJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, 4502bd41c2bdSJayamohan Kallickal BEISCSI_LOG_INIT, 4503bd41c2bdSJayamohan Kallickal "BM_%d : mgmt_epfw_cleanup FAILED" 4504bd41c2bdSJayamohan Kallickal " for ULP_%d\n", ulp_num); 4505bd41c2bdSJayamohan Kallickal } 4506bd41c2bdSJayamohan Kallickal } 4507756d29c8SJayamohan Kallickal 45086733b39aSJayamohan Kallickal hwi_purge_eq(phba); 4509756d29c8SJayamohan Kallickal hwi_cleanup(phba); 45106733b39aSJayamohan Kallickal kfree(phba->io_sgl_hndl_base); 45116733b39aSJayamohan Kallickal kfree(phba->eh_sgl_hndl_base); 45126733b39aSJayamohan Kallickal kfree(phba->ep_array); 4513a7909b39SJayamohan Kallickal kfree(phba->conn_table); 45140a3db7c0SJayamohan Kallickal 45150a3db7c0SJayamohan Kallickal for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 45160a3db7c0SJayamohan Kallickal if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { 45170a3db7c0SJayamohan Kallickal ptr_cid_info = phba->cid_array_info[ulp_num]; 45180a3db7c0SJayamohan Kallickal 45190a3db7c0SJayamohan Kallickal if (ptr_cid_info) { 45200a3db7c0SJayamohan Kallickal kfree(ptr_cid_info->cid_array); 45210a3db7c0SJayamohan Kallickal kfree(ptr_cid_info); 45220a3db7c0SJayamohan Kallickal phba->cid_array_info[ulp_num] = NULL; 45230a3db7c0SJayamohan Kallickal } 45240a3db7c0SJayamohan Kallickal } 45250a3db7c0SJayamohan Kallickal } 45260a3db7c0SJayamohan Kallickal 45276733b39aSJayamohan Kallickal } 45286733b39aSJayamohan Kallickal 4529d629c471SJohn Soni Jose /** 453043f388b0SJayamohan Kallickal * beiscsi_free_mgmt_task_handles()- Free driver CXN resources 453143f388b0SJayamohan Kallickal * @beiscsi_conn: ptr to the conn to be cleaned up 45324a4a11b9SJayamohan Kallickal * @task: ptr to iscsi_task resource to be freed. 453343f388b0SJayamohan Kallickal * 453443f388b0SJayamohan Kallickal * Free driver mgmt resources binded to CXN. 453543f388b0SJayamohan Kallickal **/ 453643f388b0SJayamohan Kallickal void 45374a4a11b9SJayamohan Kallickal beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, 45384a4a11b9SJayamohan Kallickal struct iscsi_task *task) 453943f388b0SJayamohan Kallickal { 454043f388b0SJayamohan Kallickal struct beiscsi_io_task *io_task; 454143f388b0SJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_conn->phba; 454243f388b0SJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 454343f388b0SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 4544a7909b39SJayamohan Kallickal uint16_t cri_index = BE_GET_CRI_FROM_CID( 4545a7909b39SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 454643f388b0SJayamohan Kallickal 454743f388b0SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 4548a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 4549a7909b39SJayamohan Kallickal 45504a4a11b9SJayamohan Kallickal io_task = task->dd_data; 455143f388b0SJayamohan Kallickal 455243f388b0SJayamohan Kallickal if (io_task->pwrb_handle) { 455343f388b0SJayamohan Kallickal memset(io_task->pwrb_handle->pwrb, 0, 455443f388b0SJayamohan Kallickal sizeof(struct iscsi_wrb)); 455543f388b0SJayamohan Kallickal free_wrb_handle(phba, pwrb_context, 455643f388b0SJayamohan Kallickal io_task->pwrb_handle); 455743f388b0SJayamohan Kallickal io_task->pwrb_handle = NULL; 455843f388b0SJayamohan Kallickal } 455943f388b0SJayamohan Kallickal 456043f388b0SJayamohan Kallickal if (io_task->psgl_handle) { 456143f388b0SJayamohan Kallickal spin_lock_bh(&phba->mgmt_sgl_lock); 456243f388b0SJayamohan Kallickal free_mgmt_sgl_handle(phba, 456343f388b0SJayamohan Kallickal io_task->psgl_handle); 456443f388b0SJayamohan Kallickal io_task->psgl_handle = NULL; 45654a4a11b9SJayamohan Kallickal spin_unlock_bh(&phba->mgmt_sgl_lock); 456643f388b0SJayamohan Kallickal } 456743f388b0SJayamohan Kallickal 456843f388b0SJayamohan Kallickal if (io_task->mtask_addr) 456943f388b0SJayamohan Kallickal pci_unmap_single(phba->pcidev, 457043f388b0SJayamohan Kallickal io_task->mtask_addr, 457143f388b0SJayamohan Kallickal io_task->mtask_data_count, 457243f388b0SJayamohan Kallickal PCI_DMA_TODEVICE); 457343f388b0SJayamohan Kallickal } 457443f388b0SJayamohan Kallickal 457543f388b0SJayamohan Kallickal /** 4576d629c471SJohn Soni Jose * beiscsi_cleanup_task()- Free driver resources of the task 4577d629c471SJohn Soni Jose * @task: ptr to the iscsi task 4578d629c471SJohn Soni Jose * 4579d629c471SJohn Soni Jose **/ 45801282ab76SMike Christie static void beiscsi_cleanup_task(struct iscsi_task *task) 45811282ab76SMike Christie { 45821282ab76SMike Christie struct beiscsi_io_task *io_task = task->dd_data; 45831282ab76SMike Christie struct iscsi_conn *conn = task->conn; 45841282ab76SMike Christie struct beiscsi_conn *beiscsi_conn = conn->dd_data; 45851282ab76SMike Christie struct beiscsi_hba *phba = beiscsi_conn->phba; 45861282ab76SMike Christie struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; 45871282ab76SMike Christie struct hwi_wrb_context *pwrb_context; 45881282ab76SMike Christie struct hwi_controller *phwi_ctrlr; 4589a7909b39SJayamohan Kallickal uint16_t cri_index = BE_GET_CRI_FROM_CID( 4590a7909b39SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 45911282ab76SMike Christie 45921282ab76SMike Christie phwi_ctrlr = phba->phwi_ctrlr; 4593a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 45941282ab76SMike Christie 45951282ab76SMike Christie if (io_task->cmd_bhs) { 45961282ab76SMike Christie pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, 45971282ab76SMike Christie io_task->bhs_pa.u.a64.address); 45981282ab76SMike Christie io_task->cmd_bhs = NULL; 45991282ab76SMike Christie } 46001282ab76SMike Christie 46011282ab76SMike Christie if (task->sc) { 46021282ab76SMike Christie if (io_task->pwrb_handle) { 46031282ab76SMike Christie free_wrb_handle(phba, pwrb_context, 46041282ab76SMike Christie io_task->pwrb_handle); 46051282ab76SMike Christie io_task->pwrb_handle = NULL; 46061282ab76SMike Christie } 46071282ab76SMike Christie 46081282ab76SMike Christie if (io_task->psgl_handle) { 46091282ab76SMike Christie spin_lock(&phba->io_sgl_lock); 46101282ab76SMike Christie free_io_sgl_handle(phba, io_task->psgl_handle); 46111282ab76SMike Christie spin_unlock(&phba->io_sgl_lock); 46121282ab76SMike Christie io_task->psgl_handle = NULL; 46131282ab76SMike Christie } 4614da334977SJayamohan Kallickal 4615da334977SJayamohan Kallickal if (io_task->scsi_cmnd) { 4616da334977SJayamohan Kallickal scsi_dma_unmap(io_task->scsi_cmnd); 4617da334977SJayamohan Kallickal io_task->scsi_cmnd = NULL; 4618da334977SJayamohan Kallickal } 46191282ab76SMike Christie } else { 462043f388b0SJayamohan Kallickal if (!beiscsi_conn->login_in_progress) 46214a4a11b9SJayamohan Kallickal beiscsi_free_mgmt_task_handles(beiscsi_conn, task); 46221282ab76SMike Christie } 46231282ab76SMike Christie } 46241282ab76SMike Christie 46256733b39aSJayamohan Kallickal void 46266733b39aSJayamohan Kallickal beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, 46276733b39aSJayamohan Kallickal struct beiscsi_offload_params *params) 46286733b39aSJayamohan Kallickal { 46296733b39aSJayamohan Kallickal struct wrb_handle *pwrb_handle; 46306733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_conn->phba; 46311282ab76SMike Christie struct iscsi_task *task = beiscsi_conn->task; 46321282ab76SMike Christie struct iscsi_session *session = task->conn->session; 46336733b39aSJayamohan Kallickal u32 doorbell = 0; 46346733b39aSJayamohan Kallickal 46356733b39aSJayamohan Kallickal /* 46366733b39aSJayamohan Kallickal * We can always use 0 here because it is reserved by libiscsi for 46376733b39aSJayamohan Kallickal * login/startup related tasks. 46386733b39aSJayamohan Kallickal */ 46391282ab76SMike Christie beiscsi_conn->login_in_progress = 0; 4640659743b0SShlomo Pongratz spin_lock_bh(&session->back_lock); 46411282ab76SMike Christie beiscsi_cleanup_task(task); 4642659743b0SShlomo Pongratz spin_unlock_bh(&session->back_lock); 46431282ab76SMike Christie 4644a7909b39SJayamohan Kallickal pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid); 46456733b39aSJayamohan Kallickal 4646acb9693cSJohn Soni Jose /* Check for the adapter family */ 46472c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) 4648acb9693cSJohn Soni Jose beiscsi_offload_cxn_v0(params, pwrb_handle, 4649acb9693cSJohn Soni Jose phba->init_mem); 46502c9dfd36SJayamohan Kallickal else 46512c9dfd36SJayamohan Kallickal beiscsi_offload_cxn_v2(params, pwrb_handle); 46526733b39aSJayamohan Kallickal 4653acb9693cSJohn Soni Jose be_dws_le_to_cpu(pwrb_handle->pwrb, 4654acb9693cSJohn Soni Jose sizeof(struct iscsi_target_context_update_wrb)); 46556733b39aSJayamohan Kallickal 46566733b39aSJayamohan Kallickal doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; 4657bfead3b2SJayamohan Kallickal doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) 4658bfead3b2SJayamohan Kallickal << DB_DEF_PDU_WRB_INDEX_SHIFT; 46596733b39aSJayamohan Kallickal doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; 46601e4be6ffSJayamohan Kallickal iowrite32(doorbell, phba->db_va + 46611e4be6ffSJayamohan Kallickal beiscsi_conn->doorbell_offset); 46626733b39aSJayamohan Kallickal } 46636733b39aSJayamohan Kallickal 46646733b39aSJayamohan Kallickal static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, 46656733b39aSJayamohan Kallickal int *index, int *age) 46666733b39aSJayamohan Kallickal { 4667bfead3b2SJayamohan Kallickal *index = (int)itt; 46686733b39aSJayamohan Kallickal if (age) 46696733b39aSJayamohan Kallickal *age = conn->session->age; 46706733b39aSJayamohan Kallickal } 46716733b39aSJayamohan Kallickal 46726733b39aSJayamohan Kallickal /** 46736733b39aSJayamohan Kallickal * beiscsi_alloc_pdu - allocates pdu and related resources 46746733b39aSJayamohan Kallickal * @task: libiscsi task 46756733b39aSJayamohan Kallickal * @opcode: opcode of pdu for task 46766733b39aSJayamohan Kallickal * 46776733b39aSJayamohan Kallickal * This is called with the session lock held. It will allocate 46786733b39aSJayamohan Kallickal * the wrb and sgl if needed for the command. And it will prep 46796733b39aSJayamohan Kallickal * the pdu's itt. beiscsi_parse_pdu will later translate 46806733b39aSJayamohan Kallickal * the pdu itt to the libiscsi task itt. 46816733b39aSJayamohan Kallickal */ 46826733b39aSJayamohan Kallickal static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) 46836733b39aSJayamohan Kallickal { 46846733b39aSJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 46856733b39aSJayamohan Kallickal struct iscsi_conn *conn = task->conn; 46866733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn = conn->dd_data; 46876733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_conn->phba; 46886733b39aSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 46896733b39aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 46906733b39aSJayamohan Kallickal itt_t itt; 4691a7909b39SJayamohan Kallickal uint16_t cri_index = 0; 46922afc95bfSJayamohan Kallickal struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; 46932afc95bfSJayamohan Kallickal dma_addr_t paddr; 46946733b39aSJayamohan Kallickal 46952afc95bfSJayamohan Kallickal io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool, 4696bc7accecSMike Christie GFP_ATOMIC, &paddr); 46972afc95bfSJayamohan Kallickal if (!io_task->cmd_bhs) 46982afc95bfSJayamohan Kallickal return -ENOMEM; 46992afc95bfSJayamohan Kallickal io_task->bhs_pa.u.a64.address = paddr; 4700bfead3b2SJayamohan Kallickal io_task->libiscsi_itt = (itt_t)task->itt; 47016733b39aSJayamohan Kallickal io_task->conn = beiscsi_conn; 47026733b39aSJayamohan Kallickal 47036733b39aSJayamohan Kallickal task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr; 47046733b39aSJayamohan Kallickal task->hdr_max = sizeof(struct be_cmd_bhs); 4705d2cecf0dSJayamohan Kallickal io_task->psgl_handle = NULL; 47063ec78271SJayamohan Kallickal io_task->pwrb_handle = NULL; 47076733b39aSJayamohan Kallickal 47086733b39aSJayamohan Kallickal if (task->sc) { 47096733b39aSJayamohan Kallickal spin_lock(&phba->io_sgl_lock); 47106733b39aSJayamohan Kallickal io_task->psgl_handle = alloc_io_sgl_handle(phba); 47116733b39aSJayamohan Kallickal spin_unlock(&phba->io_sgl_lock); 47128359c79bSJohn Soni Jose if (!io_task->psgl_handle) { 47138359c79bSJohn Soni Jose beiscsi_log(phba, KERN_ERR, 47148359c79bSJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 47158359c79bSJohn Soni Jose "BM_%d : Alloc of IO_SGL_ICD Failed" 47168359c79bSJohn Soni Jose "for the CID : %d\n", 47178359c79bSJohn Soni Jose beiscsi_conn->beiscsi_conn_cid); 47182afc95bfSJayamohan Kallickal goto free_hndls; 47198359c79bSJohn Soni Jose } 4720d2cecf0dSJayamohan Kallickal io_task->pwrb_handle = alloc_wrb_handle(phba, 4721a7909b39SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 47228359c79bSJohn Soni Jose if (!io_task->pwrb_handle) { 47238359c79bSJohn Soni Jose beiscsi_log(phba, KERN_ERR, 47248359c79bSJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 47258359c79bSJohn Soni Jose "BM_%d : Alloc of WRB_HANDLE Failed" 47268359c79bSJohn Soni Jose "for the CID : %d\n", 47278359c79bSJohn Soni Jose beiscsi_conn->beiscsi_conn_cid); 4728d2cecf0dSJayamohan Kallickal goto free_io_hndls; 47298359c79bSJohn Soni Jose } 47306733b39aSJayamohan Kallickal } else { 47316733b39aSJayamohan Kallickal io_task->scsi_cmnd = NULL; 4732d7aea67bSJayamohan Kallickal if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { 473343f388b0SJayamohan Kallickal beiscsi_conn->task = task; 47346733b39aSJayamohan Kallickal if (!beiscsi_conn->login_in_progress) { 47356733b39aSJayamohan Kallickal spin_lock(&phba->mgmt_sgl_lock); 47366733b39aSJayamohan Kallickal io_task->psgl_handle = (struct sgl_handle *) 47376733b39aSJayamohan Kallickal alloc_mgmt_sgl_handle(phba); 47386733b39aSJayamohan Kallickal spin_unlock(&phba->mgmt_sgl_lock); 47398359c79bSJohn Soni Jose if (!io_task->psgl_handle) { 47408359c79bSJohn Soni Jose beiscsi_log(phba, KERN_ERR, 47418359c79bSJohn Soni Jose BEISCSI_LOG_IO | 47428359c79bSJohn Soni Jose BEISCSI_LOG_CONFIG, 47438359c79bSJohn Soni Jose "BM_%d : Alloc of MGMT_SGL_ICD Failed" 47448359c79bSJohn Soni Jose "for the CID : %d\n", 47458359c79bSJohn Soni Jose beiscsi_conn-> 47468359c79bSJohn Soni Jose beiscsi_conn_cid); 47472afc95bfSJayamohan Kallickal goto free_hndls; 47488359c79bSJohn Soni Jose } 47492afc95bfSJayamohan Kallickal 47506733b39aSJayamohan Kallickal beiscsi_conn->login_in_progress = 1; 47516733b39aSJayamohan Kallickal beiscsi_conn->plogin_sgl_handle = 47526733b39aSJayamohan Kallickal io_task->psgl_handle; 4753d2cecf0dSJayamohan Kallickal io_task->pwrb_handle = 4754d2cecf0dSJayamohan Kallickal alloc_wrb_handle(phba, 4755a7909b39SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 47568359c79bSJohn Soni Jose if (!io_task->pwrb_handle) { 47578359c79bSJohn Soni Jose beiscsi_log(phba, KERN_ERR, 47588359c79bSJohn Soni Jose BEISCSI_LOG_IO | 47598359c79bSJohn Soni Jose BEISCSI_LOG_CONFIG, 47608359c79bSJohn Soni Jose "BM_%d : Alloc of WRB_HANDLE Failed" 47618359c79bSJohn Soni Jose "for the CID : %d\n", 47628359c79bSJohn Soni Jose beiscsi_conn-> 47638359c79bSJohn Soni Jose beiscsi_conn_cid); 47648359c79bSJohn Soni Jose goto free_mgmt_hndls; 47658359c79bSJohn Soni Jose } 4766d2cecf0dSJayamohan Kallickal beiscsi_conn->plogin_wrb_handle = 4767d2cecf0dSJayamohan Kallickal io_task->pwrb_handle; 4768d2cecf0dSJayamohan Kallickal 47696733b39aSJayamohan Kallickal } else { 47706733b39aSJayamohan Kallickal io_task->psgl_handle = 47716733b39aSJayamohan Kallickal beiscsi_conn->plogin_sgl_handle; 4772d2cecf0dSJayamohan Kallickal io_task->pwrb_handle = 4773d2cecf0dSJayamohan Kallickal beiscsi_conn->plogin_wrb_handle; 47746733b39aSJayamohan Kallickal } 47756733b39aSJayamohan Kallickal } else { 47766733b39aSJayamohan Kallickal spin_lock(&phba->mgmt_sgl_lock); 47776733b39aSJayamohan Kallickal io_task->psgl_handle = alloc_mgmt_sgl_handle(phba); 47786733b39aSJayamohan Kallickal spin_unlock(&phba->mgmt_sgl_lock); 47798359c79bSJohn Soni Jose if (!io_task->psgl_handle) { 47808359c79bSJohn Soni Jose beiscsi_log(phba, KERN_ERR, 47818359c79bSJohn Soni Jose BEISCSI_LOG_IO | 47828359c79bSJohn Soni Jose BEISCSI_LOG_CONFIG, 47838359c79bSJohn Soni Jose "BM_%d : Alloc of MGMT_SGL_ICD Failed" 47848359c79bSJohn Soni Jose "for the CID : %d\n", 47858359c79bSJohn Soni Jose beiscsi_conn-> 47868359c79bSJohn Soni Jose beiscsi_conn_cid); 47872afc95bfSJayamohan Kallickal goto free_hndls; 47888359c79bSJohn Soni Jose } 4789d2cecf0dSJayamohan Kallickal io_task->pwrb_handle = 4790d2cecf0dSJayamohan Kallickal alloc_wrb_handle(phba, 4791a7909b39SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 47928359c79bSJohn Soni Jose if (!io_task->pwrb_handle) { 47938359c79bSJohn Soni Jose beiscsi_log(phba, KERN_ERR, 47948359c79bSJohn Soni Jose BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, 47958359c79bSJohn Soni Jose "BM_%d : Alloc of WRB_HANDLE Failed" 47968359c79bSJohn Soni Jose "for the CID : %d\n", 47978359c79bSJohn Soni Jose beiscsi_conn->beiscsi_conn_cid); 4798d2cecf0dSJayamohan Kallickal goto free_mgmt_hndls; 47998359c79bSJohn Soni Jose } 4800d2cecf0dSJayamohan Kallickal 48016733b39aSJayamohan Kallickal } 48026733b39aSJayamohan Kallickal } 4803bfead3b2SJayamohan Kallickal itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle-> 4804bfead3b2SJayamohan Kallickal wrb_index << 16) | (unsigned int) 4805bfead3b2SJayamohan Kallickal (io_task->psgl_handle->sgl_index)); 4806bfead3b2SJayamohan Kallickal io_task->pwrb_handle->pio_handle = task; 4807bfead3b2SJayamohan Kallickal 48086733b39aSJayamohan Kallickal io_task->cmd_bhs->iscsi_hdr.itt = itt; 48096733b39aSJayamohan Kallickal return 0; 48102afc95bfSJayamohan Kallickal 4811d2cecf0dSJayamohan Kallickal free_io_hndls: 4812d2cecf0dSJayamohan Kallickal spin_lock(&phba->io_sgl_lock); 4813d2cecf0dSJayamohan Kallickal free_io_sgl_handle(phba, io_task->psgl_handle); 4814d2cecf0dSJayamohan Kallickal spin_unlock(&phba->io_sgl_lock); 4815d2cecf0dSJayamohan Kallickal goto free_hndls; 4816d2cecf0dSJayamohan Kallickal free_mgmt_hndls: 4817d2cecf0dSJayamohan Kallickal spin_lock(&phba->mgmt_sgl_lock); 4818d2cecf0dSJayamohan Kallickal free_mgmt_sgl_handle(phba, io_task->psgl_handle); 4819a7909b39SJayamohan Kallickal io_task->psgl_handle = NULL; 4820d2cecf0dSJayamohan Kallickal spin_unlock(&phba->mgmt_sgl_lock); 48212afc95bfSJayamohan Kallickal free_hndls: 48222afc95bfSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 4823a7909b39SJayamohan Kallickal cri_index = BE_GET_CRI_FROM_CID( 4824a7909b39SJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid); 4825a7909b39SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 4826d2cecf0dSJayamohan Kallickal if (io_task->pwrb_handle) 48272afc95bfSJayamohan Kallickal free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); 48282afc95bfSJayamohan Kallickal io_task->pwrb_handle = NULL; 48292afc95bfSJayamohan Kallickal pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, 48302afc95bfSJayamohan Kallickal io_task->bhs_pa.u.a64.address); 48311282ab76SMike Christie io_task->cmd_bhs = NULL; 48322afc95bfSJayamohan Kallickal return -ENOMEM; 48336733b39aSJayamohan Kallickal } 483409a1093aSJohn Soni Jose int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, 483509a1093aSJohn Soni Jose unsigned int num_sg, unsigned int xferlen, 483609a1093aSJohn Soni Jose unsigned int writedir) 483709a1093aSJohn Soni Jose { 483809a1093aSJohn Soni Jose 483909a1093aSJohn Soni Jose struct beiscsi_io_task *io_task = task->dd_data; 484009a1093aSJohn Soni Jose struct iscsi_conn *conn = task->conn; 484109a1093aSJohn Soni Jose struct beiscsi_conn *beiscsi_conn = conn->dd_data; 484209a1093aSJohn Soni Jose struct beiscsi_hba *phba = beiscsi_conn->phba; 484309a1093aSJohn Soni Jose struct iscsi_wrb *pwrb = NULL; 484409a1093aSJohn Soni Jose unsigned int doorbell = 0; 484509a1093aSJohn Soni Jose 484609a1093aSJohn Soni Jose pwrb = io_task->pwrb_handle->pwrb; 484709a1093aSJohn Soni Jose 484809a1093aSJohn Soni Jose io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; 484909a1093aSJohn Soni Jose io_task->bhs_len = sizeof(struct be_cmd_bhs); 485009a1093aSJohn Soni Jose 485109a1093aSJohn Soni Jose if (writedir) { 485209a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb, 485309a1093aSJohn Soni Jose INI_WR_CMD); 485409a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 1); 485509a1093aSJohn Soni Jose } else { 485609a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb, 485709a1093aSJohn Soni Jose INI_RD_CMD); 485809a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 0); 485909a1093aSJohn Soni Jose } 486009a1093aSJohn Soni Jose 486109a1093aSJohn Soni Jose io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb_v2, 486209a1093aSJohn Soni Jose type, pwrb); 486309a1093aSJohn Soni Jose 486409a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, lun, pwrb, 486509a1093aSJohn Soni Jose cpu_to_be16(*(unsigned short *) 486609a1093aSJohn Soni Jose &io_task->cmd_bhs->iscsi_hdr.lun)); 486709a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, xferlen); 486809a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, 486909a1093aSJohn Soni Jose io_task->pwrb_handle->wrb_index); 487009a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, 487109a1093aSJohn Soni Jose be32_to_cpu(task->cmdsn)); 487209a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, 487309a1093aSJohn Soni Jose io_task->psgl_handle->sgl_index); 487409a1093aSJohn Soni Jose 487509a1093aSJohn Soni Jose hwi_write_sgl_v2(pwrb, sg, num_sg, io_task); 487609a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, 487709a1093aSJohn Soni Jose io_task->pwrb_handle->nxt_wrb_index); 487809a1093aSJohn Soni Jose 487909a1093aSJohn Soni Jose be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); 488009a1093aSJohn Soni Jose 488109a1093aSJohn Soni Jose doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; 488209a1093aSJohn Soni Jose doorbell |= (io_task->pwrb_handle->wrb_index & 488309a1093aSJohn Soni Jose DB_DEF_PDU_WRB_INDEX_MASK) << 488409a1093aSJohn Soni Jose DB_DEF_PDU_WRB_INDEX_SHIFT; 488509a1093aSJohn Soni Jose doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; 48861e4be6ffSJayamohan Kallickal iowrite32(doorbell, phba->db_va + 48871e4be6ffSJayamohan Kallickal beiscsi_conn->doorbell_offset); 488809a1093aSJohn Soni Jose return 0; 488909a1093aSJohn Soni Jose } 48906733b39aSJayamohan Kallickal 48916733b39aSJayamohan Kallickal static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, 48926733b39aSJayamohan Kallickal unsigned int num_sg, unsigned int xferlen, 48936733b39aSJayamohan Kallickal unsigned int writedir) 48946733b39aSJayamohan Kallickal { 48956733b39aSJayamohan Kallickal 48966733b39aSJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 48976733b39aSJayamohan Kallickal struct iscsi_conn *conn = task->conn; 48986733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn = conn->dd_data; 48996733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_conn->phba; 49006733b39aSJayamohan Kallickal struct iscsi_wrb *pwrb = NULL; 49016733b39aSJayamohan Kallickal unsigned int doorbell = 0; 49026733b39aSJayamohan Kallickal 49036733b39aSJayamohan Kallickal pwrb = io_task->pwrb_handle->pwrb; 49046733b39aSJayamohan Kallickal io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; 49056733b39aSJayamohan Kallickal io_task->bhs_len = sizeof(struct be_cmd_bhs); 49066733b39aSJayamohan Kallickal 49076733b39aSJayamohan Kallickal if (writedir) { 4908bfead3b2SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, 4909bfead3b2SJayamohan Kallickal INI_WR_CMD); 49106733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); 49116733b39aSJayamohan Kallickal } else { 4912bfead3b2SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, 4913bfead3b2SJayamohan Kallickal INI_RD_CMD); 49146733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); 49156733b39aSJayamohan Kallickal } 49166733b39aSJayamohan Kallickal 491709a1093aSJohn Soni Jose io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb, 491809a1093aSJohn Soni Jose type, pwrb); 491909a1093aSJohn Soni Jose 49206733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb, 4921dc63aac6SJayamohan Kallickal cpu_to_be16(*(unsigned short *) 4922dc63aac6SJayamohan Kallickal &io_task->cmd_bhs->iscsi_hdr.lun)); 49236733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen); 49246733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, 49256733b39aSJayamohan Kallickal io_task->pwrb_handle->wrb_index); 49266733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 49276733b39aSJayamohan Kallickal be32_to_cpu(task->cmdsn)); 49286733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, 49296733b39aSJayamohan Kallickal io_task->psgl_handle->sgl_index); 49306733b39aSJayamohan Kallickal 49316733b39aSJayamohan Kallickal hwi_write_sgl(pwrb, sg, num_sg, io_task); 49326733b39aSJayamohan Kallickal 49336733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, 49346733b39aSJayamohan Kallickal io_task->pwrb_handle->nxt_wrb_index); 49356733b39aSJayamohan Kallickal be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); 49366733b39aSJayamohan Kallickal 49376733b39aSJayamohan Kallickal doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; 49386733b39aSJayamohan Kallickal doorbell |= (io_task->pwrb_handle->wrb_index & 49396733b39aSJayamohan Kallickal DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; 49406733b39aSJayamohan Kallickal doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; 49416733b39aSJayamohan Kallickal 49421e4be6ffSJayamohan Kallickal iowrite32(doorbell, phba->db_va + 49431e4be6ffSJayamohan Kallickal beiscsi_conn->doorbell_offset); 49446733b39aSJayamohan Kallickal return 0; 49456733b39aSJayamohan Kallickal } 49466733b39aSJayamohan Kallickal 49476733b39aSJayamohan Kallickal static int beiscsi_mtask(struct iscsi_task *task) 49486733b39aSJayamohan Kallickal { 4949dafab8e0SJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 49506733b39aSJayamohan Kallickal struct iscsi_conn *conn = task->conn; 49516733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn = conn->dd_data; 49526733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_conn->phba; 49536733b39aSJayamohan Kallickal struct iscsi_wrb *pwrb = NULL; 49546733b39aSJayamohan Kallickal unsigned int doorbell = 0; 4955dafab8e0SJayamohan Kallickal unsigned int cid; 495609a1093aSJohn Soni Jose unsigned int pwrb_typeoffset = 0; 49576733b39aSJayamohan Kallickal 4958bfead3b2SJayamohan Kallickal cid = beiscsi_conn->beiscsi_conn_cid; 49596733b39aSJayamohan Kallickal pwrb = io_task->pwrb_handle->pwrb; 4960caf818f1SJayamohan Kallickal memset(pwrb, 0, sizeof(*pwrb)); 496109a1093aSJohn Soni Jose 49622c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) { 49636733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 49646733b39aSJayamohan Kallickal be32_to_cpu(task->cmdsn)); 49656733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, 49666733b39aSJayamohan Kallickal io_task->pwrb_handle->wrb_index); 49676733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, 49686733b39aSJayamohan Kallickal io_task->psgl_handle->sgl_index); 496909a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, 497009a1093aSJohn Soni Jose task->data_count); 497109a1093aSJohn Soni Jose AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, 497209a1093aSJohn Soni Jose io_task->pwrb_handle->nxt_wrb_index); 497309a1093aSJohn Soni Jose pwrb_typeoffset = BE_WRB_TYPE_OFFSET; 49742c9dfd36SJayamohan Kallickal } else { 49752c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, 49762c9dfd36SJayamohan Kallickal be32_to_cpu(task->cmdsn)); 49772c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, 49782c9dfd36SJayamohan Kallickal io_task->pwrb_handle->wrb_index); 49792c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, 49802c9dfd36SJayamohan Kallickal io_task->psgl_handle->sgl_index); 49812c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, 49822c9dfd36SJayamohan Kallickal task->data_count); 49832c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, 49842c9dfd36SJayamohan Kallickal io_task->pwrb_handle->nxt_wrb_index); 49852c9dfd36SJayamohan Kallickal pwrb_typeoffset = SKH_WRB_TYPE_OFFSET; 498609a1093aSJohn Soni Jose } 498709a1093aSJohn Soni Jose 4988dafab8e0SJayamohan Kallickal 49896733b39aSJayamohan Kallickal switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { 49906733b39aSJayamohan Kallickal case ISCSI_OP_LOGIN: 49916733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1); 499209a1093aSJohn Soni Jose ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); 49936733b39aSJayamohan Kallickal hwi_write_buffer(pwrb, task); 49946733b39aSJayamohan Kallickal break; 49956733b39aSJayamohan Kallickal case ISCSI_OP_NOOP_OUT: 49961390b01bSJayamohan Kallickal if (task->hdr->ttt != ISCSI_RESERVED_TAG) { 499709a1093aSJohn Soni Jose ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); 49982c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) 49992c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, 500009a1093aSJohn Soni Jose dmsg, pwrb, 1); 500109a1093aSJohn Soni Jose else 50022c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 500309a1093aSJohn Soni Jose dmsg, pwrb, 1); 50041390b01bSJayamohan Kallickal } else { 500509a1093aSJohn Soni Jose ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset); 50062c9dfd36SJayamohan Kallickal if (is_chip_be2_be3r(phba)) 50072c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb, 500809a1093aSJohn Soni Jose dmsg, pwrb, 0); 500909a1093aSJohn Soni Jose else 50102c9dfd36SJayamohan Kallickal AMAP_SET_BITS(struct amap_iscsi_wrb_v2, 501109a1093aSJohn Soni Jose dmsg, pwrb, 0); 50121390b01bSJayamohan Kallickal } 50136733b39aSJayamohan Kallickal hwi_write_buffer(pwrb, task); 50146733b39aSJayamohan Kallickal break; 50156733b39aSJayamohan Kallickal case ISCSI_OP_TEXT: 501609a1093aSJohn Soni Jose ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); 50176733b39aSJayamohan Kallickal hwi_write_buffer(pwrb, task); 50186733b39aSJayamohan Kallickal break; 50196733b39aSJayamohan Kallickal case ISCSI_OP_SCSI_TMFUNC: 502009a1093aSJohn Soni Jose ADAPTER_SET_WRB_TYPE(pwrb, INI_TMF_CMD, pwrb_typeoffset); 50216733b39aSJayamohan Kallickal hwi_write_buffer(pwrb, task); 50226733b39aSJayamohan Kallickal break; 50236733b39aSJayamohan Kallickal case ISCSI_OP_LOGOUT: 502409a1093aSJohn Soni Jose ADAPTER_SET_WRB_TYPE(pwrb, HWH_TYPE_LOGOUT, pwrb_typeoffset); 50256733b39aSJayamohan Kallickal hwi_write_buffer(pwrb, task); 50266733b39aSJayamohan Kallickal break; 50276733b39aSJayamohan Kallickal 50286733b39aSJayamohan Kallickal default: 502999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 503099bc5d55SJohn Soni Jose "BM_%d : opcode =%d Not supported\n", 50316733b39aSJayamohan Kallickal task->hdr->opcode & ISCSI_OPCODE_MASK); 503299bc5d55SJohn Soni Jose 50336733b39aSJayamohan Kallickal return -EINVAL; 50346733b39aSJayamohan Kallickal } 50356733b39aSJayamohan Kallickal 503609a1093aSJohn Soni Jose /* Set the task type */ 50372c9dfd36SJayamohan Kallickal io_task->wrb_type = (is_chip_be2_be3r(phba)) ? 50382c9dfd36SJayamohan Kallickal AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb) : 50392c9dfd36SJayamohan Kallickal AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb); 50406733b39aSJayamohan Kallickal 5041bfead3b2SJayamohan Kallickal doorbell |= cid & DB_WRB_POST_CID_MASK; 50426733b39aSJayamohan Kallickal doorbell |= (io_task->pwrb_handle->wrb_index & 50436733b39aSJayamohan Kallickal DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; 50446733b39aSJayamohan Kallickal doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; 50451e4be6ffSJayamohan Kallickal iowrite32(doorbell, phba->db_va + 50461e4be6ffSJayamohan Kallickal beiscsi_conn->doorbell_offset); 50476733b39aSJayamohan Kallickal return 0; 50486733b39aSJayamohan Kallickal } 50496733b39aSJayamohan Kallickal 50506733b39aSJayamohan Kallickal static int beiscsi_task_xmit(struct iscsi_task *task) 50516733b39aSJayamohan Kallickal { 50526733b39aSJayamohan Kallickal struct beiscsi_io_task *io_task = task->dd_data; 50536733b39aSJayamohan Kallickal struct scsi_cmnd *sc = task->sc; 505409a1093aSJohn Soni Jose struct beiscsi_hba *phba = NULL; 50556733b39aSJayamohan Kallickal struct scatterlist *sg; 50566733b39aSJayamohan Kallickal int num_sg; 50576733b39aSJayamohan Kallickal unsigned int writedir = 0, xferlen = 0; 50586733b39aSJayamohan Kallickal 505909a1093aSJohn Soni Jose phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba; 506009a1093aSJohn Soni Jose 50616733b39aSJayamohan Kallickal if (!sc) 50626733b39aSJayamohan Kallickal return beiscsi_mtask(task); 50636733b39aSJayamohan Kallickal 50646733b39aSJayamohan Kallickal io_task->scsi_cmnd = sc; 50656733b39aSJayamohan Kallickal num_sg = scsi_dma_map(sc); 50666733b39aSJayamohan Kallickal if (num_sg < 0) { 506799bc5d55SJohn Soni Jose struct iscsi_conn *conn = task->conn; 506899bc5d55SJohn Soni Jose struct beiscsi_hba *phba = NULL; 506999bc5d55SJohn Soni Jose 507099bc5d55SJohn Soni Jose phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 5071afb96058SJayamohan Kallickal beiscsi_log(phba, KERN_ERR, 5072afb96058SJayamohan Kallickal BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, 5073afb96058SJayamohan Kallickal "BM_%d : scsi_dma_map Failed " 5074afb96058SJayamohan Kallickal "Driver_ITT : 0x%x ITT : 0x%x Xferlen : 0x%x\n", 5075afb96058SJayamohan Kallickal be32_to_cpu(io_task->cmd_bhs->iscsi_hdr.itt), 5076afb96058SJayamohan Kallickal io_task->libiscsi_itt, scsi_bufflen(sc)); 507799bc5d55SJohn Soni Jose 50786733b39aSJayamohan Kallickal return num_sg; 50796733b39aSJayamohan Kallickal } 50806733b39aSJayamohan Kallickal xferlen = scsi_bufflen(sc); 50816733b39aSJayamohan Kallickal sg = scsi_sglist(sc); 508299bc5d55SJohn Soni Jose if (sc->sc_data_direction == DMA_TO_DEVICE) 50836733b39aSJayamohan Kallickal writedir = 1; 508499bc5d55SJohn Soni Jose else 50856733b39aSJayamohan Kallickal writedir = 0; 508699bc5d55SJohn Soni Jose 508709a1093aSJohn Soni Jose return phba->iotask_fn(task, sg, num_sg, xferlen, writedir); 50886733b39aSJayamohan Kallickal } 50896733b39aSJayamohan Kallickal 5090ffce3e2eSJayamohan Kallickal /** 5091ffce3e2eSJayamohan Kallickal * beiscsi_bsg_request - handle bsg request from ISCSI transport 5092ffce3e2eSJayamohan Kallickal * @job: job to handle 5093ffce3e2eSJayamohan Kallickal */ 5094ffce3e2eSJayamohan Kallickal static int beiscsi_bsg_request(struct bsg_job *job) 5095ffce3e2eSJayamohan Kallickal { 5096ffce3e2eSJayamohan Kallickal struct Scsi_Host *shost; 5097ffce3e2eSJayamohan Kallickal struct beiscsi_hba *phba; 5098ffce3e2eSJayamohan Kallickal struct iscsi_bsg_request *bsg_req = job->request; 5099ffce3e2eSJayamohan Kallickal int rc = -EINVAL; 5100ffce3e2eSJayamohan Kallickal unsigned int tag; 5101ffce3e2eSJayamohan Kallickal struct be_dma_mem nonemb_cmd; 5102ffce3e2eSJayamohan Kallickal struct be_cmd_resp_hdr *resp; 5103ffce3e2eSJayamohan Kallickal struct iscsi_bsg_reply *bsg_reply = job->reply; 5104ffce3e2eSJayamohan Kallickal unsigned short status, extd_status; 5105ffce3e2eSJayamohan Kallickal 5106ffce3e2eSJayamohan Kallickal shost = iscsi_job_to_shost(job); 5107ffce3e2eSJayamohan Kallickal phba = iscsi_host_priv(shost); 5108ffce3e2eSJayamohan Kallickal 5109ffce3e2eSJayamohan Kallickal switch (bsg_req->msgcode) { 5110ffce3e2eSJayamohan Kallickal case ISCSI_BSG_HST_VENDOR: 5111ffce3e2eSJayamohan Kallickal nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, 5112ffce3e2eSJayamohan Kallickal job->request_payload.payload_len, 5113ffce3e2eSJayamohan Kallickal &nonemb_cmd.dma); 5114ffce3e2eSJayamohan Kallickal if (nonemb_cmd.va == NULL) { 511599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 511699bc5d55SJohn Soni Jose "BM_%d : Failed to allocate memory for " 5117ffce3e2eSJayamohan Kallickal "beiscsi_bsg_request\n"); 51188359c79bSJohn Soni Jose return -ENOMEM; 5119ffce3e2eSJayamohan Kallickal } 5120ffce3e2eSJayamohan Kallickal tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job, 5121ffce3e2eSJayamohan Kallickal &nonemb_cmd); 5122ffce3e2eSJayamohan Kallickal if (!tag) { 512399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 51248359c79bSJohn Soni Jose "BM_%d : MBX Tag Allocation Failed\n"); 512599bc5d55SJohn Soni Jose 5126ffce3e2eSJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 5127ffce3e2eSJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 5128ffce3e2eSJayamohan Kallickal return -EAGAIN; 5129e175defeSJohn Soni Jose } 5130e175defeSJohn Soni Jose 5131e175defeSJohn Soni Jose rc = wait_event_interruptible_timeout( 5132e175defeSJohn Soni Jose phba->ctrl.mcc_wait[tag], 5133e175defeSJohn Soni Jose phba->ctrl.mcc_numtag[tag], 5134e175defeSJohn Soni Jose msecs_to_jiffies( 5135e175defeSJohn Soni Jose BEISCSI_HOST_MBX_TIMEOUT)); 5136ffce3e2eSJayamohan Kallickal extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; 5137ffce3e2eSJayamohan Kallickal status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; 5138ffce3e2eSJayamohan Kallickal free_mcc_tag(&phba->ctrl, tag); 5139ffce3e2eSJayamohan Kallickal resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va; 5140ffce3e2eSJayamohan Kallickal sg_copy_from_buffer(job->reply_payload.sg_list, 5141ffce3e2eSJayamohan Kallickal job->reply_payload.sg_cnt, 5142ffce3e2eSJayamohan Kallickal nonemb_cmd.va, (resp->response_length 5143ffce3e2eSJayamohan Kallickal + sizeof(*resp))); 5144ffce3e2eSJayamohan Kallickal bsg_reply->reply_payload_rcv_len = resp->response_length; 5145ffce3e2eSJayamohan Kallickal bsg_reply->result = status; 5146ffce3e2eSJayamohan Kallickal bsg_job_done(job, bsg_reply->result, 5147ffce3e2eSJayamohan Kallickal bsg_reply->reply_payload_rcv_len); 5148ffce3e2eSJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 5149ffce3e2eSJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 5150ffce3e2eSJayamohan Kallickal if (status || extd_status) { 515199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 51528359c79bSJohn Soni Jose "BM_%d : MBX Cmd Failed" 5153ffce3e2eSJayamohan Kallickal " status = %d extd_status = %d\n", 5154ffce3e2eSJayamohan Kallickal status, extd_status); 515599bc5d55SJohn Soni Jose 5156ffce3e2eSJayamohan Kallickal return -EIO; 51578359c79bSJohn Soni Jose } else { 51588359c79bSJohn Soni Jose rc = 0; 5159ffce3e2eSJayamohan Kallickal } 5160ffce3e2eSJayamohan Kallickal break; 5161ffce3e2eSJayamohan Kallickal 5162ffce3e2eSJayamohan Kallickal default: 516399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 516499bc5d55SJohn Soni Jose "BM_%d : Unsupported bsg command: 0x%x\n", 5165ffce3e2eSJayamohan Kallickal bsg_req->msgcode); 5166ffce3e2eSJayamohan Kallickal break; 5167ffce3e2eSJayamohan Kallickal } 5168ffce3e2eSJayamohan Kallickal 5169ffce3e2eSJayamohan Kallickal return rc; 5170ffce3e2eSJayamohan Kallickal } 5171ffce3e2eSJayamohan Kallickal 517299bc5d55SJohn Soni Jose void beiscsi_hba_attrs_init(struct beiscsi_hba *phba) 517399bc5d55SJohn Soni Jose { 517499bc5d55SJohn Soni Jose /* Set the logging parameter */ 517599bc5d55SJohn Soni Jose beiscsi_log_enable_init(phba, beiscsi_log_enable); 517699bc5d55SJohn Soni Jose } 517799bc5d55SJohn Soni Jose 51784d4d1ef8SJohn Soni Jose /* 51794d4d1ef8SJohn Soni Jose * beiscsi_quiesce()- Cleanup Driver resources 51804d4d1ef8SJohn Soni Jose * @phba: Instance Priv structure 51813567f36aSJayamohan Kallickal * @unload_state:i Clean or EEH unload state 51824d4d1ef8SJohn Soni Jose * 51834d4d1ef8SJohn Soni Jose * Free the OS and HW resources held by the driver 51844d4d1ef8SJohn Soni Jose **/ 51853567f36aSJayamohan Kallickal static void beiscsi_quiesce(struct beiscsi_hba *phba, 51863567f36aSJayamohan Kallickal uint32_t unload_state) 51876733b39aSJayamohan Kallickal { 5188bfead3b2SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 5189bfead3b2SJayamohan Kallickal struct hwi_context_memory *phwi_context; 5190bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 5191bfead3b2SJayamohan Kallickal unsigned int i, msix_vec; 51926733b39aSJayamohan Kallickal 5193bfead3b2SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 5194bfead3b2SJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 51956733b39aSJayamohan Kallickal hwi_disable_intr(phba); 5196bfead3b2SJayamohan Kallickal if (phba->msix_enabled) { 5197bfead3b2SJayamohan Kallickal for (i = 0; i <= phba->num_cpus; i++) { 5198bfead3b2SJayamohan Kallickal msix_vec = phba->msix_entries[i].vector; 51993567f36aSJayamohan Kallickal synchronize_irq(msix_vec); 5200bfead3b2SJayamohan Kallickal free_irq(msix_vec, &phwi_context->be_eq[i]); 52018fcfb210SJayamohan Kallickal kfree(phba->msi_name[i]); 5202bfead3b2SJayamohan Kallickal } 5203bfead3b2SJayamohan Kallickal } else 52043567f36aSJayamohan Kallickal if (phba->pcidev->irq) { 52053567f36aSJayamohan Kallickal synchronize_irq(phba->pcidev->irq); 52066733b39aSJayamohan Kallickal free_irq(phba->pcidev->irq, phba); 52073567f36aSJayamohan Kallickal } 5208bfead3b2SJayamohan Kallickal pci_disable_msix(phba->pcidev); 52093567f36aSJayamohan Kallickal 5210bfead3b2SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 5211bfead3b2SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 5212bfead3b2SJayamohan Kallickal blk_iopoll_disable(&pbe_eq->iopoll); 5213bfead3b2SJayamohan Kallickal } 52146733b39aSJayamohan Kallickal 52153567f36aSJayamohan Kallickal if (unload_state == BEISCSI_CLEAN_UNLOAD) { 52163567f36aSJayamohan Kallickal destroy_workqueue(phba->wq); 52176733b39aSJayamohan Kallickal beiscsi_clean_port(phba); 52186733b39aSJayamohan Kallickal beiscsi_free_mem(phba); 5219e9b91193SJayamohan Kallickal 52206733b39aSJayamohan Kallickal beiscsi_unmap_pci_function(phba); 52216733b39aSJayamohan Kallickal pci_free_consistent(phba->pcidev, 52226733b39aSJayamohan Kallickal phba->ctrl.mbox_mem_alloced.size, 52236733b39aSJayamohan Kallickal phba->ctrl.mbox_mem_alloced.va, 52246733b39aSJayamohan Kallickal phba->ctrl.mbox_mem_alloced.dma); 52253567f36aSJayamohan Kallickal } else { 52263567f36aSJayamohan Kallickal hwi_purge_eq(phba); 52273567f36aSJayamohan Kallickal hwi_cleanup(phba); 52283567f36aSJayamohan Kallickal } 52297a158003SJohn Soni Jose 52307a158003SJohn Soni Jose cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); 523125602c97SJayamohan Kallickal } 523225602c97SJayamohan Kallickal 523325602c97SJayamohan Kallickal static void beiscsi_remove(struct pci_dev *pcidev) 523425602c97SJayamohan Kallickal { 523525602c97SJayamohan Kallickal 523625602c97SJayamohan Kallickal struct beiscsi_hba *phba = NULL; 523725602c97SJayamohan Kallickal 523825602c97SJayamohan Kallickal phba = pci_get_drvdata(pcidev); 523925602c97SJayamohan Kallickal if (!phba) { 524025602c97SJayamohan Kallickal dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); 524125602c97SJayamohan Kallickal return; 524225602c97SJayamohan Kallickal } 524325602c97SJayamohan Kallickal 52440e43895eSMike Christie beiscsi_destroy_def_ifaces(phba); 52453567f36aSJayamohan Kallickal beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); 52460b1d3cbfSJayamohan Kallickal iscsi_boot_destroy_kset(phba->boot_kset); 52476733b39aSJayamohan Kallickal iscsi_host_remove(phba->shost); 52486733b39aSJayamohan Kallickal pci_dev_put(phba->pcidev); 52496733b39aSJayamohan Kallickal iscsi_host_free(phba->shost); 52503567f36aSJayamohan Kallickal pci_disable_pcie_error_reporting(pcidev); 52513567f36aSJayamohan Kallickal pci_set_drvdata(pcidev, NULL); 52528dce69ffSJayamohan Kallickal pci_disable_device(pcidev); 52536733b39aSJayamohan Kallickal } 52546733b39aSJayamohan Kallickal 525525602c97SJayamohan Kallickal static void beiscsi_shutdown(struct pci_dev *pcidev) 525625602c97SJayamohan Kallickal { 525725602c97SJayamohan Kallickal 525825602c97SJayamohan Kallickal struct beiscsi_hba *phba = NULL; 525925602c97SJayamohan Kallickal 526025602c97SJayamohan Kallickal phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); 526125602c97SJayamohan Kallickal if (!phba) { 526225602c97SJayamohan Kallickal dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n"); 526325602c97SJayamohan Kallickal return; 526425602c97SJayamohan Kallickal } 526525602c97SJayamohan Kallickal 52669343be74SJayamohan Kallickal phba->state = BE_ADAPTER_STATE_SHUTDOWN; 52679343be74SJayamohan Kallickal iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); 52683567f36aSJayamohan Kallickal beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); 52698dce69ffSJayamohan Kallickal pci_disable_device(pcidev); 527025602c97SJayamohan Kallickal } 527125602c97SJayamohan Kallickal 5272bfead3b2SJayamohan Kallickal static void beiscsi_msix_enable(struct beiscsi_hba *phba) 5273bfead3b2SJayamohan Kallickal { 5274bfead3b2SJayamohan Kallickal int i, status; 5275bfead3b2SJayamohan Kallickal 5276bfead3b2SJayamohan Kallickal for (i = 0; i <= phba->num_cpus; i++) 5277bfead3b2SJayamohan Kallickal phba->msix_entries[i].entry = i; 5278bfead3b2SJayamohan Kallickal 5279bfead3b2SJayamohan Kallickal status = pci_enable_msix(phba->pcidev, phba->msix_entries, 5280bfead3b2SJayamohan Kallickal (phba->num_cpus + 1)); 5281bfead3b2SJayamohan Kallickal if (!status) 5282bfead3b2SJayamohan Kallickal phba->msix_enabled = true; 5283bfead3b2SJayamohan Kallickal 5284bfead3b2SJayamohan Kallickal return; 5285bfead3b2SJayamohan Kallickal } 5286bfead3b2SJayamohan Kallickal 528773af08e1SJayamohan Kallickal static void be_eqd_update(struct beiscsi_hba *phba) 528873af08e1SJayamohan Kallickal { 528973af08e1SJayamohan Kallickal struct be_set_eqd set_eqd[MAX_CPUS]; 529073af08e1SJayamohan Kallickal struct be_aic_obj *aic; 529173af08e1SJayamohan Kallickal struct be_eq_obj *pbe_eq; 529273af08e1SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 529373af08e1SJayamohan Kallickal struct hwi_context_memory *phwi_context; 529473af08e1SJayamohan Kallickal int eqd, i, num = 0; 529573af08e1SJayamohan Kallickal ulong now; 529673af08e1SJayamohan Kallickal u32 pps, delta; 529773af08e1SJayamohan Kallickal unsigned int tag; 529873af08e1SJayamohan Kallickal 529973af08e1SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 530073af08e1SJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 530173af08e1SJayamohan Kallickal 530273af08e1SJayamohan Kallickal for (i = 0; i <= phba->num_cpus; i++) { 530373af08e1SJayamohan Kallickal aic = &phba->aic_obj[i]; 530473af08e1SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 530573af08e1SJayamohan Kallickal now = jiffies; 530673af08e1SJayamohan Kallickal if (!aic->jiffs || time_before(now, aic->jiffs) || 530773af08e1SJayamohan Kallickal pbe_eq->cq_count < aic->eq_prev) { 530873af08e1SJayamohan Kallickal aic->jiffs = now; 530973af08e1SJayamohan Kallickal aic->eq_prev = pbe_eq->cq_count; 531073af08e1SJayamohan Kallickal continue; 531173af08e1SJayamohan Kallickal } 531273af08e1SJayamohan Kallickal delta = jiffies_to_msecs(now - aic->jiffs); 531373af08e1SJayamohan Kallickal pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); 531473af08e1SJayamohan Kallickal eqd = (pps / 1500) << 2; 531573af08e1SJayamohan Kallickal 531673af08e1SJayamohan Kallickal if (eqd < 8) 531773af08e1SJayamohan Kallickal eqd = 0; 531873af08e1SJayamohan Kallickal eqd = min_t(u32, eqd, phwi_context->max_eqd); 531973af08e1SJayamohan Kallickal eqd = max_t(u32, eqd, phwi_context->min_eqd); 532073af08e1SJayamohan Kallickal 532173af08e1SJayamohan Kallickal aic->jiffs = now; 532273af08e1SJayamohan Kallickal aic->eq_prev = pbe_eq->cq_count; 532373af08e1SJayamohan Kallickal 532473af08e1SJayamohan Kallickal if (eqd != aic->prev_eqd) { 532573af08e1SJayamohan Kallickal set_eqd[num].delay_multiplier = (eqd * 65)/100; 532673af08e1SJayamohan Kallickal set_eqd[num].eq_id = pbe_eq->q.id; 532773af08e1SJayamohan Kallickal aic->prev_eqd = eqd; 532873af08e1SJayamohan Kallickal num++; 532973af08e1SJayamohan Kallickal } 533073af08e1SJayamohan Kallickal } 533173af08e1SJayamohan Kallickal if (num) { 533273af08e1SJayamohan Kallickal tag = be_cmd_modify_eq_delay(phba, set_eqd, num); 533373af08e1SJayamohan Kallickal if (tag) 533473af08e1SJayamohan Kallickal beiscsi_mccq_compl(phba, tag, NULL, NULL); 533573af08e1SJayamohan Kallickal } 533673af08e1SJayamohan Kallickal } 533773af08e1SJayamohan Kallickal 53387a158003SJohn Soni Jose /* 53397a158003SJohn Soni Jose * beiscsi_hw_health_check()- Check adapter health 53407a158003SJohn Soni Jose * @work: work item to check HW health 53417a158003SJohn Soni Jose * 53427a158003SJohn Soni Jose * Check if adapter in an unrecoverable state or not. 53437a158003SJohn Soni Jose **/ 53447a158003SJohn Soni Jose static void 53457a158003SJohn Soni Jose beiscsi_hw_health_check(struct work_struct *work) 53467a158003SJohn Soni Jose { 53477a158003SJohn Soni Jose struct beiscsi_hba *phba = 53487a158003SJohn Soni Jose container_of(work, struct beiscsi_hba, 53497a158003SJohn Soni Jose beiscsi_hw_check_task.work); 53507a158003SJohn Soni Jose 535173af08e1SJayamohan Kallickal be_eqd_update(phba); 535273af08e1SJayamohan Kallickal 53537a158003SJohn Soni Jose beiscsi_ue_detect(phba); 53547a158003SJohn Soni Jose 53557a158003SJohn Soni Jose schedule_delayed_work(&phba->beiscsi_hw_check_task, 53567a158003SJohn Soni Jose msecs_to_jiffies(1000)); 53577a158003SJohn Soni Jose } 53587a158003SJohn Soni Jose 53593567f36aSJayamohan Kallickal 53603567f36aSJayamohan Kallickal static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, 53613567f36aSJayamohan Kallickal pci_channel_state_t state) 53623567f36aSJayamohan Kallickal { 53633567f36aSJayamohan Kallickal struct beiscsi_hba *phba = NULL; 53643567f36aSJayamohan Kallickal 53653567f36aSJayamohan Kallickal phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); 53663567f36aSJayamohan Kallickal phba->state |= BE_ADAPTER_PCI_ERR; 53673567f36aSJayamohan Kallickal 53683567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 53693567f36aSJayamohan Kallickal "BM_%d : EEH error detected\n"); 53703567f36aSJayamohan Kallickal 53713567f36aSJayamohan Kallickal beiscsi_quiesce(phba, BEISCSI_EEH_UNLOAD); 53723567f36aSJayamohan Kallickal 53733567f36aSJayamohan Kallickal if (state == pci_channel_io_perm_failure) { 53743567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 53753567f36aSJayamohan Kallickal "BM_%d : EEH : State PERM Failure"); 53763567f36aSJayamohan Kallickal return PCI_ERS_RESULT_DISCONNECT; 53773567f36aSJayamohan Kallickal } 53783567f36aSJayamohan Kallickal 53793567f36aSJayamohan Kallickal pci_disable_device(pdev); 53803567f36aSJayamohan Kallickal 53813567f36aSJayamohan Kallickal /* The error could cause the FW to trigger a flash debug dump. 53823567f36aSJayamohan Kallickal * Resetting the card while flash dump is in progress 53833567f36aSJayamohan Kallickal * can cause it not to recover; wait for it to finish. 53843567f36aSJayamohan Kallickal * Wait only for first function as it is needed only once per 53853567f36aSJayamohan Kallickal * adapter. 53863567f36aSJayamohan Kallickal **/ 53873567f36aSJayamohan Kallickal if (pdev->devfn == 0) 53883567f36aSJayamohan Kallickal ssleep(30); 53893567f36aSJayamohan Kallickal 53903567f36aSJayamohan Kallickal return PCI_ERS_RESULT_NEED_RESET; 53913567f36aSJayamohan Kallickal } 53923567f36aSJayamohan Kallickal 53933567f36aSJayamohan Kallickal static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) 53943567f36aSJayamohan Kallickal { 53953567f36aSJayamohan Kallickal struct beiscsi_hba *phba = NULL; 53963567f36aSJayamohan Kallickal int status = 0; 53973567f36aSJayamohan Kallickal 53983567f36aSJayamohan Kallickal phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); 53993567f36aSJayamohan Kallickal 54003567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 54013567f36aSJayamohan Kallickal "BM_%d : EEH Reset\n"); 54023567f36aSJayamohan Kallickal 54033567f36aSJayamohan Kallickal status = pci_enable_device(pdev); 54043567f36aSJayamohan Kallickal if (status) 54053567f36aSJayamohan Kallickal return PCI_ERS_RESULT_DISCONNECT; 54063567f36aSJayamohan Kallickal 54073567f36aSJayamohan Kallickal pci_set_master(pdev); 54083567f36aSJayamohan Kallickal pci_set_power_state(pdev, PCI_D0); 54093567f36aSJayamohan Kallickal pci_restore_state(pdev); 54103567f36aSJayamohan Kallickal 54113567f36aSJayamohan Kallickal /* Wait for the CHIP Reset to complete */ 54123567f36aSJayamohan Kallickal status = be_chk_reset_complete(phba); 54133567f36aSJayamohan Kallickal if (!status) { 54143567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, 54153567f36aSJayamohan Kallickal "BM_%d : EEH Reset Completed\n"); 54163567f36aSJayamohan Kallickal } else { 54173567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, 54183567f36aSJayamohan Kallickal "BM_%d : EEH Reset Completion Failure\n"); 54193567f36aSJayamohan Kallickal return PCI_ERS_RESULT_DISCONNECT; 54203567f36aSJayamohan Kallickal } 54213567f36aSJayamohan Kallickal 54223567f36aSJayamohan Kallickal pci_cleanup_aer_uncorrect_error_status(pdev); 54233567f36aSJayamohan Kallickal return PCI_ERS_RESULT_RECOVERED; 54243567f36aSJayamohan Kallickal } 54253567f36aSJayamohan Kallickal 54263567f36aSJayamohan Kallickal static void beiscsi_eeh_resume(struct pci_dev *pdev) 54273567f36aSJayamohan Kallickal { 54283567f36aSJayamohan Kallickal int ret = 0, i; 54293567f36aSJayamohan Kallickal struct be_eq_obj *pbe_eq; 54303567f36aSJayamohan Kallickal struct beiscsi_hba *phba = NULL; 54313567f36aSJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 54323567f36aSJayamohan Kallickal struct hwi_context_memory *phwi_context; 54333567f36aSJayamohan Kallickal 54343567f36aSJayamohan Kallickal phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); 54353567f36aSJayamohan Kallickal pci_save_state(pdev); 54363567f36aSJayamohan Kallickal 54373567f36aSJayamohan Kallickal if (enable_msix) 54383567f36aSJayamohan Kallickal find_num_cpus(phba); 54393567f36aSJayamohan Kallickal else 54403567f36aSJayamohan Kallickal phba->num_cpus = 1; 54413567f36aSJayamohan Kallickal 54423567f36aSJayamohan Kallickal if (enable_msix) { 54433567f36aSJayamohan Kallickal beiscsi_msix_enable(phba); 54443567f36aSJayamohan Kallickal if (!phba->msix_enabled) 54453567f36aSJayamohan Kallickal phba->num_cpus = 1; 54463567f36aSJayamohan Kallickal } 54473567f36aSJayamohan Kallickal 54483567f36aSJayamohan Kallickal ret = beiscsi_cmd_reset_function(phba); 54493567f36aSJayamohan Kallickal if (ret) { 54503567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 54513567f36aSJayamohan Kallickal "BM_%d : Reset Failed\n"); 54523567f36aSJayamohan Kallickal goto ret_err; 54533567f36aSJayamohan Kallickal } 54543567f36aSJayamohan Kallickal 54553567f36aSJayamohan Kallickal ret = be_chk_reset_complete(phba); 54563567f36aSJayamohan Kallickal if (ret) { 54573567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 54583567f36aSJayamohan Kallickal "BM_%d : Failed to get out of reset.\n"); 54593567f36aSJayamohan Kallickal goto ret_err; 54603567f36aSJayamohan Kallickal } 54613567f36aSJayamohan Kallickal 54623567f36aSJayamohan Kallickal beiscsi_get_params(phba); 54633567f36aSJayamohan Kallickal phba->shost->max_id = phba->params.cxns_per_ctrl; 54643567f36aSJayamohan Kallickal phba->shost->can_queue = phba->params.ios_per_ctrl; 54653567f36aSJayamohan Kallickal ret = hwi_init_controller(phba); 54663567f36aSJayamohan Kallickal 54673567f36aSJayamohan Kallickal for (i = 0; i < MAX_MCC_CMD; i++) { 54683567f36aSJayamohan Kallickal init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); 54693567f36aSJayamohan Kallickal phba->ctrl.mcc_tag[i] = i + 1; 54703567f36aSJayamohan Kallickal phba->ctrl.mcc_numtag[i + 1] = 0; 54713567f36aSJayamohan Kallickal phba->ctrl.mcc_tag_available++; 54723567f36aSJayamohan Kallickal } 54733567f36aSJayamohan Kallickal 54743567f36aSJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 54753567f36aSJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 54763567f36aSJayamohan Kallickal 54773567f36aSJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 54783567f36aSJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 54793567f36aSJayamohan Kallickal blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, 54803567f36aSJayamohan Kallickal be_iopoll); 54813567f36aSJayamohan Kallickal blk_iopoll_enable(&pbe_eq->iopoll); 54823567f36aSJayamohan Kallickal } 54833567f36aSJayamohan Kallickal 54843567f36aSJayamohan Kallickal i = (phba->msix_enabled) ? i : 0; 54853567f36aSJayamohan Kallickal /* Work item for MCC handling */ 54863567f36aSJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 54873567f36aSJayamohan Kallickal INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); 54883567f36aSJayamohan Kallickal 54893567f36aSJayamohan Kallickal ret = beiscsi_init_irqs(phba); 54903567f36aSJayamohan Kallickal if (ret < 0) { 54913567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 54923567f36aSJayamohan Kallickal "BM_%d : beiscsi_eeh_resume - " 54933567f36aSJayamohan Kallickal "Failed to beiscsi_init_irqs\n"); 54943567f36aSJayamohan Kallickal goto ret_err; 54953567f36aSJayamohan Kallickal } 54963567f36aSJayamohan Kallickal 54973567f36aSJayamohan Kallickal hwi_enable_intr(phba); 54983567f36aSJayamohan Kallickal phba->state &= ~BE_ADAPTER_PCI_ERR; 54993567f36aSJayamohan Kallickal 55003567f36aSJayamohan Kallickal return; 55013567f36aSJayamohan Kallickal ret_err: 55023567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 55033567f36aSJayamohan Kallickal "BM_%d : AER EEH Resume Failed\n"); 55043567f36aSJayamohan Kallickal } 55053567f36aSJayamohan Kallickal 55066f039790SGreg Kroah-Hartman static int beiscsi_dev_probe(struct pci_dev *pcidev, 55076733b39aSJayamohan Kallickal const struct pci_device_id *id) 55086733b39aSJayamohan Kallickal { 55096733b39aSJayamohan Kallickal struct beiscsi_hba *phba = NULL; 5510bfead3b2SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 5511bfead3b2SJayamohan Kallickal struct hwi_context_memory *phwi_context; 5512bfead3b2SJayamohan Kallickal struct be_eq_obj *pbe_eq; 55133567f36aSJayamohan Kallickal int ret = 0, i; 55146733b39aSJayamohan Kallickal 55156733b39aSJayamohan Kallickal ret = beiscsi_enable_pci(pcidev); 55166733b39aSJayamohan Kallickal if (ret < 0) { 551799bc5d55SJohn Soni Jose dev_err(&pcidev->dev, 551899bc5d55SJohn Soni Jose "beiscsi_dev_probe - Failed to enable pci device\n"); 55196733b39aSJayamohan Kallickal return ret; 55206733b39aSJayamohan Kallickal } 55216733b39aSJayamohan Kallickal 55226733b39aSJayamohan Kallickal phba = beiscsi_hba_alloc(pcidev); 55236733b39aSJayamohan Kallickal if (!phba) { 552499bc5d55SJohn Soni Jose dev_err(&pcidev->dev, 552599bc5d55SJohn Soni Jose "beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n"); 55266733b39aSJayamohan Kallickal goto disable_pci; 55276733b39aSJayamohan Kallickal } 55286733b39aSJayamohan Kallickal 55293567f36aSJayamohan Kallickal /* Enable EEH reporting */ 55303567f36aSJayamohan Kallickal ret = pci_enable_pcie_error_reporting(pcidev); 55313567f36aSJayamohan Kallickal if (ret) 55323567f36aSJayamohan Kallickal beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, 55333567f36aSJayamohan Kallickal "BM_%d : PCIe Error Reporting " 55343567f36aSJayamohan Kallickal "Enabling Failed\n"); 55353567f36aSJayamohan Kallickal 55363567f36aSJayamohan Kallickal pci_save_state(pcidev); 55373567f36aSJayamohan Kallickal 553899bc5d55SJohn Soni Jose /* Initialize Driver configuration Paramters */ 553999bc5d55SJohn Soni Jose beiscsi_hba_attrs_init(phba); 554099bc5d55SJohn Soni Jose 5541e175defeSJohn Soni Jose phba->fw_timeout = false; 55426c83185aSJayamohan Kallickal phba->mac_addr_set = false; 5543e175defeSJohn Soni Jose 5544e175defeSJohn Soni Jose 5545f98c96b0SJayamohan Kallickal switch (pcidev->device) { 5546f98c96b0SJayamohan Kallickal case BE_DEVICE_ID1: 5547f98c96b0SJayamohan Kallickal case OC_DEVICE_ID1: 5548f98c96b0SJayamohan Kallickal case OC_DEVICE_ID2: 5549f98c96b0SJayamohan Kallickal phba->generation = BE_GEN2; 555009a1093aSJohn Soni Jose phba->iotask_fn = beiscsi_iotask; 5551f98c96b0SJayamohan Kallickal break; 5552f98c96b0SJayamohan Kallickal case BE_DEVICE_ID2: 5553f98c96b0SJayamohan Kallickal case OC_DEVICE_ID3: 5554f98c96b0SJayamohan Kallickal phba->generation = BE_GEN3; 555509a1093aSJohn Soni Jose phba->iotask_fn = beiscsi_iotask; 5556f98c96b0SJayamohan Kallickal break; 5557139a1b1eSJohn Soni Jose case OC_SKH_ID1: 5558139a1b1eSJohn Soni Jose phba->generation = BE_GEN4; 555909a1093aSJohn Soni Jose phba->iotask_fn = beiscsi_iotask_v2; 5560bf9131cbSJayamohan Kallickal break; 5561f98c96b0SJayamohan Kallickal default: 5562f98c96b0SJayamohan Kallickal phba->generation = 0; 5563f98c96b0SJayamohan Kallickal } 5564f98c96b0SJayamohan Kallickal 55656733b39aSJayamohan Kallickal ret = be_ctrl_init(phba, pcidev); 55666733b39aSJayamohan Kallickal if (ret) { 556799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 556899bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe-" 55696733b39aSJayamohan Kallickal "Failed in be_ctrl_init\n"); 55706733b39aSJayamohan Kallickal goto hba_free; 55716733b39aSJayamohan Kallickal } 55726733b39aSJayamohan Kallickal 5573e5285860SJayamohan Kallickal ret = beiscsi_cmd_reset_function(phba); 5574e9b91193SJayamohan Kallickal if (ret) { 557599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 557692665a66SJayamohan Kallickal "BM_%d : Reset Failed\n"); 5577e9b91193SJayamohan Kallickal goto hba_free; 5578e9b91193SJayamohan Kallickal } 5579e9b91193SJayamohan Kallickal ret = be_chk_reset_complete(phba); 5580e9b91193SJayamohan Kallickal if (ret) { 558199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 558292665a66SJayamohan Kallickal "BM_%d : Failed to get out of reset.\n"); 5583e9b91193SJayamohan Kallickal goto hba_free; 5584e9b91193SJayamohan Kallickal } 5585e9b91193SJayamohan Kallickal 55866733b39aSJayamohan Kallickal spin_lock_init(&phba->io_sgl_lock); 55876733b39aSJayamohan Kallickal spin_lock_init(&phba->mgmt_sgl_lock); 55886733b39aSJayamohan Kallickal spin_lock_init(&phba->isr_lock); 55898f09a3b9SJayamohan Kallickal spin_lock_init(&phba->async_pdu_lock); 55907da50879SJayamohan Kallickal ret = mgmt_get_fw_config(&phba->ctrl, phba); 55917da50879SJayamohan Kallickal if (ret != 0) { 559299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 559399bc5d55SJohn Soni Jose "BM_%d : Error getting fw config\n"); 55947da50879SJayamohan Kallickal goto free_port; 55957da50879SJayamohan Kallickal } 559668c26a3aSJayamohan Kallickal 559768c26a3aSJayamohan Kallickal if (enable_msix) 559868c26a3aSJayamohan Kallickal find_num_cpus(phba); 559968c26a3aSJayamohan Kallickal else 560068c26a3aSJayamohan Kallickal phba->num_cpus = 1; 560168c26a3aSJayamohan Kallickal 560268c26a3aSJayamohan Kallickal beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 560368c26a3aSJayamohan Kallickal "BM_%d : num_cpus = %d\n", 560468c26a3aSJayamohan Kallickal phba->num_cpus); 560568c26a3aSJayamohan Kallickal 560668c26a3aSJayamohan Kallickal if (enable_msix) { 560768c26a3aSJayamohan Kallickal beiscsi_msix_enable(phba); 560868c26a3aSJayamohan Kallickal if (!phba->msix_enabled) 560968c26a3aSJayamohan Kallickal phba->num_cpus = 1; 561068c26a3aSJayamohan Kallickal } 561168c26a3aSJayamohan Kallickal 5612843ae752SJayamohan Kallickal phba->shost->max_id = phba->params.cxns_per_ctrl; 56136733b39aSJayamohan Kallickal beiscsi_get_params(phba); 5614aa874f07SJayamohan Kallickal phba->shost->can_queue = phba->params.ios_per_ctrl; 56156733b39aSJayamohan Kallickal ret = beiscsi_init_port(phba); 56166733b39aSJayamohan Kallickal if (ret < 0) { 561799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 561899bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe-" 56196733b39aSJayamohan Kallickal "Failed in beiscsi_init_port\n"); 56206733b39aSJayamohan Kallickal goto free_port; 56216733b39aSJayamohan Kallickal } 56226733b39aSJayamohan Kallickal 5623756d29c8SJayamohan Kallickal for (i = 0; i < MAX_MCC_CMD; i++) { 5624756d29c8SJayamohan Kallickal init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); 5625756d29c8SJayamohan Kallickal phba->ctrl.mcc_tag[i] = i + 1; 5626756d29c8SJayamohan Kallickal phba->ctrl.mcc_numtag[i + 1] = 0; 5627756d29c8SJayamohan Kallickal phba->ctrl.mcc_tag_available++; 56281957aa7fSJayamohan Kallickal memset(&phba->ctrl.ptag_state[i].tag_mem_state, 0, 56298fc01eaaSJayamohan Kallickal sizeof(struct be_dma_mem)); 5630756d29c8SJayamohan Kallickal } 5631756d29c8SJayamohan Kallickal 5632756d29c8SJayamohan Kallickal phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; 5633756d29c8SJayamohan Kallickal 563472fb46a9SJohn Soni Jose snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq", 56356733b39aSJayamohan Kallickal phba->shost->host_no); 5636d8537548SKees Cook phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, phba->wq_name); 56376733b39aSJayamohan Kallickal if (!phba->wq) { 563899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 563999bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe-" 56406733b39aSJayamohan Kallickal "Failed to allocate work queue\n"); 56416733b39aSJayamohan Kallickal goto free_twq; 56426733b39aSJayamohan Kallickal } 56436733b39aSJayamohan Kallickal 56447a158003SJohn Soni Jose INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, 56457a158003SJohn Soni Jose beiscsi_hw_health_check); 56466733b39aSJayamohan Kallickal 5647bfead3b2SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 5648bfead3b2SJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 564972fb46a9SJohn Soni Jose 5650bfead3b2SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 5651bfead3b2SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 5652bfead3b2SJayamohan Kallickal blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, 5653bfead3b2SJayamohan Kallickal be_iopoll); 5654bfead3b2SJayamohan Kallickal blk_iopoll_enable(&pbe_eq->iopoll); 56556733b39aSJayamohan Kallickal } 565672fb46a9SJohn Soni Jose 565772fb46a9SJohn Soni Jose i = (phba->msix_enabled) ? i : 0; 565872fb46a9SJohn Soni Jose /* Work item for MCC handling */ 565972fb46a9SJohn Soni Jose pbe_eq = &phwi_context->be_eq[i]; 566072fb46a9SJohn Soni Jose INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); 566172fb46a9SJohn Soni Jose 56626733b39aSJayamohan Kallickal ret = beiscsi_init_irqs(phba); 56636733b39aSJayamohan Kallickal if (ret < 0) { 566499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 566599bc5d55SJohn Soni Jose "BM_%d : beiscsi_dev_probe-" 56666733b39aSJayamohan Kallickal "Failed to beiscsi_init_irqs\n"); 56676733b39aSJayamohan Kallickal goto free_blkenbld; 56686733b39aSJayamohan Kallickal } 5669238f6b72SJayamohan Kallickal hwi_enable_intr(phba); 5670f457a46fSMike Christie 56710598b8afSJayamohan Kallickal if (iscsi_host_add(phba->shost, &phba->pcidev->dev)) 56720598b8afSJayamohan Kallickal goto free_blkenbld; 56730598b8afSJayamohan Kallickal 5674f457a46fSMike Christie if (beiscsi_setup_boot_info(phba)) 5675f457a46fSMike Christie /* 5676f457a46fSMike Christie * log error but continue, because we may not be using 5677f457a46fSMike Christie * iscsi boot. 5678f457a46fSMike Christie */ 567999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, 568099bc5d55SJohn Soni Jose "BM_%d : Could not set up " 56810e43895eSMike Christie "iSCSI boot info.\n"); 5682f457a46fSMike Christie 56830e43895eSMike Christie beiscsi_create_def_ifaces(phba); 56847a158003SJohn Soni Jose schedule_delayed_work(&phba->beiscsi_hw_check_task, 56857a158003SJohn Soni Jose msecs_to_jiffies(1000)); 56867a158003SJohn Soni Jose 568799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, 568899bc5d55SJohn Soni Jose "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); 56896733b39aSJayamohan Kallickal return 0; 56906733b39aSJayamohan Kallickal 56916733b39aSJayamohan Kallickal free_blkenbld: 56926733b39aSJayamohan Kallickal destroy_workqueue(phba->wq); 5693bfead3b2SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 5694bfead3b2SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 5695bfead3b2SJayamohan Kallickal blk_iopoll_disable(&pbe_eq->iopoll); 5696bfead3b2SJayamohan Kallickal } 56976733b39aSJayamohan Kallickal free_twq: 56986733b39aSJayamohan Kallickal beiscsi_clean_port(phba); 56996733b39aSJayamohan Kallickal beiscsi_free_mem(phba); 57006733b39aSJayamohan Kallickal free_port: 57016733b39aSJayamohan Kallickal pci_free_consistent(phba->pcidev, 57026733b39aSJayamohan Kallickal phba->ctrl.mbox_mem_alloced.size, 57036733b39aSJayamohan Kallickal phba->ctrl.mbox_mem_alloced.va, 57046733b39aSJayamohan Kallickal phba->ctrl.mbox_mem_alloced.dma); 57056733b39aSJayamohan Kallickal beiscsi_unmap_pci_function(phba); 57066733b39aSJayamohan Kallickal hba_free: 5707238f6b72SJayamohan Kallickal if (phba->msix_enabled) 5708238f6b72SJayamohan Kallickal pci_disable_msix(phba->pcidev); 57096733b39aSJayamohan Kallickal iscsi_host_remove(phba->shost); 57106733b39aSJayamohan Kallickal pci_dev_put(phba->pcidev); 57116733b39aSJayamohan Kallickal iscsi_host_free(phba->shost); 57126733b39aSJayamohan Kallickal disable_pci: 57136733b39aSJayamohan Kallickal pci_disable_device(pcidev); 57146733b39aSJayamohan Kallickal return ret; 57156733b39aSJayamohan Kallickal } 57166733b39aSJayamohan Kallickal 57173567f36aSJayamohan Kallickal static struct pci_error_handlers beiscsi_eeh_handlers = { 57183567f36aSJayamohan Kallickal .error_detected = beiscsi_eeh_err_detected, 57193567f36aSJayamohan Kallickal .slot_reset = beiscsi_eeh_reset, 57203567f36aSJayamohan Kallickal .resume = beiscsi_eeh_resume, 57213567f36aSJayamohan Kallickal }; 57223567f36aSJayamohan Kallickal 57236733b39aSJayamohan Kallickal struct iscsi_transport beiscsi_iscsi_transport = { 57246733b39aSJayamohan Kallickal .owner = THIS_MODULE, 57256733b39aSJayamohan Kallickal .name = DRV_NAME, 57269db0fb3aSJayamohan Kallickal .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO | 57276733b39aSJayamohan Kallickal CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD, 57286733b39aSJayamohan Kallickal .create_session = beiscsi_session_create, 57296733b39aSJayamohan Kallickal .destroy_session = beiscsi_session_destroy, 57306733b39aSJayamohan Kallickal .create_conn = beiscsi_conn_create, 57316733b39aSJayamohan Kallickal .bind_conn = beiscsi_conn_bind, 57326733b39aSJayamohan Kallickal .destroy_conn = iscsi_conn_teardown, 57333128c6c7SMike Christie .attr_is_visible = be2iscsi_attr_is_visible, 57340e43895eSMike Christie .set_iface_param = be2iscsi_iface_set_param, 57350e43895eSMike Christie .get_iface_param = be2iscsi_iface_get_param, 57366733b39aSJayamohan Kallickal .set_param = beiscsi_set_param, 5737c7f7fd5bSMike Christie .get_conn_param = iscsi_conn_get_param, 57386733b39aSJayamohan Kallickal .get_session_param = iscsi_session_get_param, 57396733b39aSJayamohan Kallickal .get_host_param = beiscsi_get_host_param, 57406733b39aSJayamohan Kallickal .start_conn = beiscsi_conn_start, 5741fa95d206SMike Christie .stop_conn = iscsi_conn_stop, 57426733b39aSJayamohan Kallickal .send_pdu = iscsi_conn_send_pdu, 57436733b39aSJayamohan Kallickal .xmit_task = beiscsi_task_xmit, 57446733b39aSJayamohan Kallickal .cleanup_task = beiscsi_cleanup_task, 57456733b39aSJayamohan Kallickal .alloc_pdu = beiscsi_alloc_pdu, 57466733b39aSJayamohan Kallickal .parse_pdu_itt = beiscsi_parse_pdu, 57476733b39aSJayamohan Kallickal .get_stats = beiscsi_conn_get_stats, 5748c7f7fd5bSMike Christie .get_ep_param = beiscsi_ep_get_param, 57496733b39aSJayamohan Kallickal .ep_connect = beiscsi_ep_connect, 57506733b39aSJayamohan Kallickal .ep_poll = beiscsi_ep_poll, 57516733b39aSJayamohan Kallickal .ep_disconnect = beiscsi_ep_disconnect, 57526733b39aSJayamohan Kallickal .session_recovery_timedout = iscsi_session_recovery_timedout, 5753ffce3e2eSJayamohan Kallickal .bsg_request = beiscsi_bsg_request, 57546733b39aSJayamohan Kallickal }; 57556733b39aSJayamohan Kallickal 57566733b39aSJayamohan Kallickal static struct pci_driver beiscsi_pci_driver = { 57576733b39aSJayamohan Kallickal .name = DRV_NAME, 57586733b39aSJayamohan Kallickal .probe = beiscsi_dev_probe, 57596733b39aSJayamohan Kallickal .remove = beiscsi_remove, 576025602c97SJayamohan Kallickal .shutdown = beiscsi_shutdown, 57613567f36aSJayamohan Kallickal .id_table = beiscsi_pci_id_table, 57623567f36aSJayamohan Kallickal .err_handler = &beiscsi_eeh_handlers 57636733b39aSJayamohan Kallickal }; 57646733b39aSJayamohan Kallickal 5765bfead3b2SJayamohan Kallickal 57666733b39aSJayamohan Kallickal static int __init beiscsi_module_init(void) 57676733b39aSJayamohan Kallickal { 57686733b39aSJayamohan Kallickal int ret; 57696733b39aSJayamohan Kallickal 57706733b39aSJayamohan Kallickal beiscsi_scsi_transport = 57716733b39aSJayamohan Kallickal iscsi_register_transport(&beiscsi_iscsi_transport); 57726733b39aSJayamohan Kallickal if (!beiscsi_scsi_transport) { 577399bc5d55SJohn Soni Jose printk(KERN_ERR 577499bc5d55SJohn Soni Jose "beiscsi_module_init - Unable to register beiscsi transport.\n"); 5775f55a24f2SJayamohan Kallickal return -ENOMEM; 57766733b39aSJayamohan Kallickal } 577799bc5d55SJohn Soni Jose printk(KERN_INFO "In beiscsi_module_init, tt=%p\n", 57786733b39aSJayamohan Kallickal &beiscsi_iscsi_transport); 57796733b39aSJayamohan Kallickal 57806733b39aSJayamohan Kallickal ret = pci_register_driver(&beiscsi_pci_driver); 57816733b39aSJayamohan Kallickal if (ret) { 578299bc5d55SJohn Soni Jose printk(KERN_ERR 578399bc5d55SJohn Soni Jose "beiscsi_module_init - Unable to register beiscsi pci driver.\n"); 57846733b39aSJayamohan Kallickal goto unregister_iscsi_transport; 57856733b39aSJayamohan Kallickal } 57866733b39aSJayamohan Kallickal return 0; 57876733b39aSJayamohan Kallickal 57886733b39aSJayamohan Kallickal unregister_iscsi_transport: 57896733b39aSJayamohan Kallickal iscsi_unregister_transport(&beiscsi_iscsi_transport); 57906733b39aSJayamohan Kallickal return ret; 57916733b39aSJayamohan Kallickal } 57926733b39aSJayamohan Kallickal 57936733b39aSJayamohan Kallickal static void __exit beiscsi_module_exit(void) 57946733b39aSJayamohan Kallickal { 57956733b39aSJayamohan Kallickal pci_unregister_driver(&beiscsi_pci_driver); 57966733b39aSJayamohan Kallickal iscsi_unregister_transport(&beiscsi_iscsi_transport); 57976733b39aSJayamohan Kallickal } 57986733b39aSJayamohan Kallickal 57996733b39aSJayamohan Kallickal module_init(beiscsi_module_init); 58006733b39aSJayamohan Kallickal module_exit(beiscsi_module_exit); 5801