RFC: beiscsi driver
PATCH 4/4 RFC: beiscsi driver
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "open-iscsi" group. To post to this group, send email to open-iscsi-/[email protected]
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/[email protected] For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---
Quoted 1 line
From
6a3837b9554ed9e4ff3994b101fb6b07fdf1b233Mon Sep 17 00:00:00 2001
From: Jayamohan Kallickal <jayamohank-i5Eg4PDOvn3+uv41P6q33AC/[email protected]>
Date: Sun, 26 Jul 2009 19:04:49 -0700
Subject: [PATCH 4/4] RFC: beiscsi driver
The open-iscsi based storage driver for ServerEngines
10 Gbps Adapter. The Adapter is Multi-Function device that provides NIC/iSCSI/FCOE Functionality.
The driver works in Full Hardware Offload mode utilizing
the hooks provided by open-iscsi layer.
--- drivers/scsi/beiscsi/be_cmds.c | 635 +++++++++++++++++++++++++++ drivers/scsi/beiscsi/be_cmds.h | 883 +++++++++++++++++++++++++++++++++++++ drivers/scsi/beiscsi/be_main.h | 949 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2467 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/beiscsi/be_cmds.c create mode 100644 drivers/scsi/beiscsi/be_cmds.h create mode 100644 drivers/scsi/beiscsi/be_main.h
drivers/scsi/beiscsi/be_cmds.c new file +635 -0
@@ -0,0 +1,635 @@ +/* +* Copyright (C) 2005 - 2009 ServerEngines +* All rights reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. The full GNU General +* Public License is included in this distribution in the file called COPYING. +* +* Contact Information: +* linux-drivers-i5Eg4PDOvn3+uv41P6q33AC/[email protected] +* +* ServerEngines +* 209 N. Fair Oaks Ave +* Sunnyvale, CA 94085 +*/ + +#include "be.h" +#include "be_mgmt.h" +#include "be_main.h" + + +/* To check if valid bit is set, check the entire word as we don't know +* the endianness of the data (old entry is host endian while a new entry is +* little endian) */ +static inline bool be_mcc_compl_is_new (struct be_mcc_compl *compl) +{ +if (compl->flags !=0 ) { + compl->flags =le32_to_cpu (compl->flags); +WARN_ON ((compl->flags &CQE_FLAGS_VALID_MASK ) ==0 ); +return true; + }else { +return false; + } +} + +/* Need to reset the entire word that houses the valid bit */ +static inline void be_mcc_compl_use (struct be_mcc_compl *compl) +{ + compl->flags =0 ; +} + +static int be_mcc_compl_process (struct be_ctrl_info *ctrl, +struct be_mcc_compl *compl) +{ +u16 compl_status, extd_status; + +/* Just swap the status to host endian; mcc tag is opaquely copied +* from mcc_wrb +*/ +be_dws_le_to_cpu (compl,4 ); + + compl_status = (compl->status >>CQE_STATUS_COMPL_SHIFT ) & +CQE_STATUS_COMPL_MASK ; +if (compl_status !=MCC_STATUS_SUCCESS ) { + extd_status = (compl->status >>CQE_STATUS_EXTD_SHIFT ) & +CQE_STATUS_EXTD_MASK ; +dev_err (&ctrl->pdev->dev, +"error in cmd completion: status(compl/extd)=%d/%d\n" , + compl_status, extd_status); +return -1 ; + } +return 0 ; +} + + +static inline bool is_link_state_evt (u32 trailer) +{ +return (((trailer >>ASYNC_TRAILER_EVENT_CODE_SHIFT ) & +ASYNC_TRAILER_EVENT_CODE_MASK ) ==ASYNC_EVENT_CODE_LINK_STATE ); +} + +void be_cq_notify (struct be_ctrl_info *ctrl,u16 qid,bool arm,u16 num_popped) +{ +u32 val =0 ; + val |= qid &DB_CQ_RING_ID_MASK ; +if (arm) + val |=1 <<DB_CQ_REARM_SHIFT ; + val |= num_popped <<DB_CQ_NUM_POPPED_SHIFT ; +iowrite32 (val, ctrl->db +DB_CQ_OFFSET ); +} + +static struct be_mcc_compl *be_mcc_compl_get (struct be_ctrl_info *ctrl) +{ +struct be_queue_info *mcc_cq = ctrl->mcc_obj.cq; +struct be_mcc_compl *compl =queue_tail_node (mcc_cq); + +if (be_mcc_compl_is_new (compl)) { +queue_tail_inc (mcc_cq); +return compl; + } +return NULL ; +} + +int be_poll_mcc (struct be_ctrl_info *ctrl) +{ +struct be_mcc_compl *compl; +int num =0 ; +int status =0 ; + +spin_lock_bh (&ctrl->mcc_cq_lock); +while ((compl =be_mcc_compl_get (ctrl))) { +if (compl->flags &CQE_FLAGS_ASYNC_MASK ) { +/* Interpret flags as an async trailer */ +WARN_ON (!is_link_state_evt (compl->flags)); + }else { + status =be_mcc_compl_process (ctrl, compl); +atomic_dec (&ctrl->mcc_obj.q->used); + } +be_mcc_compl_use (compl); + num++; + } +if (num) +be_cq_notify (ctrl, ctrl->mcc_obj.cq->id, true, num); +spin_unlock_bh (&ctrl->mcc_cq_lock); +return status; +} + +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 */ +u32 ready; + +do { + ready =ioread32 (db) &MPU_MAILBOX_DB_RDY_MASK ; +if (ready) +break ; + +if (cnt >6000000 ) { +dev_err (&ctrl->pdev->dev,"mbox_db poll timed out\n" ); +return -1 ; + } + +if (cnt >50 ) { + wait = long_delay; +mdelay (long_delay /1000 ); + }else { +udelay (wait); + } + cnt += wait; + }while (true); + +return 0 ; +} + +/* +* Insert the mailbox address into the doorbell in two steps +* Polls on the mbox doorbell till a command completion (or a timeout) occurs +*/ +int be_mbox_notify (struct be_ctrl_info *ctrl) +{ +int status; +u32 val =0 ; +void __iomem *db = ctrl->db +MPU_MAILBOX_DB_OFFSET ; +struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; +struct be_mcc_mailbox *mbox = mbox_mem->va; +struct be_mcc_compl *compl = &mbox->compl; + + val &= ~MPU_MAILBOX_DB_RDY_MASK ; + val |=MPU_MAILBOX_DB_HI_MASK ; +/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ + val |= (upper_32_bits (mbox_mem->dma) >>2 ) <<2 ; +iowrite32 (val, db); + +/* wait for ready to be set */ + status =be_mbox_db_ready_wait (ctrl); +if (status !=0 ) { +SE_DEBUG (DBG_LVL_1 ," be_mbox_db_ready_wait failed 1\n" ); +return status; + } + val =0 ; + val &= ~MPU_MAILBOX_DB_RDY_MASK ; + val &= ~MPU_MAILBOX_DB_HI_MASK ; +/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ + val |= (u32) (mbox_mem->dma >>4 ) <<2 ; +iowrite32 (val, db); + + status =be_mbox_db_ready_wait (ctrl); +if (status !=0 ) { +SE_DEBUG (DBG_LVL_1 ," be_mbox_db_ready_wait failed 2\n" ); +return status; + } +/* A cq entry has been made now */ +if (be_mcc_compl_is_new (compl)) { + status =be_mcc_compl_process (ctrl, &mbox->compl); +be_mcc_compl_use (compl); +if (status) { +SE_DEBUG (DBG_LVL_1 ,"After be_mcc_compl_process \n" ); +return status; + } + }else { +dev_err (&ctrl->pdev->dev,"invalid mailbox completion\n" ); +return -1 ; + } +return 0 ; +} + + +/* Don't touch the hdr after it's prepared */ +void be_wrb_hdr_prepare (struct be_mcc_wrb *wrb,int payload_len, +bool embedded,u8 sge_cnt) +{ +if (embedded) + wrb->embedded |=MCC_WRB_EMBEDDED_MASK ; +else + wrb->embedded |= (sge_cnt &MCC_WRB_SGE_CNT_MASK ) << +MCC_WRB_SGE_CNT_SHIFT ; + wrb->payload_length = payload_len; +be_dws_cpu_to_le (wrb,8 ); +} + +/* Don't touch the hdr after it's prepared */ +void be_cmd_hdr_prepare (struct be_cmd_req_hdr *req_hdr, +u8 subsystem,u8 opcode,int cmd_len) +{ + req_hdr->opcode = opcode; + req_hdr->subsystem = subsystem; + req_hdr->request_length =cpu_to_le32 (cmd_len -sizeof (*req_hdr)); +} + +static void be_cmd_page_addrs_prepare (struct phys_addr *pages,u32 max_pages, +struct be_dma_mem *mem) +{ +int i, buf_pages; +u64 dma = (u64 ) mem->dma; + + buf_pages =min (PAGES_4K_SPANNED (mem->va, mem->size), max_pages); +for (i =0 ; i < buf_pages; i++) { + pages[i].lo =cpu_to_le32 (dma &0xFFFFFFFF ); + pages[i].hi =cpu_to_le32 (upper_32_bits (dma)); + dma +=PAGE_SIZE_4K ; + } +} + +/* Converts interrupt delay in microseconds to multiplier value */ +static u32 eq_delay_to_mult (u32 usec_delay) +{ +#define MAX_INTR_RATE 651042 +const u32 round =10 ; +u32 multiplier; + +if (usec_delay ==0 ) { + multiplier =0 ; + }else { +u32 interrupt_rate =1000000 / usec_delay; +/* Max delay, corresponding to the lowest interrupt rate */ +if (interrupt_rate ==0 ) { + multiplier =1023 ; + }else { + multiplier = (MAX_INTR_RATE - interrupt_rate) * round; + multiplier /= interrupt_rate; +/* Round the multiplier to the closest value. */ + multiplier = (multiplier + round /2 ) / round; + multiplier =min (multiplier, (u32 )1023 ); + } + } +return multiplier; +} + +struct be_mcc_wrb *wrb_from_mbox (struct be_dma_mem *mbox_mem) +{ +return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; +} + + +int be_cmd_eq_create (struct be_ctrl_info *ctrl, +struct be_queue_info *eq,int eq_delay) +{ +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_cmd_req_eq_create *req =embedded_payload (wrb); +struct be_cmd_resp_eq_create *resp =embedded_payload (wrb); +struct be_dma_mem *q_mem = &eq->dma_mem; +int status; + +spin_lock (&ctrl->mbox_lock); +memset (wrb,0 ,sizeof (*wrb)); + +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); + +be_cmd_hdr_prepare (&req->hdr,CMD_SUBSYSTEM_COMMON , +OPCODE_COMMON_EQ_CREATE ,sizeof (*req)); + + req->num_pages =cpu_to_le16 (PAGES_4K_SPANNED (q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_eq_context, func, req->context, + PCI_FUNC(ctrl->pdev->devfn)); + AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); +/* 4byte eqe */ + AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); + AMAP_SET_BITS(struct amap_eq_context, count, req->context, + __ilog2_u32(eq->len / 256)); + AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, + eq_delay_to_mult(eq_delay)); +be_dws_cpu_to_le (req->context,sizeof (req->context)); + +be_cmd_page_addrs_prepare (req->pages,ARRAY_SIZE (req->pages), q_mem); + + status =be_mbox_notify (ctrl); +if (!status) { + eq->id =le16_to_cpu (resp->eq_id); + eq->created = true; + } +spin_unlock (&ctrl->mbox_lock); +return status; +} + +/* +*be_cmd_fw_initiallize: Needed by FW to initiallize +*/ +int be_cmd_fw_initiallize (struct be_ctrl_info *ctrl) +{ +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +int status; +u8 *endian_check; +spin_lock (&ctrl->mbox_lock); +memset (wrb,0 ,sizeof (*wrb)); + + endian_check = (u8 *) wrb; + *endian_check++ =0xFF ;/* byte 0 */ + *endian_check++ =0x12 ;/* byte 1 */ + *endian_check++ =0x34 ;/* byte 2 */ + *endian_check++ =0xFF ;/* byte 3 */ + *endian_check++ =0xFF ;/* byte 4 */ + *endian_check++ =0x56 ;/* byte 5 */ + *endian_check++ =0x78 ;/* byte 6 */ + *endian_check++ =0xFF ;/* byte 7 */ +be_dws_cpu_to_le (wrb,sizeof (*wrb)); + + status =be_mbox_notify (ctrl); +if (status) +SE_DEBUG (DBG_LVL_1 ,"Send Special Failed \n" ); + +spin_unlock (&ctrl->mbox_lock); +return status; +} + +int be_cmd_cq_create (struct be_ctrl_info *ctrl, +struct be_queue_info *cq,struct be_queue_info *eq, +bool sol_evts,bool no_delay,int coalesce_wm) +{ +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_cmd_req_cq_create *req =embedded_payload (wrb); +struct be_cmd_resp_cq_create *resp =embedded_payload (wrb); +struct be_dma_mem *q_mem = &cq->dma_mem; +void *ctxt = &req->context; +int status; + +spin_lock (&ctrl->mbox_lock); +memset (wrb,0 ,sizeof (*wrb)); + +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); + +be_cmd_hdr_prepare (&req->hdr,CMD_SUBSYSTEM_COMMON , +OPCODE_COMMON_CQ_CREATE ,sizeof (*req)); + +if (q_mem->va) { +SE_DEBUG (DBG_LVL_1 ,"In be_cmd_cq_create, q_mem->va =%p \n" , + q_mem->va); + }else +SE_DEBUG (DBG_LVL_8 , +"In be_cmd_cq_create, uninitialized q_mem->va\n" ); + + req->num_pages =cpu_to_le16 (PAGES_4K_SPANNED (q_mem->va, q_mem->size)); + + 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); + + status =be_mbox_notify (ctrl); +if (!status) { + cq->id =le16_to_cpu (resp->cq_id); + cq->created = true; + }else +SE_DEBUG (DBG_LVL_8 ,"In be_cmd_cq_create, status=ox%08x \n" , + status); +spin_unlock (&ctrl->mbox_lock); + +return status; +} + +static u32 be_encoded_q_len (int q_len) +{ +u32 len_encoded =fls (q_len);/* log2(len) + 1 */ +if (len_encoded ==16 ) + len_encoded =0 ; +return len_encoded; +} + +/* Generic destroyer function for all types of queues */ +int be_cmd_q_destroy (struct be_ctrl_info *ctrl,struct be_queue_info *q, +int queue_type) +{ +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_cmd_req_q_destroy *req =embedded_payload (wrb); +u8 subsys =0 , opcode =0 ; +int status; + +spin_lock (&ctrl->mbox_lock); + +memset (wrb,0 ,sizeof (*wrb)); +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); + +switch (queue_type) { +case QTYPE_EQ : + subsys =CMD_SUBSYSTEM_COMMON ; + opcode =OPCODE_COMMON_EQ_DESTROY ; +break ; +case QTYPE_CQ : + subsys =CMD_SUBSYSTEM_COMMON ; + opcode =OPCODE_COMMON_CQ_DESTROY ; +break ; +case QTYPE_WRBQ : + subsys =CMD_SUBSYSTEM_ISCSI ; + opcode =OPCODE_COMMON_ISCSI_WRBQ_DESTROY ; +break ; +case QTYPE_DPDUQ : + subsys =CMD_SUBSYSTEM_ISCSI ; + opcode =OPCODE_COMMON_ISCSI_DEFQ_DESTROY ; +break ; +case QTYPE_SGL : + subsys =CMD_SUBSYSTEM_ISCSI ; + opcode =OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES ; +break ; +default : +spin_unlock (&ctrl->mbox_lock); +BUG (); +return -1 ; + } +be_cmd_hdr_prepare (&req->hdr, subsys, opcode,sizeof (*req)); +if (queue_type !=QTYPE_SGL ) + req->id =cpu_to_le16 (q->id); + + status =be_mbox_notify (ctrl); + +spin_unlock (&ctrl->mbox_lock); +return status; +} + +/* Create an rx filtering policy configuration on an i/f */ + +/* Get stats is a non embedded command: the request is not embedded inside +* WRB but is a separate dma memory block +*/ + +/* set the EQ delay interval of an EQ to specified value */ + + + +int be_cmd_get_mac_addr (struct be_ctrl_info *ctrl,u8 *mac_addr) +{ +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_cmd_req_get_mac_addr *req =embedded_payload (wrb); +int status; + +spin_lock (&ctrl->mbox_lock); +memset (wrb,0 ,sizeof (*wrb)); +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); +be_cmd_hdr_prepare (&req->hdr,CMD_SUBSYSTEM_ISCSI , +OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG ,sizeof (*req)); + + status =be_mbox_notify (ctrl); +if (!status) { +struct be_cmd_resp_get_mac_addr *resp =embedded_payload (wrb); +memcpy (mac_addr, resp->mac_address,ETH_ALEN ); + } + +spin_unlock (&ctrl->mbox_lock); +return status; +} + + + + +int be_cmd_reset_function (struct be_ctrl_info *ctrl) +{ +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_cmd_req_hdr *req =embedded_payload (wrb); +int status; + +spin_lock (&ctrl->mbox_lock); + +memset (wrb,0 ,sizeof (*wrb)); + +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); + +be_cmd_hdr_prepare (req,CMD_SUBSYSTEM_COMMON , +OPCODE_COMMON_FUNCTION_RESET ,sizeof (*req)); + + status =be_mbox_notify (ctrl); + +spin_unlock (&ctrl->mbox_lock); +return status; +} + +int be_cmd_create_default_pdu_queue (struct be_ctrl_info *ctrl, +struct be_queue_info *cq, +struct be_queue_info *dq,int length, +int entry_size) +{ + +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_defq_create_req *req =embedded_payload (wrb); +struct be_dma_mem *q_mem = &dq->dma_mem; +void *ctxt = &req->context; +int status; + +spin_lock (&ctrl->mbox_lock); +memset (wrb,0 ,sizeof (*wrb)); + +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); + +be_cmd_hdr_prepare (&req->hdr,CMD_SUBSYSTEM_ISCSI , +OPCODE_COMMON_ISCSI_DEFQ_CREATE ,sizeof (*req)); + + req->num_pages =PAGES_4K_SPANNED (q_mem->va, q_mem->size); + AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0); + AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt, + 1); + AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt, + PCI_FUNC(ctrl->pdev->devfn)); + AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt, + be_encoded_q_len(length / sizeof(struct phys_addr))); + AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size, + ctxt, entry_size); + AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt, + cq->id); + +be_dws_cpu_to_le (ctxt,sizeof (req->context)); + +be_cmd_page_addrs_prepare (req->pages,ARRAY_SIZE (req->pages), q_mem); + + status =be_mbox_notify (ctrl); +if (!status) { +struct be_defq_create_resp *resp =embedded_payload (wrb); + dq->id =le16_to_cpu (resp->id); + dq->created = true; + } +spin_unlock (&ctrl->mbox_lock); + +return status; +} + +int be_cmd_wrbq_create (struct be_ctrl_info *ctrl,struct be_dma_mem *q_mem, +struct be_queue_info *wrbq) +{ + +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_wrbq_create_req *req =embedded_payload (wrb); +struct be_wrbq_create_resp *resp =embedded_payload (wrb); +int status; + +spin_lock (&ctrl->mbox_lock); +memset (wrb,0 ,sizeof (*wrb)); + +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); + +be_cmd_hdr_prepare (&req->hdr,CMD_SUBSYSTEM_ISCSI , +OPCODE_COMMON_ISCSI_WRBQ_CREATE ,sizeof (*req)); + req->num_pages =PAGES_4K_SPANNED (q_mem->va, q_mem->size); +be_cmd_page_addrs_prepare (req->pages,ARRAY_SIZE (req->pages), q_mem); + + status =be_mbox_notify (ctrl); +if (!status) + wrbq->id =le16_to_cpu (resp->cid); +spin_unlock (&ctrl->mbox_lock); +return status; +} + +int +be_cmd_iscsi_post_sgl_pages (struct be_ctrl_info *ctrl, +struct be_dma_mem *q_mem, +u32 page_offset,u32 num_pages) +{ + +struct be_mcc_wrb *wrb =wrb_from_mbox (&ctrl->mbox_mem); +struct be_post_sgl_pages_req *req =embedded_payload (wrb); +int status; +u32 internal_page_offset =0 ; +u32 temp_num_pages = num_pages; + +if (num_pages ==0xff ) + num_pages =1 ; + +spin_lock (&ctrl->mbox_lock); +do { + +memset (wrb,0 ,sizeof (*wrb)); +be_wrb_hdr_prepare (wrb,sizeof (*req), true,0 ); +be_cmd_hdr_prepare (&req->hdr,CMD_SUBSYSTEM_ISCSI , +OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES , +sizeof (*req)); + req->num_pages = +min (num_pages, + BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req, + pages)); + req->page_offset = page_offset; +be_cmd_page_addrs_prepare (req->pages, req->num_pages, q_mem); + q_mem->dma = q_mem->dma + (req->num_pages *PAGE_SIZE ); +/* Add this group to the offset. Subtract from remaining pages +* to map. +*/ + internal_page_offset += req->num_pages; + page_offset += req->num_pages; + num_pages -= req->num_pages; + +if (temp_num_pages ==0xff ) + req->num_pages = temp_num_pages; + + status =be_mbox_notify (ctrl); +if (status) { +SE_DEBUG (DBG_LVL_1 , +"FW CMD to map iscsi frags failed.\n" ); + goto error; + } + }while (num_pages >0 ); +error: +spin_unlock (&ctrl->mbox_lock); +if (status !=0 ) +be_cmd_q_destroy (ctrl,NULL ,QTYPE_SGL ); +return status; +} +
drivers/scsi/beiscsi/be_cmds.h new file +883 -0
883 lines not on this page · raw message
drivers/scsi/beiscsi/be_main.h new file +949 -0
949 lines not on this page · raw message
Signature · 1 line
1.6.3