diff options
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be.h | 12 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 17 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.h | 74 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 111 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.h | 13 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 397 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 30 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 140 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 43 |
9 files changed, 360 insertions, 477 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index ca9440fb2325..55e3f8b40eb3 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -1,18 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #ifndef BEISCSI_H @@ -154,7 +151,6 @@ struct be_ctrl_info { #define PAGE_SHIFT_4K 12 #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) #define mcc_timeout 120000 /* 12s timeout */ -#define BEISCSI_LOGOUT_SYNC_DELAY 250 /* Returns number of pages spanned by the data starting at the given addr */ #define PAGES_4K_SPANNED(_address, size) \ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 5d59e2630ce6..a79a5e72c777 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -1,18 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #include <scsi/iscsi_proto.h> @@ -246,6 +243,12 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, { int rc = 0; + if (!tag || tag > MAX_MCC_CMD) { + __beiscsi_log(phba, KERN_ERR, + "BC_%d : invalid tag %u\n", tag); + return -EINVAL; + } + if (beiscsi_hba_in_error(phba)) { clear_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 1d40e83b0790..d9b6773facdb 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -1,18 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #ifndef BEISCSI_CMDS_H @@ -1145,24 +1142,49 @@ struct tcp_connect_and_offload_out { #define DB_DEF_PDU_EVENT_SHIFT 15 #define DB_DEF_PDU_CQPROC_SHIFT 16 -struct dmsg_cqe { - u32 dw[4]; +struct be_invalidate_connection_params_in { + struct be_cmd_req_hdr hdr; + u32 session_handle; + u16 cid; + u16 unused; +#define BE_CLEANUP_TYPE_INVALIDATE 0x8001 +#define BE_CLEANUP_TYPE_ISSUE_TCP_RST 0x8002 + u16 cleanup_type; + u16 save_cfg; +} __packed; + +struct be_invalidate_connection_params_out { + u32 session_handle; + u16 cid; + u16 unused; +} __packed; + +union be_invalidate_connection_params { + struct be_invalidate_connection_params_in req; + struct be_invalidate_connection_params_out resp; } __packed; -struct tcp_upload_params_in { +struct be_tcp_upload_params_in { struct be_cmd_req_hdr hdr; u16 id; +#define BE_UPLOAD_TYPE_GRACEFUL 1 +/* abortive upload with reset */ +#define BE_UPLOAD_TYPE_ABORT_RESET 2 +/* abortive upload without reset */ +#define BE_UPLOAD_TYPE_ABORT 3 +/* abortive upload with reset, sequence number by driver */ +#define BE_UPLOAD_TYPE_ABORT_WITH_SEQ 4 u16 upload_type; u32 reset_seq; } __packed; -struct tcp_upload_params_out { +struct be_tcp_upload_params_out { u32 dw[32]; } __packed; -union tcp_upload_params { - struct tcp_upload_params_in request; - struct tcp_upload_params_out response; +union be_tcp_upload_params { + struct be_tcp_upload_params_in request; + struct be_tcp_upload_params_out response; } __packed; struct be_ulp_fw_cfg { @@ -1243,10 +1265,7 @@ struct be_cmd_get_port_name { #define OPCODE_COMMON_WRITE_FLASH 96 #define OPCODE_COMMON_READ_FLASH 97 -/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ #define CMD_ISCSI_COMMAND_INVALIDATE 1 -#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 -#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 #define INI_WR_CMD 1 /* Initiator write command */ #define INI_TMF_CMD 2 /* Initiator TMF command */ @@ -1269,27 +1288,6 @@ struct be_cmd_get_port_name { * preparedby * driver should not be touched */ -/* --- CMD_CHUTE_TYPE --- */ -#define CMD_CONNECTION_CHUTE_0 1 -#define CMD_CONNECTION_CHUTE_1 2 -#define CMD_CONNECTION_CHUTE_2 3 - -#define EQ_MAJOR_CODE_COMPLETION 0 - -#define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0 -#define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1 - -/* --- CONNECTION_UPLOAD_PARAMS --- */ -/* These parameters are used to define the type of upload desired. */ -#define CONNECTION_UPLOAD_GRACEFUL 1 /* Graceful upload */ -#define CONNECTION_UPLOAD_ABORT_RESET 2 /* Abortive upload with - * reset - */ -#define CONNECTION_UPLOAD_ABORT 3 /* Abortive upload without - * reset - */ -#define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset, - * sequence number by driver */ /* Returns the number of items in the field array. */ #define BE_NUMBER_OF_FIELD(_type_, _field_) \ diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index a4844578e357..97dca4681784 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1,20 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * - * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) - * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #include <scsi/libiscsi.h> @@ -1263,31 +1258,58 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) } /** - * beiscsi_close_conn - Upload the connection + * beiscsi_conn_close - Invalidate and upload connection * @ep: The iscsi endpoint - * @flag: The type of connection closure + * + * Returns 0 on success, -1 on failure. */ -static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) +static int beiscsi_conn_close(struct beiscsi_endpoint *beiscsi_ep) { - int ret = 0; - unsigned int tag; struct beiscsi_hba *phba = beiscsi_ep->phba; + unsigned int tag, attempts; + int ret; - tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag); - if (!tag) { - beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, - "BS_%d : upload failed for cid 0x%x\n", - beiscsi_ep->ep_cid); - - ret = -EAGAIN; + /** + * Without successfully invalidating and uploading connection + * driver can't reuse the CID so attempt more than once. + */ + attempts = 0; + while (attempts++ < 3) { + tag = beiscsi_invalidate_cxn(phba, beiscsi_ep); + if (tag) { + ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); + if (!ret) + break; + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, + "BS_%d : invalidate conn failed cid %d\n", + beiscsi_ep->ep_cid); + } } - ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); - - /* Flush the CQ entries */ + /* wait for all completions to arrive, then process them */ + msleep(250); + /* flush CQ entries */ beiscsi_flush_cq(phba); - return ret; + if (attempts > 3) + return -1; + + attempts = 0; + while (attempts++ < 3) { + tag = beiscsi_upload_cxn(phba, beiscsi_ep); + if (tag) { + ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); + if (!ret) + break; + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, + "BS_%d : upload conn failed cid %d\n", + beiscsi_ep->ep_cid); + } + } + if (attempts > 3) + return -1; + + return 0; } /** @@ -1298,12 +1320,9 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) */ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) { - struct beiscsi_conn *beiscsi_conn; struct beiscsi_endpoint *beiscsi_ep; + struct beiscsi_conn *beiscsi_conn; struct beiscsi_hba *phba; - unsigned int tag; - uint8_t mgmt_invalidate_flag, tcp_upload_flag; - unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; uint16_t cri_index; beiscsi_ep = ep->dd_data; @@ -1324,39 +1343,27 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) if (beiscsi_ep->conn) { beiscsi_conn = beiscsi_ep->conn; iscsi_suspend_queue(beiscsi_conn->conn); - mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE; - tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL; - } else { - mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE; - tcp_upload_flag = CONNECTION_UPLOAD_ABORT; } if (!beiscsi_hba_is_online(phba)) { beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, "BS_%d : HBA in error 0x%lx\n", phba->state); - goto free_ep; - } - - tag = mgmt_invalidate_connection(phba, beiscsi_ep, - beiscsi_ep->ep_cid, - mgmt_invalidate_flag, - savecfg_flag); - if (!tag) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n", - beiscsi_ep->ep_cid); + } else { + /** + * Make CID available even if close fails. + * If not freed, FW might fail open using the CID. + */ + if (beiscsi_conn_close(beiscsi_ep) < 0) + __beiscsi_log(phba, KERN_ERR, + "BS_%d : close conn failed cid %d\n", + beiscsi_ep->ep_cid); } - beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); - beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); -free_ep: - msleep(BEISCSI_LOGOUT_SYNC_DELAY); beiscsi_free_ep(beiscsi_ep); if (!phba->conn_table[cri_index]) __beiscsi_log(phba, KERN_ERR, - "BS_%d : conn_table empty at %u: cid %u\n", - cri_index, - beiscsi_ep->ep_cid); + "BS_%d : conn_table empty at %u: cid %u\n", + cri_index, beiscsi_ep->ep_cid); phba->conn_table[cri_index] = NULL; iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); } diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index e4d67dfea4cb..b9d459a21f25 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h @@ -1,20 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * - * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) - * * Contact Information: * linux-drivers@broadcom.com * - * Avago Technologies - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #ifndef _BE_ISCSI_ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 32b2713cec93..f862332261f8 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1,20 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * - * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) - * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #include <linux/reboot.h> @@ -337,7 +332,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) inv_tbl->task[nents] = task; nents++; } - spin_unlock_bh(&session->back_lock); + spin_unlock(&session->back_lock); spin_unlock_bh(&session->frwd_lock); rc = SUCCESS; @@ -636,7 +631,6 @@ static void beiscsi_get_params(struct beiscsi_hba *phba) (total_cid_count + BE2_TMFS + BE2_NOPOUT_REQ)); phba->params.cxns_per_ctrl = total_cid_count; - phba->params.asyncpdus_per_ctrl = total_cid_count; phba->params.icds_per_ctrl = total_icd_count; phba->params.num_sge_per_io = BE2_SGE; phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; @@ -802,12 +796,12 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) struct pci_dev *pcidev = phba->pcidev; struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; - int ret, msix_vec, i, j; + int ret, i, j; phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; - if (phba->msix_enabled) { + if (pcidev->msix_enabled) { for (i = 0; i < phba->num_cpus; i++) { phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL); @@ -818,9 +812,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) sprintf(phba->msi_name[i], "beiscsi_%02x_%02x", phba->shost->host_no, i); - msix_vec = phba->msix_entries[i].vector; - ret = request_irq(msix_vec, be_isr_msix, 0, - phba->msi_name[i], + ret = request_irq(pci_irq_vector(pcidev, i), + be_isr_msix, 0, phba->msi_name[i], &phwi_context->be_eq[i]); if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, @@ -838,9 +831,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) } sprintf(phba->msi_name[i], "beiscsi_mcc_%02x", phba->shost->host_no); - msix_vec = phba->msix_entries[i].vector; - ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i], - &phwi_context->be_eq[i]); + ret = request_irq(pci_irq_vector(pcidev, i), be_isr_mcc, 0, + phba->msi_name[i], &phwi_context->be_eq[i]); if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT , "BM_%d : beiscsi_init_irqs-" @@ -862,9 +854,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba) return 0; free_msix_irqs: for (j = i - 1; j >= 0; j--) { + free_irq(pci_irq_vector(pcidev, i), &phwi_context->be_eq[j]); kfree(phba->msi_name[j]); - msix_vec = phba->msix_entries[j].vector; - free_irq(msix_vec, &phwi_context->be_eq[j]); } return ret; } @@ -1454,30 +1445,45 @@ static inline void beiscsi_hdl_put_handle(struct hd_async_context *pasync_ctx, struct hd_async_handle *pasync_handle) { - if (pasync_handle->is_header) { - list_add_tail(&pasync_handle->link, - &pasync_ctx->async_header.free_list); - pasync_ctx->async_header.free_entries++; - } else { - list_add_tail(&pasync_handle->link, - &pasync_ctx->async_data.free_list); - pasync_ctx->async_data.free_entries++; - } + pasync_handle->is_final = 0; + pasync_handle->buffer_len = 0; + pasync_handle->in_use = 0; + list_del_init(&pasync_handle->link); +} + +static void +beiscsi_hdl_purge_handles(struct beiscsi_hba *phba, + struct hd_async_context *pasync_ctx, + u16 cri) +{ + struct hd_async_handle *pasync_handle, *tmp_handle; + struct list_head *plist; + + plist = &pasync_ctx->async_entry[cri].wq.list; + list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) + beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); + + INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list); + pasync_ctx->async_entry[cri].wq.hdr_len = 0; + pasync_ctx->async_entry[cri].wq.bytes_received = 0; + pasync_ctx->async_entry[cri].wq.bytes_needed = 0; } static struct hd_async_handle * beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, struct hd_async_context *pasync_ctx, - struct i_t_dpdu_cqe *pdpdu_cqe) + struct i_t_dpdu_cqe *pdpdu_cqe, + u8 *header) { struct beiscsi_hba *phba = beiscsi_conn->phba; struct hd_async_handle *pasync_handle; struct be_bus_address phys_addr; + u16 cid, code, ci, cri; u8 final, error = 0; - u16 cid, code, ci; u32 dpl; cid = beiscsi_conn->beiscsi_conn_cid; + cri = BE_GET_ASYNC_CRI_FROM_CID(cid); /** * This function is invoked to get the right async_handle structure * from a given DEF PDU CQ entry. @@ -1516,6 +1522,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, switch (code) { case UNSOL_HDR_NOTIFY: pasync_handle = pasync_ctx->async_entry[ci].header; + *header = 1; break; case UNSOL_DATA_DIGEST_ERROR_NOTIFY: error = 1; @@ -1524,15 +1531,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, break; /* called only for above codes */ default: - pasync_handle = NULL; - break; - } - - if (!pasync_handle) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, - "BM_%d : cid %d async PDU handle not found - code %d ci %d addr %llx\n", - cid, code, ci, phys_addr.u.a64.address); - return pasync_handle; + return NULL; } if (pasync_handle->pa.u.a64.address != phys_addr.u.a64.address || @@ -1549,47 +1548,32 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, } /** - * Each CID is associated with unique CRI. - * ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different. - **/ - pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID(cid); - pasync_handle->is_final = final; - pasync_handle->buffer_len = dpl; - /* empty the slot */ - if (pasync_handle->is_header) - pasync_ctx->async_entry[ci].header = NULL; - else - pasync_ctx->async_entry[ci].data = NULL; - - /** * DEF PDU header and data buffers with errors should be simply * dropped as there are no consumers for it. */ if (error) { beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); - pasync_handle = NULL; + return NULL; } - return pasync_handle; -} - -static void -beiscsi_hdl_purge_handles(struct beiscsi_hba *phba, - struct hd_async_context *pasync_ctx, - u16 cri) -{ - struct hd_async_handle *pasync_handle, *tmp_handle; - struct list_head *plist; - plist = &pasync_ctx->async_entry[cri].wq.list; - list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { - list_del(&pasync_handle->link); - beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); + if (pasync_handle->in_use || !list_empty(&pasync_handle->link)) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, + "BM_%d : cid %d async PDU handle in use - code %d ci %d addr %llx\n", + cid, code, ci, phys_addr.u.a64.address); + beiscsi_hdl_purge_handles(phba, pasync_ctx, cri); } - INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list); - pasync_ctx->async_entry[cri].wq.hdr_len = 0; - pasync_ctx->async_entry[cri].wq.bytes_received = 0; - pasync_ctx->async_entry[cri].wq.bytes_needed = 0; + list_del_init(&pasync_handle->link); + /** + * Each CID is associated with unique CRI. + * ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different. + **/ + pasync_handle->cri = cri; + pasync_handle->is_final = final; + pasync_handle->buffer_len = dpl; + pasync_handle->in_use = 1; + + return pasync_handle; } static unsigned int @@ -1619,6 +1603,10 @@ beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn, dlen = pasync_handle->buffer_len; continue; } + if (!pasync_handle->buffer_len || + (dlen + pasync_handle->buffer_len) > + pasync_ctx->async_data.buffer_size) + break; memcpy(pdata + dlen, pasync_handle->pbuffer, pasync_handle->buffer_len); dlen += pasync_handle->buffer_len; @@ -1627,8 +1615,9 @@ beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn, if (!plast_handle->is_final) { /* last handle should have final PDU notification from FW */ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, - "BM_%d : cid %u %p fwd async PDU with last handle missing - HL%u:DN%u:DR%u\n", + "BM_%d : cid %u %p fwd async PDU opcode %x with last handle missing - HL%u:DN%u:DR%u\n", beiscsi_conn->beiscsi_conn_cid, plast_handle, + AMAP_GET_BITS(struct amap_pdu_base, opcode, phdr), pasync_ctx->async_entry[cri].wq.hdr_len, pasync_ctx->async_entry[cri].wq.bytes_needed, pasync_ctx->async_entry[cri].wq.bytes_received); @@ -1709,85 +1698,53 @@ drop_pdu: static void beiscsi_hdq_post_handles(struct beiscsi_hba *phba, - u8 header, u8 ulp_num) + u8 header, u8 ulp_num, u16 nbuf) { - struct hd_async_handle *pasync_handle, *tmp, **slot; + struct hd_async_handle *pasync_handle; struct hd_async_context *pasync_ctx; struct hwi_controller *phwi_ctrlr; - struct list_head *hfree_list; struct phys_addr *pasync_sge; u32 ring_id, doorbell = 0; u32 doorbell_offset; - u16 prod = 0, cons; - u16 index; + u16 prod, pi; phwi_ctrlr = phba->phwi_ctrlr; pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); if (header) { - cons = pasync_ctx->async_header.free_entries; - hfree_list = &pasync_ctx->async_header.free_list; + pasync_sge = pasync_ctx->async_header.ring_base; + pi = pasync_ctx->async_header.pi; ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. doorbell_offset; } else { - cons = pasync_ctx->async_data.free_entries; - hfree_list = &pasync_ctx->async_data.free_list; + pasync_sge = pasync_ctx->async_data.ring_base; + pi = pasync_ctx->async_data.pi; ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num]. doorbell_offset; } - /* number of entries posted must be in multiples of 8 */ - if (cons % 8) - return; - - list_for_each_entry_safe(pasync_handle, tmp, hfree_list, link) { - list_del_init(&pasync_handle->link); - pasync_handle->is_final = 0; - pasync_handle->buffer_len = 0; - /* handles can be consumed out of order, use index in handle */ - index = pasync_handle->index; - WARN_ON(pasync_handle->is_header != header); + for (prod = 0; prod < nbuf; prod++) { if (header) - slot = &pasync_ctx->async_entry[index].header; + pasync_handle = pasync_ctx->async_entry[pi].header; else - slot = &pasync_ctx->async_entry[index].data; - /** - * The slot just tracks handle's hold and release, so - * overwriting at the same index won't do any harm but - * needs to be caught. - */ - if (*slot != NULL) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, - "BM_%d : async PDU %s slot at %u not empty\n", - header ? "header" : "data", index); + pasync_handle = pasync_ctx->async_entry[pi].data; + WARN_ON(pasync_handle->is_header != header); + WARN_ON(pasync_handle->index != pi); + /* setup the ring only once */ + if (nbuf == pasync_ctx->num_entries) { + /* note hi is lo */ + pasync_sge[pi].hi = pasync_handle->pa.u.a32.address_lo; + pasync_sge[pi].lo = pasync_handle->pa.u.a32.address_hi; } - /** - * We use same freed index as in completion to post so this - * operation is not required for refills. Its required only - * for ring creation. - */ - if (header) - pasync_sge = pasync_ctx->async_header.ring_base; - else - pasync_sge = pasync_ctx->async_data.ring_base; - pasync_sge += index; - /* if its a refill then address is same; hi is lo */ - WARN_ON(pasync_sge->hi && - pasync_sge->hi != pasync_handle->pa.u.a32.address_lo); - WARN_ON(pasync_sge->lo && - pasync_sge->lo != pasync_handle->pa.u.a32.address_hi); - pasync_sge->hi = pasync_handle->pa.u.a32.address_lo; - pasync_sge->lo = pasync_handle->pa.u.a32.address_hi; - - *slot = pasync_handle; - if (++prod == cons) - break; + if (++pi == pasync_ctx->num_entries) + pi = 0; } + if (header) - pasync_ctx->async_header.free_entries -= prod; + pasync_ctx->async_header.pi = pi; else - pasync_ctx->async_data.free_entries -= prod; + pasync_ctx->async_data.pi = pi; doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK; doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT; @@ -1804,20 +1761,26 @@ beiscsi_hdq_process_compl(struct beiscsi_conn *beiscsi_conn, struct hd_async_handle *pasync_handle = NULL; struct hd_async_context *pasync_ctx; struct hwi_controller *phwi_ctrlr; + u8 ulp_num, consumed, header = 0; u16 cid_cri; - u8 ulp_num; phwi_ctrlr = phba->phwi_ctrlr; cid_cri = BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid); ulp_num = BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cid_cri); pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); pasync_handle = beiscsi_hdl_get_handle(beiscsi_conn, pasync_ctx, - pdpdu_cqe); - if (!pasync_handle) - return; - - beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle); - beiscsi_hdq_post_handles(phba, pasync_handle->is_header, ulp_num); + pdpdu_cqe, &header); + if (is_chip_be2_be3r(phba)) + consumed = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, + num_cons, pdpdu_cqe); + else + consumed = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, + num_cons, pdpdu_cqe); + if (pasync_handle) + beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle); + /* num_cons indicates number of 8 RQEs consumed */ + if (consumed) + beiscsi_hdq_post_handles(phba, header, ulp_num, 8 * consumed); } void beiscsi_process_mcc_cq(struct beiscsi_hba *phba) @@ -2407,22 +2370,22 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { num_async_pdu_buf_sgl_pages = - PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( + PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE( phba, ulp_num) * sizeof(struct phys_addr)); num_async_pdu_buf_pages = - PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( + PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE( phba, ulp_num) * phba->params.defpdu_hdr_sz); num_async_pdu_data_pages = - PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( + PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE( phba, ulp_num) * phba->params.defpdu_data_sz); num_async_pdu_data_sgl_pages = - PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( + PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE( phba, ulp_num) * sizeof(struct phys_addr)); @@ -2459,21 +2422,21 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) mem_descr_index = (HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + (ulp_num * MEM_DESCR_OFFSET)); phba->mem_req[mem_descr_index] = - BEISCSI_GET_CID_COUNT(phba, ulp_num) * - sizeof(struct hd_async_handle); + BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) * + sizeof(struct hd_async_handle); mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + (ulp_num * MEM_DESCR_OFFSET)); phba->mem_req[mem_descr_index] = - BEISCSI_GET_CID_COUNT(phba, ulp_num) * - sizeof(struct hd_async_handle); + BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) * + sizeof(struct hd_async_handle); mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + (ulp_num * MEM_DESCR_OFFSET)); phba->mem_req[mem_descr_index] = - sizeof(struct hd_async_context) + - (BEISCSI_GET_CID_COUNT(phba, ulp_num) * - sizeof(struct hd_async_entry)); + sizeof(struct hd_async_context) + + (BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) * + sizeof(struct hd_async_entry)); } } } @@ -2757,7 +2720,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) ((long unsigned int)pasync_ctx + sizeof(struct hd_async_context)); - pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, + pasync_ctx->num_entries = BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num); /* setup header buffers */ mem_descr = (struct be_mem_descriptor *)phba->init_mem; @@ -2776,6 +2739,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) "BM_%d : No Virtual address for ULP : %d\n", ulp_num); + pasync_ctx->async_header.pi = 0; pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz; pasync_ctx->async_header.va_base = mem_descr->mem_array[0].virtual_address; @@ -2823,7 +2787,6 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) pasync_ctx->async_header.handle_base = mem_descr->mem_array[0].virtual_address; - INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); /* setup data buffer sgls */ mem_descr = (struct be_mem_descriptor *)phba->init_mem; @@ -2857,7 +2820,6 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) pasync_ctx->async_data.handle_base = mem_descr->mem_array[0].virtual_address; - INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); pasync_header_h = (struct hd_async_handle *) @@ -2884,6 +2846,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) ulp_num); idx = 0; + pasync_ctx->async_data.pi = 0; pasync_ctx->async_data.buffer_size = p->defpdu_data_sz; pasync_ctx->async_data.va_base = mem_descr->mem_array[idx].virtual_address; @@ -2895,7 +2858,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) phba->params.defpdu_data_sz); num_per_mem = 0; - for (index = 0; index < BEISCSI_GET_CID_COUNT + for (index = 0; index < BEISCSI_ASYNC_HDQ_SIZE (phba, ulp_num); index++) { pasync_header_h->cri = -1; pasync_header_h->is_header = 1; @@ -2911,14 +2874,11 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) pasync_ctx->async_header.pa_base.u.a64. address + (p->defpdu_hdr_sz * index); - list_add_tail(&pasync_header_h->link, - &pasync_ctx->async_header. - free_list); + pasync_ctx->async_entry[index].header = + pasync_header_h; pasync_header_h++; - pasync_ctx->async_header.free_entries++; INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. wq.list); - pasync_ctx->async_entry[index].header = NULL; pasync_data_h->cri = -1; pasync_data_h->is_header = 0; @@ -2952,12 +2912,9 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) num_per_mem++; num_async_data--; - list_add_tail(&pasync_data_h->link, - &pasync_ctx->async_data. - free_list); + pasync_ctx->async_entry[index].data = + pasync_data_h; pasync_data_h++; - pasync_ctx->async_data.free_entries++; - pasync_ctx->async_entry[index].data = NULL; } } } @@ -3040,7 +2997,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \ sizeof(struct be_eq_entry)); - if (phba->msix_enabled) + if (phba->pcidev->msix_enabled) eq_for_mcc = 1; else eq_for_mcc = 0; @@ -3550,7 +3507,7 @@ static int be_mcc_queues_create(struct beiscsi_hba *phba, sizeof(struct be_mcc_compl))) goto err; /* Ask BE to create MCC compl queue; */ - if (phba->msix_enabled) { + if (phba->pcidev->msix_enabled) { if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq [phba->num_cpus].q, false, true, 0)) goto mcc_cq_free; @@ -3581,42 +3538,35 @@ err: return -ENOMEM; } -/** - * find_num_cpus()- Get the CPU online count - * @phba: ptr to priv structure - * - * CPU count is used for creating EQ. - **/ -static void find_num_cpus(struct beiscsi_hba *phba) +static void be2iscsi_enable_msix(struct beiscsi_hba *phba) { - int num_cpus = 0; - - num_cpus = num_online_cpus(); + int nvec = 1; switch (phba->generation) { case BE_GEN2: case BE_GEN3: - phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ? - BEISCSI_MAX_NUM_CPUS : num_cpus; + nvec = BEISCSI_MAX_NUM_CPUS + 1; break; case BE_GEN4: - /* - * If eqid_count == 1 fall back to - * INTX mechanism - **/ - if (phba->fw_config.eqid_count == 1) { - enable_msix = 0; - phba->num_cpus = 1; - return; - } - - phba->num_cpus = - (num_cpus > (phba->fw_config.eqid_count - 1)) ? - (phba->fw_config.eqid_count - 1) : num_cpus; + nvec = phba->fw_config.eqid_count; break; default: - phba->num_cpus = 1; + nvec = 2; + break; } + + /* if eqid_count == 1 fall back to INTX */ + if (enable_msix && nvec > 1) { + const struct irq_affinity desc = { .post_vectors = 1 }; + + if (pci_alloc_irq_vectors_affinity(phba->pcidev, 2, nvec, + PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc) < 0) { + phba->num_cpus = nvec - 1; + return; + } + } + + phba->num_cpus = 1; } static void hwi_purge_eq(struct beiscsi_hba *phba) @@ -3633,7 +3583,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; - if (phba->msix_enabled) + if (phba->pcidev->msix_enabled) eq_msix = 1; else eq_msix = 0; @@ -3711,7 +3661,7 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba) } be_mcc_queues_destroy(phba); - if (phba->msix_enabled) + if (phba->pcidev->msix_enabled) eq_for_mcc = 1; else eq_for_mcc = 0; @@ -3735,6 +3685,7 @@ static int hwi_init_port(struct beiscsi_hba *phba) unsigned int def_pdu_ring_sz; struct be_ctrl_info *ctrl = &phba->ctrl; int status, ulp_num; + u16 nbufs; phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; @@ -3771,9 +3722,8 @@ static int hwi_init_port(struct beiscsi_hba *phba) for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { - def_pdu_ring_sz = - BEISCSI_GET_CID_COUNT(phba, ulp_num) * - sizeof(struct phys_addr); + nbufs = phwi_context->pasync_ctx[ulp_num]->num_entries; + def_pdu_ring_sz = nbufs * sizeof(struct phys_addr); status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr, @@ -3801,9 +3751,9 @@ static int hwi_init_port(struct beiscsi_hba *phba) * let EP know about it. */ beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR, - ulp_num); + ulp_num, nbufs); beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA, - ulp_num); + ulp_num, nbufs); } } @@ -4157,7 +4107,7 @@ static void hwi_enable_intr(struct beiscsi_hba *phba) iowrite32(reg, addr); } - if (!phba->msix_enabled) { + if (!phba->pcidev->msix_enabled) { eq = &phwi_context->be_eq[0].q; beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BM_%d : eq->id=%d\n", eq->id); @@ -5280,19 +5230,6 @@ static void beiscsi_eqd_update_work(struct work_struct *work) msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL)); } -static void beiscsi_msix_enable(struct beiscsi_hba *phba) -{ - int i, status; - - for (i = 0; i <= phba->num_cpus; i++) - phba->msix_entries[i].entry = i; - - status = pci_enable_msix_range(phba->pcidev, phba->msix_entries, - phba->num_cpus + 1, phba->num_cpus + 1); - if (status > 0) - phba->msix_enabled = true; -} - static void beiscsi_hw_tpe_check(unsigned long ptr) { struct beiscsi_hba *phba; @@ -5360,15 +5297,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba) if (ret) return ret; - if (enable_msix) - find_num_cpus(phba); - else - phba->num_cpus = 1; - if (enable_msix) { - beiscsi_msix_enable(phba); - if (!phba->msix_enabled) - phba->num_cpus = 1; - } + be2iscsi_enable_msix(phba); beiscsi_get_params(phba); /* Re-enable UER. If different TPE occurs then it is recoverable. */ @@ -5397,7 +5326,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba) irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll); } - i = (phba->msix_enabled) ? i : 0; + i = (phba->pcidev->msix_enabled) ? i : 0; /* Work item for MCC handling */ pbe_eq = &phwi_context->be_eq[i]; INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work); @@ -5435,9 +5364,7 @@ cleanup_port: hwi_cleanup_port(phba); disable_msix: - if (phba->msix_enabled) - pci_disable_msix(phba->pcidev); - + pci_free_irq_vectors(phba->pcidev); return ret; } @@ -5454,7 +5381,7 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload) struct hwi_context_memory *phwi_context; struct hwi_controller *phwi_ctrlr; struct be_eq_obj *pbe_eq; - unsigned int i, msix_vec; + unsigned int i; if (!test_and_clear_bit(BEISCSI_HBA_ONLINE, &phba->state)) return; @@ -5462,16 +5389,16 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload) phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; hwi_disable_intr(phba); - if (phba->msix_enabled) { + if (phba->pcidev->msix_enabled) { for (i = 0; i <= phba->num_cpus; i++) { - msix_vec = phba->msix_entries[i].vector; - free_irq(msix_vec, &phwi_context->be_eq[i]); + free_irq(pci_irq_vector(phba->pcidev, i), + &phwi_context->be_eq[i]); kfree(phba->msi_name[i]); } } else if (phba->pcidev->irq) free_irq(phba->pcidev->irq, phba); - pci_disable_msix(phba->pcidev); + pci_free_irq_vectors(phba->pcidev); for (i = 0; i < phba->num_cpus; i++) { pbe_eq = &phwi_context->be_eq[i]; @@ -5681,21 +5608,12 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, beiscsi_get_params(phba); beiscsi_set_uer_feature(phba); - if (enable_msix) - find_num_cpus(phba); - else - phba->num_cpus = 1; + be2iscsi_enable_msix(phba); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BM_%d : num_cpus = %d\n", phba->num_cpus); - if (enable_msix) { - beiscsi_msix_enable(phba); - if (!phba->msix_enabled) - phba->num_cpus = 1; - } - phba->shost->max_id = phba->params.cxns_per_ctrl; phba->shost->can_queue = phba->params.ios_per_ctrl; ret = beiscsi_get_memory(phba); @@ -5745,7 +5663,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll); } - i = (phba->msix_enabled) ? i : 0; + i = (phba->pcidev->msix_enabled) ? i : 0; /* Work item for MCC handling */ pbe_eq = &phwi_context->be_eq[i]; INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work); @@ -5816,8 +5734,7 @@ free_port: phba->ctrl.mbox_mem_alloced.dma); beiscsi_unmap_pci_function(phba); hba_free: - if (phba->msix_enabled) - pci_disable_msix(phba->pcidev); + pci_disable_msix(phba->pcidev); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); pci_set_drvdata(pcidev, NULL); diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 218857926566..338dbe0800c1 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -1,20 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * - * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) - * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #ifndef _BEISCSI_MAIN_ @@ -36,7 +31,7 @@ #include <scsi/scsi_transport_iscsi.h> #define DRV_NAME "be2iscsi" -#define BUILD_STR "11.2.1.0" +#define BUILD_STR "11.4.0.0" #define BE_NAME "Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" @@ -235,7 +230,6 @@ struct sgl_handle { struct hba_parameters { unsigned int ios_per_ctrl; unsigned int cxns_per_ctrl; - unsigned int asyncpdus_per_ctrl; unsigned int icds_per_ctrl; unsigned int num_sge_per_io; unsigned int defpdu_hdr_sz; @@ -323,9 +317,7 @@ struct beiscsi_hba { struct pci_dev *pcidev; unsigned int num_cpus; unsigned int nxt_cqid; - struct msix_entry msix_entries[MAX_CPUS]; char *msi_name[MAX_CPUS]; - bool msix_enabled; struct be_mem_descriptor *init_mem; unsigned short io_sgl_alloc_index; @@ -597,8 +589,12 @@ struct hd_async_handle { u16 cri; u8 is_header; u8 is_final; + u8 in_use; }; +#define BEISCSI_ASYNC_HDQ_SIZE(phba, ulp) \ + (BEISCSI_GET_CID_COUNT((phba), (ulp)) * 2) + /** * This has list of async PDUs that are waiting to be processed. * Buffers live in this list for a brief duration before they get @@ -624,14 +620,8 @@ struct hd_async_buf_context { void *va_base; void *ring_base; struct hd_async_handle *handle_base; - u16 free_entries; u32 buffer_size; - /** - * Once iSCSI layer finishes processing an async PDU, the - * handles used for the PDU are added to this list. - * They are posted back to FW in groups of 8. - */ - struct list_head free_list; + u16 pi; }; /** diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 2f6d5c2ac329..c73775368d09 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1,20 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * - * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) - * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #include <linux/bsg-lib.h> @@ -126,67 +121,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, return tag; } -unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, - struct beiscsi_endpoint *beiscsi_ep, - unsigned short cid, - unsigned short issue_reset, - unsigned short savecfg_flag) -{ - struct be_ctrl_info *ctrl = &phba->ctrl; - struct be_mcc_wrb *wrb; - struct iscsi_invalidate_connection_params_in *req; - unsigned int tag = 0; - - mutex_lock(&ctrl->mbox_lock); - wrb = alloc_mcc_wrb(phba, &tag); - if (!wrb) { - mutex_unlock(&ctrl->mbox_lock); - return 0; - } - - req = embedded_payload(wrb); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, - OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, - sizeof(*req)); - req->session_handle = beiscsi_ep->fw_handle; - req->cid = cid; - if (issue_reset) - req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST; - else - req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; - req->save_cfg = savecfg_flag; - be_mcc_notify(phba, tag); - mutex_unlock(&ctrl->mbox_lock); - return tag; -} - -unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, - unsigned short cid, unsigned int upload_flag) -{ - struct be_ctrl_info *ctrl = &phba->ctrl; - struct be_mcc_wrb *wrb; - struct tcp_upload_params_in *req; - unsigned int tag; - - mutex_lock(&ctrl->mbox_lock); - wrb = alloc_mcc_wrb(phba, &tag); - if (!wrb) { - mutex_unlock(&ctrl->mbox_lock); - return 0; - } - - req = embedded_payload(wrb); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); - be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, - OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); - req->id = (unsigned short)cid; - req->upload_type = (unsigned char)upload_flag; - be_mcc_notify(phba, tag); - mutex_unlock(&ctrl->mbox_lock); - return tag; -} - /** * mgmt_open_connection()- Establish a TCP CXN * @dst_addr: Destination Address @@ -1449,6 +1383,72 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, exp_statsn) / 32] + 1)); } +unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba, + struct beiscsi_endpoint *beiscsi_ep) +{ + struct be_invalidate_connection_params_in *req; + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + unsigned int tag = 0; + + mutex_lock(&ctrl->mbox_lock); + wrb = alloc_mcc_wrb(phba, &tag); + if (!wrb) { + mutex_unlock(&ctrl->mbox_lock); + return 0; + } + + req = embedded_payload(wrb); + be_wrb_hdr_prepare(wrb, sizeof(union be_invalidate_connection_params), + true, 0); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, + OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, + sizeof(*req)); + req->session_handle = beiscsi_ep->fw_handle; + req->cid = beiscsi_ep->ep_cid; + if (beiscsi_ep->conn) + req->cleanup_type = BE_CLEANUP_TYPE_INVALIDATE; + else + req->cleanup_type = BE_CLEANUP_TYPE_ISSUE_TCP_RST; + /** + * 0 - non-persistent targets + * 1 - save session info on flash + */ + req->save_cfg = 0; + be_mcc_notify(phba, tag); + mutex_unlock(&ctrl->mbox_lock); + return tag; +} + +unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba, + struct beiscsi_endpoint *beiscsi_ep) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + struct be_tcp_upload_params_in *req; + unsigned int tag; + + mutex_lock(&ctrl->mbox_lock); + wrb = alloc_mcc_wrb(phba, &tag); + if (!wrb) { + mutex_unlock(&ctrl->mbox_lock); + return 0; + } + + req = embedded_payload(wrb); + be_wrb_hdr_prepare(wrb, sizeof(union be_tcp_upload_params), true, 0); + be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, + OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); + req->id = beiscsi_ep->ep_cid; + if (beiscsi_ep->conn) + req->upload_type = BE_UPLOAD_TYPE_GRACEFUL; + else + req->upload_type = BE_UPLOAD_TYPE_ABORT; + be_mcc_notify(phba, tag); + mutex_unlock(&ctrl->mbox_lock); + return tag; +} + int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba, struct invldt_cmd_tbl *inv_tbl, unsigned int nents) diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 308f1472f98a..06ddc5ad6874 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -1,20 +1,15 @@ -/** - * Copyright (C) 2005 - 2016 Broadcom - * All rights reserved. +/* + * Copyright 2017 Broadcom. All Rights Reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. The full GNU General + * as published by the Free Software Foundation. The full GNU General * Public License is included in this distribution in the file called COPYING. * - * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) - * * Contact Information: * linux-drivers@broadcom.com * - * Emulex - * 3333 Susan Street - * Costa Mesa, CA 92626 */ #ifndef _BEISCSI_MGMT_ @@ -41,35 +36,11 @@ int mgmt_open_connection(struct beiscsi_hba *phba, struct beiscsi_endpoint *beiscsi_ep, struct be_dma_mem *nonemb_cmd); -unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, - unsigned short cid, - unsigned int upload_flag); unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba, struct bsg_job *job, struct be_dma_mem *nonemb_cmd); -#define BEISCSI_NO_RST_ISSUE 0 -struct iscsi_invalidate_connection_params_in { - struct be_cmd_req_hdr hdr; - unsigned int session_handle; - unsigned short cid; - unsigned short unused; - unsigned short cleanup_type; - unsigned short save_cfg; -} __packed; - -struct iscsi_invalidate_connection_params_out { - unsigned int session_handle; - unsigned short cid; - unsigned short unused; -} __packed; - -union iscsi_invalidate_connection_params { - struct iscsi_invalidate_connection_params_in request; - struct iscsi_invalidate_connection_params_out response; -} __packed; - #define BE_INVLDT_CMD_TBL_SZ 128 struct invldt_cmd_tbl { unsigned short icd; @@ -265,6 +236,12 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, struct wrb_handle *pwrb_handle, struct hwi_wrb_context *pwrb_context); +unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba, + struct beiscsi_endpoint *beiscsi_ep); + +unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba, + struct beiscsi_endpoint *beiscsi_ep); + int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *, int num); |