diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-14 04:20:31 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-14 04:20:31 +0100 |
commit | e777d192ffb9f2929d547a2f8a5f65b7db7a9552 (patch) | |
tree | c9a82698ae66c0465aeb07908c9063d8c098da27 /drivers/scsi/be2iscsi | |
parent | Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/r... (diff) | |
parent | [SCSI] mpt3sas: add new driver supporting 12GB SAS (diff) | |
download | linux-e777d192ffb9f2929d547a2f8a5f65b7db7a9552.tar.xz linux-e777d192ffb9f2929d547a2f8a5f65b7db7a9552.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley:
"This patch set includes two large new drivers: mpt3sas (for the next
gen fusion SAS hardware) and csiostor a FCoE offload driver for the
Chelsio converged network cards (this includes some net changes which
I've OK'd with DaveM).
The rest of the patch is driver updates (qla2xxx, lpfc, hptiop,
be2iscsi) plus a few assorted updates and bug fixes.
We also have a Power Management rework in the Upper Layer Drivers
preparatory to doing ACPI zero power optical devices, but the actual
enabler is still being worked on.
Signed-off-by: James Bottomley <JBottomley@Parallels.com>"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (72 commits)
[SCSI] mpt3sas: add new driver supporting 12GB SAS
[SCSI] scsi_transport_sas: add 12GB definitions for mpt3sas
[SCSI] miscdevice: Adding support for MPT3SAS_MINOR(222)
[SCSI] csiostor: remove unneeded memset()
[SCSI] csiostor: Fix sparse warnings.
[SCSI] qla2xxx: Display that driver is operating in legacy interrupt mode.
[SCSI] qla2xxx: Dont clear drv active on iospace config failure.
[SCSI] qla2xxx: Fix typo in qla2xxx driver.
[SCSI] qla2xxx: Update ql2xextended_error_logging parameter description with new option.
[SCSI] qla2xxx: Parameterize the link speed of hba rather than fcport.
[SCSI] qla2xxx: Add 16Gb/s case to get port speed capability.
[SCSI] qla2xxx: Move marking fcport online ahead of setting iiDMA speed.
[SCSI] qla2xxx: Add acquiring of risc semaphore before doing ISP reset.
[SCSI] qla2xxx: Ignore driver ack bit if corresponding presence bit is not set.
[SCSI] qla2xxx: Fix typo in qla83xx_fw_dump function.
[SCSI] qla2xxx: Add Gen3 PCIe speed 8GT/s to the log message.
[SCSI] qla2xxx: Use correct Request-Q-Out register during bidirectional request processing
[SCSI] qla2xxx: Move noisy Start scsi failed messages to verbose logging level.
[SCSI] qla2xxx: Fix coccinelle warnings in qla2x00_relogin.
[SCSI] qla2xxx: No fcport FC-4 type assignment in GA_NXT response.
...
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be.h | 7 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 236 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.h | 93 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 124 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.h | 2 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 1059 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 152 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 424 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 23 |
9 files changed, 1546 insertions, 574 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index a50b6a9030e8..f1733dfa3ae2 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -28,7 +28,7 @@ /* BladeEngine Generation numbers */ #define BE_GEN2 2 #define BE_GEN3 3 - +#define BE_GEN4 4 struct be_dma_mem { void *va; dma_addr_t dma; @@ -84,9 +84,12 @@ static inline void queue_tail_inc(struct be_queue_info *q) /*ISCSI */ struct be_eq_obj { + bool todo_mcc_cq; + bool todo_cq; struct be_queue_info q; struct beiscsi_hba *phba; struct be_queue_info *cq; + struct work_struct work_cqs; /* Work Item */ struct blk_iopoll iopoll; }; diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 07d2cb126d93..5c87768c109c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -56,7 +56,7 @@ int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) writel(pconline0, (void *)pci_online0_offset); writel(pconline1, (void *)pci_online1_offset); - sreset = BE2_SET_RESET; + sreset |= BE2_SET_RESET; writel(sreset, (void *)pci_reset_offset); i = 0; @@ -133,6 +133,87 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) return tag; } +/* + * beiscsi_mccq_compl()- Wait for completion of MBX + * @phba: Driver private structure + * @tag: Tag for the MBX Command + * @wrb: the WRB used for the MBX Command + * @cmd_hdr: IOCTL Hdr for the MBX Cmd + * + * Waits for MBX completion with the passed TAG. + * + * return + * Success: 0 + * Failure: Non-Zero + **/ +int beiscsi_mccq_compl(struct beiscsi_hba *phba, + uint32_t tag, struct be_mcc_wrb **wrb, + void *cmd_hdr) +{ + int rc = 0; + uint32_t mcc_tag_response; + uint16_t status = 0, addl_status = 0, wrb_num = 0; + struct be_mcc_wrb *temp_wrb; + struct be_cmd_req_hdr *ioctl_hdr; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + + if (beiscsi_error(phba)) + return -EIO; + + /* wait for the mccq completion */ + rc = wait_event_interruptible_timeout( + phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag], + msecs_to_jiffies( + BEISCSI_HOST_MBX_TIMEOUT)); + + if (rc <= 0) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_INIT | BEISCSI_LOG_EH | + BEISCSI_LOG_CONFIG, + "BC_%d : MBX Cmd Completion timed out\n"); + rc = -EAGAIN; + goto release_mcc_tag; + } else + rc = 0; + + mcc_tag_response = phba->ctrl.mcc_numtag[tag]; + status = (mcc_tag_response & CQE_STATUS_MASK); + addl_status = ((mcc_tag_response & CQE_STATUS_ADDL_MASK) >> + CQE_STATUS_ADDL_SHIFT); + + if (cmd_hdr) { + ioctl_hdr = (struct be_cmd_req_hdr *)cmd_hdr; + } else { + wrb_num = (mcc_tag_response & CQE_STATUS_WRB_MASK) >> + CQE_STATUS_WRB_SHIFT; + temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); + ioctl_hdr = embedded_payload(temp_wrb); + + if (wrb) + *wrb = temp_wrb; + } + + if (status || addl_status) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_INIT | BEISCSI_LOG_EH | + BEISCSI_LOG_CONFIG, + "BC_%d : MBX Cmd Failed for " + "Subsys : %d Opcode : %d with " + "Status : %d and Extd_Status : %d\n", + ioctl_hdr->subsystem, + ioctl_hdr->opcode, + status, addl_status); + rc = -EAGAIN; + } + +release_mcc_tag: + /* Release the MCC entry */ + free_mcc_tag(&phba->ctrl, tag); + + return rc; +} + void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { spin_lock(&ctrl->mbox_lock); @@ -168,11 +249,24 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) compl->flags = 0; } +/* + * be_mcc_compl_process()- Check the MBX comapletion status + * @ctrl: Function specific MBX data structure + * @compl: Completion status of MBX Command + * + * Check for the MBX completion status when BMBX method used + * + * return + * Success: Zero + * Failure: Non-Zero + **/ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, struct be_mcc_compl *compl) { u16 compl_status, extd_status; + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + struct be_cmd_req_hdr *hdr = embedded_payload(wrb); be_dws_le_to_cpu(compl, 4); @@ -184,7 +278,10 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : error in cmd completion: status(compl/extd)=%d/%d\n", + "BC_%d : error in cmd completion: " + "Subsystem : %d Opcode : %d " + "status(compl/extd)=%d/%d\n", + hdr->subsystem, hdr->opcode, compl_status, extd_status); return -EBUSY; @@ -314,11 +411,24 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) return status; } -/* Wait till no more pending mcc requests are present */ +/* + * be_mcc_wait_compl()- Wait for MBX completion + * @phba: driver private structure + * + * Wait till no more pending mcc requests are present + * + * return + * Success: 0 + * Failure: Non-Zero + * + **/ static int be_mcc_wait_compl(struct beiscsi_hba *phba) { int i, status; for (i = 0; i < mcc_timeout; i++) { + if (beiscsi_error(phba)) + return -EIO; + status = beiscsi_process_mcc(phba); if (status) return status; @@ -330,51 +440,83 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba) if (i == mcc_timeout) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : mccq poll timed out\n"); - + "BC_%d : FW Timed Out\n"); + phba->fw_timeout = true; + beiscsi_ue_detect(phba); return -EBUSY; } return 0; } -/* Notify MCC requests and wait for completion */ +/* + * be_mcc_notify_wait()- Notify and wait for Compl + * @phba: driver private structure + * + * Notify MCC requests and wait for completion + * + * return + * Success: 0 + * Failure: Non-Zero + **/ int be_mcc_notify_wait(struct beiscsi_hba *phba) { be_mcc_notify(phba); return be_mcc_wait_compl(phba); } +/* + * be_mbox_db_ready_wait()- Check ready status + * @ctrl: Function specific MBX data structure + * + * Check for the ready status of FW to send BMBX + * commands to adapter. + * + * return + * Success: 0 + * Failure: Non-Zero + **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define long_delay 2000 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; - int cnt = 0, wait = 5; /* in usecs */ + struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + int wait = 0; u32 ready; do { + + if (beiscsi_error(phba)) + return -EIO; + ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; if (ready) break; - if (cnt > 12000000) { - struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + if (wait > BEISCSI_HOST_MBX_TIMEOUT) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : mbox_db poll timed out\n"); - + "BC_%d : FW Timed Out\n"); + phba->fw_timeout = true; + beiscsi_ue_detect(phba); return -EBUSY; } - if (cnt > 50) { - wait = long_delay; - mdelay(long_delay / 1000); - } else - udelay(wait); - cnt += wait; + mdelay(1); + wait++; } while (true); return 0; } +/* + * be_mbox_notify: Notify adapter of new BMBX command + * @ctrl: Function specific MBX data structure + * + * Ring doorbell to inform adapter of a BMBX command + * to process + * + * return + * Success: 0 + * Failure: Non-Zero + **/ int be_mbox_notify(struct be_ctrl_info *ctrl) { int status; @@ -391,13 +533,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) iowrite32(val, db); status = be_mbox_db_ready_wait(ctrl); - if (status != 0) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : be_mbox_db_ready_wait failed\n"); - + if (status) return status; - } + val = 0; val &= ~MPU_MAILBOX_DB_RDY_MASK; val &= ~MPU_MAILBOX_DB_HI_MASK; @@ -405,13 +543,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) iowrite32(val, db); status = be_mbox_db_ready_wait(ctrl); - if (status != 0) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : be_mbox_db_ready_wait failed\n"); - + if (status) return status; - } + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); @@ -499,7 +633,7 @@ void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, req_hdr->opcode = opcode; req_hdr->subsystem = subsystem; req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); - req_hdr->timeout = 120; + req_hdr->timeout = BEISCSI_FW_MBX_TIMEOUT; } static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, @@ -649,18 +783,34 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, OPCODE_COMMON_CQ_CREATE, sizeof(*req)); req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + if (chip_skh_r(ctrl->pdev)) { + req->hdr.version = MBX_CMD_VER2; + req->page_size = 1; + AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, + ctxt, coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, + ctxt, no_delay); + AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, + __ilog2_u32(cq->len / 256)); + AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1); + } else { + AMAP_SET_BITS(struct amap_cq_context, coalescwm, + ctxt, coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); + AMAP_SET_BITS(struct amap_cq_context, count, ctxt, + __ilog2_u32(cq->len / 256)); + AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, func, ctxt, + PCI_FUNC(ctrl->pdev->devfn)); + } - AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); - AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); - AMAP_SET_BITS(struct amap_cq_context, count, ctxt, - __ilog2_u32(cq->len / 256)); - AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); - AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); - AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, func, ctxt, - PCI_FUNC(ctrl->pdev->devfn)); be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 2c8f98df1287..23397d51ac54 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -57,6 +57,16 @@ struct be_mcc_wrb { #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ #define CQE_STATUS_EXTD_MASK 0xFFFF #define CQE_STATUS_EXTD_SHIFT 16 /* bits 0 - 15 */ +#define CQE_STATUS_ADDL_MASK 0xFF00 +#define CQE_STATUS_MASK 0xFF +#define CQE_STATUS_ADDL_SHIFT 0x08 +#define CQE_STATUS_WRB_MASK 0xFF0000 +#define CQE_STATUS_WRB_SHIFT 16 +#define BEISCSI_HOST_MBX_TIMEOUT (110 * 1000) +#define BEISCSI_FW_MBX_TIMEOUT 100 + +/* MBOX Command VER */ +#define MBX_CMD_VER2 0x02 struct be_mcc_compl { u32 status; /* dword 0 */ @@ -183,7 +193,8 @@ struct be_cmd_req_hdr { u8 domain; /* dword 0 */ u32 timeout; /* dword 1 */ u32 request_length; /* dword 2 */ - u32 rsvd0; /* dword 3 */ + u8 version; /* dword 3 */ + u8 rsvd0[3]; /* dword 3 */ }; struct be_cmd_resp_hdr { @@ -483,10 +494,28 @@ struct amap_cq_context { u8 rsvd5[32]; /* dword 3 */ } __packed; +struct amap_cq_context_v2 { + u8 rsvd0[12]; /* dword 0 */ + u8 coalescwm[2]; /* dword 0 */ + u8 nodelay; /* dword 0 */ + u8 rsvd1[12]; /* dword 0 */ + u8 count[2]; /* dword 0 */ + u8 valid; /* dword 0 */ + u8 rsvd2; /* dword 0 */ + u8 eventable; /* dword 0 */ + u8 eqid[16]; /* dword 1 */ + u8 rsvd3[15]; /* dword 1 */ + u8 armed; /* dword 1 */ + u8 cqecount[16];/* dword 2 */ + u8 rsvd4[16]; /* dword 2 */ + u8 rsvd5[32]; /* dword 3 */ +}; + struct be_cmd_req_cq_create { struct be_cmd_req_hdr hdr; u16 num_pages; - u16 rsvd0; + u8 page_size; + u8 rsvd0; u8 context[sizeof(struct amap_cq_context) / 8]; struct phys_addr pages[4]; } __packed; @@ -663,6 +692,9 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba); unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba); void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); + +int beiscsi_mccq_compl(struct beiscsi_hba *phba, + uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va); /*ISCSI Functuions */ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); @@ -804,6 +836,59 @@ struct amap_sol_cqe_ring { u8 valid; /* dword 3 */ } __packed; +struct amap_sol_cqe_v2 { + u8 hw_sts[8]; /* dword 0 */ + u8 i_sts[8]; /* dword 0 */ + u8 wrb_index[16]; /* dword 0 */ + u8 i_exp_cmd_sn[32]; /* dword 1 */ + u8 code[6]; /* dword 2 */ + u8 cmd_cmpl; /* dword 2 */ + u8 rsvd0; /* dword 2 */ + u8 i_cmd_wnd[8]; /* dword 2 */ + u8 cid[13]; /* dword 2 */ + u8 u; /* dword 2 */ + u8 o; /* dword 2 */ + u8 s; /* dword 2 */ + u8 i_res_cnt[31]; /* dword 3 */ + u8 valid; /* dword 3 */ +} __packed; + +struct common_sol_cqe { + u32 exp_cmdsn; + u32 res_cnt; + u16 wrb_index; + u16 cid; + u8 hw_sts; + u8 cmd_wnd; + u8 res_flag; /* the s feild of structure */ + u8 i_resp; /* for skh if cmd_complete is set then i_sts is response */ + u8 i_flags; /* for skh or the u and o feilds */ + u8 i_sts; /* for skh if cmd_complete is not-set then i_sts is status */ +}; + +/*** iSCSI ack/driver message completions ***/ +struct amap_it_dmsg_cqe { + u8 ack_num[32]; /* DWORD 0 */ + u8 pdu_bytes_rcvd[32]; /* DWORD 1 */ + u8 code[6]; /* DWORD 2 */ + u8 cid[10]; /* DWORD 2 */ + u8 wrb_idx[8]; /* DWORD 2 */ + u8 rsvd0[8]; /* DWORD 2*/ + u8 rsvd1[31]; /* DWORD 3*/ + u8 valid; /* DWORD 3 */ +} __packed; + +struct amap_it_dmsg_cqe_v2 { + u8 ack_num[32]; /* DWORD 0 */ + u8 pdu_bytes_rcvd[32]; /* DWORD 1 */ + u8 code[6]; /* DWORD 2 */ + u8 rsvd0[10]; /* DWORD 2 */ + u8 wrb_idx[16]; /* DWORD 2 */ + u8 rsvd1[16]; /* DWORD 3 */ + u8 cid[13]; /* DWORD 3 */ + u8 rsvd2[2]; /* DWORD 3 */ + u8 valid; /* DWORD 3 */ +} __packed; /** @@ -992,8 +1077,6 @@ struct be_cmd_get_all_if_id_req { #define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset, * sequence number by driver */ -/* Returns byte size of given field with a structure. */ - /* Returns the number of items in the field array. */ #define BE_NUMBER_OF_FIELD(_type_, _field_) \ (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\ diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index aedb0d9a9dae..214d691adb53 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -531,9 +531,9 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, break; case ISCSI_NET_PARAM_IPV4_BOOTPROTO: if (!if_info.dhcp_state) - len = sprintf(buf, "static"); + len = sprintf(buf, "static\n"); else - len = sprintf(buf, "dhcp"); + len = sprintf(buf, "dhcp\n"); break; case ISCSI_NET_PARAM_IPV4_SUBNET: len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask); @@ -541,7 +541,7 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, case ISCSI_NET_PARAM_VLAN_ENABLED: len = sprintf(buf, "%s\n", (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) - ? "Disabled" : "Enabled"); + ? "Disabled\n" : "Enabled\n"); break; case ISCSI_NET_PARAM_VLAN_ID: if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) @@ -586,7 +586,7 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, len = be2iscsi_get_if_param(phba, iface, param, buf); break; case ISCSI_NET_PARAM_IFACE_ENABLE: - len = sprintf(buf, "enabled"); + len = sprintf(buf, "enabled\n"); break; case ISCSI_NET_PARAM_IPV4_GW: memset(&gateway, 0, sizeof(gateway)); @@ -690,11 +690,9 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba) { int rc; - unsigned int tag, wrb_num; - unsigned short status, extd_status; + unsigned int tag; struct be_mcc_wrb *wrb; struct be_cmd_hba_name *resp; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; tag = be_cmd_get_initname(phba); if (!tag) { @@ -702,26 +700,16 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba) "BS_%d : Getting Initiator Name Failed\n"); return -EBUSY; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + } - if (status || extd_status) { + rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); + if (rc) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BS_%d : MailBox Command Failed with " - "status = %d extd_status = %d\n", - status, extd_status); - - free_mcc_tag(&phba->ctrl, tag); - return -EAGAIN; + "BS_%d : Initiator Name MBX Failed\n"); + return rc; } - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); + resp = embedded_payload(wrb); rc = sprintf(buf, "%s\n", resp->initiator_name); return rc; @@ -731,7 +719,6 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba) * beiscsi_get_port_state - Get the Port State * @shost : pointer to scsi_host structure * - * returns number of bytes */ static void beiscsi_get_port_state(struct Scsi_Host *shost) { @@ -750,13 +737,12 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) */ static int beiscsi_get_port_speed(struct Scsi_Host *shost) { - unsigned int tag, wrb_num; - unsigned short status, extd_status; + int rc; + unsigned int tag; struct be_mcc_wrb *wrb; struct be_cmd_ntwk_link_status_resp *resp; struct beiscsi_hba *phba = iscsi_host_priv(shost); struct iscsi_cls_host *ihost = shost->shost_data; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; tag = be_cmd_get_port_speed(phba); if (!tag) { @@ -764,26 +750,14 @@ static int beiscsi_get_port_speed(struct Scsi_Host *shost) "BS_%d : Getting Port Speed Failed\n"); return -EBUSY; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - - if (status || extd_status) { + } + rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); + if (rc) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BS_%d : MailBox Command Failed with " - "status = %d extd_status = %d\n", - status, extd_status); - - free_mcc_tag(&phba->ctrl, tag); - return -EAGAIN; + "BS_%d : Port Speed MBX Failed\n"); + return rc; } - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); resp = embedded_payload(wrb); switch (resp->mac_speed) { @@ -937,6 +911,14 @@ static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, session->initial_r2t_en); AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params, session->imm_data_en); + AMAP_SET_BITS(struct amap_beiscsi_offload_params, + data_seq_inorder, params, + session->dataseq_inorder_en); + AMAP_SET_BITS(struct amap_beiscsi_offload_params, + pdu_seq_inorder, params, + session->pdu_inorder_en); + AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params, + session->max_r2t); AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, (conn->exp_statsn - 1)); } @@ -1027,12 +1009,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, { struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; struct beiscsi_hba *phba = beiscsi_ep->phba; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; struct be_mcc_wrb *wrb; struct tcp_connect_and_offload_out *ptcpcnct_out; - unsigned short status, extd_status; struct be_dma_mem nonemb_cmd; - unsigned int tag, wrb_num; + unsigned int tag; int ret = -ENOMEM; beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, @@ -1084,35 +1064,26 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); return -EAGAIN; - } else { - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); } - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { + + ret = beiscsi_mccq_compl(phba, tag, &wrb, NULL); + if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BS_%d : mgmt_open_connection Failed" - " status = %d extd_status = %d\n", - status, extd_status); + "BS_%d : mgmt_open_connection Failed"); - free_mcc_tag(&phba->ctrl, tag); pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); goto free_ep; - } else { - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); - - ptcpcnct_out = embedded_payload(wrb); - beiscsi_ep = ep->dd_data; - beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; - beiscsi_ep->cid_vld = 1; - beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, - "BS_%d : mgmt_open_connection Success\n"); } + + ptcpcnct_out = embedded_payload(wrb); + beiscsi_ep = ep->dd_data; + beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; + beiscsi_ep->cid_vld = 1; + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, + "BS_%d : mgmt_open_connection Success\n"); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); return 0; @@ -1150,8 +1121,8 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, if (phba->state != BE_ADAPTER_UP) { ret = -EBUSY; - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BS_%d : The Adapter state is Not UP\n"); + beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, + "BS_%d : The Adapter Port state is Down!!!\n"); return ERR_PTR(ret); } @@ -1216,11 +1187,9 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) beiscsi_ep->ep_cid); ret = -EAGAIN; - } else { - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - free_mcc_tag(&phba->ctrl, tag); } + + ret = beiscsi_mccq_compl(phba, tag, NULL, NULL); return ret; } @@ -1281,12 +1250,9 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n", beiscsi_ep->ep_cid); - } else { - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - free_mcc_tag(&phba->ctrl, tag); } + beiscsi_mccq_compl(phba, tag, NULL, NULL); beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); beiscsi_free_ep(beiscsi_ep); beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 8b826fc06bcc..38eab7232159 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index ff73f9500b01..48d37dded8f1 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -47,8 +47,6 @@ static unsigned int be_iopoll_budget = 10; static unsigned int be_max_phys_size = 64; static unsigned int enable_msix = 1; -static unsigned int gcrashmode = 0; -static unsigned int num_hba = 0; MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); @@ -153,11 +151,54 @@ BEISCSI_RW_ATTR(log_enable, 0x00, "\t\t\t\tIO Path Events : 0x10\n" "\t\t\t\tConfiguration Path : 0x20\n"); +DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); +DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); struct device_attribute *beiscsi_attrs[] = { &dev_attr_beiscsi_log_enable, + &dev_attr_beiscsi_drvr_ver, + &dev_attr_beiscsi_adapter_family, NULL, }; +static char const *cqe_desc[] = { + "RESERVED_DESC", + "SOL_CMD_COMPLETE", + "SOL_CMD_KILLED_DATA_DIGEST_ERR", + "CXN_KILLED_PDU_SIZE_EXCEEDS_DSL", + "CXN_KILLED_BURST_LEN_MISMATCH", + "CXN_KILLED_AHS_RCVD", + "CXN_KILLED_HDR_DIGEST_ERR", + "CXN_KILLED_UNKNOWN_HDR", + "CXN_KILLED_STALE_ITT_TTT_RCVD", + "CXN_KILLED_INVALID_ITT_TTT_RCVD", + "CXN_KILLED_RST_RCVD", + "CXN_KILLED_TIMED_OUT", + "CXN_KILLED_RST_SENT", + "CXN_KILLED_FIN_RCVD", + "CXN_KILLED_BAD_UNSOL_PDU_RCVD", + "CXN_KILLED_BAD_WRB_INDEX_ERROR", + "CXN_KILLED_OVER_RUN_RESIDUAL", + "CXN_KILLED_UNDER_RUN_RESIDUAL", + "CMD_KILLED_INVALID_STATSN_RCVD", + "CMD_KILLED_INVALID_R2T_RCVD", + "CMD_CXN_KILLED_LUN_INVALID", + "CMD_CXN_KILLED_ICD_INVALID", + "CMD_CXN_KILLED_ITT_INVALID", + "CMD_CXN_KILLED_SEQ_OUTOFORDER", + "CMD_CXN_KILLED_INVALID_DATASN_RCVD", + "CXN_INVALIDATE_NOTIFY", + "CXN_INVALIDATE_INDEX_NOTIFY", + "CMD_INVALIDATED_NOTIFY", + "UNSOL_HDR_NOTIFY", + "UNSOL_DATA_NOTIFY", + "UNSOL_DATA_DIGEST_ERROR_NOTIFY", + "DRIVERMSG_NOTIFY", + "CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN", + "SOL_CMD_KILLED_DIF_ERR", + "CXN_KILLED_SYN_RCVD", + "CXN_KILLED_IMM_DATA_RCVD" +}; + static int beiscsi_slave_configure(struct scsi_device *sdev) { blk_queue_max_segment_size(sdev->request_queue, 65536); @@ -226,11 +267,9 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) nonemb_cmd.va, nonemb_cmd.dma); return FAILED; - } else { - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - free_mcc_tag(&phba->ctrl, tag); } + + beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); return iscsi_eh_abort(sc); @@ -301,11 +340,9 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); return FAILED; - } else { - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - free_mcc_tag(&phba->ctrl, tag); } + + beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); return iscsi_eh_device_reset(sc); @@ -482,6 +519,7 @@ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, + { PCI_DEVICE(ELX_VENDOR_ID, OC_SKH_ID1) }, { 0 } }; MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); @@ -730,7 +768,7 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) resource_id) / 32] & EQE_RESID_MASK) >> 16) == mcc->id) { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_mcc_cq = 1; + pbe_eq->todo_mcc_cq = true; spin_unlock_irqrestore(&phba->isr_lock, flags); } AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); @@ -738,8 +776,8 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) eqe = queue_tail_node(eq); num_eq_processed++; } - if (phba->todo_mcc_cq) - queue_work(phba->wq, &phba->work_cqs); + if (pbe_eq->todo_mcc_cq) + queue_work(phba->wq, &pbe_eq->work_cqs); if (num_eq_processed) hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); @@ -779,29 +817,26 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id) eqe = queue_tail_node(eq); num_eq_processed++; } - if (num_eq_processed) - hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); - - return IRQ_HANDLED; } else { while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] & EQE_VALID_MASK) { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_cq = 1; + pbe_eq->todo_cq = true; spin_unlock_irqrestore(&phba->isr_lock, flags); AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); queue_tail_inc(eq); eqe = queue_tail_node(eq); num_eq_processed++; } - if (phba->todo_cq) - queue_work(phba->wq, &phba->work_cqs); - if (num_eq_processed) - hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); - - return IRQ_HANDLED; + if (pbe_eq->todo_cq) + queue_work(phba->wq, &pbe_eq->work_cqs); } + + if (num_eq_processed) + hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + + return IRQ_HANDLED; } /** @@ -849,7 +884,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) resource_id) / 32] & EQE_RESID_MASK) >> 16) == mcc->id) { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_mcc_cq = 1; + pbe_eq->todo_mcc_cq = true; spin_unlock_irqrestore(&phba->isr_lock, flags); num_mcceq_processed++; } else { @@ -862,8 +897,8 @@ static irqreturn_t be_isr(int irq, void *dev_id) eqe = queue_tail_node(eq); } if (num_ioeq_processed || num_mcceq_processed) { - if (phba->todo_mcc_cq) - queue_work(phba->wq, &phba->work_cqs); + if (pbe_eq->todo_mcc_cq) + queue_work(phba->wq, &pbe_eq->work_cqs); if ((num_mcceq_processed) && (!num_ioeq_processed)) hwi_ring_eq_db(phba, eq->id, 0, @@ -886,11 +921,11 @@ static irqreturn_t be_isr(int irq, void *dev_id) resource_id) / 32] & EQE_RESID_MASK) >> 16) != cq->id) { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_mcc_cq = 1; + pbe_eq->todo_mcc_cq = true; spin_unlock_irqrestore(&phba->isr_lock, flags); } else { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_cq = 1; + pbe_eq->todo_cq = true; spin_unlock_irqrestore(&phba->isr_lock, flags); } AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); @@ -898,8 +933,8 @@ static irqreturn_t be_isr(int irq, void *dev_id) eqe = queue_tail_node(eq); num_ioeq_processed++; } - if (phba->todo_cq || phba->todo_mcc_cq) - queue_work(phba->wq, &phba->work_cqs); + if (pbe_eq->todo_cq || pbe_eq->todo_mcc_cq) + queue_work(phba->wq, &pbe_eq->work_cqs); if (num_ioeq_processed) { hwi_ring_eq_db(phba, eq->id, 0, @@ -1211,7 +1246,8 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) static void be_complete_io(struct beiscsi_conn *beiscsi_conn, - struct iscsi_task *task, struct sol_cqe *psol) + struct iscsi_task *task, + struct common_sol_cqe *csol_cqe) { struct beiscsi_io_task *io_task = task->dd_data; struct be_status_bhs *sts_bhs = @@ -1221,20 +1257,14 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, u32 resid = 0, exp_cmdsn, max_cmdsn; u8 rsp, status, flags; - exp_cmdsn = (psol-> - dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] - & SOL_EXP_CMD_SN_MASK); - max_cmdsn = ((psol-> - dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] - & SOL_EXP_CMD_SN_MASK) + - ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) - / 32] & SOL_CMD_WND_MASK) >> 24) - 1); - rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32] - & SOL_RESP_MASK) >> 16); - status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32] - & SOL_STS_MASK) >> 8); - flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] - & SOL_FLAGS_MASK) >> 24) | 0x80; + exp_cmdsn = csol_cqe->exp_cmdsn; + max_cmdsn = (csol_cqe->exp_cmdsn + + csol_cqe->cmd_wnd - 1); + rsp = csol_cqe->i_resp; + status = csol_cqe->i_sts; + flags = csol_cqe->i_flags; + resid = csol_cqe->res_cnt; + if (!task->sc) { if (io_task->scsi_cmnd) scsi_dma_unmap(io_task->scsi_cmnd); @@ -1249,9 +1279,6 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, /* bidi not initially supported */ if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) { - resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / - 32] & SOL_RES_CNT_MASK); - if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW)) task->sc->result = DID_ERROR << 16; @@ -1273,13 +1300,8 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); } - if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) { - if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] - & SOL_RES_CNT_MASK) - conn->rxdata_octets += (psol-> - dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] - & SOL_RES_CNT_MASK); - } + if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) + conn->rxdata_octets += resid; unmap: scsi_dma_unmap(io_task->scsi_cmnd); iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn); @@ -1287,7 +1309,8 @@ unmap: static void be_complete_logout(struct beiscsi_conn *beiscsi_conn, - struct iscsi_task *task, struct sol_cqe *psol) + struct iscsi_task *task, + struct common_sol_cqe *csol_cqe) { struct iscsi_logout_rsp *hdr; struct beiscsi_io_task *io_task = task->dd_data; @@ -1297,18 +1320,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn, hdr->opcode = ISCSI_OP_LOGOUT_RSP; hdr->t2wait = 5; hdr->t2retain = 0; - hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] - & SOL_FLAGS_MASK) >> 24) | 0x80; - hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / - 32] & SOL_RESP_MASK); - hdr->exp_cmdsn = cpu_to_be32(psol-> - dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] - & SOL_EXP_CMD_SN_MASK); - hdr->max_cmdsn = be32_to_cpu((psol-> - dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] - & SOL_EXP_CMD_SN_MASK) + - ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) - / 32] & SOL_CMD_WND_MASK) >> 24) - 1); + hdr->flags = csol_cqe->i_flags; + hdr->response = csol_cqe->i_resp; + hdr->exp_cmdsn = csol_cqe->exp_cmdsn; + hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1); + hdr->dlength[0] = 0; hdr->dlength[1] = 0; hdr->dlength[2] = 0; @@ -1319,7 +1335,8 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn, static void be_complete_tmf(struct beiscsi_conn *beiscsi_conn, - struct iscsi_task *task, struct sol_cqe *psol) + struct iscsi_task *task, + struct common_sol_cqe *csol_cqe) { struct iscsi_tm_rsp *hdr; struct iscsi_conn *conn = beiscsi_conn->conn; @@ -1327,16 +1344,12 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn, hdr = (struct iscsi_tm_rsp *)task->hdr; hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; - hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] - & SOL_FLAGS_MASK) >> 24) | 0x80; - hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / - 32] & SOL_RESP_MASK); - hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, - i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); - hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, - i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + - ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) - / 32] & SOL_CMD_WND_MASK) >> 24) - 1); + hdr->flags = csol_cqe->i_flags; + hdr->response = csol_cqe->i_resp; + hdr->exp_cmdsn = csol_cqe->exp_cmdsn; + hdr->max_cmdsn = (csol_cqe->exp_cmdsn + + csol_cqe->cmd_wnd - 1); + hdr->itt = io_task->libiscsi_itt; __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); } @@ -1352,15 +1365,24 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, struct beiscsi_io_task *io_task; struct iscsi_conn *conn = beiscsi_conn->conn; struct iscsi_session *session = conn->session; + uint16_t wrb_index, cid; phwi_ctrlr = phba->phwi_ctrlr; - pwrb_context = &phwi_ctrlr->wrb_context[((psol-> - dw[offsetof(struct amap_sol_cqe, cid) / 32] & - SOL_CID_MASK) >> 6) - - phba->fw_config.iscsi_cid_start]; - pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> - dw[offsetof(struct amap_sol_cqe, wrb_index) / - 32] & SOL_WRB_INDEX_MASK) >> 16)]; + if (chip_skh_r(phba->pcidev)) { + wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, + wrb_idx, psol); + cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, + cid, psol); + } else { + wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe, + wrb_idx, psol); + cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe, + cid, psol); + } + + pwrb_context = &phwi_ctrlr->wrb_context[ + cid - phba->fw_config.iscsi_cid_start]; + pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; task = pwrb_handle->pio_handle; io_task = task->dd_data; @@ -1374,26 +1396,78 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, static void be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, - struct iscsi_task *task, struct sol_cqe *psol) + struct iscsi_task *task, + struct common_sol_cqe *csol_cqe) { struct iscsi_nopin *hdr; struct iscsi_conn *conn = beiscsi_conn->conn; struct beiscsi_io_task *io_task = task->dd_data; hdr = (struct iscsi_nopin *)task->hdr; - hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] - & SOL_FLAGS_MASK) >> 24) | 0x80; - hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, - i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); - hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, - i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + - ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) - / 32] & SOL_CMD_WND_MASK) >> 24) - 1); + hdr->flags = csol_cqe->i_flags; + hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); + hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn + + csol_cqe->cmd_wnd - 1); + hdr->opcode = ISCSI_OP_NOOP_IN; hdr->itt = io_task->libiscsi_itt; __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); } +static void adapter_get_sol_cqe(struct beiscsi_hba *phba, + struct sol_cqe *psol, + struct common_sol_cqe *csol_cqe) +{ + if (chip_skh_r(phba->pcidev)) { + csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2, + i_exp_cmd_sn, psol); + csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2, + i_res_cnt, psol); + csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe_v2, + wrb_index, psol); + csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, + cid, psol); + csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, + hw_sts, psol); + csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, + i_cmd_wnd, psol); + if (AMAP_GET_BITS(struct amap_sol_cqe_v2, + cmd_cmpl, psol)) + csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, + i_sts, psol); + else + csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe_v2, + i_sts, psol); + if (AMAP_GET_BITS(struct amap_sol_cqe_v2, + u, psol)) + csol_cqe->i_flags = ISCSI_FLAG_CMD_UNDERFLOW; + + if (AMAP_GET_BITS(struct amap_sol_cqe_v2, + o, psol)) + csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW; + } else { + csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe, + i_exp_cmd_sn, psol); + csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe, + i_res_cnt, psol); + csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, + i_cmd_wnd, psol); + csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe, + wrb_index, psol); + csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe, + cid, psol); + csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe, + hw_sts, psol); + csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe, + i_resp, psol); + csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe, + i_sts, psol); + csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe, + i_flags, psol); + } +} + + static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, struct beiscsi_hba *phba, struct sol_cqe *psol) { @@ -1405,19 +1479,22 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, unsigned int type; struct iscsi_conn *conn = beiscsi_conn->conn; struct iscsi_session *session = conn->session; + struct common_sol_cqe csol_cqe = {0}; phwi_ctrlr = phba->phwi_ctrlr; - pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof - (struct amap_sol_cqe, cid) / 32] - & SOL_CID_MASK) >> 6) - - phba->fw_config.iscsi_cid_start]; - pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> - dw[offsetof(struct amap_sol_cqe, wrb_index) / - 32] & SOL_WRB_INDEX_MASK) >> 16)]; + + /* Copy the elements to a common structure */ + adapter_get_sol_cqe(phba, psol, &csol_cqe); + + pwrb_context = &phwi_ctrlr->wrb_context[ + csol_cqe.cid - phba->fw_config.iscsi_cid_start]; + + pwrb_handle = pwrb_context->pwrb_handle_basestd[ + csol_cqe.wrb_index]; + task = pwrb_handle->pio_handle; pwrb = pwrb_handle->pwrb; - type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] & - WRB_TYPE_MASK) >> 28; + type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type; spin_lock_bh(&session->lock); switch (type) { @@ -1425,17 +1502,16 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, case HWH_TYPE_IO_RD: if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_NOOP_OUT) - be_complete_nopin_resp(beiscsi_conn, task, psol); + be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe); else - be_complete_io(beiscsi_conn, task, psol); + be_complete_io(beiscsi_conn, task, &csol_cqe); break; case HWH_TYPE_LOGOUT: if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) - be_complete_logout(beiscsi_conn, task, psol); + be_complete_logout(beiscsi_conn, task, &csol_cqe); else - be_complete_tmf(beiscsi_conn, task, psol); - + be_complete_tmf(beiscsi_conn, task, &csol_cqe); break; case HWH_TYPE_LOGIN: @@ -1446,7 +1522,7 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, break; case HWH_TYPE_NOP: - be_complete_nopin_resp(beiscsi_conn, task, psol); + be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe); break; default: @@ -1454,10 +1530,8 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, "BM_%d : In hwi_complete_cmd, unknown type = %d" "wrb_index 0x%x CID 0x%x\n", type, - ((psol->dw[offsetof(struct amap_iscsi_wrb, - type) / 32] & SOL_WRB_INDEX_MASK) >> 16), - ((psol->dw[offsetof(struct amap_sol_cqe, - cid) / 32] & SOL_CID_MASK) >> 6)); + csol_cqe.wrb_index, + csol_cqe.cid); break; } @@ -1485,13 +1559,26 @@ hwi_get_async_handle(struct beiscsi_hba *phba, struct list_head *pbusy_list; struct async_pdu_handle *pasync_handle = NULL; unsigned char is_header = 0; + unsigned int index, dpl; + + if (chip_skh_r(phba->pcidev)) { + dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, + dpl, pdpdu_cqe); + index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, + index, pdpdu_cqe); + } else { + dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, + dpl, pdpdu_cqe); + index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, + index, pdpdu_cqe); + } phys_addr.u.a32.address_lo = - pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] - - ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] - & PDUCQE_DPL_MASK) >> 16); + (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, + db_addr_lo) / 32] - dpl); phys_addr.u.a32.address_hi = - pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32]; + pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, + db_addr_hi) / 32]; phys_addr.u.a64.address = *((unsigned long long *)(&phys_addr.u.a64.address)); @@ -1501,14 +1588,12 @@ hwi_get_async_handle(struct beiscsi_hba *phba, case UNSOL_HDR_NOTIFY: is_header = 1; - pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1, - (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, - index) / 32] & PDUCQE_INDEX_MASK)); + pbusy_list = hwi_get_async_busy_list(pasync_ctx, + is_header, index); break; case UNSOL_DATA_NOTIFY: - pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe-> - dw[offsetof(struct amap_i_t_dpdu_cqe, - index) / 32] & PDUCQE_INDEX_MASK)); + pbusy_list = hwi_get_async_busy_list(pasync_ctx, + is_header, index); break; default: pbusy_list = NULL; @@ -1531,12 +1616,9 @@ hwi_get_async_handle(struct beiscsi_hba *phba, pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid - phba->fw_config.iscsi_cid_start; pasync_handle->is_header = is_header; - pasync_handle->buffer_len = ((pdpdu_cqe-> - dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] - & PDUCQE_DPL_MASK) >> 16); + pasync_handle->buffer_len = dpl; + *pcq_index = index; - *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, - index) / 32] & PDUCQE_INDEX_MASK); return pasync_handle; } @@ -1914,6 +1996,13 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) } +/** + * beiscsi_process_cq()- Process the Completion Queue + * @pbe_eq: Event Q on which the Completion has come + * + * return + * Number of Completion Entries processed. + **/ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) { struct be_queue_info *cq; @@ -1935,12 +2024,24 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) CQE_VALID_MASK) { be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); - cid = ((sol->dw[offsetof(struct amap_sol_cqe, cid)/32] & - CQE_CID_MASK) >> 6); - code = (sol->dw[offsetof(struct amap_sol_cqe, code)/32] & - CQE_CODE_MASK); - ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start]; + code = (sol->dw[offsetof(struct amap_sol_cqe, code) / + 32] & CQE_CODE_MASK); + + /* Get the CID */ + if (chip_skh_r(phba->pcidev)) { + if ((code == DRIVERMSG_NOTIFY) || + (code == UNSOL_HDR_NOTIFY) || + (code == UNSOL_DATA_NOTIFY)) + cid = AMAP_GET_BITS( + struct amap_i_t_dpdu_cqe_v2, + cid, sol); + else + cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, + cid, sol); + } else + cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol); + ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start]; beiscsi_ep = ep->dd_data; beiscsi_conn = beiscsi_ep->conn; @@ -1958,7 +2059,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case DRIVERMSG_NOTIFY: beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : Received DRIVERMSG_NOTIFY\n"); + "BM_%d : Received %s[%d] on CID : %d\n", + cqe_desc[code], code, cid); dmsg = (struct dmsg_cqe *)sol; hwi_complete_drvr_msgs(beiscsi_conn, phba, sol); @@ -1966,7 +2068,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case UNSOL_HDR_NOTIFY: beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : Received UNSOL_HDR_ NOTIFY\n"); + "BM_%d : Received %s[%d] on CID : %d\n", + cqe_desc[code], code, cid); hwi_process_default_pdu_ring(beiscsi_conn, phba, (struct i_t_dpdu_cqe *)sol); @@ -1974,7 +2077,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case UNSOL_DATA_NOTIFY: beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, - "BM_%d : Received UNSOL_DATA_NOTIFY\n"); + "BM_%d : Received %s[%d] on CID : %d\n", + cqe_desc[code], code, cid); hwi_process_default_pdu_ring(beiscsi_conn, phba, (struct i_t_dpdu_cqe *)sol); @@ -1984,8 +2088,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case CXN_INVALIDATE_NOTIFY: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : Ignoring CQ Error notification for" - " cmd/cxn invalidate\n"); + "BM_%d : Ignoring %s[%d] on CID : %d\n", + cqe_desc[code], code, cid); break; case SOL_CMD_KILLED_DATA_DIGEST_ERR: case CMD_KILLED_INVALID_STATSN_RCVD: @@ -1997,14 +2101,14 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case CMD_CXN_KILLED_INVALID_DATASN_RCVD: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, - "BM_%d : CQ Error notification for cmd.. " - "code %d cid 0x%x\n", code, cid); + "BM_%d : Cmd Notification %s[%d] on CID : %d\n", + cqe_desc[code], code, cid); break; case UNSOL_DATA_DIGEST_ERROR_NOTIFY: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : Digest error on def pdu ring," - " dropping..\n"); + "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", + cqe_desc[code], code, cid); hwi_flush_default_pdu_buffer(phba, beiscsi_conn, (struct i_t_dpdu_cqe *) sol); break; @@ -2017,6 +2121,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case CXN_KILLED_INVALID_ITT_TTT_RCVD: case CXN_KILLED_TIMED_OUT: case CXN_KILLED_FIN_RCVD: + case CXN_KILLED_RST_SENT: + case CXN_KILLED_RST_RCVD: case CXN_KILLED_BAD_UNSOL_PDU_RCVD: case CXN_KILLED_BAD_WRB_INDEX_ERROR: case CXN_KILLED_OVER_RUN_RESIDUAL: @@ -2024,19 +2130,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : CQ Error %d, reset CID 0x%x...\n", - code, cid); - if (beiscsi_conn) - iscsi_conn_failure(beiscsi_conn->conn, - ISCSI_ERR_CONN_FAILED); - break; - case CXN_KILLED_RST_SENT: - case CXN_KILLED_RST_RCVD: - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : CQ Error %d, reset" - "received/sent on CID 0x%x...\n", - code, cid); + "BM_%d : Event %s[%d] received on CID : %d\n", + cqe_desc[code], code, cid); if (beiscsi_conn) iscsi_conn_failure(beiscsi_conn->conn, ISCSI_ERR_CONN_FAILED); @@ -2044,8 +2139,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) default: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : CQ Error Invalid code= %d " - "received on CID 0x%x...\n", + "BM_%d : Invalid CQE Event Received Code : %d" + "CID 0x%x...\n", code, cid); break; } @@ -2068,30 +2163,30 @@ void beiscsi_process_all_cqs(struct work_struct *work) unsigned long flags; struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; - struct be_eq_obj *pbe_eq; - struct beiscsi_hba *phba = - container_of(work, struct beiscsi_hba, work_cqs); + struct beiscsi_hba *phba; + struct be_eq_obj *pbe_eq = + container_of(work, struct be_eq_obj, work_cqs); + phba = pbe_eq->phba; phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; - if (phba->msix_enabled) - pbe_eq = &phwi_context->be_eq[phba->num_cpus]; - else - pbe_eq = &phwi_context->be_eq[0]; - if (phba->todo_mcc_cq) { + if (pbe_eq->todo_mcc_cq) { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_mcc_cq = 0; + pbe_eq->todo_mcc_cq = false; spin_unlock_irqrestore(&phba->isr_lock, flags); beiscsi_process_mcc_isr(phba); } - if (phba->todo_cq) { + if (pbe_eq->todo_cq) { spin_lock_irqsave(&phba->isr_lock, flags); - phba->todo_cq = 0; + pbe_eq->todo_cq = false; spin_unlock_irqrestore(&phba->isr_lock, flags); beiscsi_process_cq(pbe_eq); } + + /* rearm EQ for further interrupts */ + hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); } static int be_iopoll(struct blk_iopoll *iop, int budget) @@ -2115,6 +2210,101 @@ static int be_iopoll(struct blk_iopoll *iop, int budget) } static void +hwi_write_sgl_v2(struct iscsi_wrb *pwrb, struct scatterlist *sg, + unsigned int num_sg, struct beiscsi_io_task *io_task) +{ + struct iscsi_sge *psgl; + unsigned int sg_len, index; + unsigned int sge_len = 0; + unsigned long long addr; + struct scatterlist *l_sg; + unsigned int offset; + + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_lo, pwrb, + io_task->bhs_pa.u.a32.address_lo); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_hi, pwrb, + io_task->bhs_pa.u.a32.address_hi); + + l_sg = sg; + for (index = 0; (index < num_sg) && (index < 2); index++, + sg = sg_next(sg)) { + if (index == 0) { + sg_len = sg_dma_len(sg); + addr = (u64) sg_dma_address(sg); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + sge0_addr_lo, pwrb, + lower_32_bits(addr)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + sge0_addr_hi, pwrb, + upper_32_bits(addr)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + sge0_len, pwrb, + sg_len); + sge_len = sg_len; + } else { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_r2t_offset, + pwrb, sge_len); + sg_len = sg_dma_len(sg); + addr = (u64) sg_dma_address(sg); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + sge1_addr_lo, pwrb, + lower_32_bits(addr)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + sge1_addr_hi, pwrb, + upper_32_bits(addr)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + sge1_len, pwrb, + sg_len); + } + } + psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; + memset(psgl, 0, sizeof(*psgl) * BE2_SGE); + + AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2); + + AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, + io_task->bhs_pa.u.a32.address_hi); + AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, + io_task->bhs_pa.u.a32.address_lo); + + if (num_sg == 1) { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, + 1); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, + 0); + } else if (num_sg == 2) { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, + 0); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, + 1); + } else { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, + 0); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, + 0); + } + + sg = l_sg; + psgl++; + psgl++; + offset = 0; + for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) { + sg_len = sg_dma_len(sg); + addr = (u64) sg_dma_address(sg); + AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, + lower_32_bits(addr)); + AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, + upper_32_bits(addr)); + AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len); + AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset); + AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); + offset += sg_len; + } + psgl--; + AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); +} + +static void hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, unsigned int num_sg, struct beiscsi_io_task *io_task) { @@ -2202,13 +2392,18 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); } +/** + * hwi_write_buffer()- Populate the WRB with task info + * @pwrb: ptr to the WRB entry + * @task: iscsi task which is to be executed + **/ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) { struct iscsi_sge *psgl; - unsigned long long addr; struct beiscsi_io_task *io_task = task->dd_data; struct beiscsi_conn *beiscsi_conn = io_task->conn; struct beiscsi_hba *phba = beiscsi_conn->phba; + uint8_t dsp_value = 0; io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2; AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb, @@ -2217,26 +2412,38 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) io_task->bhs_pa.u.a32.address_hi); if (task->data) { - if (task->data_count) { - AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); - addr = (u64) pci_map_single(phba->pcidev, - task->data, - task->data_count, 1); - } else { - AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); - addr = 0; - } + + /* Check for the data_count */ + dsp_value = (task->data_count) ? 1 : 0; + + if (chip_skh_r(phba->pcidev)) + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, + pwrb, dsp_value); + else + AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, + pwrb, dsp_value); + + /* Map addr only if there is data_count */ + if (dsp_value) { + io_task->mtask_addr = pci_map_single(phba->pcidev, + task->data, + task->data_count, + PCI_DMA_TODEVICE); + io_task->mtask_data_count = task->data_count; + } else + io_task->mtask_addr = 0; + AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, - ((u32)(addr & 0xFFFFFFFF))); + lower_32_bits(io_task->mtask_addr)); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, - ((u32)(addr >> 32))); + upper_32_bits(io_task->mtask_addr)); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, task->data_count); AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1); } else { AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); - addr = 0; + io_task->mtask_addr = 0; } psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; @@ -2259,9 +2466,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) psgl++; if (task->data) { AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, - ((u32)(addr & 0xFFFFFFFF))); + lower_32_bits(io_task->mtask_addr)); AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, - ((u32)(addr >> 32))); + upper_32_bits(io_task->mtask_addr)); } AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106); } @@ -2843,7 +3050,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, } return 0; create_eq_error: - for (i = 0; i < (phba->num_cpus + 1); i++) { + for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { eq = &phwi_context->be_eq[i].q; mem = &eq->dma_mem; if (mem->va) @@ -3268,15 +3475,31 @@ err: return -ENOMEM; } -static int find_num_cpus(void) +/** + * 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) { int num_cpus = 0; num_cpus = num_online_cpus(); - if (num_cpus >= MAX_CPUS) - num_cpus = MAX_CPUS - 1; - return num_cpus; + switch (phba->generation) { + case BE_GEN2: + case BE_GEN3: + phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ? + BEISCSI_MAX_NUM_CPUS : num_cpus; + break; + case BE_GEN4: + phba->num_cpus = (num_cpus > OC_SKH_MAX_NUM_CPUS) ? + OC_SKH_MAX_NUM_CPUS : num_cpus; + break; + default: + phba->num_cpus = 1; + } } static int hwi_init_port(struct beiscsi_hba *phba) @@ -3644,12 +3867,9 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) static int beiscsi_get_boot_info(struct beiscsi_hba *phba) { struct be_cmd_get_session_resp *session_resp; - struct be_mcc_wrb *wrb; struct be_dma_mem nonemb_cmd; - unsigned int tag, wrb_num; - unsigned short status, extd_status; + unsigned int tag; unsigned int s_handle; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; int ret = -ENOMEM; /* Get the session handle of the boot target */ @@ -3682,25 +3902,16 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) " Failed\n"); goto boot_freemem; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); + } - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { + ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); + if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, - "BM_%d : beiscsi_get_session_info Failed" - " status = %d extd_status = %d\n", - status, extd_status); - - free_mcc_tag(&phba->ctrl, tag); + "BM_%d : beiscsi_get_session_info Failed"); goto boot_freemem; } - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); + session_resp = nonemb_cmd.va ; memcpy(&phba->boot_sess, &session_resp->session_info, @@ -3853,6 +4064,11 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) kfree(phba->ep_array); } +/** + * beiscsi_cleanup_task()- Free driver resources of the task + * @task: ptr to the iscsi task + * + **/ static void beiscsi_cleanup_task(struct iscsi_task *task) { struct beiscsi_io_task *io_task = task->dd_data; @@ -3900,6 +4116,13 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) spin_unlock(&phba->mgmt_sgl_lock); io_task->psgl_handle = NULL; } + if (io_task->mtask_addr) { + pci_unmap_single(phba->pcidev, + io_task->mtask_addr, + io_task->mtask_data_count, + PCI_DMA_TODEVICE); + io_task->mtask_addr = 0; + } } } } @@ -3909,8 +4132,6 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, struct beiscsi_offload_params *params) { struct wrb_handle *pwrb_handle; - struct iscsi_target_context_update_wrb *pwrb = NULL; - struct be_mem_descriptor *mem_descr; struct beiscsi_hba *phba = beiscsi_conn->phba; struct iscsi_task *task = beiscsi_conn->task; struct iscsi_session *session = task->conn->session; @@ -3927,67 +4148,16 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid - phba->fw_config.iscsi_cid_start)); - pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb; - memset(pwrb, 0, sizeof(*pwrb)); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, - max_burst_length, pwrb, params->dw[offsetof - (struct amap_beiscsi_offload_params, - max_burst_length) / 32]); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, - max_send_data_segment_length, pwrb, - params->dw[offsetof(struct amap_beiscsi_offload_params, - max_send_data_segment_length) / 32]); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, - first_burst_length, - pwrb, - params->dw[offsetof(struct amap_beiscsi_offload_params, - first_burst_length) / 32]); - - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb, - (params->dw[offsetof(struct amap_beiscsi_offload_params, - erl) / 32] & OFFLD_PARAMS_ERL)); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb, - (params->dw[offsetof(struct amap_beiscsi_offload_params, - dde) / 32] & OFFLD_PARAMS_DDE) >> 2); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb, - (params->dw[offsetof(struct amap_beiscsi_offload_params, - hde) / 32] & OFFLD_PARAMS_HDE) >> 3); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb, - (params->dw[offsetof(struct amap_beiscsi_offload_params, - ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb, - (params->dw[offsetof(struct amap_beiscsi_offload_params, - imd) / 32] & OFFLD_PARAMS_IMD) >> 5); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn, - pwrb, - (params->dw[offsetof(struct amap_beiscsi_offload_params, - exp_statsn) / 32] + 1)); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb, - 0x7); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx, - pwrb, pwrb_handle->wrb_index); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, - pwrb, pwrb_handle->nxt_wrb_index); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, - session_state, pwrb, 0); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, - pwrb, 1); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq, - pwrb, 0); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb, - 0); - mem_descr = phba->init_mem; - mem_descr += ISCSI_MEM_GLOBAL_HEADER; - - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, - pad_buffer_addr_hi, pwrb, - mem_descr->mem_array[0].bus_address.u.a32.address_hi); - AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, - pad_buffer_addr_lo, pwrb, - mem_descr->mem_array[0].bus_address.u.a32.address_lo); + /* Check for the adapter family */ + if (chip_skh_r(phba->pcidev)) + beiscsi_offload_cxn_v2(params, pwrb_handle); + else + beiscsi_offload_cxn_v0(params, pwrb_handle, + phba->init_mem); - be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb)); + be_dws_le_to_cpu(pwrb_handle->pwrb, + sizeof(struct iscsi_target_context_update_wrb)); doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) @@ -4044,13 +4214,25 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) spin_lock(&phba->io_sgl_lock); io_task->psgl_handle = alloc_io_sgl_handle(phba); spin_unlock(&phba->io_sgl_lock); - if (!io_task->psgl_handle) + if (!io_task->psgl_handle) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, + "BM_%d : Alloc of IO_SGL_ICD Failed" + "for the CID : %d\n", + beiscsi_conn->beiscsi_conn_cid); goto free_hndls; + } io_task->pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid - phba->fw_config.iscsi_cid_start); - if (!io_task->pwrb_handle) + if (!io_task->pwrb_handle) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, + "BM_%d : Alloc of WRB_HANDLE Failed" + "for the CID : %d\n", + beiscsi_conn->beiscsi_conn_cid); goto free_io_hndls; + } } else { io_task->scsi_cmnd = NULL; if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { @@ -4059,8 +4241,16 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) io_task->psgl_handle = (struct sgl_handle *) alloc_mgmt_sgl_handle(phba); spin_unlock(&phba->mgmt_sgl_lock); - if (!io_task->psgl_handle) + if (!io_task->psgl_handle) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_IO | + BEISCSI_LOG_CONFIG, + "BM_%d : Alloc of MGMT_SGL_ICD Failed" + "for the CID : %d\n", + beiscsi_conn-> + beiscsi_conn_cid); goto free_hndls; + } beiscsi_conn->login_in_progress = 1; beiscsi_conn->plogin_sgl_handle = @@ -4069,8 +4259,16 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid - phba->fw_config.iscsi_cid_start); - if (!io_task->pwrb_handle) - goto free_io_hndls; + if (!io_task->pwrb_handle) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_IO | + BEISCSI_LOG_CONFIG, + "BM_%d : Alloc of WRB_HANDLE Failed" + "for the CID : %d\n", + beiscsi_conn-> + beiscsi_conn_cid); + goto free_mgmt_hndls; + } beiscsi_conn->plogin_wrb_handle = io_task->pwrb_handle; @@ -4085,14 +4283,28 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) spin_lock(&phba->mgmt_sgl_lock); io_task->psgl_handle = alloc_mgmt_sgl_handle(phba); spin_unlock(&phba->mgmt_sgl_lock); - if (!io_task->psgl_handle) + if (!io_task->psgl_handle) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_IO | + BEISCSI_LOG_CONFIG, + "BM_%d : Alloc of MGMT_SGL_ICD Failed" + "for the CID : %d\n", + beiscsi_conn-> + beiscsi_conn_cid); goto free_hndls; + } io_task->pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid - phba->fw_config.iscsi_cid_start); - if (!io_task->pwrb_handle) + if (!io_task->pwrb_handle) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, + "BM_%d : Alloc of WRB_HANDLE Failed" + "for the CID : %d\n", + beiscsi_conn->beiscsi_conn_cid); goto free_mgmt_hndls; + } } } @@ -4124,11 +4336,64 @@ free_hndls: pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, io_task->bhs_pa.u.a64.address); io_task->cmd_bhs = NULL; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, - "BM_%d : Alloc of SGL_ICD Failed\n"); return -ENOMEM; } +int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, + unsigned int num_sg, unsigned int xferlen, + unsigned int writedir) +{ + + struct beiscsi_io_task *io_task = task->dd_data; + struct iscsi_conn *conn = task->conn; + struct beiscsi_conn *beiscsi_conn = conn->dd_data; + struct beiscsi_hba *phba = beiscsi_conn->phba; + struct iscsi_wrb *pwrb = NULL; + unsigned int doorbell = 0; + + pwrb = io_task->pwrb_handle->pwrb; + memset(pwrb, 0, sizeof(*pwrb)); + + io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; + io_task->bhs_len = sizeof(struct be_cmd_bhs); + + if (writedir) { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb, + INI_WR_CMD); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 1); + } else { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb, + INI_RD_CMD); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 0); + } + + io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb_v2, + type, pwrb); + + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, lun, pwrb, + cpu_to_be16(*(unsigned short *) + &io_task->cmd_bhs->iscsi_hdr.lun)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, xferlen); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, + io_task->pwrb_handle->wrb_index); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, + be32_to_cpu(task->cmdsn)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, + io_task->psgl_handle->sgl_index); + + hwi_write_sgl_v2(pwrb, sg, num_sg, io_task); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, + io_task->pwrb_handle->nxt_wrb_index); + + be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); + + doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; + doorbell |= (io_task->pwrb_handle->wrb_index & + DB_DEF_PDU_WRB_INDEX_MASK) << + DB_DEF_PDU_WRB_INDEX_SHIFT; + doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; + iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); + return 0; +} static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, unsigned int num_sg, unsigned int xferlen, @@ -4156,6 +4421,9 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); } + io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb, + type, pwrb); + AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb, cpu_to_be16(*(unsigned short *) &io_task->cmd_bhs->iscsi_hdr.lun)); @@ -4191,55 +4459,75 @@ static int beiscsi_mtask(struct iscsi_task *task) struct iscsi_wrb *pwrb = NULL; unsigned int doorbell = 0; unsigned int cid; + unsigned int pwrb_typeoffset = 0; cid = beiscsi_conn->beiscsi_conn_cid; pwrb = io_task->pwrb_handle->pwrb; memset(pwrb, 0, sizeof(*pwrb)); - AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, - be32_to_cpu(task->cmdsn)); - AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, - io_task->pwrb_handle->wrb_index); - AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, - io_task->psgl_handle->sgl_index); + + if (chip_skh_r(phba->pcidev)) { + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, + be32_to_cpu(task->cmdsn)); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, + io_task->pwrb_handle->wrb_index); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, + io_task->psgl_handle->sgl_index); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, + task->data_count); + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, + io_task->pwrb_handle->nxt_wrb_index); + pwrb_typeoffset = SKH_WRB_TYPE_OFFSET; + } else { + AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, + be32_to_cpu(task->cmdsn)); + AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, + io_task->pwrb_handle->wrb_index); + AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, + io_task->psgl_handle->sgl_index); + AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, + task->data_count); + AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, + io_task->pwrb_handle->nxt_wrb_index); + pwrb_typeoffset = BE_WRB_TYPE_OFFSET; + } + switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { case ISCSI_OP_LOGIN: - AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - TGT_DM_CMD); - AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1); + ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); hwi_write_buffer(pwrb, task); break; case ISCSI_OP_NOOP_OUT: if (task->hdr->ttt != ISCSI_RESERVED_TAG) { - AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - TGT_DM_CMD); - AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, - pwrb, 0); - AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1); + ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); + if (chip_skh_r(phba->pcidev)) + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + dmsg, pwrb, 1); + else + AMAP_SET_BITS(struct amap_iscsi_wrb, + dmsg, pwrb, 1); } else { - AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - INI_RD_CMD); - AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); + ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset); + if (chip_skh_r(phba->pcidev)) + AMAP_SET_BITS(struct amap_iscsi_wrb_v2, + dmsg, pwrb, 0); + else + AMAP_SET_BITS(struct amap_iscsi_wrb, + dmsg, pwrb, 0); } hwi_write_buffer(pwrb, task); break; case ISCSI_OP_TEXT: - AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - TGT_DM_CMD); - AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); + ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); hwi_write_buffer(pwrb, task); break; case ISCSI_OP_SCSI_TMFUNC: - AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - INI_TMF_CMD); - AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); + ADAPTER_SET_WRB_TYPE(pwrb, INI_TMF_CMD, pwrb_typeoffset); hwi_write_buffer(pwrb, task); break; case ISCSI_OP_LOGOUT: - AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); - AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, - HWH_TYPE_LOGOUT); + ADAPTER_SET_WRB_TYPE(pwrb, HWH_TYPE_LOGOUT, pwrb_typeoffset); hwi_write_buffer(pwrb, task); break; @@ -4251,11 +4539,10 @@ static int beiscsi_mtask(struct iscsi_task *task) return -EINVAL; } - AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, - task->data_count); - AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, - io_task->pwrb_handle->nxt_wrb_index); - be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); + /* Set the task type */ + io_task->wrb_type = (chip_skh_r(phba->pcidev)) ? + AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb) : + AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb); doorbell |= cid & DB_WRB_POST_CID_MASK; doorbell |= (io_task->pwrb_handle->wrb_index & @@ -4269,10 +4556,13 @@ static int beiscsi_task_xmit(struct iscsi_task *task) { struct beiscsi_io_task *io_task = task->dd_data; struct scsi_cmnd *sc = task->sc; + struct beiscsi_hba *phba = NULL; struct scatterlist *sg; int num_sg; unsigned int writedir = 0, xferlen = 0; + phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba; + if (!sc) return beiscsi_mtask(task); @@ -4295,7 +4585,7 @@ static int beiscsi_task_xmit(struct iscsi_task *task) else writedir = 0; - return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); + return phba->iotask_fn(task, sg, num_sg, xferlen, writedir); } /** @@ -4326,20 +4616,24 @@ static int beiscsi_bsg_request(struct bsg_job *job) beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BM_%d : Failed to allocate memory for " "beiscsi_bsg_request\n"); - return -EIO; + return -ENOMEM; } tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job, &nonemb_cmd); if (!tag) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BM_%d : be_cmd_get_mac_addr Failed\n"); + "BM_%d : MBX Tag Allocation Failed\n"); pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, nonemb_cmd.va, nonemb_cmd.dma); return -EAGAIN; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); + } + + rc = wait_event_interruptible_timeout( + phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag], + msecs_to_jiffies( + BEISCSI_HOST_MBX_TIMEOUT)); extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; free_mcc_tag(&phba->ctrl, tag); @@ -4356,11 +4650,13 @@ static int beiscsi_bsg_request(struct bsg_job *job) nonemb_cmd.va, nonemb_cmd.dma); if (status || extd_status) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BM_%d : be_cmd_get_mac_addr Failed" + "BM_%d : MBX Cmd Failed" " status = %d extd_status = %d\n", status, extd_status); return -EIO; + } else { + rc = 0; } break; @@ -4380,14 +4676,18 @@ void beiscsi_hba_attrs_init(struct beiscsi_hba *phba) beiscsi_log_enable_init(phba, beiscsi_log_enable); } +/* + * beiscsi_quiesce()- Cleanup Driver resources + * @phba: Instance Priv structure + * + * Free the OS and HW resources held by the driver + **/ static void beiscsi_quiesce(struct beiscsi_hba *phba) { struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; struct be_eq_obj *pbe_eq; unsigned int i, msix_vec; - u8 *real_offset = 0; - u32 value = 0; phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; @@ -4411,19 +4711,14 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba) beiscsi_clean_port(phba); beiscsi_free_mem(phba); - real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; - value = readl((void *)real_offset); - - if (value & 0x00010000) { - value &= 0xfffeffff; - writel(value, (void *)real_offset); - } beiscsi_unmap_pci_function(phba); pci_free_consistent(phba->pcidev, phba->ctrl.mbox_mem_alloced.size, phba->ctrl.mbox_mem_alloced.va, phba->ctrl.mbox_mem_alloced.dma); + + cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); } static void beiscsi_remove(struct pci_dev *pcidev) @@ -4476,6 +4771,25 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba) return; } +/* + * beiscsi_hw_health_check()- Check adapter health + * @work: work item to check HW health + * + * Check if adapter in an unrecoverable state or not. + **/ +static void +beiscsi_hw_health_check(struct work_struct *work) +{ + struct beiscsi_hba *phba = + container_of(work, struct beiscsi_hba, + beiscsi_hw_check_task.work); + + beiscsi_ue_detect(phba); + + schedule_delayed_work(&phba->beiscsi_hw_check_task, + msecs_to_jiffies(1000)); +} + static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, const struct pci_device_id *id) { @@ -4483,9 +4797,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, struct hwi_controller *phwi_ctrlr; struct hwi_context_memory *phwi_context; struct be_eq_obj *pbe_eq; - int ret, num_cpus, i; - u8 *real_offset = 0; - u32 value = 0; + int ret, i; ret = beiscsi_enable_pci(pcidev); if (ret < 0) { @@ -4504,25 +4816,33 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, /* Initialize Driver configuration Paramters */ beiscsi_hba_attrs_init(phba); + phba->fw_timeout = false; + + switch (pcidev->device) { case BE_DEVICE_ID1: case OC_DEVICE_ID1: case OC_DEVICE_ID2: phba->generation = BE_GEN2; + phba->iotask_fn = beiscsi_iotask; break; case BE_DEVICE_ID2: case OC_DEVICE_ID3: phba->generation = BE_GEN3; + phba->iotask_fn = beiscsi_iotask; break; + case OC_SKH_ID1: + phba->generation = BE_GEN4; + phba->iotask_fn = beiscsi_iotask_v2; default: phba->generation = 0; } if (enable_msix) - num_cpus = find_num_cpus(); + find_num_cpus(phba); else - num_cpus = 1; - phba->num_cpus = num_cpus; + phba->num_cpus = 1; + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "BM_%d : num_cpus = %d\n", phba->num_cpus); @@ -4540,31 +4860,18 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, goto hba_free; } - if (!num_hba) { - real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; - value = readl((void *)real_offset); - if (value & 0x00010000) { - gcrashmode++; - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, - "BM_%d : Loading Driver in crashdump mode\n"); - ret = beiscsi_cmd_reset_function(phba); - if (ret) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, - "BM_%d : Reset Failed. Aborting Crashdump\n"); - goto hba_free; - } - ret = be_chk_reset_complete(phba); - if (ret) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, - "BM_%d : Failed to get out of reset." - "Aborting Crashdump\n"); - goto hba_free; - } - } else { - value |= 0x00010000; - writel(value, (void *)real_offset); - num_hba++; - } + ret = beiscsi_cmd_reset_function(phba); + if (ret) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BM_%d : Reset Failed. Aborting Crashdump\n"); + goto hba_free; + } + ret = be_chk_reset_complete(phba); + if (ret) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BM_%d : Failed to get out of reset." + "Aborting Crashdump\n"); + goto hba_free; } spin_lock_init(&phba->io_sgl_lock); @@ -4596,7 +4903,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; - snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", + snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq", phba->shost->host_no); phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1); if (!phba->wq) { @@ -4606,10 +4913,12 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, goto free_twq; } - INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs); + INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, + beiscsi_hw_health_check); phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; + if (blk_iopoll_enabled) { for (i = 0; i < phba->num_cpus; i++) { pbe_eq = &phwi_context->be_eq[i]; @@ -4617,7 +4926,25 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, be_iopoll); blk_iopoll_enable(&pbe_eq->iopoll); } + + i = (phba->msix_enabled) ? i : 0; + /* Work item for MCC handling */ + pbe_eq = &phwi_context->be_eq[i]; + INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); + } else { + if (phba->msix_enabled) { + for (i = 0; i <= phba->num_cpus; i++) { + pbe_eq = &phwi_context->be_eq[i]; + INIT_WORK(&pbe_eq->work_cqs, + beiscsi_process_all_cqs); + } + } else { + pbe_eq = &phwi_context->be_eq[0]; + INIT_WORK(&pbe_eq->work_cqs, + beiscsi_process_all_cqs); + } } + ret = beiscsi_init_irqs(phba); if (ret < 0) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, @@ -4637,6 +4964,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, "iSCSI boot info.\n"); beiscsi_create_def_ifaces(phba); + schedule_delayed_work(&phba->beiscsi_hw_check_task, + msecs_to_jiffies(1000)); + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); return 0; @@ -4652,15 +4982,6 @@ free_twq: beiscsi_clean_port(phba); beiscsi_free_mem(phba); free_port: - real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; - - value = readl((void *)real_offset); - - if (value & 0x00010000) { - value &= 0xfffeffff; - writel(value, (void *)real_offset); - } - pci_free_consistent(phba->pcidev, phba->ctrl.mbox_mem_alloced.size, phba->ctrl.mbox_mem_alloced.va, diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index b8912263ef4e..5946577d79d6 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -36,12 +36,13 @@ #include "be.h" #define DRV_NAME "be2iscsi" -#define BUILD_STR "4.4.58.0" +#define BUILD_STR "10.0.272.0" #define BE_NAME "Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" #define BE_VENDOR_ID 0x19A2 +#define ELX_VENDOR_ID 0x10DF /* DEVICE ID's for BE2 */ #define BE_DEVICE_ID1 0x212 #define OC_DEVICE_ID1 0x702 @@ -51,6 +52,9 @@ #define BE_DEVICE_ID2 0x222 #define OC_DEVICE_ID3 0x712 +/* DEVICE ID for SKH */ +#define OC_SKH_ID1 0x722 + #define BE2_IO_DEPTH 1024 #define BE2_MAX_SESSIONS 256 #define BE2_CMDS_PER_CXN 128 @@ -60,7 +64,11 @@ #define BE2_DEFPDU_HDR_SZ 64 #define BE2_DEFPDU_DATA_SZ 8192 -#define MAX_CPUS 31 +#define MAX_CPUS 64 +#define BEISCSI_MAX_NUM_CPUS 7 +#define OC_SKH_MAX_NUM_CPUS 63 + + #define BEISCSI_SGLIST_ELEMENTS 30 #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ @@ -257,6 +265,7 @@ struct invalidate_command_table { unsigned short cid; } __packed; +#define chip_skh_r(pdev) (pdev->device == OC_SKH_ID1) struct beiscsi_hba { struct hba_parameters params; struct hwi_controller *phwi_ctrlr; @@ -270,12 +279,11 @@ struct beiscsi_hba { struct be_bus_address pci_pa; /* CSR */ /* PCI representation of our HBA */ struct pci_dev *pcidev; - unsigned int state; unsigned short asic_revision; unsigned int num_cpus; unsigned int nxt_cqid; - struct msix_entry msix_entries[MAX_CPUS + 1]; - char *msi_name[MAX_CPUS + 1]; + struct msix_entry msix_entries[MAX_CPUS]; + char *msi_name[MAX_CPUS]; bool msix_enabled; struct be_mem_descriptor *init_mem; @@ -325,12 +333,14 @@ struct beiscsi_hba { spinlock_t cid_lock; } fw_config; + unsigned int state; + bool fw_timeout; + bool ue_detected; + struct delayed_work beiscsi_hw_check_task; + u8 mac_address[ETH_ALEN]; - unsigned short todo_cq; - unsigned short todo_mcc_cq; char wq_name[20]; struct workqueue_struct *wq; /* The actuak work queue */ - struct work_struct work_cqs; /* The work being queued */ struct be_ctrl_info ctrl; unsigned int generation; unsigned int interface_handle; @@ -338,7 +348,10 @@ struct beiscsi_hba { struct invalidate_command_table inv_tbl[128]; unsigned int attr_log_enable; - + int (*iotask_fn)(struct iscsi_task *, + struct scatterlist *sg, + uint32_t num_sg, uint32_t xferlen, + uint32_t writedir); }; struct beiscsi_session { @@ -410,6 +423,9 @@ struct beiscsi_io_task { struct be_cmd_bhs *cmd_bhs; struct be_bus_address bhs_pa; unsigned short bhs_len; + dma_addr_t mtask_addr; + uint32_t mtask_data_count; + uint8_t wrb_type; }; struct be_nonio_bhs { @@ -457,6 +473,9 @@ struct beiscsi_offload_params { #define OFFLD_PARAMS_HDE 0x00000008 #define OFFLD_PARAMS_IR2T 0x00000010 #define OFFLD_PARAMS_IMD 0x00000020 +#define OFFLD_PARAMS_DATA_SEQ_INORDER 0x00000040 +#define OFFLD_PARAMS_PDU_SEQ_INORDER 0x00000080 +#define OFFLD_PARAMS_MAX_R2T 0x00FFFF00 /** * Pseudo amap definition in which each bit of the actual structure is defined @@ -471,7 +490,10 @@ struct amap_beiscsi_offload_params { u8 hde[1]; u8 ir2t[1]; u8 imd[1]; - u8 pad[26]; + u8 data_seq_inorder[1]; + u8 pdu_seq_inorder[1]; + u8 max_r2t[16]; + u8 pad[8]; u8 exp_statsn[32]; }; @@ -569,6 +591,20 @@ struct amap_i_t_dpdu_cqe { u8 valid; } __packed; +struct amap_i_t_dpdu_cqe_v2 { + u8 db_addr_hi[32]; /* DWORD 0 */ + u8 db_addr_lo[32]; /* DWORD 1 */ + u8 code[6]; /* DWORD 2 */ + u8 num_cons; /* DWORD 2*/ + u8 rsvd0[8]; /* DWORD 2 */ + u8 dpl[17]; /* DWORD 2 */ + u8 index[16]; /* DWORD 3 */ + u8 cid[13]; /* DWORD 3 */ + u8 rsvd1; /* DWORD 3 */ + u8 final; /* DWORD 3 */ + u8 valid; /* DWORD 3 */ +} __packed; + #define CQE_VALID_MASK 0x80000000 #define CQE_CODE_MASK 0x0000003F #define CQE_CID_MASK 0x0000FFC0 @@ -617,6 +653,11 @@ struct iscsi_wrb { } __packed; #define WRB_TYPE_MASK 0xF0000000 +#define SKH_WRB_TYPE_OFFSET 27 +#define BE_WRB_TYPE_OFFSET 28 + +#define ADAPTER_SET_WRB_TYPE(pwrb, wrb_type, type_offset) \ + (pwrb->dw[0] |= (wrb_type << type_offset)) /** * Pseudo amap definition in which each bit of the actual structure is defined @@ -663,12 +704,57 @@ struct amap_iscsi_wrb { } __packed; +struct amap_iscsi_wrb_v2 { + u8 r2t_exp_dtl[25]; /* DWORD 0 */ + u8 rsvd0[2]; /* DWORD 0*/ + u8 type[5]; /* DWORD 0 */ + u8 ptr2nextwrb[8]; /* DWORD 1 */ + u8 wrb_idx[8]; /* DWORD 1 */ + u8 lun[16]; /* DWORD 1 */ + u8 sgl_idx[16]; /* DWORD 2 */ + u8 ref_sgl_icd_idx[16]; /* DWORD 2 */ + u8 exp_data_sn[32]; /* DWORD 3 */ + u8 iscsi_bhs_addr_hi[32]; /* DWORD 4 */ + u8 iscsi_bhs_addr_lo[32]; /* DWORD 5 */ + u8 cq_id[16]; /* DWORD 6 */ + u8 rsvd1[16]; /* DWORD 6 */ + u8 cmdsn_itt[32]; /* DWORD 7 */ + u8 sge0_addr_hi[32]; /* DWORD 8 */ + u8 sge0_addr_lo[32]; /* DWORD 9 */ + u8 sge0_offset[24]; /* DWORD 10 */ + u8 rsvd2[7]; /* DWORD 10 */ + u8 sge0_last; /* DWORD 10 */ + u8 sge0_len[17]; /* DWORD 11 */ + u8 rsvd3[7]; /* DWORD 11 */ + u8 diff_enbl; /* DWORD 11 */ + u8 u_run; /* DWORD 11 */ + u8 o_run; /* DWORD 11 */ + u8 invalid; /* DWORD 11 */ + u8 dsp; /* DWORD 11 */ + u8 dmsg; /* DWORD 11 */ + u8 rsvd4; /* DWORD 11 */ + u8 lt; /* DWORD 11 */ + u8 sge1_addr_hi[32]; /* DWORD 12 */ + u8 sge1_addr_lo[32]; /* DWORD 13 */ + u8 sge1_r2t_offset[24]; /* DWORD 14 */ + u8 rsvd5[7]; /* DWORD 14 */ + u8 sge1_last; /* DWORD 14 */ + u8 sge1_len[17]; /* DWORD 15 */ + u8 rsvd6[15]; /* DWORD 15 */ +} __packed; + + struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid); void free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); void beiscsi_process_all_cqs(struct work_struct *work); +static inline bool beiscsi_error(struct beiscsi_hba *phba) +{ + return phba->ue_detected || phba->fw_timeout; +} + struct pdu_nop_out { u32 dw[12]; }; @@ -728,6 +814,7 @@ struct iscsi_target_context_update_wrb { * Pseudo amap definition in which each bit of the actual structure is defined * as a byte: used to calculate offset/shift/mask of each field */ +#define BE_TGT_CTX_UPDT_CMD 0x07 struct amap_iscsi_target_context_update_wrb { u8 lun[14]; /* DWORD 0 */ u8 lt; /* DWORD 0 */ @@ -773,6 +860,47 @@ struct amap_iscsi_target_context_update_wrb { } __packed; +#define BEISCSI_MAX_RECV_DATASEG_LEN (64 * 1024) +#define BEISCSI_MAX_CXNS 1 +struct amap_iscsi_target_context_update_wrb_v2 { + u8 max_burst_length[24]; /* DWORD 0 */ + u8 rsvd0[3]; /* DWORD 0 */ + u8 type[5]; /* DWORD 0 */ + u8 ptr2nextwrb[8]; /* DWORD 1 */ + u8 wrb_idx[8]; /* DWORD 1 */ + u8 rsvd1[16]; /* DWORD 1 */ + u8 max_send_data_segment_length[24]; /* DWORD 2 */ + u8 rsvd2[8]; /* DWORD 2 */ + u8 first_burst_length[24]; /* DWORD 3 */ + u8 rsvd3[8]; /* DOWRD 3 */ + u8 max_r2t[16]; /* DWORD 4 */ + u8 rsvd4[10]; /* DWORD 4 */ + u8 hde; /* DWORD 4 */ + u8 dde; /* DWORD 4 */ + u8 erl[2]; /* DWORD 4 */ + u8 imd; /* DWORD 4 */ + u8 ir2t; /* DWORD 4 */ + u8 stat_sn[32]; /* DWORD 5 */ + u8 rsvd5[32]; /* DWORD 6 */ + u8 rsvd6[32]; /* DWORD 7 */ + u8 max_recv_dataseg_len[24]; /* DWORD 8 */ + u8 rsvd7[8]; /* DWORD 8 */ + u8 rsvd8[32]; /* DWORD 9 */ + u8 rsvd9[32]; /* DWORD 10 */ + u8 max_cxns[16]; /* DWORD 11 */ + u8 rsvd10[11]; /* DWORD 11*/ + u8 invld; /* DWORD 11 */ + u8 rsvd11;/* DWORD 11*/ + u8 dmsg; /* DWORD 11 */ + u8 data_seq_inorder; /* DWORD 11 */ + u8 pdu_seq_inorder; /* DWORD 11 */ + u8 rsvd12[32]; /*DWORD 12 */ + u8 rsvd13[32]; /* DWORD 13 */ + u8 rsvd14[32]; /* DWORD 14 */ + u8 rsvd15[32]; /* DWORD 15 */ +} __packed; + + struct be_ring { u32 pages; /* queue size in pages */ u32 id; /* queue id assigned by beklib */ @@ -837,7 +965,7 @@ struct hwi_context_memory { u16 max_eqd; /* in usecs */ u16 cur_eqd; /* in usecs */ struct be_eq_obj be_eq[MAX_CPUS]; - struct be_queue_info be_cq[MAX_CPUS]; + struct be_queue_info be_cq[MAX_CPUS - 1]; struct be_queue_info be_def_hdrq; struct be_queue_info be_def_dataq; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index aab5dd359e2c..a6c2fe4b4d65 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,6 +22,138 @@ #include <scsi/scsi_bsg_iscsi.h> #include "be_mgmt.h" #include "be_iscsi.h" +#include "be_main.h" + +/* UE Status Low CSR */ +static const char * const desc_ue_status_low[] = { + "CEV", + "CTX", + "DBUF", + "ERX", + "Host", + "MPU", + "NDMA", + "PTC ", + "RDMA ", + "RXF ", + "RXIPS ", + "RXULP0 ", + "RXULP1 ", + "RXULP2 ", + "TIM ", + "TPOST ", + "TPRE ", + "TXIPS ", + "TXULP0 ", + "TXULP1 ", + "UC ", + "WDMA ", + "TXULP2 ", + "HOST1 ", + "P0_OB_LINK ", + "P1_OB_LINK ", + "HOST_GPIO ", + "MBOX ", + "AXGMAC0", + "AXGMAC1", + "JTAG", + "MPU_INTPEND" +}; + +/* UE Status High CSR */ +static const char * const desc_ue_status_hi[] = { + "LPCMEMHOST", + "MGMT_MAC", + "PCS0ONLINE", + "MPU_IRAM", + "PCS1ONLINE", + "PCTL0", + "PCTL1", + "PMEM", + "RR", + "TXPB", + "RXPP", + "XAUI", + "TXP", + "ARM", + "IPC", + "HOST2", + "HOST3", + "HOST4", + "HOST5", + "HOST6", + "HOST7", + "HOST8", + "HOST9", + "NETC", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown" +}; + +/* + * beiscsi_ue_detec()- Detect Unrecoverable Error on adapter + * @phba: Driver priv structure + * + * Read registers linked to UE and check for the UE status + **/ +void beiscsi_ue_detect(struct beiscsi_hba *phba) +{ + uint32_t ue_hi = 0, ue_lo = 0; + uint32_t ue_mask_hi = 0, ue_mask_lo = 0; + uint8_t i = 0; + + if (phba->ue_detected) + return; + + pci_read_config_dword(phba->pcidev, + PCICFG_UE_STATUS_LOW, &ue_lo); + pci_read_config_dword(phba->pcidev, + PCICFG_UE_STATUS_MASK_LOW, + &ue_mask_lo); + pci_read_config_dword(phba->pcidev, + PCICFG_UE_STATUS_HIGH, + &ue_hi); + pci_read_config_dword(phba->pcidev, + PCICFG_UE_STATUS_MASK_HI, + &ue_mask_hi); + + ue_lo = (ue_lo & ~ue_mask_lo); + ue_hi = (ue_hi & ~ue_mask_hi); + + + if (ue_lo || ue_hi) { + phba->ue_detected = true; + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BG_%d : Error detected on the adapter\n"); + } + + if (ue_lo) { + for (i = 0; ue_lo; ue_lo >>= 1, i++) { + if (ue_lo & 1) + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG, + "BG_%d : UE_LOW %s bit set\n", + desc_ue_status_low[i]); + } + } + + if (ue_hi) { + for (i = 0; ue_hi; ue_hi >>= 1, i++) { + if (ue_hi & 1) + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG, + "BG_%d : UE_HIGH %s bit set\n", + desc_ue_status_hi[i]); + } + } +} /** * mgmt_reopen_session()- Reopen a session based on reopen_type @@ -575,13 +707,20 @@ unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) return status; } +/* + * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd + * @phba: Driver priv structure + * @nonemb_cmd: Address of the MBX command issued + * @resp_buf: Buffer to copy the MBX cmd response + * @resp_buf_len: respone lenght to be copied + * + **/ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, struct be_dma_mem *nonemb_cmd, void *resp_buf, int resp_buf_len) { struct be_ctrl_info *ctrl = &phba->ctrl; struct be_mcc_wrb *wrb = wrb_from_mccq(phba); - unsigned short status, extd_status; struct be_sge *sge; unsigned int tag; int rc = 0; @@ -599,31 +738,25 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1); sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); - sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma)); sge->len = cpu_to_le32(nonemb_cmd->size); be_mcc_notify(phba); spin_unlock(&ctrl->mbox_lock); - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { + rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); + if (rc) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BG_%d : mgmt_exec_nonemb_cmd Failed status = %d" - "extd_status = %d\n", status, extd_status); + "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); + rc = -EIO; - goto free_tag; + goto free_cmd; } if (resp_buf) memcpy(resp_buf, nonemb_cmd->va, resp_buf_len); -free_tag: - free_mcc_tag(&phba->ctrl, tag); free_cmd: pci_free_consistent(ctrl->pdev, nonemb_cmd->size, nonemb_cmd->va, nonemb_cmd->dma); @@ -1009,10 +1142,9 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, { struct be_cmd_get_boot_target_resp *boot_resp; struct be_mcc_wrb *wrb; - unsigned int tag, wrb_num; + unsigned int tag; uint8_t boot_retry = 3; - unsigned short status, extd_status; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + int rc; do { /* Get the Boot Target Session Handle and Count*/ @@ -1022,24 +1154,16 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, "BG_%d : Getting Boot Target Info Failed\n"); return -EAGAIN; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { + } + + rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); + if (rc) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, - "BG_%d : mgmt_get_boot_target Failed" - " status = %d extd_status = %d\n", - status, extd_status); - free_mcc_tag(&phba->ctrl, tag); + "BG_%d : MBX CMD get_boot_target Failed\n"); return -EBUSY; } - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); + boot_resp = embedded_payload(wrb); /* Check if the there are any Boot targets configured */ @@ -1064,24 +1188,15 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, "BG_%d : mgmt_reopen_session Failed\n"); return -EAGAIN; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { + } + + rc = beiscsi_mccq_compl(phba, tag, NULL, NULL); + if (rc) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, - "BG_%d : mgmt_reopen_session Failed" - " status = %d extd_status = %d\n", - status, extd_status); - free_mcc_tag(&phba->ctrl, tag); - return -EBUSY; + "BG_%d : mgmt_reopen_session Failed"); + return rc; } - free_mcc_tag(&phba->ctrl, tag); - } while (--boot_retry); /* Couldn't log into the boot target */ @@ -1106,8 +1221,9 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag) { - unsigned int tag, wrb_num; - unsigned short status, extd_status; + int rc; + unsigned int tag; + struct be_mcc_wrb *wrb = NULL; tag = be_cmd_set_vlan(phba, vlan_tag); if (!tag) { @@ -1115,24 +1231,208 @@ int mgmt_set_vlan(struct beiscsi_hba *phba, (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), "BG_%d : VLAN Setting Failed\n"); return -EBUSY; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + } - if (status || extd_status) { + rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); + if (rc) { beiscsi_log(phba, KERN_ERR, (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), - "BS_%d : status : %d extd_status : %d\n", - status, extd_status); + "BS_%d : VLAN MBX Cmd Failed\n"); + return rc; + } + return rc; +} - free_mcc_tag(&phba->ctrl, tag); - return -EAGAIN; +/** + * beiscsi_drvr_ver_disp()- Display the driver Name and Version + * @dev: ptr to device not used. + * @attr: device attribute, not used. + * @buf: contains formatted text driver name and version + * + * return + * size of the formatted string + **/ +ssize_t +beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, BE_NAME "\n"); +} + +/** + * beiscsi_adap_family_disp()- Display adapter family. + * @dev: ptr to device to get priv structure + * @attr: device attribute, not used. + * @buf: contains formatted text driver name and version + * + * return + * size of the formatted string + **/ +ssize_t +beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + uint16_t dev_id = 0; + struct Scsi_Host *shost = class_to_shost(dev); + struct beiscsi_hba *phba = iscsi_host_priv(shost); + + dev_id = phba->pcidev->device; + switch (dev_id) { + case BE_DEVICE_ID1: + case OC_DEVICE_ID1: + case OC_DEVICE_ID2: + return snprintf(buf, PAGE_SIZE, "BE2 Adapter Family\n"); + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID3: + return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n"); + break; + case OC_SKH_ID1: + return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n"); + break; + default: + return snprintf(buf, PAGE_SIZE, + "Unkown Adapter Family: 0x%x\n", dev_id); + break; } +} - free_mcc_tag(&phba->ctrl, tag); - return 0; + +void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, + struct wrb_handle *pwrb_handle, + struct be_mem_descriptor *mem_descr) +{ + struct iscsi_wrb *pwrb = pwrb_handle->pwrb; + + memset(pwrb, 0, sizeof(*pwrb)); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + max_send_data_segment_length, pwrb, + params->dw[offsetof(struct amap_beiscsi_offload_params, + max_send_data_segment_length) / 32]); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb, + BE_TGT_CTX_UPDT_CMD); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + first_burst_length, + pwrb, + params->dw[offsetof(struct amap_beiscsi_offload_params, + first_burst_length) / 32]); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + erl) / 32] & OFFLD_PARAMS_ERL)); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + dde) / 32] & OFFLD_PARAMS_DDE) >> 2); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + hde) / 32] & OFFLD_PARAMS_HDE) >> 3); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + imd) / 32] & OFFLD_PARAMS_IMD) >> 5); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn, + pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + exp_statsn) / 32] + 1)); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx, + pwrb, pwrb_handle->wrb_index); + + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + max_burst_length, pwrb, params->dw[offsetof + (struct amap_beiscsi_offload_params, + max_burst_length) / 32]); + + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, + pwrb, pwrb_handle->nxt_wrb_index); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + session_state, pwrb, 0); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, + pwrb, 1); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq, + pwrb, 0); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb, + 0); + + mem_descr += ISCSI_MEM_GLOBAL_HEADER; + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + pad_buffer_addr_hi, pwrb, + mem_descr->mem_array[0].bus_address.u.a32.address_hi); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + pad_buffer_addr_lo, pwrb, + mem_descr->mem_array[0].bus_address.u.a32.address_lo); +} + +void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, + struct wrb_handle *pwrb_handle) +{ + struct iscsi_wrb *pwrb = pwrb_handle->pwrb; + + memset(pwrb, 0, sizeof(*pwrb)); + + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, + max_burst_length, pwrb, params->dw[offsetof + (struct amap_beiscsi_offload_params, + max_burst_length) / 32]); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + max_burst_length, pwrb, params->dw[offsetof + (struct amap_beiscsi_offload_params, + max_burst_length) / 32]); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + type, pwrb, + BE_TGT_CTX_UPDT_CMD); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + ptr2nextwrb, + pwrb, pwrb_handle->nxt_wrb_index); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx, + pwrb, pwrb_handle->wrb_index); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + max_send_data_segment_length, pwrb, + params->dw[offsetof(struct amap_beiscsi_offload_params, + max_send_data_segment_length) / 32]); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + first_burst_length, pwrb, + params->dw[offsetof(struct amap_beiscsi_offload_params, + first_burst_length) / 32]); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + max_recv_dataseg_len, pwrb, BEISCSI_MAX_RECV_DATASEG_LEN); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + max_cxns, pwrb, BEISCSI_MAX_CXNS); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + erl) / 32] & OFFLD_PARAMS_ERL)); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + dde) / 32] & OFFLD_PARAMS_DDE) >> 2); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + hde) / 32] & OFFLD_PARAMS_HDE) >> 3); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + ir2t, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + imd) / 32] & OFFLD_PARAMS_IMD) >> 5); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + data_seq_inorder, + pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + data_seq_inorder) / 32] & + OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, + pdu_seq_inorder, + pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + pdu_seq_inorder) / 32] & + OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t, + pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + max_r2t) / 32] & + OFFLD_PARAMS_MAX_R2T) >> 8); + AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn, + pwrb, + (params->dw[offsetof(struct amap_beiscsi_offload_params, + exp_statsn) / 32] + 1)); } diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index c50cef6fec0d..2e4968add799 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2005 - 2011 Emulex + * Copyright (C) 2005 - 2012 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -30,6 +30,12 @@ #define IP_V6_LEN 16 #define IP_V4_LEN 4 +/* UE Status and Mask register */ +#define PCICFG_UE_STATUS_LOW 0xA0 +#define PCICFG_UE_STATUS_HIGH 0xA4 +#define PCICFG_UE_STATUS_MASK_LOW 0xA8 +#define PCICFG_UE_STATUS_MASK_HI 0xAC + /** * Pseudo amap definition in which each bit of the actual structure is defined * as a byte: used to calculate offset/shift/mask of each field @@ -301,4 +307,19 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba); int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag); + +ssize_t beiscsi_drvr_ver_disp(struct device *dev, + struct device_attribute *attr, char *buf); + +ssize_t beiscsi_adap_family_disp(struct device *dev, + struct device_attribute *attr, char *buf); + +void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, + struct wrb_handle *pwrb_handle, + struct be_mem_descriptor *mem_descr); + +void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, + struct wrb_handle *pwrb_handle); +void beiscsi_ue_detect(struct beiscsi_hba *phba); + #endif |