提交 0d522ee7 编写于 作者: L Linus Torvalds

Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull first round of SCSI updates from James Bottomley:
 "This patch set is driver updates for qla4xxx, scsi_debug, pm80xx,
  fcoe/libfc, eas2r, lpfc, be2iscsi and megaraid_sas plus some assorted
  bug fixes and cleanups"

* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (106 commits)
  [SCSI] scsi_error: Escalate to LUN reset if abort fails
  [SCSI] Add 'eh_deadline' to limit SCSI EH runtime
  [SCSI] remove check for 'resetting'
  [SCSI] dc395: Move 'last_reset' into internal host structure
  [SCSI] tmscsim: Move 'last_reset' into host structure
  [SCSI] advansys: Remove 'last_reset' references
  [SCSI] dpt_i2o: return SCSI_MLQUEUE_HOST_BUSY when in reset
  [SCSI] dpt_i2o: Remove DPTI_STATE_IOCTL
  [SCSI] megaraid_sas: Fix synchronization problem between sysPD IO path and AEN path
  [SCSI] lpfc: Fix typo on NULL assignment
  [SCSI] scsi_dh_alua: ALUA handler attach should succeed while TPG is transitioning
  [SCSI] scsi_dh_alua: ALUA check sense should retry device internal reset unit attention
  [SCSI] esas2r: Cleanup snprinf formatting of firmware version
  [SCSI] esas2r: Remove superfluous mask of pcie_cap_reg
  [SCSI] esas2r: Fixes for big-endian platforms
  [SCSI] esas2r: Directly call kernel functions for atomic bit operations
  [SCSI] lpfc 8.3.43: Update lpfc version to driver version 8.3.43
  [SCSI] lpfc 8.3.43: Fixed not processing task management IOCB response status
  [SCSI] lpfc 8.3.43: Fixed spinlock hang.
  [SCSI] lpfc 8.3.43: Fixed invalid Total_Data_Placed value received for els and ct command responses
  ...
...@@ -1867,7 +1867,7 @@ S: Supported ...@@ -1867,7 +1867,7 @@ S: Supported
F: drivers/net/wireless/brcm80211/ F: drivers/net/wireless/brcm80211/
BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
M: Bhanu Prakash Gollapudi <bprakash@broadcom.com> M: Eddie Wai <eddie.wai@broadcom.com>
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
S: Supported S: Supported
F: drivers/scsi/bnx2fc/ F: drivers/scsi/bnx2fc/
......
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
*/ */
#define blogic_drvr_version "2.1.16" #define blogic_drvr_version "2.1.17"
#define blogic_drvr_date "18 July 2002" #define blogic_drvr_date "12 September 2013"
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -311,11 +311,13 @@ static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter) ...@@ -311,11 +311,13 @@ static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter)
caller. caller.
*/ */
static void blogic_dealloc_ccb(struct blogic_ccb *ccb) static void blogic_dealloc_ccb(struct blogic_ccb *ccb, int dma_unmap)
{ {
struct blogic_adapter *adapter = ccb->adapter; struct blogic_adapter *adapter = ccb->adapter;
if (ccb->command != NULL)
scsi_dma_unmap(ccb->command); scsi_dma_unmap(ccb->command);
if (dma_unmap)
pci_unmap_single(adapter->pci_device, ccb->sensedata, pci_unmap_single(adapter->pci_device, ccb->sensedata,
ccb->sense_datalen, PCI_DMA_FROMDEVICE); ccb->sense_datalen, PCI_DMA_FROMDEVICE);
...@@ -2762,7 +2764,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter) ...@@ -2762,7 +2764,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter)
/* /*
Place CCB back on the Host Adapter's free list. Place CCB back on the Host Adapter's free list.
*/ */
blogic_dealloc_ccb(ccb); blogic_dealloc_ccb(ccb, 1);
#if 0 /* this needs to be redone different for new EH */ #if 0 /* this needs to be redone different for new EH */
/* /*
Bus Device Reset CCBs have the command field Bus Device Reset CCBs have the command field
...@@ -2791,7 +2793,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter) ...@@ -2791,7 +2793,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter)
if (ccb->status == BLOGIC_CCB_RESET && if (ccb->status == BLOGIC_CCB_RESET &&
ccb->tgt_id == tgt_id) { ccb->tgt_id == tgt_id) {
command = ccb->command; command = ccb->command;
blogic_dealloc_ccb(ccb); blogic_dealloc_ccb(ccb, 1);
adapter->active_cmds[tgt_id]--; adapter->active_cmds[tgt_id]--;
command->result = DID_RESET << 16; command->result = DID_RESET << 16;
command->scsi_done(command); command->scsi_done(command);
...@@ -2862,7 +2864,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter) ...@@ -2862,7 +2864,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter)
/* /*
Place CCB back on the Host Adapter's free list. Place CCB back on the Host Adapter's free list.
*/ */
blogic_dealloc_ccb(ccb); blogic_dealloc_ccb(ccb, 1);
/* /*
Call the SCSI Command Completion Routine. Call the SCSI Command Completion Routine.
*/ */
...@@ -3034,6 +3036,7 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command, ...@@ -3034,6 +3036,7 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command,
int buflen = scsi_bufflen(command); int buflen = scsi_bufflen(command);
int count; int count;
struct blogic_ccb *ccb; struct blogic_ccb *ccb;
dma_addr_t sense_buf;
/* /*
SCSI REQUEST_SENSE commands will be executed automatically by the SCSI REQUEST_SENSE commands will be executed automatically by the
...@@ -3179,10 +3182,17 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command, ...@@ -3179,10 +3182,17 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command,
} }
memcpy(ccb->cdb, cdb, cdblen); memcpy(ccb->cdb, cdb, cdblen);
ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE; ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE;
ccb->sensedata = pci_map_single(adapter->pci_device, ccb->command = command;
sense_buf = pci_map_single(adapter->pci_device,
command->sense_buffer, ccb->sense_datalen, command->sense_buffer, ccb->sense_datalen,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
ccb->command = command; if (dma_mapping_error(&adapter->pci_device->dev, sense_buf)) {
blogic_err("DMA mapping for sense data buffer failed\n",
adapter);
blogic_dealloc_ccb(ccb, 0);
return SCSI_MLQUEUE_HOST_BUSY;
}
ccb->sensedata = sense_buf;
command->scsi_done = comp_cb; command->scsi_done = comp_cb;
if (blogic_multimaster_type(adapter)) { if (blogic_multimaster_type(adapter)) {
/* /*
...@@ -3203,7 +3213,7 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command, ...@@ -3203,7 +3213,7 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command,
if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
ccb)) { ccb)) {
blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter); blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter);
blogic_dealloc_ccb(ccb); blogic_dealloc_ccb(ccb, 1);
command->result = DID_ERROR << 16; command->result = DID_ERROR << 16;
command->scsi_done(command); command->scsi_done(command);
} }
...@@ -3337,7 +3347,7 @@ static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset) ...@@ -3337,7 +3347,7 @@ static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset)
for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all) for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
if (ccb->status == BLOGIC_CCB_ACTIVE) if (ccb->status == BLOGIC_CCB_ACTIVE)
blogic_dealloc_ccb(ccb); blogic_dealloc_ccb(ccb, 1);
/* /*
* Wait a few seconds between the Host Adapter Hard Reset which * Wait a few seconds between the Host Adapter Hard Reset which
* initiates a SCSI Bus Reset and issuing any SCSI Commands. Some * initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
......
...@@ -2511,8 +2511,8 @@ static void asc_prt_scsi_host(struct Scsi_Host *s) ...@@ -2511,8 +2511,8 @@ static void asc_prt_scsi_host(struct Scsi_Host *s)
struct asc_board *boardp = shost_priv(s); struct asc_board *boardp = shost_priv(s);
printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev)); printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev));
printk(" host_busy %u, host_no %d, last_reset %d,\n", printk(" host_busy %u, host_no %d,\n",
s->host_busy, s->host_no, (unsigned)s->last_reset); s->host_busy, s->host_no);
printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
(ulong)s->base, (ulong)s->io_port, boardp->irq); (ulong)s->base, (ulong)s->io_port, boardp->irq);
...@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) ...@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost)
shost->host_no); shost->host_no);
seq_printf(m, seq_printf(m,
" host_busy %u, last_reset %lu, max_id %u, max_lun %u, max_channel %u\n", " host_busy %u, max_id %u, max_lun %u, max_channel %u\n",
shost->host_busy, shost->last_reset, shost->max_id, shost->host_busy, shost->max_id,
shost->max_lun, shost->max_channel); shost->max_lun, shost->max_channel);
seq_printf(m, seq_printf(m,
......
...@@ -128,7 +128,7 @@ struct be_ctrl_info { ...@@ -128,7 +128,7 @@ struct be_ctrl_info {
#define PAGE_SHIFT_4K 12 #define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
#define mcc_timeout 120000 /* 5s timeout */ #define mcc_timeout 120000 /* 12s timeout */
/* Returns number of pages spanned by the data starting at the given addr */ /* Returns number of pages spanned by the data starting at the given addr */
#define PAGES_4K_SPANNED(_address, size) \ #define PAGES_4K_SPANNED(_address, size) \
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
#include <scsi/iscsi_proto.h> #include <scsi/iscsi_proto.h>
#include "be_main.h"
#include "be.h" #include "be.h"
#include "be_mgmt.h" #include "be_mgmt.h"
#include "be_main.h"
int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) int beiscsi_pci_soft_reset(struct beiscsi_hba *phba)
{ {
...@@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, ...@@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
struct be_cmd_resp_hdr *ioctl_resp_hdr; struct be_cmd_resp_hdr *ioctl_resp_hdr;
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
if (beiscsi_error(phba)) if (beiscsi_error(phba)) {
free_mcc_tag(&phba->ctrl, tag);
return -EIO; return -EIO;
}
/* wait for the mccq completion */ /* wait for the mccq completion */
rc = wait_event_interruptible_timeout( rc = wait_event_interruptible_timeout(
...@@ -173,7 +175,11 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, ...@@ -173,7 +175,11 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
BEISCSI_LOG_INIT | BEISCSI_LOG_EH | BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
BEISCSI_LOG_CONFIG, BEISCSI_LOG_CONFIG,
"BC_%d : MBX Cmd Completion timed out\n"); "BC_%d : MBX Cmd Completion timed out\n");
rc = -EAGAIN; rc = -EBUSY;
/* decrement the mccq used count */
atomic_dec(&phba->ctrl.mcc_obj.q.used);
goto release_mcc_tag; goto release_mcc_tag;
} else } else
rc = 0; rc = 0;
...@@ -208,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, ...@@ -208,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { if (status == MCC_STATUS_INSUFFICIENT_BUFFER) {
ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr;
if (ioctl_resp_hdr->response_length) beiscsi_log(phba, KERN_WARNING,
BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
BEISCSI_LOG_CONFIG,
"BC_%d : Insufficent Buffer Error "
"Resp_Len : %d Actual_Resp_Len : %d\n",
ioctl_resp_hdr->response_length,
ioctl_resp_hdr->actual_resp_len);
rc = -EAGAIN;
goto release_mcc_tag; goto release_mcc_tag;
} }
rc = -EAGAIN; rc = -EIO;
} }
release_mcc_tag: release_mcc_tag:
...@@ -363,7 +377,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, ...@@ -363,7 +377,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
} else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) ||
((evt->port_link_status & ASYNC_EVENT_LOGICAL) && ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
(evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) {
phba->state = BE_ADAPTER_UP; phba->state = BE_ADAPTER_LINK_UP;
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
...@@ -486,33 +500,47 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) ...@@ -486,33 +500,47 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba)
**/ **/
static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
{ {
#define BEISCSI_MBX_RDY_BIT_TIMEOUT 4000 /* 4sec */
void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
uint32_t wait = 0; unsigned long timeout;
bool read_flag = false;
int ret = 0, i;
u32 ready; u32 ready;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q);
do {
if (beiscsi_error(phba)) if (beiscsi_error(phba))
return -EIO; return -EIO;
timeout = jiffies + (HZ * 110);
do {
for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) {
ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
if (ready) if (ready) {
read_flag = true;
break; break;
}
mdelay(1);
}
if (!read_flag) {
wait_event_timeout(rdybit_check_q,
(read_flag != true),
HZ * 5);
}
} while ((time_before(jiffies, timeout)) && !read_flag);
if (wait > BEISCSI_HOST_MBX_TIMEOUT) { if (!read_flag) {
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BC_%d : FW Timed Out\n"); "BC_%d : FW Timed Out\n");
phba->fw_timeout = true; phba->fw_timeout = true;
beiscsi_ue_detect(phba); beiscsi_ue_detect(phba);
return -EBUSY; ret = -EBUSY;
} }
mdelay(1); return ret;
wait++;
} while (true);
return 0;
} }
/* /*
...@@ -699,7 +727,7 @@ struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba) ...@@ -699,7 +727,7 @@ struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba)
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
BUG_ON(atomic_read(&mccq->used) >= mccq->len); WARN_ON(atomic_read(&mccq->used) >= mccq->len);
wrb = queue_head_node(mccq); wrb = queue_head_node(mccq);
memset(wrb, 0, sizeof(*wrb)); memset(wrb, 0, sizeof(*wrb));
wrb->tag0 = (mccq->head & 0x000000FF) << 16; wrb->tag0 = (mccq->head & 0x000000FF) << 16;
...@@ -1009,10 +1037,29 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, ...@@ -1009,10 +1037,29 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
return status; return status;
} }
/**
* be_cmd_create_default_pdu_queue()- Create DEFQ for the adapter
* @ctrl: ptr to ctrl_info
* @cq: Completion Queue
* @dq: Default Queue
* @lenght: ring size
* @entry_size: size of each entry in DEFQ
* @is_header: Header or Data DEFQ
* @ulp_num: Bind to which ULP
*
* Create HDR/Data DEFQ for the passed ULP. Unsol PDU are posted
* on this queue by the FW
*
* return
* Success: 0
* Failure: Non-Zero Value
*
**/
int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
struct be_queue_info *cq, struct be_queue_info *cq,
struct be_queue_info *dq, int length, struct be_queue_info *dq, int length,
int entry_size) int entry_size, uint8_t is_header,
uint8_t ulp_num)
{ {
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_defq_create_req *req = embedded_payload(wrb); struct be_defq_create_req *req = embedded_payload(wrb);
...@@ -1030,6 +1077,11 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, ...@@ -1030,6 +1077,11 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
if (phba->fw_config.dual_ulp_aware) {
req->ulp_num = ulp_num;
req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT);
req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT);
}
if (is_chip_be2_be3r(phba)) { if (is_chip_be2_be3r(phba)) {
AMAP_SET_BITS(struct amap_be_default_pdu_context, AMAP_SET_BITS(struct amap_be_default_pdu_context,
...@@ -1067,22 +1119,53 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, ...@@ -1067,22 +1119,53 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
status = be_mbox_notify(ctrl); status = be_mbox_notify(ctrl);
if (!status) { if (!status) {
struct be_ring *defq_ring;
struct be_defq_create_resp *resp = embedded_payload(wrb); struct be_defq_create_resp *resp = embedded_payload(wrb);
dq->id = le16_to_cpu(resp->id); dq->id = le16_to_cpu(resp->id);
dq->created = true; dq->created = true;
if (is_header)
defq_ring = &phba->phwi_ctrlr->default_pdu_hdr[ulp_num];
else
defq_ring = &phba->phwi_ctrlr->
default_pdu_data[ulp_num];
defq_ring->id = dq->id;
if (!phba->fw_config.dual_ulp_aware) {
defq_ring->ulp_num = BEISCSI_ULP0;
defq_ring->doorbell_offset = DB_RXULP0_OFFSET;
} else {
defq_ring->ulp_num = resp->ulp_num;
defq_ring->doorbell_offset = resp->doorbell_offset;
}
} }
spin_unlock(&ctrl->mbox_lock); spin_unlock(&ctrl->mbox_lock);
return status; return status;
} }
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, /**
struct be_queue_info *wrbq) * be_cmd_wrbq_create()- Create WRBQ
* @ctrl: ptr to ctrl_info
* @q_mem: memory details for the queue
* @wrbq: queue info
* @pwrb_context: ptr to wrb_context
* @ulp_num: ULP on which the WRBQ is to be created
*
* Create WRBQ on the passed ULP_NUM.
*
**/
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem,
struct be_queue_info *wrbq,
struct hwi_wrb_context *pwrb_context,
uint8_t ulp_num)
{ {
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_wrbq_create_req *req = embedded_payload(wrb); struct be_wrbq_create_req *req = embedded_payload(wrb);
struct be_wrbq_create_resp *resp = embedded_payload(wrb); struct be_wrbq_create_resp *resp = embedded_payload(wrb);
struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
int status; int status;
spin_lock(&ctrl->mbox_lock); spin_lock(&ctrl->mbox_lock);
...@@ -1093,13 +1176,74 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, ...@@ -1093,13 +1176,74 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req)); OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req));
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
if (phba->fw_config.dual_ulp_aware) {
req->ulp_num = ulp_num;
req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT);
req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT);
}
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
status = be_mbox_notify(ctrl); status = be_mbox_notify(ctrl);
if (!status) { if (!status) {
wrbq->id = le16_to_cpu(resp->cid); wrbq->id = le16_to_cpu(resp->cid);
wrbq->created = true; wrbq->created = true;
pwrb_context->cid = wrbq->id;
if (!phba->fw_config.dual_ulp_aware) {
pwrb_context->doorbell_offset = DB_TXULP0_OFFSET;
pwrb_context->ulp_num = BEISCSI_ULP0;
} else {
pwrb_context->ulp_num = resp->ulp_num;
pwrb_context->doorbell_offset = resp->doorbell_offset;
} }
}
spin_unlock(&ctrl->mbox_lock);
return status;
}
int be_cmd_iscsi_post_template_hdr(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem)
{
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_post_template_pages_req *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_COMMON,
OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS,
sizeof(*req));
req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI;
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
status = be_mbox_notify(ctrl);
spin_unlock(&ctrl->mbox_lock);
return status;
}
int be_cmd_iscsi_remove_template_hdr(struct be_ctrl_info *ctrl)
{
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_remove_template_pages_req *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_COMMON,
OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS,
sizeof(*req));
req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI;
status = be_mbox_notify(ctrl);
spin_unlock(&ctrl->mbox_lock); spin_unlock(&ctrl->mbox_lock);
return status; return status;
} }
......
...@@ -40,6 +40,7 @@ struct be_mcc_wrb { ...@@ -40,6 +40,7 @@ struct be_mcc_wrb {
u32 tag1; /* dword 3 */ u32 tag1; /* dword 3 */
u32 rsvd; /* dword 4 */ u32 rsvd; /* dword 4 */
union { union {
#define EMBED_MBX_MAX_PAYLOAD_SIZE 220
u8 embedded_payload[236]; /* used by embedded cmds */ u8 embedded_payload[236]; /* used by embedded cmds */
struct be_sge sgl[19]; /* used by non-embedded cmds */ struct be_sge sgl[19]; /* used by non-embedded cmds */
} payload; } payload;
...@@ -162,6 +163,8 @@ struct be_mcc_mailbox { ...@@ -162,6 +163,8 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_CQ_CREATE 12 #define OPCODE_COMMON_CQ_CREATE 12
#define OPCODE_COMMON_EQ_CREATE 13 #define OPCODE_COMMON_EQ_CREATE 13
#define OPCODE_COMMON_MCC_CREATE 21 #define OPCODE_COMMON_MCC_CREATE 21
#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS 24
#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS 25
#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32 #define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32
#define OPCODE_COMMON_GET_FW_VERSION 35 #define OPCODE_COMMON_GET_FW_VERSION 35
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 #define OPCODE_COMMON_MODIFY_EQ_DELAY 41
...@@ -217,6 +220,10 @@ struct phys_addr { ...@@ -217,6 +220,10 @@ struct phys_addr {
u32 hi; u32 hi;
}; };
struct virt_addr {
u32 lo;
u32 hi;
};
/************************** /**************************
* BE Command definitions * * BE Command definitions *
**************************/ **************************/
...@@ -722,7 +729,13 @@ int be_mbox_notify(struct be_ctrl_info *ctrl); ...@@ -722,7 +729,13 @@ int be_mbox_notify(struct be_ctrl_info *ctrl);
int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
struct be_queue_info *cq, struct be_queue_info *cq,
struct be_queue_info *dq, int length, struct be_queue_info *dq, int length,
int entry_size); int entry_size, uint8_t is_header,
uint8_t ulp_num);
int be_cmd_iscsi_post_template_hdr(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem);
int be_cmd_iscsi_remove_template_hdr(struct be_ctrl_info *ctrl);
int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem, u32 page_offset, struct be_dma_mem *q_mem, u32 page_offset,
...@@ -731,7 +744,9 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, ...@@ -731,7 +744,9 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
int beiscsi_cmd_reset_function(struct beiscsi_hba *phba); int beiscsi_cmd_reset_function(struct beiscsi_hba *phba);
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
struct be_queue_info *wrbq); struct be_queue_info *wrbq,
struct hwi_wrb_context *pwrb_context,
uint8_t ulp_num);
bool is_link_state_evt(u32 trailer); bool is_link_state_evt(u32 trailer);
...@@ -776,7 +791,9 @@ struct be_defq_create_req { ...@@ -776,7 +791,9 @@ struct be_defq_create_req {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
u16 num_pages; u16 num_pages;
u8 ulp_num; u8 ulp_num;
u8 rsvd0; #define BEISCSI_DUAL_ULP_AWARE_BIT 0 /* Byte 3 - Bit 0 */
#define BEISCSI_BIND_Q_TO_ULP_BIT 1 /* Byte 3 - Bit 1 */
u8 dua_feature;
struct be_default_pdu_context context; struct be_default_pdu_context context;
struct phys_addr pages[8]; struct phys_addr pages[8];
} __packed; } __packed;
...@@ -784,6 +801,27 @@ struct be_defq_create_req { ...@@ -784,6 +801,27 @@ struct be_defq_create_req {
struct be_defq_create_resp { struct be_defq_create_resp {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
u16 id; u16 id;
u8 rsvd0;
u8 ulp_num;
u32 doorbell_offset;
u16 register_set;
u16 doorbell_format;
} __packed;
struct be_post_template_pages_req {
struct be_cmd_req_hdr hdr;
u16 num_pages;
#define BEISCSI_TEMPLATE_HDR_TYPE_ISCSI 0x1
u16 type;
struct phys_addr scratch_pa;
struct virt_addr scratch_va;
struct virt_addr pages_va;
struct phys_addr pages[16];
} __packed;
struct be_remove_template_pages_req {
struct be_cmd_req_hdr hdr;
u16 type;
u16 rsvd0; u16 rsvd0;
} __packed; } __packed;
...@@ -800,14 +838,18 @@ struct be_wrbq_create_req { ...@@ -800,14 +838,18 @@ struct be_wrbq_create_req {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
u16 num_pages; u16 num_pages;
u8 ulp_num; u8 ulp_num;
u8 rsvd0; u8 dua_feature;
struct phys_addr pages[8]; struct phys_addr pages[8];
} __packed; } __packed;
struct be_wrbq_create_resp { struct be_wrbq_create_resp {
struct be_cmd_resp_hdr resp_hdr; struct be_cmd_resp_hdr resp_hdr;
u16 cid; u16 cid;
u16 rsvd0; u8 rsvd0;
u8 ulp_num;
u32 doorbell_offset;
u16 register_set;
u16 doorbell_format;
} __packed; } __packed;
#define SOL_CID_MASK 0x0000FFC0 #define SOL_CID_MASK 0x0000FFC0
...@@ -1002,6 +1044,7 @@ union tcp_upload_params { ...@@ -1002,6 +1044,7 @@ union tcp_upload_params {
} __packed; } __packed;
struct be_ulp_fw_cfg { struct be_ulp_fw_cfg {
#define BEISCSI_ULP_ISCSI_INI_MODE 0x10
u32 ulp_mode; u32 ulp_mode;
u32 etx_base; u32 etx_base;
u32 etx_count; u32 etx_count;
...@@ -1017,14 +1060,26 @@ struct be_ulp_fw_cfg { ...@@ -1017,14 +1060,26 @@ struct be_ulp_fw_cfg {
u32 icd_count; u32 icd_count;
}; };
struct be_ulp_chain_icd {
u32 chain_base;
u32 chain_count;
};
struct be_fw_cfg { struct be_fw_cfg {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
u32 be_config_number; u32 be_config_number;
u32 asic_revision; u32 asic_revision;
u32 phys_port; u32 phys_port;
#define BEISCSI_FUNC_ISCSI_INI_MODE 0x10
#define BEISCSI_FUNC_DUA_MODE 0x800
u32 function_mode; u32 function_mode;
struct be_ulp_fw_cfg ulp[2]; struct be_ulp_fw_cfg ulp[2];
u32 function_caps; u32 function_caps;
u32 cqid_base;
u32 cqid_count;
u32 eqid_base;
u32 eqid_count;
struct be_ulp_chain_icd chain_icd[2];
} __packed; } __packed;
struct be_cmd_get_all_if_id_req { struct be_cmd_get_all_if_id_req {
......
...@@ -58,10 +58,15 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, ...@@ -58,10 +58,15 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
} }
beiscsi_ep = ep->dd_data; beiscsi_ep = ep->dd_data;
phba = beiscsi_ep->phba; phba = beiscsi_ep->phba;
shost = phba->shost;
if (phba->state & BE_ADAPTER_PCI_ERR) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : PCI_ERROR Recovery\n");
return NULL;
} else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : In beiscsi_session_create\n"); "BS_%d : In beiscsi_session_create\n");
}
if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
...@@ -74,6 +79,7 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, ...@@ -74,6 +79,7 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
} }
shost = phba->shost;
cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
shost, cmds_max, shost, cmds_max,
sizeof(*beiscsi_sess), sizeof(*beiscsi_sess),
...@@ -194,6 +200,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, ...@@ -194,6 +200,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
struct beiscsi_conn *beiscsi_conn = conn->dd_data; struct beiscsi_conn *beiscsi_conn = conn->dd_data;
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
struct beiscsi_hba *phba = iscsi_host_priv(shost); struct beiscsi_hba *phba = iscsi_host_priv(shost);
struct hwi_controller *phwi_ctrlr = phba->phwi_ctrlr;
struct hwi_wrb_context *pwrb_context;
struct beiscsi_endpoint *beiscsi_ep; struct beiscsi_endpoint *beiscsi_ep;
struct iscsi_endpoint *ep; struct iscsi_endpoint *ep;
...@@ -214,9 +222,13 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, ...@@ -214,9 +222,13 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
return -EEXIST; return -EEXIST;
} }
pwrb_context = &phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(
beiscsi_ep->ep_cid)];
beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
beiscsi_conn->ep = beiscsi_ep; beiscsi_conn->ep = beiscsi_ep;
beiscsi_ep->conn = beiscsi_conn; beiscsi_ep->conn = beiscsi_conn;
beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n", "BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n",
...@@ -265,13 +277,17 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) ...@@ -265,13 +277,17 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) void beiscsi_create_def_ifaces(struct beiscsi_hba *phba)
{ {
struct be_cmd_get_if_info_resp if_info; struct be_cmd_get_if_info_resp *if_info;
if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) {
beiscsi_create_ipv4_iface(phba); beiscsi_create_ipv4_iface(phba);
kfree(if_info);
}
if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) {
beiscsi_create_ipv6_iface(phba); beiscsi_create_ipv6_iface(phba);
kfree(if_info);
}
} }
void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
...@@ -467,6 +483,12 @@ int be2iscsi_iface_set_param(struct Scsi_Host *shost, ...@@ -467,6 +483,12 @@ int be2iscsi_iface_set_param(struct Scsi_Host *shost,
uint32_t rm_len = dt_len; uint32_t rm_len = dt_len;
int ret = 0 ; int ret = 0 ;
if (phba->state & BE_ADAPTER_PCI_ERR) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : In PCI_ERROR Recovery\n");
return -EBUSY;
}
nla_for_each_attr(attrib, data, dt_len, rm_len) { nla_for_each_attr(attrib, data, dt_len, rm_len) {
iface_param = nla_data(attrib); iface_param = nla_data(attrib);
...@@ -512,59 +534,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, ...@@ -512,59 +534,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
struct iscsi_iface *iface, int param, struct iscsi_iface *iface, int param,
char *buf) char *buf)
{ {
struct be_cmd_get_if_info_resp if_info; struct be_cmd_get_if_info_resp *if_info;
int len, ip_type = BE2_IPV4; int len, ip_type = BE2_IPV4;
memset(&if_info, 0, sizeof(if_info));
if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
ip_type = BE2_IPV6; ip_type = BE2_IPV6;
len = mgmt_get_if_info(phba, ip_type, &if_info); len = mgmt_get_if_info(phba, ip_type, &if_info);
if (len) if (len) {
kfree(if_info);
return len; return len;
}
switch (param) { switch (param) {
case ISCSI_NET_PARAM_IPV4_ADDR: case ISCSI_NET_PARAM_IPV4_ADDR:
len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr); len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr);
break; break;
case ISCSI_NET_PARAM_IPV6_ADDR: case ISCSI_NET_PARAM_IPV6_ADDR:
len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr); len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr);
break; break;
case ISCSI_NET_PARAM_IPV4_BOOTPROTO: case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
if (!if_info.dhcp_state) if (!if_info->dhcp_state)
len = sprintf(buf, "static\n"); len = sprintf(buf, "static\n");
else else
len = sprintf(buf, "dhcp\n"); len = sprintf(buf, "dhcp\n");
break; break;
case ISCSI_NET_PARAM_IPV4_SUBNET: case ISCSI_NET_PARAM_IPV4_SUBNET:
len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask); len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask);
break; break;
case ISCSI_NET_PARAM_VLAN_ENABLED: case ISCSI_NET_PARAM_VLAN_ENABLED:
len = sprintf(buf, "%s\n", len = sprintf(buf, "%s\n",
(if_info.vlan_priority == BEISCSI_VLAN_DISABLE) (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
? "Disabled\n" : "Enabled\n"); ? "Disabled\n" : "Enabled\n");
break; break;
case ISCSI_NET_PARAM_VLAN_ID: case ISCSI_NET_PARAM_VLAN_ID:
if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
return -EINVAL; return -EINVAL;
else else
len = sprintf(buf, "%d\n", len = sprintf(buf, "%d\n",
(if_info.vlan_priority & (if_info->vlan_priority &
ISCSI_MAX_VLAN_ID)); ISCSI_MAX_VLAN_ID));
break; break;
case ISCSI_NET_PARAM_VLAN_PRIORITY: case ISCSI_NET_PARAM_VLAN_PRIORITY:
if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
return -EINVAL; return -EINVAL;
else else
len = sprintf(buf, "%d\n", len = sprintf(buf, "%d\n",
((if_info.vlan_priority >> 13) & ((if_info->vlan_priority >> 13) &
ISCSI_MAX_VLAN_PRIORITY)); ISCSI_MAX_VLAN_PRIORITY));
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
} }
kfree(if_info);
return len; return len;
} }
...@@ -577,6 +600,12 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, ...@@ -577,6 +600,12 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface,
struct be_cmd_get_def_gateway_resp gateway; struct be_cmd_get_def_gateway_resp gateway;
int len = -ENOSYS; int len = -ENOSYS;
if (phba->state & BE_ADAPTER_PCI_ERR) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : In PCI_ERROR Recovery\n");
return -EBUSY;
}
switch (param) { switch (param) {
case ISCSI_NET_PARAM_IPV4_ADDR: case ISCSI_NET_PARAM_IPV4_ADDR:
case ISCSI_NET_PARAM_IPV4_SUBNET: case ISCSI_NET_PARAM_IPV4_SUBNET:
...@@ -672,8 +701,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, ...@@ -672,8 +701,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
session->max_burst = 262144; session->max_burst = 262144;
break; break;
case ISCSI_PARAM_MAX_XMIT_DLENGTH: case ISCSI_PARAM_MAX_XMIT_DLENGTH:
if ((conn->max_xmit_dlength > 65536) || if (conn->max_xmit_dlength > 65536)
(conn->max_xmit_dlength == 0))
conn->max_xmit_dlength = 65536; conn->max_xmit_dlength = 65536;
default: default:
return 0; return 0;
...@@ -727,7 +755,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) ...@@ -727,7 +755,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost)
struct beiscsi_hba *phba = iscsi_host_priv(shost); struct beiscsi_hba *phba = iscsi_host_priv(shost);
struct iscsi_cls_host *ihost = shost->shost_data; struct iscsi_cls_host *ihost = shost->shost_data;
ihost->port_state = (phba->state == BE_ADAPTER_UP) ? ihost->port_state = (phba->state == BE_ADAPTER_LINK_UP) ?
ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
} }
...@@ -795,9 +823,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, ...@@ -795,9 +823,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
struct beiscsi_hba *phba = iscsi_host_priv(shost); struct beiscsi_hba *phba = iscsi_host_priv(shost);
int status = 0; int status = 0;
if (phba->state & BE_ADAPTER_PCI_ERR) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : In PCI_ERROR Recovery\n");
return -EBUSY;
} else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : In beiscsi_get_host_param," "BS_%d : In beiscsi_get_host_param,"
" param= %d\n", param); " param = %d\n", param);
}
switch (param) { switch (param) {
case ISCSI_HOST_PARAM_HWADDRESS: case ISCSI_HOST_PARAM_HWADDRESS:
...@@ -840,7 +875,7 @@ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) ...@@ -840,7 +875,7 @@ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
struct be_cmd_get_nic_conf_resp resp; struct be_cmd_get_nic_conf_resp resp;
int rc; int rc;
if (strlen(phba->mac_address)) if (phba->mac_addr_set)
return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
...@@ -848,6 +883,7 @@ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) ...@@ -848,6 +883,7 @@ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
if (rc) if (rc)
return rc; return rc;
phba->mac_addr_set = true;
memcpy(phba->mac_address, resp.mac_address, ETH_ALEN); memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
} }
...@@ -923,6 +959,10 @@ static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, ...@@ -923,6 +959,10 @@ static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
session->max_r2t); session->max_r2t);
AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
(conn->exp_statsn - 1)); (conn->exp_statsn - 1));
AMAP_SET_BITS(struct amap_beiscsi_offload_params,
max_recv_data_segment_length, params,
conn->max_recv_dlength);
} }
/** /**
...@@ -935,10 +975,19 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) ...@@ -935,10 +975,19 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
struct beiscsi_conn *beiscsi_conn = conn->dd_data; struct beiscsi_conn *beiscsi_conn = conn->dd_data;
struct beiscsi_endpoint *beiscsi_ep; struct beiscsi_endpoint *beiscsi_ep;
struct beiscsi_offload_params params; struct beiscsi_offload_params params;
struct beiscsi_hba *phba;
phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
if (phba->state & BE_ADAPTER_PCI_ERR) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : In PCI_ERROR Recovery\n");
return -EBUSY;
} else {
beiscsi_log(beiscsi_conn->phba, KERN_INFO, beiscsi_log(beiscsi_conn->phba, KERN_INFO,
BEISCSI_LOG_CONFIG, BEISCSI_LOG_CONFIG,
"BS_%d : In beiscsi_conn_start\n"); "BS_%d : In beiscsi_conn_start\n");
}
memset(&params, 0, sizeof(struct beiscsi_offload_params)); memset(&params, 0, sizeof(struct beiscsi_offload_params));
beiscsi_ep = beiscsi_conn->ep; beiscsi_ep = beiscsi_conn->ep;
...@@ -960,15 +1009,31 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) ...@@ -960,15 +1009,31 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
*/ */
static int beiscsi_get_cid(struct beiscsi_hba *phba) static int beiscsi_get_cid(struct beiscsi_hba *phba)
{ {
unsigned short cid = 0xFFFF; unsigned short cid = 0xFFFF, cid_from_ulp;
struct ulp_cid_info *cid_info = NULL;
if (!phba->avlbl_cids) uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1;
/* Find the ULP which has more CID available */
cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ?
BEISCSI_ULP0_AVLBL_CID(phba) : 0;
cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ?
BEISCSI_ULP1_AVLBL_CID(phba) : 0;
cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ?
BEISCSI_ULP0 : BEISCSI_ULP1;
if (test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) {
cid_info = phba->cid_array_info[cid_from_ulp];
if (!cid_info->avlbl_cids)
return cid; return cid;
cid = phba->cid_array[phba->cid_alloc++]; cid = cid_info->cid_array[cid_info->cid_alloc++];
if (phba->cid_alloc == phba->params.cxns_per_ctrl)
phba->cid_alloc = 0; if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(
phba->avlbl_cids--; phba, cid_from_ulp))
cid_info->cid_alloc = 0;
cid_info->avlbl_cids--;
}
return cid; return cid;
} }
...@@ -979,10 +1044,22 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba) ...@@ -979,10 +1044,22 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba)
*/ */
static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
{ {
phba->avlbl_cids++; uint16_t cid_post_ulp;
phba->cid_array[phba->cid_free++] = cid; struct hwi_controller *phwi_ctrlr;
if (phba->cid_free == phba->params.cxns_per_ctrl) struct hwi_wrb_context *pwrb_context;
phba->cid_free = 0; struct ulp_cid_info *cid_info = NULL;
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
phwi_ctrlr = phba->phwi_ctrlr;
pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
cid_post_ulp = pwrb_context->ulp_num;
cid_info = phba->cid_array_info[cid_post_ulp];
cid_info->avlbl_cids++;
cid_info->cid_array[cid_info->cid_free++] = cid;
if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp))
cid_info->cid_free = 0;
} }
/** /**
...@@ -1135,7 +1212,12 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, ...@@ -1135,7 +1212,12 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
if (phba->state != BE_ADAPTER_UP) { if (phba->state & BE_ADAPTER_PCI_ERR) {
ret = -EBUSY;
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : In PCI_ERROR Recovery\n");
return ERR_PTR(ret);
} else if (phba->state & BE_ADAPTER_LINK_DOWN) {
ret = -EBUSY; ret = -EBUSY;
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BS_%d : The Adapter Port state is Down!!!\n"); "BS_%d : The Adapter Port state is Down!!!\n");
...@@ -1260,6 +1342,12 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -1260,6 +1342,12 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
tcp_upload_flag = CONNECTION_UPLOAD_ABORT; tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
} }
if (phba->state & BE_ADAPTER_PCI_ERR) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : PCI_ERROR Recovery\n");
goto free_ep;
}
tag = mgmt_invalidate_connection(phba, beiscsi_ep, tag = mgmt_invalidate_connection(phba, beiscsi_ep,
beiscsi_ep->ep_cid, beiscsi_ep->ep_cid,
mgmt_invalidate_flag, mgmt_invalidate_flag,
...@@ -1272,6 +1360,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -1272,6 +1360,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
beiscsi_mccq_compl(phba, tag, NULL, NULL); beiscsi_mccq_compl(phba, tag, NULL, NULL);
beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
free_ep:
beiscsi_free_ep(beiscsi_ep); beiscsi_free_ep(beiscsi_ep);
beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
......
此差异已折叠。
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/aer.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
...@@ -34,9 +35,8 @@ ...@@ -34,9 +35,8 @@
#include <scsi/libiscsi.h> #include <scsi/libiscsi.h>
#include <scsi/scsi_transport_iscsi.h> #include <scsi/scsi_transport_iscsi.h>
#include "be.h"
#define DRV_NAME "be2iscsi" #define DRV_NAME "be2iscsi"
#define BUILD_STR "10.0.467.0" #define BUILD_STR "10.0.659.0"
#define BE_NAME "Emulex OneConnect" \ #define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR "Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver" #define DRV_DESC BE_NAME " " "Driver"
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#define MAX_CPUS 64 #define MAX_CPUS 64
#define BEISCSI_MAX_NUM_CPUS 7 #define BEISCSI_MAX_NUM_CPUS 7
#define OC_SKH_MAX_NUM_CPUS 31
#define BEISCSI_VER_STRLEN 32 #define BEISCSI_VER_STRLEN 32
...@@ -74,6 +73,7 @@ ...@@ -74,6 +73,7 @@
#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */
#define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */
#define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */
#define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */
#define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */
...@@ -97,14 +97,19 @@ ...@@ -97,14 +97,19 @@
#define INVALID_SESS_HANDLE 0xFFFFFFFF #define INVALID_SESS_HANDLE 0xFFFFFFFF
#define BE_ADAPTER_UP 0x00000000 #define BE_ADAPTER_LINK_UP 0x001
#define BE_ADAPTER_LINK_DOWN 0x00000001 #define BE_ADAPTER_LINK_DOWN 0x002
#define BE_ADAPTER_PCI_ERR 0x004
#define BEISCSI_CLEAN_UNLOAD 0x01
#define BEISCSI_EEH_UNLOAD 0x02
/** /**
* hardware needs the async PDU buffers to be posted in multiples of 8 * hardware needs the async PDU buffers to be posted in multiples of 8
* So have atleast 8 of them by default * So have atleast 8 of them by default
*/ */
#define HWI_GET_ASYNC_PDU_CTX(phwi) (phwi->phwi_ctxt->pasync_ctx) #define HWI_GET_ASYNC_PDU_CTX(phwi, ulp_num) \
(phwi->phwi_ctxt->pasync_ctx[ulp_num])
/********* Memory BAR register ************/ /********* Memory BAR register ************/
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
...@@ -149,29 +154,41 @@ ...@@ -149,29 +154,41 @@
#define DB_CQ_REARM_SHIFT (29) /* bit 29 */ #define DB_CQ_REARM_SHIFT (29) /* bit 29 */
#define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr) #define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr)
#define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\ #define HWI_GET_DEF_BUFQ_ID(pc, ulp_num) (((struct hwi_controller *)\
(GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data.id) (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data[ulp_num].id)
#define HWI_GET_DEF_HDRQ_ID(pc) (((struct hwi_controller *)\ #define HWI_GET_DEF_HDRQ_ID(pc, ulp_num) (((struct hwi_controller *)\
(GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr.id) (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr[ulp_num].id)
#define PAGES_REQUIRED(x) \ #define PAGES_REQUIRED(x) \
((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE)) ((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE))
#define BEISCSI_MSI_NAME 20 /* size of msi_name string */ #define BEISCSI_MSI_NAME 20 /* size of msi_name string */
#define MEM_DESCR_OFFSET 8
#define BEISCSI_DEFQ_HDR 1
#define BEISCSI_DEFQ_DATA 0
enum be_mem_enum { enum be_mem_enum {
HWI_MEM_ADDN_CONTEXT, HWI_MEM_ADDN_CONTEXT,
HWI_MEM_WRB, HWI_MEM_WRB,
HWI_MEM_WRBH, HWI_MEM_WRBH,
HWI_MEM_SGLH, HWI_MEM_SGLH,
HWI_MEM_SGE, HWI_MEM_SGE,
HWI_MEM_ASYNC_HEADER_BUF, /* 5 */ HWI_MEM_TEMPLATE_HDR_ULP0,
HWI_MEM_ASYNC_DATA_BUF, HWI_MEM_ASYNC_HEADER_BUF_ULP0, /* 6 */
HWI_MEM_ASYNC_HEADER_RING, HWI_MEM_ASYNC_DATA_BUF_ULP0,
HWI_MEM_ASYNC_DATA_RING, HWI_MEM_ASYNC_HEADER_RING_ULP0,
HWI_MEM_ASYNC_HEADER_HANDLE, HWI_MEM_ASYNC_DATA_RING_ULP0,
HWI_MEM_ASYNC_DATA_HANDLE, /* 10 */ HWI_MEM_ASYNC_HEADER_HANDLE_ULP0,
HWI_MEM_ASYNC_PDU_CONTEXT, HWI_MEM_ASYNC_DATA_HANDLE_ULP0, /* 11 */
HWI_MEM_ASYNC_PDU_CONTEXT_ULP0,
HWI_MEM_TEMPLATE_HDR_ULP1,
HWI_MEM_ASYNC_HEADER_BUF_ULP1, /* 14 */
HWI_MEM_ASYNC_DATA_BUF_ULP1,
HWI_MEM_ASYNC_HEADER_RING_ULP1,
HWI_MEM_ASYNC_DATA_RING_ULP1,
HWI_MEM_ASYNC_HEADER_HANDLE_ULP1,
HWI_MEM_ASYNC_DATA_HANDLE_ULP1, /* 19 */
HWI_MEM_ASYNC_PDU_CONTEXT_ULP1,
ISCSI_MEM_GLOBAL_HEADER, ISCSI_MEM_GLOBAL_HEADER,
SE_MEM_MAX SE_MEM_MAX
}; };
...@@ -266,9 +283,49 @@ struct invalidate_command_table { ...@@ -266,9 +283,49 @@ struct invalidate_command_table {
unsigned short cid; unsigned short cid;
} __packed; } __packed;
#define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \
(phwi_ctrlr->wrb_context[cri].ulp_num)
struct hwi_wrb_context {
struct list_head wrb_handle_list;
struct list_head wrb_handle_drvr_list;
struct wrb_handle **pwrb_handle_base;
struct wrb_handle **pwrb_handle_basestd;
struct iscsi_wrb *plast_wrb;
unsigned short alloc_index;
unsigned short free_index;
unsigned short wrb_handles_available;
unsigned short cid;
uint8_t ulp_num; /* ULP to which CID binded */
uint16_t register_set;
uint16_t doorbell_format;
uint32_t doorbell_offset;
};
struct ulp_cid_info {
unsigned short *cid_array;
unsigned short avlbl_cids;
unsigned short cid_alloc;
unsigned short cid_free;
};
#include "be.h"
#define chip_be2(phba) (phba->generation == BE_GEN2) #define chip_be2(phba) (phba->generation == BE_GEN2)
#define chip_be3_r(phba) (phba->generation == BE_GEN3) #define chip_be3_r(phba) (phba->generation == BE_GEN3)
#define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba))) #define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba)))
#define BEISCSI_ULP0 0
#define BEISCSI_ULP1 1
#define BEISCSI_ULP_COUNT 2
#define BEISCSI_ULP0_LOADED 0x01
#define BEISCSI_ULP1_LOADED 0x02
#define BEISCSI_ULP_AVLBL_CID(phba, ulp_num) \
(((struct ulp_cid_info *)phba->cid_array_info[ulp_num])->avlbl_cids)
#define BEISCSI_ULP0_AVLBL_CID(phba) \
BEISCSI_ULP_AVLBL_CID(phba, BEISCSI_ULP0)
#define BEISCSI_ULP1_AVLBL_CID(phba) \
BEISCSI_ULP_AVLBL_CID(phba, BEISCSI_ULP1)
struct beiscsi_hba { struct beiscsi_hba {
struct hba_parameters params; struct hba_parameters params;
struct hwi_controller *phwi_ctrlr; struct hwi_controller *phwi_ctrlr;
...@@ -303,17 +360,15 @@ struct beiscsi_hba { ...@@ -303,17 +360,15 @@ struct beiscsi_hba {
spinlock_t io_sgl_lock; spinlock_t io_sgl_lock;
spinlock_t mgmt_sgl_lock; spinlock_t mgmt_sgl_lock;
spinlock_t isr_lock; spinlock_t isr_lock;
spinlock_t async_pdu_lock;
unsigned int age; unsigned int age;
unsigned short avlbl_cids;
unsigned short cid_alloc;
unsigned short cid_free;
struct list_head hba_queue; struct list_head hba_queue;
#define BE_MAX_SESSION 2048 #define BE_MAX_SESSION 2048
#define BE_SET_CID_TO_CRI(cri_index, cid) \ #define BE_SET_CID_TO_CRI(cri_index, cid) \
(phba->cid_to_cri_map[cid] = cri_index) (phba->cid_to_cri_map[cid] = cri_index)
#define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid])
unsigned short cid_to_cri_map[BE_MAX_SESSION]; unsigned short cid_to_cri_map[BE_MAX_SESSION];
unsigned short *cid_array; struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT];
struct iscsi_endpoint **ep_array; struct iscsi_endpoint **ep_array;
struct beiscsi_conn **conn_table; struct beiscsi_conn **conn_table;
struct iscsi_boot_kset *boot_kset; struct iscsi_boot_kset *boot_kset;
...@@ -325,20 +380,21 @@ struct beiscsi_hba { ...@@ -325,20 +380,21 @@ struct beiscsi_hba {
* group together since they are used most frequently * group together since they are used most frequently
* for cid to cri conversion * for cid to cri conversion
*/ */
unsigned int iscsi_cid_start;
unsigned int phys_port; unsigned int phys_port;
unsigned int eqid_count;
unsigned int cqid_count;
unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT];
#define BEISCSI_GET_CID_COUNT(phba, ulp_num) \
(phba->fw_config.iscsi_cid_count[ulp_num])
unsigned int iscsi_cid_count[BEISCSI_ULP_COUNT];
unsigned int iscsi_icd_count[BEISCSI_ULP_COUNT];
unsigned int iscsi_icd_start[BEISCSI_ULP_COUNT];
unsigned int iscsi_chain_start[BEISCSI_ULP_COUNT];
unsigned int iscsi_chain_count[BEISCSI_ULP_COUNT];
unsigned int isr_offset;
unsigned int iscsi_icd_start;
unsigned int iscsi_cid_count;
unsigned int iscsi_icd_count;
unsigned int pci_function;
unsigned short cid_alloc;
unsigned short cid_free;
unsigned short avlbl_cids;
unsigned short iscsi_features; unsigned short iscsi_features;
spinlock_t cid_lock; uint16_t dual_ulp_aware;
unsigned long ulp_supported;
} fw_config; } fw_config;
unsigned int state; unsigned int state;
...@@ -346,6 +402,7 @@ struct beiscsi_hba { ...@@ -346,6 +402,7 @@ struct beiscsi_hba {
bool ue_detected; bool ue_detected;
struct delayed_work beiscsi_hw_check_task; struct delayed_work beiscsi_hw_check_task;
bool mac_addr_set;
u8 mac_address[ETH_ALEN]; u8 mac_address[ETH_ALEN];
char fw_ver_str[BEISCSI_VER_STRLEN]; char fw_ver_str[BEISCSI_VER_STRLEN];
char wq_name[20]; char wq_name[20];
...@@ -374,6 +431,7 @@ struct beiscsi_conn { ...@@ -374,6 +431,7 @@ struct beiscsi_conn {
struct iscsi_conn *conn; struct iscsi_conn *conn;
struct beiscsi_hba *phba; struct beiscsi_hba *phba;
u32 exp_statsn; u32 exp_statsn;
u32 doorbell_offset;
u32 beiscsi_conn_cid; u32 beiscsi_conn_cid;
struct beiscsi_endpoint *ep; struct beiscsi_endpoint *ep;
unsigned short login_in_progress; unsigned short login_in_progress;
...@@ -474,7 +532,7 @@ struct amap_iscsi_sge { ...@@ -474,7 +532,7 @@ struct amap_iscsi_sge {
}; };
struct beiscsi_offload_params { struct beiscsi_offload_params {
u32 dw[5]; u32 dw[6];
}; };
#define OFFLD_PARAMS_ERL 0x00000003 #define OFFLD_PARAMS_ERL 0x00000003
...@@ -504,6 +562,7 @@ struct amap_beiscsi_offload_params { ...@@ -504,6 +562,7 @@ struct amap_beiscsi_offload_params {
u8 max_r2t[16]; u8 max_r2t[16];
u8 pad[8]; u8 pad[8];
u8 exp_statsn[32]; u8 exp_statsn[32];
u8 max_recv_data_segment_length[32];
}; };
/* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, /* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
...@@ -567,7 +626,8 @@ struct hwi_async_pdu_context { ...@@ -567,7 +626,8 @@ struct hwi_async_pdu_context {
unsigned int buffer_size; unsigned int buffer_size;
unsigned int num_entries; unsigned int num_entries;
#define BE_GET_ASYNC_CRI_FROM_CID(cid) (pasync_ctx->cid_to_async_cri_map[cid])
unsigned short cid_to_async_cri_map[BE_MAX_SESSION];
/** /**
* This is a varying size list! Do not add anything * This is a varying size list! Do not add anything
* after this entry!! * after this entry!!
...@@ -885,30 +945,32 @@ struct amap_iscsi_target_context_update_wrb_v2 { ...@@ -885,30 +945,32 @@ struct amap_iscsi_target_context_update_wrb_v2 {
u8 first_burst_length[24]; /* DWORD 3 */ u8 first_burst_length[24]; /* DWORD 3 */
u8 rsvd3[8]; /* DOWRD 3 */ u8 rsvd3[8]; /* DOWRD 3 */
u8 max_r2t[16]; /* DWORD 4 */ u8 max_r2t[16]; /* DWORD 4 */
u8 rsvd4[10]; /* DWORD 4 */ u8 rsvd4; /* DWORD 4 */
u8 hde; /* DWORD 4 */ u8 hde; /* DWORD 4 */
u8 dde; /* DWORD 4 */ u8 dde; /* DWORD 4 */
u8 erl[2]; /* DWORD 4 */ u8 erl[2]; /* DWORD 4 */
u8 rsvd5[6]; /* DWORD 4 */
u8 imd; /* DWORD 4 */ u8 imd; /* DWORD 4 */
u8 ir2t; /* DWORD 4 */ u8 ir2t; /* DWORD 4 */
u8 rsvd6[3]; /* DWORD 4 */
u8 stat_sn[32]; /* DWORD 5 */ u8 stat_sn[32]; /* DWORD 5 */
u8 rsvd5[32]; /* DWORD 6 */ u8 rsvd7[32]; /* DWORD 6 */
u8 rsvd6[32]; /* DWORD 7 */ u8 rsvd8[32]; /* DWORD 7 */
u8 max_recv_dataseg_len[24]; /* DWORD 8 */ u8 max_recv_dataseg_len[24]; /* DWORD 8 */
u8 rsvd7[8]; /* DWORD 8 */ u8 rsvd9[8]; /* DWORD 8 */
u8 rsvd8[32]; /* DWORD 9 */ u8 rsvd10[32]; /* DWORD 9 */
u8 rsvd9[32]; /* DWORD 10 */ u8 rsvd11[32]; /* DWORD 10 */
u8 max_cxns[16]; /* DWORD 11 */ u8 max_cxns[16]; /* DWORD 11 */
u8 rsvd10[11]; /* DWORD 11*/ u8 rsvd12[11]; /* DWORD 11*/
u8 invld; /* DWORD 11 */ u8 invld; /* DWORD 11 */
u8 rsvd11;/* DWORD 11*/ u8 rsvd13;/* DWORD 11*/
u8 dmsg; /* DWORD 11 */ u8 dmsg; /* DWORD 11 */
u8 data_seq_inorder; /* DWORD 11 */ u8 data_seq_inorder; /* DWORD 11 */
u8 pdu_seq_inorder; /* DWORD 11 */ u8 pdu_seq_inorder; /* DWORD 11 */
u8 rsvd12[32]; /*DWORD 12 */ u8 rsvd14[32]; /*DWORD 12 */
u8 rsvd13[32]; /* DWORD 13 */ u8 rsvd15[32]; /* DWORD 13 */
u8 rsvd14[32]; /* DWORD 14 */ u8 rsvd16[32]; /* DWORD 14 */
u8 rsvd15[32]; /* DWORD 15 */ u8 rsvd17[32]; /* DWORD 15 */
} __packed; } __packed;
...@@ -919,6 +981,10 @@ struct be_ring { ...@@ -919,6 +981,10 @@ struct be_ring {
u32 cidx; /* consumer index */ u32 cidx; /* consumer index */
u32 pidx; /* producer index -- not used by most rings */ u32 pidx; /* producer index -- not used by most rings */
u32 item_size; /* size in bytes of one object */ u32 item_size; /* size in bytes of one object */
u8 ulp_num; /* ULP to which CID binded */
u16 register_set;
u16 doorbell_format;
u32 doorbell_offset;
void *va; /* The virtual address of the ring. This void *va; /* The virtual address of the ring. This
* should be last to allow 32 & 64 bit debugger * should be last to allow 32 & 64 bit debugger
...@@ -926,18 +992,6 @@ struct be_ring { ...@@ -926,18 +992,6 @@ struct be_ring {
*/ */
}; };
struct hwi_wrb_context {
struct list_head wrb_handle_list;
struct list_head wrb_handle_drvr_list;
struct wrb_handle **pwrb_handle_base;
struct wrb_handle **pwrb_handle_basestd;
struct iscsi_wrb *plast_wrb;
unsigned short alloc_index;
unsigned short free_index;
unsigned short wrb_handles_available;
unsigned short cid;
};
struct hwi_controller { struct hwi_controller {
struct list_head io_sgl_list; struct list_head io_sgl_list;
struct list_head eh_sgl_list; struct list_head eh_sgl_list;
...@@ -946,8 +1000,8 @@ struct hwi_controller { ...@@ -946,8 +1000,8 @@ struct hwi_controller {
struct hwi_wrb_context *wrb_context; struct hwi_wrb_context *wrb_context;
struct mcc_wrb *pmcc_wrb_base; struct mcc_wrb *pmcc_wrb_base;
struct be_ring default_pdu_hdr; struct be_ring default_pdu_hdr[BEISCSI_ULP_COUNT];
struct be_ring default_pdu_data; struct be_ring default_pdu_data[BEISCSI_ULP_COUNT];
struct hwi_context_memory *phwi_ctxt; struct hwi_context_memory *phwi_ctxt;
}; };
...@@ -978,11 +1032,10 @@ struct hwi_context_memory { ...@@ -978,11 +1032,10 @@ struct hwi_context_memory {
struct be_eq_obj be_eq[MAX_CPUS]; struct be_eq_obj be_eq[MAX_CPUS];
struct be_queue_info be_cq[MAX_CPUS - 1]; struct be_queue_info be_cq[MAX_CPUS - 1];
struct be_queue_info be_def_hdrq;
struct be_queue_info be_def_dataq;
struct be_queue_info *be_wrbq; struct be_queue_info *be_wrbq;
struct hwi_async_pdu_context *pasync_ctx; struct be_queue_info be_def_hdrq[BEISCSI_ULP_COUNT];
struct be_queue_info be_def_dataq[BEISCSI_ULP_COUNT];
struct hwi_async_pdu_context *pasync_ctx[BEISCSI_ULP_COUNT];
}; };
/* Logging related definitions */ /* Logging related definitions */
...@@ -992,6 +1045,7 @@ struct hwi_context_memory { ...@@ -992,6 +1045,7 @@ struct hwi_context_memory {
#define BEISCSI_LOG_EH 0x0008 /* Error Handler */ #define BEISCSI_LOG_EH 0x0008 /* Error Handler */
#define BEISCSI_LOG_IO 0x0010 /* IO Code Path */ #define BEISCSI_LOG_IO 0x0010 /* IO Code Path */
#define BEISCSI_LOG_CONFIG 0x0020 /* CONFIG Code Path */ #define BEISCSI_LOG_CONFIG 0x0020 /* CONFIG Code Path */
#define BEISCSI_LOG_ISCSI 0x0040 /* SCSI/iSCSI Protocol related Logs */
#define beiscsi_log(phba, level, mask, fmt, arg...) \ #define beiscsi_log(phba, level, mask, fmt, arg...) \
do { \ do { \
......
...@@ -278,6 +278,18 @@ unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, ...@@ -278,6 +278,18 @@ unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
return tag; return tag;
} }
/**
* mgmt_get_fw_config()- Get the FW config for the function
* @ctrl: ptr to Ctrl Info
* @phba: ptr to the dev priv structure
*
* Get the FW config and resources available for the function.
* The resources are created based on the count received here.
*
* return
* Success: 0
* Failure: Non-Zero Value
**/
int mgmt_get_fw_config(struct be_ctrl_info *ctrl, int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba) struct beiscsi_hba *phba)
{ {
...@@ -291,31 +303,79 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, ...@@ -291,31 +303,79 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
EMBED_MBX_MAX_PAYLOAD_SIZE);
status = be_mbox_notify(ctrl); status = be_mbox_notify(ctrl);
if (!status) { if (!status) {
uint8_t ulp_num = 0;
struct be_fw_cfg *pfw_cfg; struct be_fw_cfg *pfw_cfg;
pfw_cfg = req; pfw_cfg = req;
if (!is_chip_be2_be3r(phba)) {
phba->fw_config.eqid_count = pfw_cfg->eqid_count;
phba->fw_config.cqid_count = pfw_cfg->cqid_count;
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_INIT,
"BG_%d : EQ_Count : %d CQ_Count : %d\n",
phba->fw_config.eqid_count,
phba->fw_config.cqid_count);
}
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
if (pfw_cfg->ulp[ulp_num].ulp_mode &
BEISCSI_ULP_ISCSI_INI_MODE)
set_bit(ulp_num,
&phba->fw_config.ulp_supported);
phba->fw_config.phys_port = pfw_cfg->phys_port; phba->fw_config.phys_port = pfw_cfg->phys_port;
phba->fw_config.iscsi_icd_start = for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
pfw_cfg->ulp[0].icd_base; if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
phba->fw_config.iscsi_icd_count =
pfw_cfg->ulp[0].icd_count; phba->fw_config.iscsi_cid_start[ulp_num] =
phba->fw_config.iscsi_cid_start = pfw_cfg->ulp[ulp_num].sq_base;
pfw_cfg->ulp[0].sq_base; phba->fw_config.iscsi_cid_count[ulp_num] =
phba->fw_config.iscsi_cid_count = pfw_cfg->ulp[ulp_num].sq_count;
pfw_cfg->ulp[0].sq_count;
if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { phba->fw_config.iscsi_icd_start[ulp_num] =
pfw_cfg->ulp[ulp_num].icd_base;
phba->fw_config.iscsi_icd_count[ulp_num] =
pfw_cfg->ulp[ulp_num].icd_count;
phba->fw_config.iscsi_chain_start[ulp_num] =
pfw_cfg->chain_icd[ulp_num].chain_base;
phba->fw_config.iscsi_chain_count[ulp_num] =
pfw_cfg->chain_icd[ulp_num].chain_count;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : FW reported MAX CXNS as %d\t" "BG_%d : Function loaded on ULP : %d\n"
"Max Supported = %d.\n", "\tiscsi_cid_count : %d\n"
phba->fw_config.iscsi_cid_count, "\tiscsi_cid_start : %d\n"
BE2_MAX_SESSIONS); "\t iscsi_icd_count : %d\n"
phba->fw_config.iscsi_cid_count = BE2_MAX_SESSIONS / 2; "\t iscsi_icd_start : %d\n",
ulp_num,
phba->fw_config.
iscsi_cid_count[ulp_num],
phba->fw_config.
iscsi_cid_start[ulp_num],
phba->fw_config.
iscsi_icd_count[ulp_num],
phba->fw_config.
iscsi_icd_start[ulp_num]);
}
} }
phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
BEISCSI_FUNC_DUA_MODE);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : DUA Mode : 0x%x\n",
phba->fw_config.dual_ulp_aware);
} else { } else {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : Failed in mgmt_get_fw_config\n"); "BG_%d : Failed in mgmt_get_fw_config\n");
status = -EINVAL;
} }
spin_unlock(&ctrl->mbox_lock); spin_unlock(&ctrl->mbox_lock);
...@@ -448,7 +508,16 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, ...@@ -448,7 +508,16 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
return tag; return tag;
} }
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) /**
* mgmt_epfw_cleanup()- Inform FW to cleanup data structures.
* @phba: pointer to dev priv structure
* @ulp_num: ULP number.
*
* return
* Success: 0
* Failure: Non-Zero Value
**/
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num)
{ {
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb = wrb_from_mccq(phba); struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
...@@ -462,9 +531,9 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) ...@@ -462,9 +531,9 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
req->chute = chute; req->chute = (1 << ulp_num);
req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba)); req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, ulp_num));
req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba)); req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, ulp_num));
status = be_mcc_notify_wait(phba); status = be_mcc_notify_wait(phba);
if (status) if (status)
...@@ -585,6 +654,16 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, ...@@ -585,6 +654,16 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
return tag; return tag;
} }
/**
* mgmt_open_connection()- Establish a TCP CXN
* @dst_addr: Destination Address
* @beiscsi_ep: ptr to device endpoint struct
* @nonemb_cmd: ptr to memory allocated for command
*
* return
* Success: Tag number of the MBX Command issued
* Failure: Error code
**/
int mgmt_open_connection(struct beiscsi_hba *phba, int mgmt_open_connection(struct beiscsi_hba *phba,
struct sockaddr *dst_addr, struct sockaddr *dst_addr,
struct beiscsi_endpoint *beiscsi_ep, struct beiscsi_endpoint *beiscsi_ep,
...@@ -602,14 +681,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -602,14 +681,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
struct phys_addr template_address = { 0, 0 }; struct phys_addr template_address = { 0, 0 };
struct phys_addr *ptemplate_address; struct phys_addr *ptemplate_address;
unsigned int tag = 0; unsigned int tag = 0;
unsigned int i; unsigned int i, ulp_num;
unsigned short cid = beiscsi_ep->ep_cid; unsigned short cid = beiscsi_ep->ep_cid;
struct be_sge *sge; struct be_sge *sge;
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt; phwi_context = phwi_ctrlr->phwi_ctxt;
def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba);
def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba); ulp_num = phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(cid)].ulp_num;
def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba, ulp_num);
def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba, ulp_num);
ptemplate_address = &template_address; ptemplate_address = &template_address;
ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
...@@ -748,11 +830,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, ...@@ -748,11 +830,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va);
if (rc) { if (rc) {
/* Check if the IOCTL needs to be re-issued */
if (rc == -EAGAIN)
return rc;
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); "BG_%d : mgmt_exec_nonemb_cmd Failed status\n");
rc = -EIO;
goto free_cmd; goto free_cmd;
} }
...@@ -861,7 +946,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -861,7 +946,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
uint32_t boot_proto) uint32_t boot_proto)
{ {
struct be_cmd_get_def_gateway_resp gtway_addr_set; struct be_cmd_get_def_gateway_resp gtway_addr_set;
struct be_cmd_get_if_info_resp if_info; struct be_cmd_get_if_info_resp *if_info;
struct be_cmd_set_dhcp_req *dhcpreq; struct be_cmd_set_dhcp_req *dhcpreq;
struct be_cmd_rel_dhcp_req *reldhcp; struct be_cmd_rel_dhcp_req *reldhcp;
struct be_dma_mem nonemb_cmd; struct be_dma_mem nonemb_cmd;
...@@ -872,16 +957,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -872,16 +957,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
if (mgmt_get_all_if_id(phba)) if (mgmt_get_all_if_id(phba))
return -EIO; return -EIO;
memset(&if_info, 0, sizeof(if_info));
ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
BE2_IPV6 : BE2_IPV4 ; BE2_IPV6 : BE2_IPV4 ;
rc = mgmt_get_if_info(phba, ip_type, &if_info); rc = mgmt_get_if_info(phba, ip_type, &if_info);
if (rc) if (rc) {
kfree(if_info);
return rc; return rc;
}
if (boot_proto == ISCSI_BOOTPROTO_DHCP) { if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
if (if_info.dhcp_state) { if (if_info->dhcp_state) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : DHCP Already Enabled\n"); "BG_%d : DHCP Already Enabled\n");
return 0; return 0;
...@@ -894,9 +980,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -894,9 +980,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
IP_V6_LEN : IP_V4_LEN; IP_V6_LEN : IP_V4_LEN;
} else { } else {
if (if_info.dhcp_state) { if (if_info->dhcp_state) {
memset(&if_info, 0, sizeof(if_info)); memset(if_info, 0, sizeof(*if_info));
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
sizeof(*reldhcp)); sizeof(*reldhcp));
...@@ -919,8 +1005,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -919,8 +1005,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
} }
/* Delete the Static IP Set */ /* Delete the Static IP Set */
if (if_info.ip_addr.addr[0]) { if (if_info->ip_addr.addr[0]) {
rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL, rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
IP_ACTION_DEL); IP_ACTION_DEL);
if (rc) if (rc)
return rc; return rc;
...@@ -966,7 +1052,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -966,7 +1052,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
} else { } else {
return mgmt_static_ip_modify(phba, &if_info, ip_param, return mgmt_static_ip_modify(phba, if_info, ip_param,
subnet_param, IP_ACTION_ADD); subnet_param, IP_ACTION_ADD);
} }
...@@ -1031,18 +1117,20 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, ...@@ -1031,18 +1117,20 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
} }
int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_if_info_resp *if_info) struct be_cmd_get_if_info_resp **if_info)
{ {
struct be_cmd_get_if_info_req *req; struct be_cmd_get_if_info_req *req;
struct be_dma_mem nonemb_cmd; struct be_dma_mem nonemb_cmd;
uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp);
int rc; int rc;
if (mgmt_get_all_if_id(phba)) if (mgmt_get_all_if_id(phba))
return -EIO; return -EIO;
do {
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
sizeof(*if_info)); ioctl_size);
if (rc) if (rc)
return rc; return rc;
...@@ -1050,8 +1138,43 @@ int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, ...@@ -1050,8 +1138,43 @@ int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
req->interface_hndl = phba->interface_handle; req->interface_hndl = phba->interface_handle;
req->ip_type = ip_type; req->ip_type = ip_type;
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info, /* Allocate memory for if_info */
sizeof(*if_info)); *if_info = kzalloc(ioctl_size, GFP_KERNEL);
if (!*if_info) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
"BG_%d : Memory Allocation Failure\n");
/* Free the DMA memory for the IOCTL issuing */
pci_free_consistent(phba->ctrl.pdev,
nonemb_cmd.size,
nonemb_cmd.va,
nonemb_cmd.dma);
return -ENOMEM;
}
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *if_info,
ioctl_size);
/* Check if the error is because of Insufficent_Buffer */
if (rc == -EAGAIN) {
/* Get the new memory size */
ioctl_size = ((struct be_cmd_resp_hdr *)
nonemb_cmd.va)->actual_resp_len;
ioctl_size += sizeof(struct be_cmd_req_hdr);
/* Free the previous allocated DMA memory */
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va,
nonemb_cmd.dma);
/* Free the virtual memory */
kfree(*if_info);
} else
break;
} while (true);
return rc;
} }
int mgmt_get_nic_conf(struct beiscsi_hba *phba, int mgmt_get_nic_conf(struct beiscsi_hba *phba,
...@@ -1281,7 +1404,39 @@ beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, ...@@ -1281,7 +1404,39 @@ beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr,
} }
/** /**
* beiscsi_active_cid_disp()- Display Sessions Active * beiscsi_active_session_disp()- Display Sessions Active
* @dev: ptr to device not used.
* @attr: device attribute, not used.
* @buf: contains formatted text Session Count
*
* return
* size of the formatted string
**/
ssize_t
beiscsi_active_session_disp(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct beiscsi_hba *phba = iscsi_host_priv(shost);
uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0;
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) {
avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num);
total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num);
len += snprintf(buf+len, PAGE_SIZE - len,
"ULP%d : %d\n", ulp_num,
(total_cids - avlbl_cids));
} else
len += snprintf(buf+len, PAGE_SIZE - len,
"ULP%d : %d\n", ulp_num, 0);
}
return len;
}
/**
* beiscsi_free_session_disp()- Display Avaliable Session
* @dev: ptr to device not used. * @dev: ptr to device not used.
* @attr: device attribute, not used. * @attr: device attribute, not used.
* @buf: contains formatted text Session Count * @buf: contains formatted text Session Count
...@@ -1290,14 +1445,24 @@ beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, ...@@ -1290,14 +1445,24 @@ beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr,
* size of the formatted string * size of the formatted string
**/ **/
ssize_t ssize_t
beiscsi_active_cid_disp(struct device *dev, struct device_attribute *attr, beiscsi_free_session_disp(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct Scsi_Host *shost = class_to_shost(dev); struct Scsi_Host *shost = class_to_shost(dev);
struct beiscsi_hba *phba = iscsi_host_priv(shost); struct beiscsi_hba *phba = iscsi_host_priv(shost);
uint16_t ulp_num, len = 0;
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported))
len += snprintf(buf+len, PAGE_SIZE - len,
"ULP%d : %d\n", ulp_num,
BEISCSI_ULP_AVLBL_CID(phba, ulp_num));
else
len += snprintf(buf+len, PAGE_SIZE - len,
"ULP%d : %d\n", ulp_num, 0);
}
return snprintf(buf, PAGE_SIZE, "%d\n", return len;
(phba->params.cxns_per_ctrl - phba->avlbl_cids));
} }
/** /**
...@@ -1338,6 +1503,25 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, ...@@ -1338,6 +1503,25 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,
} }
} }
/**
* beiscsi_phys_port()- Display Physical Port Identifier
* @dev: ptr to device not used.
* @attr: device attribute, not used.
* @buf: contains formatted text port identifier
*
* return
* size of the formatted string
**/
ssize_t
beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct beiscsi_hba *phba = iscsi_host_priv(shost);
return snprintf(buf, PAGE_SIZE, "Port Identifier : %d\n",
phba->fw_config.phys_port);
}
void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle, struct wrb_handle *pwrb_handle,
...@@ -1411,10 +1595,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, ...@@ -1411,10 +1595,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
memset(pwrb, 0, sizeof(*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, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
max_burst_length, pwrb, params->dw[offsetof max_burst_length, pwrb, params->dw[offsetof
(struct amap_beiscsi_offload_params, (struct amap_beiscsi_offload_params,
...@@ -1436,7 +1616,9 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, ...@@ -1436,7 +1616,9 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
params->dw[offsetof(struct amap_beiscsi_offload_params, params->dw[offsetof(struct amap_beiscsi_offload_params,
first_burst_length) / 32]); first_burst_length) / 32]);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
max_recv_dataseg_len, pwrb, BEISCSI_MAX_RECV_DATASEG_LEN); max_recv_dataseg_len, pwrb,
params->dw[offsetof(struct amap_beiscsi_offload_params,
max_recv_data_segment_length) / 32]);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
max_cxns, pwrb, BEISCSI_MAX_CXNS); max_cxns, pwrb, BEISCSI_MAX_CXNS);
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb, AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb,
......
...@@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba, ...@@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba,
struct be_cmd_get_nic_conf_resp *mac); struct be_cmd_get_nic_conf_resp *mac);
int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_if_info_resp *if_info); struct be_cmd_get_if_info_resp **if_info);
int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_def_gateway_resp *gateway); struct be_cmd_get_def_gateway_resp *gateway);
...@@ -315,12 +315,19 @@ ssize_t beiscsi_drvr_ver_disp(struct device *dev, ...@@ -315,12 +315,19 @@ ssize_t beiscsi_drvr_ver_disp(struct device *dev,
ssize_t beiscsi_fw_ver_disp(struct device *dev, ssize_t beiscsi_fw_ver_disp(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
ssize_t beiscsi_active_cid_disp(struct device *dev, ssize_t beiscsi_active_session_disp(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
ssize_t beiscsi_adap_family_disp(struct device *dev, ssize_t beiscsi_adap_family_disp(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
ssize_t beiscsi_free_session_disp(struct device *dev,
struct device_attribute *attr, char *buf);
ssize_t beiscsi_phys_port_disp(struct device *dev,
struct device_attribute *attr, char *buf);
void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
struct wrb_handle *pwrb_handle, struct wrb_handle *pwrb_handle,
struct be_mem_descriptor *mem_descr); struct be_mem_descriptor *mem_descr);
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
#include "bnx2fc_constants.h" #include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc" #define BNX2FC_NAME "bnx2fc"
#define BNX2FC_VERSION "1.0.14" #define BNX2FC_VERSION "2.4.1"
#define PFX "bnx2fc: " #define PFX "bnx2fc: "
......
...@@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); ...@@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
#define DRV_MODULE_NAME "bnx2fc" #define DRV_MODULE_NAME "bnx2fc"
#define DRV_MODULE_VERSION BNX2FC_VERSION #define DRV_MODULE_VERSION BNX2FC_VERSION
#define DRV_MODULE_RELDATE "Mar 08, 2013" #define DRV_MODULE_RELDATE "Sep 17, 2013"
static char version[] = static char version[] =
...@@ -542,8 +542,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) ...@@ -542,8 +542,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id)); vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
if (vn_port) { if (vn_port) {
port = lport_priv(vn_port); port = lport_priv(vn_port);
if (compare_ether_addr(port->data_src_addr, dest_mac) if (!ether_addr_equal(port->data_src_addr, dest_mac)) {
!= 0) {
BNX2FC_HBA_DBG(lport, "fpma mismatch\n"); BNX2FC_HBA_DBG(lport, "fpma mismatch\n");
put_cpu(); put_cpu();
kfree_skb(skb); kfree_skb(skb);
...@@ -1381,6 +1380,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, ...@@ -1381,6 +1380,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,
return NULL; return NULL;
} }
ctlr = fcoe_ctlr_device_priv(ctlr_dev); ctlr = fcoe_ctlr_device_priv(ctlr_dev);
ctlr->cdev = ctlr_dev;
interface = fcoe_ctlr_priv(ctlr); interface = fcoe_ctlr_priv(ctlr);
dev_hold(netdev); dev_hold(netdev);
kref_init(&interface->kref); kref_init(&interface->kref);
...@@ -2004,6 +2004,24 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev) ...@@ -2004,6 +2004,24 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic); set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
} }
/* Assumes rtnl_lock and the bnx2fc_dev_lock are already taken */
static int __bnx2fc_disable(struct fcoe_ctlr *ctlr)
{
struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
if (interface->enabled == true) {
if (!ctlr->lp) {
pr_err(PFX "__bnx2fc_disable: lport not found\n");
return -ENODEV;
} else {
interface->enabled = false;
fcoe_ctlr_link_down(ctlr);
fcoe_clean_pending_queue(ctlr->lp);
}
}
return 0;
}
/** /**
* Deperecated: Use bnx2fc_enabled() * Deperecated: Use bnx2fc_enabled()
*/ */
...@@ -2018,20 +2036,34 @@ static int bnx2fc_disable(struct net_device *netdev) ...@@ -2018,20 +2036,34 @@ static int bnx2fc_disable(struct net_device *netdev)
interface = bnx2fc_interface_lookup(netdev); interface = bnx2fc_interface_lookup(netdev);
ctlr = bnx2fc_to_ctlr(interface); ctlr = bnx2fc_to_ctlr(interface);
if (!interface || !ctlr->lp) {
if (!interface) {
rc = -ENODEV; rc = -ENODEV;
printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); pr_err(PFX "bnx2fc_disable: interface not found\n");
} else { } else {
interface->enabled = false; rc = __bnx2fc_disable(ctlr);
fcoe_ctlr_link_down(ctlr);
fcoe_clean_pending_queue(ctlr->lp);
} }
mutex_unlock(&bnx2fc_dev_lock); mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock(); rtnl_unlock();
return rc; return rc;
} }
static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
{
struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
if (interface->enabled == false) {
if (!ctlr->lp) {
pr_err(PFX "__bnx2fc_enable: lport not found\n");
return -ENODEV;
} else if (!bnx2fc_link_ok(ctlr->lp)) {
fcoe_ctlr_link_up(ctlr);
interface->enabled = true;
}
}
return 0;
}
/** /**
* Deprecated: Use bnx2fc_enabled() * Deprecated: Use bnx2fc_enabled()
*/ */
...@@ -2046,12 +2078,11 @@ static int bnx2fc_enable(struct net_device *netdev) ...@@ -2046,12 +2078,11 @@ static int bnx2fc_enable(struct net_device *netdev)
interface = bnx2fc_interface_lookup(netdev); interface = bnx2fc_interface_lookup(netdev);
ctlr = bnx2fc_to_ctlr(interface); ctlr = bnx2fc_to_ctlr(interface);
if (!interface || !ctlr->lp) { if (!interface) {
rc = -ENODEV; rc = -ENODEV;
printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); pr_err(PFX "bnx2fc_enable: interface not found\n");
} else if (!bnx2fc_link_ok(ctlr->lp)) { } else {
fcoe_ctlr_link_up(ctlr); rc = __bnx2fc_enable(ctlr);
interface->enabled = true;
} }
mutex_unlock(&bnx2fc_dev_lock); mutex_unlock(&bnx2fc_dev_lock);
...@@ -2072,14 +2103,12 @@ static int bnx2fc_enable(struct net_device *netdev) ...@@ -2072,14 +2103,12 @@ static int bnx2fc_enable(struct net_device *netdev)
static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev) static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev)
{ {
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev); struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev);
struct fc_lport *lport = ctlr->lp;
struct net_device *netdev = bnx2fc_netdev(lport);
switch (cdev->enabled) { switch (cdev->enabled) {
case FCOE_CTLR_ENABLED: case FCOE_CTLR_ENABLED:
return bnx2fc_enable(netdev); return __bnx2fc_enable(ctlr);
case FCOE_CTLR_DISABLED: case FCOE_CTLR_DISABLED:
return bnx2fc_disable(netdev); return __bnx2fc_disable(ctlr);
case FCOE_CTLR_UNUSED: case FCOE_CTLR_UNUSED:
default: default:
return -ENOTSUPP; return -ENOTSUPP;
......
...@@ -1246,6 +1246,12 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) ...@@ -1246,6 +1246,12 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
kref_put(&io_req->refcount, kref_put(&io_req->refcount,
bnx2fc_cmd_release); /* drop timer hold */ bnx2fc_cmd_release); /* drop timer hold */
rc = bnx2fc_expl_logo(lport, io_req); rc = bnx2fc_expl_logo(lport, io_req);
/* This only occurs when an task abort was requested while ABTS
is in progress. Setting the IO_CLEANUP flag will skip the
RRQ process in the case when the fw generated SCSI_CMD cmpl
was a result from the ABTS request rather than the CLEANUP
request */
set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags);
goto out; goto out;
} }
......
...@@ -308,6 +308,8 @@ struct AdapterCtlBlk { ...@@ -308,6 +308,8 @@ struct AdapterCtlBlk {
struct timer_list waiting_timer; struct timer_list waiting_timer;
struct timer_list selto_timer; struct timer_list selto_timer;
unsigned long last_reset;
u16 srb_count; u16 srb_count;
u8 sel_timeout; u8 sel_timeout;
...@@ -860,9 +862,9 @@ static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to) ...@@ -860,9 +862,9 @@ static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to)
init_timer(&acb->waiting_timer); init_timer(&acb->waiting_timer);
acb->waiting_timer.function = waiting_timeout; acb->waiting_timer.function = waiting_timeout;
acb->waiting_timer.data = (unsigned long) acb; acb->waiting_timer.data = (unsigned long) acb;
if (time_before(jiffies + to, acb->scsi_host->last_reset - HZ / 2)) if (time_before(jiffies + to, acb->last_reset - HZ / 2))
acb->waiting_timer.expires = acb->waiting_timer.expires =
acb->scsi_host->last_reset - HZ / 2 + 1; acb->last_reset - HZ / 2 + 1;
else else
acb->waiting_timer.expires = jiffies + to + 1; acb->waiting_timer.expires = jiffies + to + 1;
add_timer(&acb->waiting_timer); add_timer(&acb->waiting_timer);
...@@ -1319,7 +1321,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) ...@@ -1319,7 +1321,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
udelay(500); udelay(500);
/* We may be in serious trouble. Wait some seconds */ /* We may be in serious trouble. Wait some seconds */
acb->scsi_host->last_reset = acb->last_reset =
jiffies + 3 * HZ / 2 + jiffies + 3 * HZ / 2 +
HZ * acb->eeprom.delay_time; HZ * acb->eeprom.delay_time;
...@@ -1462,9 +1464,9 @@ static void selto_timer(struct AdapterCtlBlk *acb) ...@@ -1462,9 +1464,9 @@ static void selto_timer(struct AdapterCtlBlk *acb)
acb->selto_timer.function = selection_timeout_missed; acb->selto_timer.function = selection_timeout_missed;
acb->selto_timer.data = (unsigned long) acb; acb->selto_timer.data = (unsigned long) acb;
if (time_before if (time_before
(jiffies + HZ, acb->scsi_host->last_reset + HZ / 2)) (jiffies + HZ, acb->last_reset + HZ / 2))
acb->selto_timer.expires = acb->selto_timer.expires =
acb->scsi_host->last_reset + HZ / 2 + 1; acb->last_reset + HZ / 2 + 1;
else else
acb->selto_timer.expires = jiffies + HZ + 1; acb->selto_timer.expires = jiffies + HZ + 1;
add_timer(&acb->selto_timer); add_timer(&acb->selto_timer);
...@@ -1535,7 +1537,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, ...@@ -1535,7 +1537,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
} }
/* Allow starting of SCSI commands half a second before we allow the mid-level /* Allow starting of SCSI commands half a second before we allow the mid-level
* to queue them again after a reset */ * to queue them again after a reset */
if (time_before(jiffies, acb->scsi_host->last_reset - HZ / 2)) { if (time_before(jiffies, acb->last_reset - HZ / 2)) {
dprintkdbg(DBG_KG, "start_scsi: Refuse cmds (reset wait)\n"); dprintkdbg(DBG_KG, "start_scsi: Refuse cmds (reset wait)\n");
return 1; return 1;
} }
...@@ -3031,7 +3033,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3031,7 +3033,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
dprintkl(KERN_ERR, "disconnect: No such device\n"); dprintkl(KERN_ERR, "disconnect: No such device\n");
udelay(500); udelay(500);
/* Suspend queue for a while */ /* Suspend queue for a while */
acb->scsi_host->last_reset = acb->last_reset =
jiffies + HZ / 2 + jiffies + HZ / 2 +
HZ * acb->eeprom.delay_time; HZ * acb->eeprom.delay_time;
clear_fifo(acb, "disconnectEx"); clear_fifo(acb, "disconnectEx");
...@@ -3053,7 +3055,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3053,7 +3055,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
waiting_process_next(acb); waiting_process_next(acb);
} else if (srb->state & SRB_ABORT_SENT) { } else if (srb->state & SRB_ABORT_SENT) {
dcb->flag &= ~ABORT_DEV_; dcb->flag &= ~ABORT_DEV_;
acb->scsi_host->last_reset = jiffies + HZ / 2 + 1; acb->last_reset = jiffies + HZ / 2 + 1;
dprintkl(KERN_ERR, "disconnect: SRB_ABORT_SENT\n"); dprintkl(KERN_ERR, "disconnect: SRB_ABORT_SENT\n");
doing_srb_done(acb, DID_ABORT, srb->cmd, 1); doing_srb_done(acb, DID_ABORT, srb->cmd, 1);
waiting_process_next(acb); waiting_process_next(acb);
...@@ -3649,7 +3651,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb) ...@@ -3649,7 +3651,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb)
/*DC395x_write8(acb, TRM_S1040_DMA_CONTROL,STOPDMAXFER); */ /*DC395x_write8(acb, TRM_S1040_DMA_CONTROL,STOPDMAXFER); */
udelay(500); udelay(500);
/* Maybe we locked up the bus? Then lets wait even longer ... */ /* Maybe we locked up the bus? Then lets wait even longer ... */
acb->scsi_host->last_reset = acb->last_reset =
jiffies + 5 * HZ / 2 + jiffies + 5 * HZ / 2 +
HZ * acb->eeprom.delay_time; HZ * acb->eeprom.delay_time;
...@@ -4426,7 +4428,7 @@ static void adapter_init_scsi_host(struct Scsi_Host *host) ...@@ -4426,7 +4428,7 @@ static void adapter_init_scsi_host(struct Scsi_Host *host)
host->dma_channel = -1; host->dma_channel = -1;
host->unique_id = acb->io_port_base; host->unique_id = acb->io_port_base;
host->irq = acb->irq_level; host->irq = acb->irq_level;
host->last_reset = jiffies; acb->last_reset = jiffies;
host->max_id = 16; host->max_id = 16;
if (host->max_id - 1 == eeprom->scsi_id) if (host->max_id - 1 == eeprom->scsi_id)
...@@ -4484,7 +4486,7 @@ static void adapter_init_chip(struct AdapterCtlBlk *acb) ...@@ -4484,7 +4486,7 @@ static void adapter_init_chip(struct AdapterCtlBlk *acb)
/*spin_unlock_irq (&io_request_lock); */ /*spin_unlock_irq (&io_request_lock); */
udelay(500); udelay(500);
acb->scsi_host->last_reset = acb->last_reset =
jiffies + HZ / 2 + jiffies + HZ / 2 +
HZ * acb->eeprom.delay_time; HZ * acb->eeprom.delay_time;
......
...@@ -481,6 +481,11 @@ static int alua_check_sense(struct scsi_device *sdev, ...@@ -481,6 +481,11 @@ static int alua_check_sense(struct scsi_device *sdev,
* Power On, Reset, or Bus Device Reset, just retry. * Power On, Reset, or Bus Device Reset, just retry.
*/ */
return ADD_TO_MLQUEUE; return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x04)
/*
* Device internal reset
*/
return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01) if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01)
/* /*
* Mode Parameters Changed * Mode Parameters Changed
...@@ -517,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev, ...@@ -517,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev,
/* /*
* alua_rtpg - Evaluate REPORT TARGET GROUP STATES * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
* @sdev: the device to be evaluated. * @sdev: the device to be evaluated.
* @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for device to exit transitioning state
* *
* Evaluate the Target Port Group State. * Evaluate the Target Port Group State.
* Returns SCSI_DH_DEV_OFFLINED if the path is * Returns SCSI_DH_DEV_OFFLINED if the path is
* found to be unusable. * found to be unusable.
*/ */
static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_for_transition)
{ {
struct scsi_sense_hdr sense_hdr; struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0; int len, k, off, valid_states = 0;
...@@ -594,7 +600,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) ...@@ -594,7 +600,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
else else
h->transition_tmo = ALUA_FAILOVER_TIMEOUT; h->transition_tmo = ALUA_FAILOVER_TIMEOUT;
if (orig_transition_tmo != h->transition_tmo) { if (wait_for_transition && (orig_transition_tmo != h->transition_tmo)) {
sdev_printk(KERN_INFO, sdev, sdev_printk(KERN_INFO, sdev,
"%s: transition timeout set to %d seconds\n", "%s: transition timeout set to %d seconds\n",
ALUA_DH_NAME, h->transition_tmo); ALUA_DH_NAME, h->transition_tmo);
...@@ -632,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) ...@@ -632,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
switch (h->state) { switch (h->state) {
case TPGS_STATE_TRANSITIONING: case TPGS_STATE_TRANSITIONING:
if (wait_for_transition) {
if (time_before(jiffies, expiry)) { if (time_before(jiffies, expiry)) {
/* State transition, retry */ /* State transition, retry */
interval += 2000; interval += 2000;
msleep(interval); msleep(interval);
goto retry; goto retry;
} }
/* Transitioning time exceeded, set port to standby */
err = SCSI_DH_RETRY; err = SCSI_DH_RETRY;
} else {
err = SCSI_DH_OK;
}
/* Transitioning time exceeded, set port to standby */
h->state = TPGS_STATE_STANDBY; h->state = TPGS_STATE_STANDBY;
break; break;
case TPGS_STATE_OFFLINE: case TPGS_STATE_OFFLINE:
...@@ -673,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) ...@@ -673,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
if (err != SCSI_DH_OK) if (err != SCSI_DH_OK)
goto out; goto out;
err = alua_rtpg(sdev, h); err = alua_rtpg(sdev, h, 0);
if (err != SCSI_DH_OK) if (err != SCSI_DH_OK)
goto out; goto out;
...@@ -733,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev, ...@@ -733,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev,
int err = SCSI_DH_OK; int err = SCSI_DH_OK;
int stpg = 0; int stpg = 0;
err = alua_rtpg(sdev, h); err = alua_rtpg(sdev, h, 1);
if (err != SCSI_DH_OK) if (err != SCSI_DH_OK)
goto out; goto out;
......
...@@ -786,6 +786,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { ...@@ -786,6 +786,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
{"IBM", "1742"}, {"IBM", "1742"},
{"IBM", "1745"}, {"IBM", "1745"},
{"IBM", "1746"}, {"IBM", "1746"},
{"IBM", "1813"},
{"IBM", "1814"}, {"IBM", "1814"},
{"IBM", "1815"}, {"IBM", "1815"},
{"IBM", "1818"}, {"IBM", "1818"},
......
...@@ -448,19 +448,8 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd ...@@ -448,19 +448,8 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd
} }
rmb(); rmb();
/* if ((pHba->state) & DPTI_STATE_RESET)
* TODO: I need to block here if I am processing ioctl cmds return SCSI_MLQUEUE_HOST_BUSY;
* but if the outstanding cmds all finish before the ioctl,
* the scsi-core will not know to start sending cmds to me again.
* I need to a way to restart the scsi-cores queues or should I block
* calling scsi_done on the outstanding cmds instead
* for now we don't set the IOCTL state
*/
if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {
pHba->host->last_reset = jiffies;
pHba->host->resetting = 1;
return 1;
}
// TODO if the cmd->device if offline then I may need to issue a bus rescan // TODO if the cmd->device if offline then I may need to issue a bus rescan
// followed by a get_lct to see if the device is there anymore // followed by a get_lct to see if the device is there anymore
...@@ -1811,21 +1800,23 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) ...@@ -1811,21 +1800,23 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
} }
do { do {
if(pHba->host) /*
* Stop any new commands from enterring the
* controller while processing the ioctl
*/
if (pHba->host) {
scsi_block_requests(pHba->host);
spin_lock_irqsave(pHba->host->host_lock, flags); spin_lock_irqsave(pHba->host->host_lock, flags);
// This state stops any new commands from enterring the }
// controller while processing the ioctl
// pHba->state |= DPTI_STATE_IOCTL;
// We can't set this now - The scsi subsystem sets host_blocked and
// the queue empties and stops. We need a way to restart the queue
rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
if (rcode != 0) if (rcode != 0)
printk("adpt_i2o_passthru: post wait failed %d %p\n", printk("adpt_i2o_passthru: post wait failed %d %p\n",
rcode, reply); rcode, reply);
// pHba->state &= ~DPTI_STATE_IOCTL; if (pHba->host) {
if(pHba->host)
spin_unlock_irqrestore(pHba->host->host_lock, flags); spin_unlock_irqrestore(pHba->host->host_lock, flags);
} while(rcode == -ETIMEDOUT); scsi_unblock_requests(pHba->host);
}
} while (rcode == -ETIMEDOUT);
if(rcode){ if(rcode){
goto cleanup; goto cleanup;
......
...@@ -202,7 +202,6 @@ struct adpt_channel { ...@@ -202,7 +202,6 @@ struct adpt_channel {
// HBA state flags // HBA state flags
#define DPTI_STATE_RESET (0x01) #define DPTI_STATE_RESET (0x01)
#define DPTI_STATE_IOCTL (0x02)
typedef struct _adpt_hba { typedef struct _adpt_hba {
struct _adpt_hba *next; struct _adpt_hba *next;
......
...@@ -799,47 +799,47 @@ struct esas2r_adapter { ...@@ -799,47 +799,47 @@ struct esas2r_adapter {
struct esas2r_target *targetdb_end; struct esas2r_target *targetdb_end;
unsigned char *regs; unsigned char *regs;
unsigned char *data_window; unsigned char *data_window;
u32 volatile flags; long flags;
#define AF_PORT_CHANGE (u32)(0x00000001) #define AF_PORT_CHANGE 0
#define AF_CHPRST_NEEDED (u32)(0x00000004) #define AF_CHPRST_NEEDED 1
#define AF_CHPRST_PENDING (u32)(0x00000008) #define AF_CHPRST_PENDING 2
#define AF_CHPRST_DETECTED (u32)(0x00000010) #define AF_CHPRST_DETECTED 3
#define AF_BUSRST_NEEDED (u32)(0x00000020) #define AF_BUSRST_NEEDED 4
#define AF_BUSRST_PENDING (u32)(0x00000040) #define AF_BUSRST_PENDING 5
#define AF_BUSRST_DETECTED (u32)(0x00000080) #define AF_BUSRST_DETECTED 6
#define AF_DISABLED (u32)(0x00000100) #define AF_DISABLED 7
#define AF_FLASH_LOCK (u32)(0x00000200) #define AF_FLASH_LOCK 8
#define AF_OS_RESET (u32)(0x00002000) #define AF_OS_RESET 9
#define AF_FLASHING (u32)(0x00004000) #define AF_FLASHING 10
#define AF_POWER_MGT (u32)(0x00008000) #define AF_POWER_MGT 11
#define AF_NVR_VALID (u32)(0x00010000) #define AF_NVR_VALID 12
#define AF_DEGRADED_MODE (u32)(0x00020000) #define AF_DEGRADED_MODE 13
#define AF_DISC_PENDING (u32)(0x00040000) #define AF_DISC_PENDING 14
#define AF_TASKLET_SCHEDULED (u32)(0x00080000) #define AF_TASKLET_SCHEDULED 15
#define AF_HEARTBEAT (u32)(0x00200000) #define AF_HEARTBEAT 16
#define AF_HEARTBEAT_ENB (u32)(0x00400000) #define AF_HEARTBEAT_ENB 17
#define AF_NOT_PRESENT (u32)(0x00800000) #define AF_NOT_PRESENT 18
#define AF_CHPRST_STARTED (u32)(0x01000000) #define AF_CHPRST_STARTED 19
#define AF_FIRST_INIT (u32)(0x02000000) #define AF_FIRST_INIT 20
#define AF_POWER_DOWN (u32)(0x04000000) #define AF_POWER_DOWN 21
#define AF_DISC_IN_PROG (u32)(0x08000000) #define AF_DISC_IN_PROG 22
#define AF_COMM_LIST_TOGGLE (u32)(0x10000000) #define AF_COMM_LIST_TOGGLE 23
#define AF_LEGACY_SGE_MODE (u32)(0x20000000) #define AF_LEGACY_SGE_MODE 24
#define AF_DISC_POLLED (u32)(0x40000000) #define AF_DISC_POLLED 25
u32 volatile flags2; long flags2;
#define AF2_SERIAL_FLASH (u32)(0x00000001) #define AF2_SERIAL_FLASH 0
#define AF2_DEV_SCAN (u32)(0x00000002) #define AF2_DEV_SCAN 1
#define AF2_DEV_CNT_OK (u32)(0x00000004) #define AF2_DEV_CNT_OK 2
#define AF2_COREDUMP_AVAIL (u32)(0x00000008) #define AF2_COREDUMP_AVAIL 3
#define AF2_COREDUMP_SAVED (u32)(0x00000010) #define AF2_COREDUMP_SAVED 4
#define AF2_VDA_POWER_DOWN (u32)(0x00000100) #define AF2_VDA_POWER_DOWN 5
#define AF2_THUNDERLINK (u32)(0x00000200) #define AF2_THUNDERLINK 6
#define AF2_THUNDERBOLT (u32)(0x00000400) #define AF2_THUNDERBOLT 7
#define AF2_INIT_DONE (u32)(0x00000800) #define AF2_INIT_DONE 8
#define AF2_INT_PENDING (u32)(0x00001000) #define AF2_INT_PENDING 9
#define AF2_TIMER_TICK (u32)(0x00002000) #define AF2_TIMER_TICK 10
#define AF2_IRQ_CLAIMED (u32)(0x00004000) #define AF2_IRQ_CLAIMED 11
#define AF2_MSI_ENABLED (u32)(0x00008000) #define AF2_MSI_ENABLED 12
atomic_t disable_cnt; atomic_t disable_cnt;
atomic_t dis_ints_cnt; atomic_t dis_ints_cnt;
u32 int_stat; u32 int_stat;
...@@ -1150,16 +1150,6 @@ void esas2r_queue_fw_event(struct esas2r_adapter *a, ...@@ -1150,16 +1150,6 @@ void esas2r_queue_fw_event(struct esas2r_adapter *a,
int data_sz); int data_sz);
/* Inline functions */ /* Inline functions */
static inline u32 esas2r_lock_set_flags(volatile u32 *flags, u32 bits)
{
return test_and_set_bit(ilog2(bits), (volatile unsigned long *)flags);
}
static inline u32 esas2r_lock_clear_flags(volatile u32 *flags, u32 bits)
{
return test_and_clear_bit(ilog2(bits),
(volatile unsigned long *)flags);
}
/* Allocate a chip scatter/gather list entry */ /* Allocate a chip scatter/gather list entry */
static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a) static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a)
...@@ -1217,7 +1207,6 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq, ...@@ -1217,7 +1207,6 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq,
struct esas2r_adapter *a) struct esas2r_adapter *a)
{ {
union atto_vda_req *vrq = rq->vrq; union atto_vda_req *vrq = rq->vrq;
u32 handle;
INIT_LIST_HEAD(&rq->sg_table_head); INIT_LIST_HEAD(&rq->sg_table_head);
rq->data_buf = (void *)(vrq + 1); rq->data_buf = (void *)(vrq + 1);
...@@ -1253,11 +1242,9 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq, ...@@ -1253,11 +1242,9 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq,
/* /*
* add a reference number to the handle to make it unique (until it * add a reference number to the handle to make it unique (until it
* wraps of course) while preserving the upper word * wraps of course) while preserving the least significant word
*/ */
vrq->scsi.handle = (a->cmd_ref_no++ << 16) | (u16)vrq->scsi.handle;
handle = be32_to_cpu(vrq->scsi.handle) & 0xFFFF0000;
vrq->scsi.handle = cpu_to_be32(handle + a->cmd_ref_no++);
/* /*
* the following formats a SCSI request. the caller can override as * the following formats a SCSI request. the caller can override as
...@@ -1303,10 +1290,13 @@ static inline void esas2r_rq_destroy_request(struct esas2r_request *rq, ...@@ -1303,10 +1290,13 @@ static inline void esas2r_rq_destroy_request(struct esas2r_request *rq,
static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a) static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a)
{ {
return (a->flags & (AF_BUSRST_NEEDED | AF_BUSRST_DETECTED
| AF_CHPRST_NEEDED | AF_CHPRST_DETECTED return test_bit(AF_BUSRST_NEEDED, &a->flags) ||
| AF_PORT_CHANGE)) test_bit(AF_BUSRST_DETECTED, &a->flags) ||
? true : false; test_bit(AF_CHPRST_NEEDED, &a->flags) ||
test_bit(AF_CHPRST_DETECTED, &a->flags) ||
test_bit(AF_PORT_CHANGE, &a->flags);
} }
/* /*
...@@ -1345,24 +1335,24 @@ static inline void esas2r_enable_chip_interrupts(struct esas2r_adapter *a) ...@@ -1345,24 +1335,24 @@ static inline void esas2r_enable_chip_interrupts(struct esas2r_adapter *a)
static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a) static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a)
{ {
/* make sure we don't schedule twice */ /* make sure we don't schedule twice */
if (!(esas2r_lock_set_flags(&a->flags, AF_TASKLET_SCHEDULED) & if (!test_and_set_bit(AF_TASKLET_SCHEDULED, &a->flags))
ilog2(AF_TASKLET_SCHEDULED)))
tasklet_hi_schedule(&a->tasklet); tasklet_hi_schedule(&a->tasklet);
} }
static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a) static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a)
{ {
if (!(a->flags & (AF_DEGRADED_MODE | AF_CHPRST_PENDING)) if (!test_bit(AF_DEGRADED_MODE, &a->flags) &&
&& (a->nvram->options2 & SASNVR2_HEARTBEAT)) !test_bit(AF_CHPRST_PENDING, &a->flags) &&
esas2r_lock_set_flags(&a->flags, AF_HEARTBEAT_ENB); (a->nvram->options2 & SASNVR2_HEARTBEAT))
set_bit(AF_HEARTBEAT_ENB, &a->flags);
else else
esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT_ENB); clear_bit(AF_HEARTBEAT_ENB, &a->flags);
} }
static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a) static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a)
{ {
esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT_ENB); clear_bit(AF_HEARTBEAT_ENB, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT); clear_bit(AF_HEARTBEAT, &a->flags);
} }
/* Set the initial state for resetting the adapter on the next pass through /* Set the initial state for resetting the adapter on the next pass through
...@@ -1372,9 +1362,9 @@ static inline void esas2r_local_reset_adapter(struct esas2r_adapter *a) ...@@ -1372,9 +1362,9 @@ static inline void esas2r_local_reset_adapter(struct esas2r_adapter *a)
{ {
esas2r_disable_heartbeat(a); esas2r_disable_heartbeat(a);
esas2r_lock_set_flags(&a->flags, AF_CHPRST_NEEDED); set_bit(AF_CHPRST_NEEDED, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_CHPRST_PENDING); set_bit(AF_CHPRST_PENDING, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_DISC_PENDING); set_bit(AF_DISC_PENDING, &a->flags);
} }
/* See if an interrupt is pending on the adapter. */ /* See if an interrupt is pending on the adapter. */
......
...@@ -86,9 +86,9 @@ void esas2r_disc_initialize(struct esas2r_adapter *a) ...@@ -86,9 +86,9 @@ void esas2r_disc_initialize(struct esas2r_adapter *a)
esas2r_trace_enter(); esas2r_trace_enter();
esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG); clear_bit(AF_DISC_IN_PROG, &a->flags);
esas2r_lock_clear_flags(&a->flags2, AF2_DEV_SCAN); clear_bit(AF2_DEV_SCAN, &a->flags2);
esas2r_lock_clear_flags(&a->flags2, AF2_DEV_CNT_OK); clear_bit(AF2_DEV_CNT_OK, &a->flags2);
a->disc_start_time = jiffies_to_msecs(jiffies); a->disc_start_time = jiffies_to_msecs(jiffies);
a->disc_wait_time = nvr->dev_wait_time * 1000; a->disc_wait_time = nvr->dev_wait_time * 1000;
...@@ -107,7 +107,8 @@ void esas2r_disc_initialize(struct esas2r_adapter *a) ...@@ -107,7 +107,8 @@ void esas2r_disc_initialize(struct esas2r_adapter *a)
a->general_req.interrupt_cx = NULL; a->general_req.interrupt_cx = NULL;
if (a->flags & (AF_CHPRST_DETECTED | AF_POWER_MGT)) { if (test_bit(AF_CHPRST_DETECTED, &a->flags) ||
test_bit(AF_POWER_MGT, &a->flags)) {
if (a->prev_dev_cnt == 0) { if (a->prev_dev_cnt == 0) {
/* Don't bother waiting if there is nothing to wait /* Don't bother waiting if there is nothing to wait
* for. * for.
...@@ -212,9 +213,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) ...@@ -212,9 +213,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
|| a->disc_wait_cnt == 0)) { || a->disc_wait_cnt == 0)) {
/* After three seconds of waiting, schedule a scan. */ /* After three seconds of waiting, schedule a scan. */
if (time >= 3000 if (time >= 3000
&& !(esas2r_lock_set_flags(&a->flags2, && !test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
AF2_DEV_SCAN) &
ilog2(AF2_DEV_SCAN))) {
spin_lock_irqsave(&a->mem_lock, flags); spin_lock_irqsave(&a->mem_lock, flags);
esas2r_disc_queue_event(a, DCDE_DEV_SCAN); esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
spin_unlock_irqrestore(&a->mem_lock, flags); spin_unlock_irqrestore(&a->mem_lock, flags);
...@@ -228,18 +227,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) ...@@ -228,18 +227,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
* We are done waiting...we think. Adjust the wait time to * We are done waiting...we think. Adjust the wait time to
* consume events after the count is met. * consume events after the count is met.
*/ */
if (!(esas2r_lock_set_flags(&a->flags2, AF2_DEV_CNT_OK) if (!test_and_set_bit(AF2_DEV_CNT_OK, &a->flags2))
& ilog2(AF2_DEV_CNT_OK)))
a->disc_wait_time = time + 3000; a->disc_wait_time = time + 3000;
/* If we haven't done a full scan yet, do it now. */ /* If we haven't done a full scan yet, do it now. */
if (!(esas2r_lock_set_flags(&a->flags2, if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
AF2_DEV_SCAN) &
ilog2(AF2_DEV_SCAN))) {
spin_lock_irqsave(&a->mem_lock, flags); spin_lock_irqsave(&a->mem_lock, flags);
esas2r_disc_queue_event(a, DCDE_DEV_SCAN); esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
spin_unlock_irqrestore(&a->mem_lock, flags); spin_unlock_irqrestore(&a->mem_lock, flags);
esas2r_trace_exit(); esas2r_trace_exit();
return; return;
} }
...@@ -253,9 +248,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) ...@@ -253,9 +248,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
return; return;
} }
} else { } else {
if (!(esas2r_lock_set_flags(&a->flags2, if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
AF2_DEV_SCAN) &
ilog2(AF2_DEV_SCAN))) {
spin_lock_irqsave(&a->mem_lock, flags); spin_lock_irqsave(&a->mem_lock, flags);
esas2r_disc_queue_event(a, DCDE_DEV_SCAN); esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
spin_unlock_irqrestore(&a->mem_lock, flags); spin_unlock_irqrestore(&a->mem_lock, flags);
...@@ -265,8 +258,8 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) ...@@ -265,8 +258,8 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
/* We want to stop waiting for devices. */ /* We want to stop waiting for devices. */
a->disc_wait_time = 0; a->disc_wait_time = 0;
if ((a->flags & AF_DISC_POLLED) if (test_bit(AF_DISC_POLLED, &a->flags) &&
&& (a->flags & AF_DISC_IN_PROG)) { test_bit(AF_DISC_IN_PROG, &a->flags)) {
/* /*
* Polled discovery is still pending so continue the active * Polled discovery is still pending so continue the active
* discovery until it is done. At that point, we will stop * discovery until it is done. At that point, we will stop
...@@ -280,14 +273,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) ...@@ -280,14 +273,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a)
* driven; i.e. There is no transition. * driven; i.e. There is no transition.
*/ */
esas2r_disc_fix_curr_requests(a); esas2r_disc_fix_curr_requests(a);
esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING); clear_bit(AF_DISC_PENDING, &a->flags);
/* /*
* We have deferred target state changes until now because we * We have deferred target state changes until now because we
* don't want to report any removals (due to the first arrival) * don't want to report any removals (due to the first arrival)
* until the device wait time expires. * until the device wait time expires.
*/ */
esas2r_lock_set_flags(&a->flags, AF_PORT_CHANGE); set_bit(AF_PORT_CHANGE, &a->flags);
} }
esas2r_trace_exit(); esas2r_trace_exit();
...@@ -308,7 +301,8 @@ void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt) ...@@ -308,7 +301,8 @@ void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt)
* Don't start discovery before or during polled discovery. if we did, * Don't start discovery before or during polled discovery. if we did,
* we would have a deadlock if we are in the ISR already. * we would have a deadlock if we are in the ISR already.
*/ */
if (!(a->flags & (AF_CHPRST_PENDING | AF_DISC_POLLED))) if (!test_bit(AF_CHPRST_PENDING, &a->flags) &&
!test_bit(AF_DISC_POLLED, &a->flags))
esas2r_disc_start_port(a); esas2r_disc_start_port(a);
esas2r_trace_exit(); esas2r_trace_exit();
...@@ -322,7 +316,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) ...@@ -322,7 +316,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)
esas2r_trace_enter(); esas2r_trace_enter();
if (a->flags & AF_DISC_IN_PROG) { if (test_bit(AF_DISC_IN_PROG, &a->flags)) {
esas2r_trace_exit(); esas2r_trace_exit();
return false; return false;
...@@ -330,7 +324,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) ...@@ -330,7 +324,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)
/* If there is a discovery waiting, process it. */ /* If there is a discovery waiting, process it. */
if (dc->disc_evt) { if (dc->disc_evt) {
if ((a->flags & AF_DISC_POLLED) if (test_bit(AF_DISC_POLLED, &a->flags)
&& a->disc_wait_time == 0) { && a->disc_wait_time == 0) {
/* /*
* We are doing polled discovery, but we no longer want * We are doing polled discovery, but we no longer want
...@@ -347,7 +341,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) ...@@ -347,7 +341,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)
esas2r_hdebug("disc done"); esas2r_hdebug("disc done");
esas2r_lock_set_flags(&a->flags, AF_PORT_CHANGE); set_bit(AF_PORT_CHANGE, &a->flags);
esas2r_trace_exit(); esas2r_trace_exit();
...@@ -356,10 +350,10 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) ...@@ -356,10 +350,10 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)
/* Handle the discovery context */ /* Handle the discovery context */
esas2r_trace("disc_evt: %d", dc->disc_evt); esas2r_trace("disc_evt: %d", dc->disc_evt);
esas2r_lock_set_flags(&a->flags, AF_DISC_IN_PROG); set_bit(AF_DISC_IN_PROG, &a->flags);
dc->flags = 0; dc->flags = 0;
if (a->flags & AF_DISC_POLLED) if (test_bit(AF_DISC_POLLED, &a->flags))
dc->flags |= DCF_POLLED; dc->flags |= DCF_POLLED;
rq->interrupt_cx = dc; rq->interrupt_cx = dc;
...@@ -379,7 +373,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) ...@@ -379,7 +373,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a)
} }
/* Continue interrupt driven discovery */ /* Continue interrupt driven discovery */
if (!(a->flags & AF_DISC_POLLED)) if (!test_bit(AF_DISC_POLLED, &a->flags))
ret = esas2r_disc_continue(a, rq); ret = esas2r_disc_continue(a, rq);
else else
ret = true; ret = true;
...@@ -453,10 +447,10 @@ static bool esas2r_disc_continue(struct esas2r_adapter *a, ...@@ -453,10 +447,10 @@ static bool esas2r_disc_continue(struct esas2r_adapter *a,
/* Discovery is done...for now. */ /* Discovery is done...for now. */
rq->interrupt_cx = NULL; rq->interrupt_cx = NULL;
if (!(a->flags & AF_DISC_PENDING)) if (!test_bit(AF_DISC_PENDING, &a->flags))
esas2r_disc_fix_curr_requests(a); esas2r_disc_fix_curr_requests(a);
esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG); clear_bit(AF_DISC_IN_PROG, &a->flags);
/* Start the next discovery. */ /* Start the next discovery. */
return esas2r_disc_start_port(a); return esas2r_disc_start_port(a);
...@@ -480,7 +474,8 @@ static bool esas2r_disc_start_request(struct esas2r_adapter *a, ...@@ -480,7 +474,8 @@ static bool esas2r_disc_start_request(struct esas2r_adapter *a,
spin_lock_irqsave(&a->queue_lock, flags); spin_lock_irqsave(&a->queue_lock, flags);
if (!(a->flags & (AF_CHPRST_PENDING | AF_FLASHING))) if (!test_bit(AF_CHPRST_PENDING, &a->flags) &&
!test_bit(AF_FLASHING, &a->flags))
esas2r_disc_local_start_request(a, rq); esas2r_disc_local_start_request(a, rq);
else else
list_add_tail(&rq->req_list, &a->defer_list); list_add_tail(&rq->req_list, &a->defer_list);
......
...@@ -231,7 +231,7 @@ static bool load_image(struct esas2r_adapter *a, struct esas2r_request *rq) ...@@ -231,7 +231,7 @@ static bool load_image(struct esas2r_adapter *a, struct esas2r_request *rq)
* RS_PENDING, FM API tasks will continue. * RS_PENDING, FM API tasks will continue.
*/ */
rq->req_stat = RS_PENDING; rq->req_stat = RS_PENDING;
if (a->flags & AF_DEGRADED_MODE) if (test_bit(AF_DEGRADED_MODE, &a->flags))
/* not suppported for now */; /* not suppported for now */;
else else
build_flash_msg(a, rq); build_flash_msg(a, rq);
...@@ -315,7 +315,7 @@ static bool complete_fmapi_req(struct esas2r_adapter *a, ...@@ -315,7 +315,7 @@ static bool complete_fmapi_req(struct esas2r_adapter *a,
memset(fc->scratch, 0, FM_BUF_SZ); memset(fc->scratch, 0, FM_BUF_SZ);
esas2r_enable_heartbeat(a); esas2r_enable_heartbeat(a);
esas2r_lock_clear_flags(&a->flags, AF_FLASH_LOCK); clear_bit(AF_FLASH_LOCK, &a->flags);
return false; return false;
} }
...@@ -526,7 +526,7 @@ static void fw_download_proc(struct esas2r_adapter *a, ...@@ -526,7 +526,7 @@ static void fw_download_proc(struct esas2r_adapter *a,
* The download is complete. If in degraded mode, * The download is complete. If in degraded mode,
* attempt a chip reset. * attempt a chip reset.
*/ */
if (a->flags & AF_DEGRADED_MODE) if (test_bit(AF_DEGRADED_MODE, &a->flags))
esas2r_local_reset_adapter(a); esas2r_local_reset_adapter(a);
a->flash_ver = fi->cmp_hdr[CH_IT_BIOS].version; a->flash_ver = fi->cmp_hdr[CH_IT_BIOS].version;
...@@ -890,7 +890,7 @@ bool esas2r_process_fs_ioctl(struct esas2r_adapter *a, ...@@ -890,7 +890,7 @@ bool esas2r_process_fs_ioctl(struct esas2r_adapter *a,
} }
} }
if (a->flags & AF_DEGRADED_MODE) { if (test_bit(AF_DEGRADED_MODE, &a->flags)) {
fs->status = ATTO_STS_DEGRADED; fs->status = ATTO_STS_DEGRADED;
return false; return false;
} }
...@@ -945,8 +945,12 @@ static bool esas2r_flash_access(struct esas2r_adapter *a, u32 function) ...@@ -945,8 +945,12 @@ static bool esas2r_flash_access(struct esas2r_adapter *a, u32 function)
/* Now wait for the firmware to process it */ /* Now wait for the firmware to process it */
starttime = jiffies_to_msecs(jiffies); starttime = jiffies_to_msecs(jiffies);
timeout = a->flags &
(AF_CHPRST_PENDING | AF_DISC_PENDING) ? 40000 : 5000; if (test_bit(AF_CHPRST_PENDING, &a->flags) ||
test_bit(AF_DISC_PENDING, &a->flags))
timeout = 40000;
else
timeout = 5000;
while (true) { while (true) {
intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT); intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT);
...@@ -1008,7 +1012,7 @@ bool esas2r_read_flash_block(struct esas2r_adapter *a, ...@@ -1008,7 +1012,7 @@ bool esas2r_read_flash_block(struct esas2r_adapter *a,
u32 offset; u32 offset;
u32 iatvr; u32 iatvr;
if (a->flags2 & AF2_SERIAL_FLASH) if (test_bit(AF2_SERIAL_FLASH, &a->flags2))
iatvr = MW_DATA_ADDR_SER_FLASH + (from & -WINDOW_SIZE); iatvr = MW_DATA_ADDR_SER_FLASH + (from & -WINDOW_SIZE);
else else
iatvr = MW_DATA_ADDR_PAR_FLASH + (from & -WINDOW_SIZE); iatvr = MW_DATA_ADDR_PAR_FLASH + (from & -WINDOW_SIZE);
...@@ -1236,9 +1240,9 @@ static void esas2r_nvram_callback(struct esas2r_adapter *a, ...@@ -1236,9 +1240,9 @@ static void esas2r_nvram_callback(struct esas2r_adapter *a,
if (rq->req_stat != RS_PENDING) { if (rq->req_stat != RS_PENDING) {
/* update the NVRAM state */ /* update the NVRAM state */
if (rq->req_stat == RS_SUCCESS) if (rq->req_stat == RS_SUCCESS)
esas2r_lock_set_flags(&a->flags, AF_NVR_VALID); set_bit(AF_NVR_VALID, &a->flags);
else else
esas2r_lock_clear_flags(&a->flags, AF_NVR_VALID); clear_bit(AF_NVR_VALID, &a->flags);
esas2r_enable_heartbeat(a); esas2r_enable_heartbeat(a);
...@@ -1258,7 +1262,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, ...@@ -1258,7 +1262,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq,
u32 *sas_address_dwords = (u32 *)&sas_address_bytes[0]; u32 *sas_address_dwords = (u32 *)&sas_address_bytes[0];
struct atto_vda_flash_req *vrq = &rq->vrq->flash; struct atto_vda_flash_req *vrq = &rq->vrq->flash;
if (a->flags & AF_DEGRADED_MODE) if (test_bit(AF_DEGRADED_MODE, &a->flags))
return false; return false;
if (down_interruptible(&a->nvram_semaphore)) if (down_interruptible(&a->nvram_semaphore))
...@@ -1302,7 +1306,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, ...@@ -1302,7 +1306,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq,
FLS_OFFSET_NVR, FLS_OFFSET_NVR,
sizeof(struct esas2r_sas_nvram)); sizeof(struct esas2r_sas_nvram));
if (a->flags & AF_LEGACY_SGE_MODE) { if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) {
vrq->data.sge[0].length = vrq->data.sge[0].length =
cpu_to_le32(SGE_LAST | cpu_to_le32(SGE_LAST |
...@@ -1337,7 +1341,7 @@ bool esas2r_nvram_validate(struct esas2r_adapter *a) ...@@ -1337,7 +1341,7 @@ bool esas2r_nvram_validate(struct esas2r_adapter *a)
} else if (n->version > SASNVR_VERSION) { } else if (n->version > SASNVR_VERSION) {
esas2r_hdebug("invalid NVRAM version"); esas2r_hdebug("invalid NVRAM version");
} else { } else {
esas2r_lock_set_flags(&a->flags, AF_NVR_VALID); set_bit(AF_NVR_VALID, &a->flags);
rslt = true; rslt = true;
} }
...@@ -1359,7 +1363,7 @@ void esas2r_nvram_set_defaults(struct esas2r_adapter *a) ...@@ -1359,7 +1363,7 @@ void esas2r_nvram_set_defaults(struct esas2r_adapter *a)
struct esas2r_sas_nvram *n = a->nvram; struct esas2r_sas_nvram *n = a->nvram;
u32 time = jiffies_to_msecs(jiffies); u32 time = jiffies_to_msecs(jiffies);
esas2r_lock_clear_flags(&a->flags, AF_NVR_VALID); clear_bit(AF_NVR_VALID, &a->flags);
*n = default_sas_nvram; *n = default_sas_nvram;
n->sas_addr[3] |= 0x0F; n->sas_addr[3] |= 0x0F;
n->sas_addr[4] = HIBYTE(LOWORD(time)); n->sas_addr[4] = HIBYTE(LOWORD(time));
...@@ -1389,7 +1393,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, ...@@ -1389,7 +1393,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi,
u8 j; u8 j;
struct esas2r_component_header *ch; struct esas2r_component_header *ch;
if (esas2r_lock_set_flags(&a->flags, AF_FLASH_LOCK) & AF_FLASH_LOCK) { if (test_and_set_bit(AF_FLASH_LOCK, &a->flags)) {
/* flag was already set */ /* flag was already set */
fi->status = FI_STAT_BUSY; fi->status = FI_STAT_BUSY;
return false; return false;
...@@ -1413,7 +1417,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, ...@@ -1413,7 +1417,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi,
return complete_fmapi_req(a, rq, FI_STAT_IMG_VER); return complete_fmapi_req(a, rq, FI_STAT_IMG_VER);
} }
if (a->flags & AF_DEGRADED_MODE) if (test_bit(AF_DEGRADED_MODE, &a->flags))
return complete_fmapi_req(a, rq, FI_STAT_DEGRADED); return complete_fmapi_req(a, rq, FI_STAT_DEGRADED);
switch (fi->action) { switch (fi->action) {
......
...@@ -216,7 +216,7 @@ static void esas2r_setup_interrupts(struct esas2r_adapter *a, int intr_mode) ...@@ -216,7 +216,7 @@ static void esas2r_setup_interrupts(struct esas2r_adapter *a, int intr_mode)
goto use_legacy_interrupts; goto use_legacy_interrupts;
} }
a->intr_mode = INTR_MODE_MSI; a->intr_mode = INTR_MODE_MSI;
esas2r_lock_set_flags(&a->flags2, AF2_MSI_ENABLED); set_bit(AF2_MSI_ENABLED, &a->flags2);
break; break;
...@@ -252,7 +252,7 @@ static void esas2r_claim_interrupts(struct esas2r_adapter *a) ...@@ -252,7 +252,7 @@ static void esas2r_claim_interrupts(struct esas2r_adapter *a)
return; return;
} }
esas2r_lock_set_flags(&a->flags2, AF2_IRQ_CLAIMED); set_bit(AF2_IRQ_CLAIMED, &a->flags2);
esas2r_log(ESAS2R_LOG_INFO, esas2r_log(ESAS2R_LOG_INFO,
"claimed IRQ %d flags: 0x%lx", "claimed IRQ %d flags: 0x%lx",
a->pcid->irq, flags); a->pcid->irq, flags);
...@@ -380,10 +380,10 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, ...@@ -380,10 +380,10 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
/* interrupts will be disabled until we are done with init */ /* interrupts will be disabled until we are done with init */
atomic_inc(&a->dis_ints_cnt); atomic_inc(&a->dis_ints_cnt);
atomic_inc(&a->disable_cnt); atomic_inc(&a->disable_cnt);
a->flags |= AF_CHPRST_PENDING set_bit(AF_CHPRST_PENDING, &a->flags);
| AF_DISC_PENDING set_bit(AF_DISC_PENDING, &a->flags);
| AF_FIRST_INIT set_bit(AF_FIRST_INIT, &a->flags);
| AF_LEGACY_SGE_MODE; set_bit(AF_LEGACY_SGE_MODE, &a->flags);
a->init_msg = ESAS2R_INIT_MSG_START; a->init_msg = ESAS2R_INIT_MSG_START;
a->max_vdareq_size = 128; a->max_vdareq_size = 128;
...@@ -440,11 +440,11 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, ...@@ -440,11 +440,11 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
esas2r_claim_interrupts(a); esas2r_claim_interrupts(a);
if (a->flags2 & AF2_IRQ_CLAIMED) if (test_bit(AF2_IRQ_CLAIMED, &a->flags2))
esas2r_enable_chip_interrupts(a); esas2r_enable_chip_interrupts(a);
esas2r_lock_set_flags(&a->flags2, AF2_INIT_DONE); set_bit(AF2_INIT_DONE, &a->flags2);
if (!(a->flags & AF_DEGRADED_MODE)) if (!test_bit(AF_DEGRADED_MODE, &a->flags))
esas2r_kickoff_timer(a); esas2r_kickoff_timer(a);
esas2r_debug("esas2r_init_adapter done for %p (%d)", esas2r_debug("esas2r_init_adapter done for %p (%d)",
a, a->disable_cnt); a, a->disable_cnt);
...@@ -457,8 +457,8 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a, ...@@ -457,8 +457,8 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a,
{ {
struct esas2r_mem_desc *memdesc, *next; struct esas2r_mem_desc *memdesc, *next;
if ((a->flags2 & AF2_INIT_DONE) if ((test_bit(AF2_INIT_DONE, &a->flags2))
&& (!(a->flags & AF_DEGRADED_MODE))) { && (!test_bit(AF_DEGRADED_MODE, &a->flags))) {
if (!power_management) { if (!power_management) {
del_timer_sync(&a->timer); del_timer_sync(&a->timer);
tasklet_kill(&a->tasklet); tasklet_kill(&a->tasklet);
...@@ -508,19 +508,19 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a, ...@@ -508,19 +508,19 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a,
} }
/* Clean up interrupts */ /* Clean up interrupts */
if (a->flags2 & AF2_IRQ_CLAIMED) { if (test_bit(AF2_IRQ_CLAIMED, &a->flags2)) {
esas2r_log_dev(ESAS2R_LOG_INFO, esas2r_log_dev(ESAS2R_LOG_INFO,
&(a->pcid->dev), &(a->pcid->dev),
"free_irq(%d) called", a->pcid->irq); "free_irq(%d) called", a->pcid->irq);
free_irq(a->pcid->irq, a); free_irq(a->pcid->irq, a);
esas2r_debug("IRQ released"); esas2r_debug("IRQ released");
esas2r_lock_clear_flags(&a->flags2, AF2_IRQ_CLAIMED); clear_bit(AF2_IRQ_CLAIMED, &a->flags2);
} }
if (a->flags2 & AF2_MSI_ENABLED) { if (test_bit(AF2_MSI_ENABLED, &a->flags2)) {
pci_disable_msi(a->pcid); pci_disable_msi(a->pcid);
esas2r_lock_clear_flags(&a->flags2, AF2_MSI_ENABLED); clear_bit(AF2_MSI_ENABLED, &a->flags2);
esas2r_debug("MSI disabled"); esas2r_debug("MSI disabled");
} }
...@@ -641,12 +641,10 @@ void esas2r_kill_adapter(int i) ...@@ -641,12 +641,10 @@ void esas2r_kill_adapter(int i)
pci_set_drvdata(a->pcid, NULL); pci_set_drvdata(a->pcid, NULL);
esas2r_adapters[i] = NULL; esas2r_adapters[i] = NULL;
if (a->flags2 & AF2_INIT_DONE) { if (test_bit(AF2_INIT_DONE, &a->flags2)) {
esas2r_lock_clear_flags(&a->flags2, clear_bit(AF2_INIT_DONE, &a->flags2);
AF2_INIT_DONE);
esas2r_lock_set_flags(&a->flags, set_bit(AF_DEGRADED_MODE, &a->flags);
AF_DEGRADED_MODE);
esas2r_log_dev(ESAS2R_LOG_INFO, esas2r_log_dev(ESAS2R_LOG_INFO,
&(a->host->shost_gendev), &(a->host->shost_gendev),
...@@ -759,7 +757,7 @@ int esas2r_resume(struct pci_dev *pdev) ...@@ -759,7 +757,7 @@ int esas2r_resume(struct pci_dev *pdev)
esas2r_claim_interrupts(a); esas2r_claim_interrupts(a);
if (a->flags2 & AF2_IRQ_CLAIMED) { if (test_bit(AF2_IRQ_CLAIMED, &a->flags2)) {
/* /*
* Now that system interrupt(s) are claimed, we can enable * Now that system interrupt(s) are claimed, we can enable
* chip interrupts. * chip interrupts.
...@@ -781,7 +779,7 @@ int esas2r_resume(struct pci_dev *pdev) ...@@ -781,7 +779,7 @@ int esas2r_resume(struct pci_dev *pdev)
bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str) bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str)
{ {
esas2r_lock_set_flags(&a->flags, AF_DEGRADED_MODE); set_bit(AF_DEGRADED_MODE, &a->flags);
esas2r_log(ESAS2R_LOG_CRIT, esas2r_log(ESAS2R_LOG_CRIT,
"setting adapter to degraded mode: %s\n", error_str); "setting adapter to degraded mode: %s\n", error_str);
return false; return false;
...@@ -809,7 +807,7 @@ static void esas2r_init_pci_cfg_space(struct esas2r_adapter *a) ...@@ -809,7 +807,7 @@ static void esas2r_init_pci_cfg_space(struct esas2r_adapter *a)
int pcie_cap_reg; int pcie_cap_reg;
pcie_cap_reg = pci_find_capability(a->pcid, PCI_CAP_ID_EXP); pcie_cap_reg = pci_find_capability(a->pcid, PCI_CAP_ID_EXP);
if (0xffff & pcie_cap_reg) { if (pcie_cap_reg) {
u16 devcontrol; u16 devcontrol;
pci_read_config_word(a->pcid, pcie_cap_reg + PCI_EXP_DEVCTL, pci_read_config_word(a->pcid, pcie_cap_reg + PCI_EXP_DEVCTL,
...@@ -896,7 +894,7 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, ...@@ -896,7 +894,7 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a,
&& (a->pcid->subsystem_device & ATTO_SSDID_TBT)) && (a->pcid->subsystem_device & ATTO_SSDID_TBT))
a->flags2 |= AF2_THUNDERBOLT; a->flags2 |= AF2_THUNDERBOLT;
if (a->flags2 & AF2_THUNDERBOLT) if (test_bit(AF2_THUNDERBOLT, &a->flags2))
a->flags2 |= AF2_SERIAL_FLASH; a->flags2 |= AF2_SERIAL_FLASH;
if (a->pcid->subsystem_device == ATTO_TLSH_1068) if (a->pcid->subsystem_device == ATTO_TLSH_1068)
...@@ -956,14 +954,14 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, ...@@ -956,14 +954,14 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a,
a->outbound_copy = (u32 volatile *)high; a->outbound_copy = (u32 volatile *)high;
high += sizeof(u32); high += sizeof(u32);
if (!(a->flags & AF_NVR_VALID)) if (!test_bit(AF_NVR_VALID, &a->flags))
esas2r_nvram_set_defaults(a); esas2r_nvram_set_defaults(a);
/* update the caller's uncached memory area pointer */ /* update the caller's uncached memory area pointer */
*uncached_area = (void *)high; *uncached_area = (void *)high;
/* initialize the allocated memory */ /* initialize the allocated memory */
if (a->flags & AF_FIRST_INIT) { if (test_bit(AF_FIRST_INIT, &a->flags)) {
memset(a->req_table, 0, memset(a->req_table, 0,
(num_requests + num_ae_requests + (num_requests + num_ae_requests +
1) * sizeof(struct esas2r_request *)); 1) * sizeof(struct esas2r_request *));
...@@ -1019,7 +1017,7 @@ bool esas2r_check_adapter(struct esas2r_adapter *a) ...@@ -1019,7 +1017,7 @@ bool esas2r_check_adapter(struct esas2r_adapter *a)
* if the chip reset detected flag is set, we can bypass a bunch of * if the chip reset detected flag is set, we can bypass a bunch of
* stuff. * stuff.
*/ */
if (a->flags & AF_CHPRST_DETECTED) if (test_bit(AF_CHPRST_DETECTED, &a->flags))
goto skip_chip_reset; goto skip_chip_reset;
/* /*
...@@ -1057,14 +1055,12 @@ bool esas2r_check_adapter(struct esas2r_adapter *a) ...@@ -1057,14 +1055,12 @@ bool esas2r_check_adapter(struct esas2r_adapter *a)
doorbell); doorbell);
if (ver == DRBL_FW_VER_0) { if (ver == DRBL_FW_VER_0) {
esas2r_lock_set_flags(&a->flags, set_bit(AF_LEGACY_SGE_MODE, &a->flags);
AF_LEGACY_SGE_MODE);
a->max_vdareq_size = 128; a->max_vdareq_size = 128;
a->build_sgl = esas2r_build_sg_list_sge; a->build_sgl = esas2r_build_sg_list_sge;
} else if (ver == DRBL_FW_VER_1) { } else if (ver == DRBL_FW_VER_1) {
esas2r_lock_clear_flags(&a->flags, clear_bit(AF_LEGACY_SGE_MODE, &a->flags);
AF_LEGACY_SGE_MODE);
a->max_vdareq_size = 1024; a->max_vdareq_size = 1024;
a->build_sgl = esas2r_build_sg_list_prd; a->build_sgl = esas2r_build_sg_list_prd;
...@@ -1139,7 +1135,7 @@ bool esas2r_check_adapter(struct esas2r_adapter *a) ...@@ -1139,7 +1135,7 @@ bool esas2r_check_adapter(struct esas2r_adapter *a)
*a->outbound_copy = *a->outbound_copy =
a->last_write = a->last_write =
a->last_read = a->list_size - 1; a->last_read = a->list_size - 1;
esas2r_lock_set_flags(&a->flags, AF_COMM_LIST_TOGGLE); set_bit(AF_COMM_LIST_TOGGLE, &a->flags);
esas2r_write_register_dword(a, MU_IN_LIST_WRITE, MU_ILW_TOGGLE | esas2r_write_register_dword(a, MU_IN_LIST_WRITE, MU_ILW_TOGGLE |
a->last_write); a->last_write);
esas2r_write_register_dword(a, MU_OUT_LIST_COPY, MU_OLC_TOGGLE | esas2r_write_register_dword(a, MU_OUT_LIST_COPY, MU_OLC_TOGGLE |
...@@ -1204,9 +1200,9 @@ bool esas2r_check_adapter(struct esas2r_adapter *a) ...@@ -1204,9 +1200,9 @@ bool esas2r_check_adapter(struct esas2r_adapter *a)
*/ */
doorbell = esas2r_read_register_dword(a, MU_DOORBELL_IN_ENB); doorbell = esas2r_read_register_dword(a, MU_DOORBELL_IN_ENB);
if (doorbell & DRBL_POWER_DOWN) if (doorbell & DRBL_POWER_DOWN)
esas2r_lock_set_flags(&a->flags2, AF2_VDA_POWER_DOWN); set_bit(AF2_VDA_POWER_DOWN, &a->flags2);
else else
esas2r_lock_clear_flags(&a->flags2, AF2_VDA_POWER_DOWN); clear_bit(AF2_VDA_POWER_DOWN, &a->flags2);
/* /*
* enable assertion of outbound queue and doorbell interrupts in the * enable assertion of outbound queue and doorbell interrupts in the
...@@ -1239,8 +1235,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, ...@@ -1239,8 +1235,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a,
0, 0,
NULL); NULL);
ci = (struct atto_vda_cfg_init *)&rq->vrq->cfg.data.init; ci = (struct atto_vda_cfg_init *)&rq->vrq->cfg.data.init;
ci->sgl_page_size = sgl_page_size; ci->sgl_page_size = cpu_to_le32(sgl_page_size);
ci->epoch_time = now.tv_sec; ci->epoch_time = cpu_to_le32(now.tv_sec);
rq->flags |= RF_FAILURE_OK; rq->flags |= RF_FAILURE_OK;
a->init_msg = ESAS2R_INIT_MSG_INIT; a->init_msg = ESAS2R_INIT_MSG_INIT;
break; break;
...@@ -1250,12 +1246,15 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, ...@@ -1250,12 +1246,15 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a,
if (rq->req_stat == RS_SUCCESS) { if (rq->req_stat == RS_SUCCESS) {
u32 major; u32 major;
u32 minor; u32 minor;
u16 fw_release;
a->fw_version = le16_to_cpu( a->fw_version = le16_to_cpu(
rq->func_rsp.cfg_rsp.vda_version); rq->func_rsp.cfg_rsp.vda_version);
a->fw_build = rq->func_rsp.cfg_rsp.fw_build; a->fw_build = rq->func_rsp.cfg_rsp.fw_build;
major = LOBYTE(rq->func_rsp.cfg_rsp.fw_release); fw_release = le16_to_cpu(
minor = HIBYTE(rq->func_rsp.cfg_rsp.fw_release); rq->func_rsp.cfg_rsp.fw_release);
major = LOBYTE(fw_release);
minor = HIBYTE(fw_release);
a->fw_version += (major << 16) + (minor << 24); a->fw_version += (major << 16) + (minor << 24);
} else { } else {
esas2r_hdebug("FAILED"); esas2r_hdebug("FAILED");
...@@ -1266,9 +1265,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, ...@@ -1266,9 +1265,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a,
* unsupported config requests correctly. * unsupported config requests correctly.
*/ */
if ((a->flags2 & AF2_THUNDERBOLT) if ((test_bit(AF2_THUNDERBOLT, &a->flags2))
|| (be32_to_cpu(a->fw_version) > || (be32_to_cpu(a->fw_version) > 0x00524702)) {
be32_to_cpu(0x47020052))) {
esas2r_hdebug("CFG get init"); esas2r_hdebug("CFG get init");
esas2r_build_cfg_req(a, esas2r_build_cfg_req(a,
rq, rq,
...@@ -1361,10 +1359,10 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1361,10 +1359,10 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
struct esas2r_request *rq; struct esas2r_request *rq;
u32 i; u32 i;
if (a->flags & AF_DEGRADED_MODE) if (test_bit(AF_DEGRADED_MODE, &a->flags))
goto exit; goto exit;
if (!(a->flags & AF_NVR_VALID)) { if (!test_bit(AF_NVR_VALID, &a->flags)) {
if (!esas2r_nvram_read_direct(a)) if (!esas2r_nvram_read_direct(a))
esas2r_log(ESAS2R_LOG_WARN, esas2r_log(ESAS2R_LOG_WARN,
"invalid/missing NVRAM parameters"); "invalid/missing NVRAM parameters");
...@@ -1376,8 +1374,8 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1376,8 +1374,8 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
} }
/* The firmware is ready. */ /* The firmware is ready. */
esas2r_lock_clear_flags(&a->flags, AF_DEGRADED_MODE); clear_bit(AF_DEGRADED_MODE, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); clear_bit(AF_CHPRST_PENDING, &a->flags);
/* Post all the async event requests */ /* Post all the async event requests */
for (i = 0, rq = a->first_ae_req; i < num_ae_requests; i++, rq++) for (i = 0, rq = a->first_ae_req; i < num_ae_requests; i++, rq++)
...@@ -1398,8 +1396,8 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1398,8 +1396,8 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
esas2r_hdebug("firmware revision: %s", a->fw_rev); esas2r_hdebug("firmware revision: %s", a->fw_rev);
if ((a->flags & AF_CHPRST_DETECTED) if (test_bit(AF_CHPRST_DETECTED, &a->flags)
&& (a->flags & AF_FIRST_INIT)) { && (test_bit(AF_FIRST_INIT, &a->flags))) {
esas2r_enable_chip_interrupts(a); esas2r_enable_chip_interrupts(a);
return true; return true;
} }
...@@ -1423,18 +1421,18 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1423,18 +1421,18 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
* Block Tasklets from getting scheduled and indicate this is * Block Tasklets from getting scheduled and indicate this is
* polled discovery. * polled discovery.
*/ */
esas2r_lock_set_flags(&a->flags, AF_TASKLET_SCHEDULED); set_bit(AF_TASKLET_SCHEDULED, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_DISC_POLLED); set_bit(AF_DISC_POLLED, &a->flags);
/* /*
* Temporarily bring the disable count to zero to enable * Temporarily bring the disable count to zero to enable
* deferred processing. Note that the count is already zero * deferred processing. Note that the count is already zero
* after the first initialization. * after the first initialization.
*/ */
if (a->flags & AF_FIRST_INIT) if (test_bit(AF_FIRST_INIT, &a->flags))
atomic_dec(&a->disable_cnt); atomic_dec(&a->disable_cnt);
while (a->flags & AF_DISC_PENDING) { while (test_bit(AF_DISC_PENDING, &a->flags)) {
schedule_timeout_interruptible(msecs_to_jiffies(100)); schedule_timeout_interruptible(msecs_to_jiffies(100));
/* /*
...@@ -1453,7 +1451,7 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1453,7 +1451,7 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
* we have to make sure the timer tick processes the * we have to make sure the timer tick processes the
* doorbell indicating the firmware is ready. * doorbell indicating the firmware is ready.
*/ */
if (!(a->flags & AF_CHPRST_PENDING)) if (!test_bit(AF_CHPRST_PENDING, &a->flags))
esas2r_disc_check_for_work(a); esas2r_disc_check_for_work(a);
/* Simulate a timer tick. */ /* Simulate a timer tick. */
...@@ -1473,11 +1471,11 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1473,11 +1471,11 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
} }
if (a->flags & AF_FIRST_INIT) if (test_bit(AF_FIRST_INIT, &a->flags))
atomic_inc(&a->disable_cnt); atomic_inc(&a->disable_cnt);
esas2r_lock_clear_flags(&a->flags, AF_DISC_POLLED); clear_bit(AF_DISC_POLLED, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_TASKLET_SCHEDULED); clear_bit(AF_TASKLET_SCHEDULED, &a->flags);
} }
...@@ -1504,26 +1502,26 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1504,26 +1502,26 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
* need to get done before we exit. * need to get done before we exit.
*/ */
if ((a->flags & AF_CHPRST_DETECTED) if (test_bit(AF_CHPRST_DETECTED, &a->flags) &&
&& (a->flags & AF_FIRST_INIT)) { test_bit(AF_FIRST_INIT, &a->flags)) {
/* /*
* Reinitialization was performed during the first * Reinitialization was performed during the first
* initialization. Only clear the chip reset flag so the * initialization. Only clear the chip reset flag so the
* original device polling is not cancelled. * original device polling is not cancelled.
*/ */
if (!rslt) if (!rslt)
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); clear_bit(AF_CHPRST_PENDING, &a->flags);
} else { } else {
/* First initialization or a subsequent re-init is complete. */ /* First initialization or a subsequent re-init is complete. */
if (!rslt) { if (!rslt) {
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); clear_bit(AF_CHPRST_PENDING, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING); clear_bit(AF_DISC_PENDING, &a->flags);
} }
/* Enable deferred processing after the first initialization. */ /* Enable deferred processing after the first initialization. */
if (a->flags & AF_FIRST_INIT) { if (test_bit(AF_FIRST_INIT, &a->flags)) {
esas2r_lock_clear_flags(&a->flags, AF_FIRST_INIT); clear_bit(AF_FIRST_INIT, &a->flags);
if (atomic_dec_return(&a->disable_cnt) == 0) if (atomic_dec_return(&a->disable_cnt) == 0)
esas2r_do_deferred_processes(a); esas2r_do_deferred_processes(a);
...@@ -1535,7 +1533,7 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) ...@@ -1535,7 +1533,7 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll)
void esas2r_reset_adapter(struct esas2r_adapter *a) void esas2r_reset_adapter(struct esas2r_adapter *a)
{ {
esas2r_lock_set_flags(&a->flags, AF_OS_RESET); set_bit(AF_OS_RESET, &a->flags);
esas2r_local_reset_adapter(a); esas2r_local_reset_adapter(a);
esas2r_schedule_tasklet(a); esas2r_schedule_tasklet(a);
} }
...@@ -1550,17 +1548,17 @@ void esas2r_reset_chip(struct esas2r_adapter *a) ...@@ -1550,17 +1548,17 @@ void esas2r_reset_chip(struct esas2r_adapter *a)
* dump is located in the upper 512KB of the onchip SRAM. Make sure * dump is located in the upper 512KB of the onchip SRAM. Make sure
* to not overwrite a previous crash that was saved. * to not overwrite a previous crash that was saved.
*/ */
if ((a->flags2 & AF2_COREDUMP_AVAIL) if (test_bit(AF2_COREDUMP_AVAIL, &a->flags2) &&
&& !(a->flags2 & AF2_COREDUMP_SAVED)) { !test_bit(AF2_COREDUMP_SAVED, &a->flags2)) {
esas2r_read_mem_block(a, esas2r_read_mem_block(a,
a->fw_coredump_buff, a->fw_coredump_buff,
MW_DATA_ADDR_SRAM + 0x80000, MW_DATA_ADDR_SRAM + 0x80000,
ESAS2R_FWCOREDUMP_SZ); ESAS2R_FWCOREDUMP_SZ);
esas2r_lock_set_flags(&a->flags2, AF2_COREDUMP_SAVED); set_bit(AF2_COREDUMP_SAVED, &a->flags2);
} }
esas2r_lock_clear_flags(&a->flags2, AF2_COREDUMP_AVAIL); clear_bit(AF2_COREDUMP_AVAIL, &a->flags2);
/* Reset the chip */ /* Reset the chip */
if (a->pcid->revision == MVR_FREY_B2) if (a->pcid->revision == MVR_FREY_B2)
...@@ -1606,10 +1604,10 @@ static void esas2r_power_down_notify_firmware(struct esas2r_adapter *a) ...@@ -1606,10 +1604,10 @@ static void esas2r_power_down_notify_firmware(struct esas2r_adapter *a)
*/ */
void esas2r_power_down(struct esas2r_adapter *a) void esas2r_power_down(struct esas2r_adapter *a)
{ {
esas2r_lock_set_flags(&a->flags, AF_POWER_MGT); set_bit(AF_POWER_MGT, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_POWER_DOWN); set_bit(AF_POWER_DOWN, &a->flags);
if (!(a->flags & AF_DEGRADED_MODE)) { if (!test_bit(AF_DEGRADED_MODE, &a->flags)) {
u32 starttime; u32 starttime;
u32 doorbell; u32 doorbell;
...@@ -1649,14 +1647,14 @@ void esas2r_power_down(struct esas2r_adapter *a) ...@@ -1649,14 +1647,14 @@ void esas2r_power_down(struct esas2r_adapter *a)
* For versions of firmware that support it tell them the driver * For versions of firmware that support it tell them the driver
* is powering down. * is powering down.
*/ */
if (a->flags2 & AF2_VDA_POWER_DOWN) if (test_bit(AF2_VDA_POWER_DOWN, &a->flags2))
esas2r_power_down_notify_firmware(a); esas2r_power_down_notify_firmware(a);
} }
/* Suspend I/O processing. */ /* Suspend I/O processing. */
esas2r_lock_set_flags(&a->flags, AF_OS_RESET); set_bit(AF_OS_RESET, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_DISC_PENDING); set_bit(AF_DISC_PENDING, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_CHPRST_PENDING); set_bit(AF_CHPRST_PENDING, &a->flags);
esas2r_process_adapter_reset(a); esas2r_process_adapter_reset(a);
...@@ -1673,9 +1671,9 @@ bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll) ...@@ -1673,9 +1671,9 @@ bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll)
{ {
bool ret; bool ret;
esas2r_lock_clear_flags(&a->flags, AF_POWER_DOWN); clear_bit(AF_POWER_DOWN, &a->flags);
esas2r_init_pci_cfg_space(a); esas2r_init_pci_cfg_space(a);
esas2r_lock_set_flags(&a->flags, AF_FIRST_INIT); set_bit(AF_FIRST_INIT, &a->flags);
atomic_inc(&a->disable_cnt); atomic_inc(&a->disable_cnt);
/* reinitialize the adapter */ /* reinitialize the adapter */
...@@ -1687,17 +1685,17 @@ bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll) ...@@ -1687,17 +1685,17 @@ bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll)
esas2r_send_reset_ae(a, true); esas2r_send_reset_ae(a, true);
/* clear this flag after initialization. */ /* clear this flag after initialization. */
esas2r_lock_clear_flags(&a->flags, AF_POWER_MGT); clear_bit(AF_POWER_MGT, &a->flags);
return ret; return ret;
} }
bool esas2r_is_adapter_present(struct esas2r_adapter *a) bool esas2r_is_adapter_present(struct esas2r_adapter *a)
{ {
if (a->flags & AF_NOT_PRESENT) if (test_bit(AF_NOT_PRESENT, &a->flags))
return false; return false;
if (esas2r_read_register_dword(a, MU_DOORBELL_OUT) == 0xFFFFFFFF) { if (esas2r_read_register_dword(a, MU_DOORBELL_OUT) == 0xFFFFFFFF) {
esas2r_lock_set_flags(&a->flags, AF_NOT_PRESENT); set_bit(AF_NOT_PRESENT, &a->flags);
return false; return false;
} }
......
...@@ -96,7 +96,7 @@ irqreturn_t esas2r_interrupt(int irq, void *dev_id) ...@@ -96,7 +96,7 @@ irqreturn_t esas2r_interrupt(int irq, void *dev_id)
if (!esas2r_adapter_interrupt_pending(a)) if (!esas2r_adapter_interrupt_pending(a))
return IRQ_NONE; return IRQ_NONE;
esas2r_lock_set_flags(&a->flags2, AF2_INT_PENDING); set_bit(AF2_INT_PENDING, &a->flags2);
esas2r_schedule_tasklet(a); esas2r_schedule_tasklet(a);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -317,9 +317,10 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a) ...@@ -317,9 +317,10 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a)
* = 2 - can start any request * = 2 - can start any request
*/ */
if (a->flags & (AF_CHPRST_PENDING | AF_FLASHING)) if (test_bit(AF_CHPRST_PENDING, &a->flags) ||
test_bit(AF_FLASHING, &a->flags))
startreqs = 0; startreqs = 0;
else if (a->flags & AF_DISC_PENDING) else if (test_bit(AF_DISC_PENDING, &a->flags))
startreqs = 1; startreqs = 1;
atomic_inc(&a->disable_cnt); atomic_inc(&a->disable_cnt);
...@@ -367,7 +368,7 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a) ...@@ -367,7 +368,7 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a)
* Flashing could have been set by last local * Flashing could have been set by last local
* start * start
*/ */
if (a->flags & AF_FLASHING) if (test_bit(AF_FLASHING, &a->flags))
break; break;
} }
} }
...@@ -404,7 +405,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a) ...@@ -404,7 +405,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a)
dc->disc_evt = 0; dc->disc_evt = 0;
esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG); clear_bit(AF_DISC_IN_PROG, &a->flags);
} }
/* /*
...@@ -425,7 +426,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a) ...@@ -425,7 +426,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a)
a->last_write = a->last_write =
a->last_read = a->list_size - 1; a->last_read = a->list_size - 1;
esas2r_lock_set_flags(&a->flags, AF_COMM_LIST_TOGGLE); set_bit(AF_COMM_LIST_TOGGLE, &a->flags);
/* Kill all the requests on the active list */ /* Kill all the requests on the active list */
list_for_each(element, &a->defer_list) { list_for_each(element, &a->defer_list) {
...@@ -470,7 +471,7 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a) ...@@ -470,7 +471,7 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a)
if (atomic_read(&a->disable_cnt) == 0) if (atomic_read(&a->disable_cnt) == 0)
esas2r_do_deferred_processes(a); esas2r_do_deferred_processes(a);
esas2r_lock_clear_flags(&a->flags, AF_OS_RESET); clear_bit(AF_OS_RESET, &a->flags);
esas2r_trace_exit(); esas2r_trace_exit();
} }
...@@ -478,10 +479,10 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a) ...@@ -478,10 +479,10 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a)
static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
{ {
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_NEEDED); clear_bit(AF_CHPRST_NEEDED, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_BUSRST_NEEDED); clear_bit(AF_BUSRST_NEEDED, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_BUSRST_DETECTED); clear_bit(AF_BUSRST_DETECTED, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_BUSRST_PENDING); clear_bit(AF_BUSRST_PENDING, &a->flags);
/* /*
* Make sure we don't get attempt more than 3 resets * Make sure we don't get attempt more than 3 resets
* when the uptime between resets does not exceed one * when the uptime between resets does not exceed one
...@@ -507,10 +508,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) ...@@ -507,10 +508,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
* prevent the heartbeat from trying to recover. * prevent the heartbeat from trying to recover.
*/ */
esas2r_lock_set_flags(&a->flags, AF_DEGRADED_MODE); set_bit(AF_DEGRADED_MODE, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_DISABLED); set_bit(AF_DISABLED, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); clear_bit(AF_CHPRST_PENDING, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING); clear_bit(AF_DISC_PENDING, &a->flags);
esas2r_disable_chip_interrupts(a); esas2r_disable_chip_interrupts(a);
a->int_mask = 0; a->int_mask = 0;
...@@ -519,18 +520,17 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) ...@@ -519,18 +520,17 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
esas2r_log(ESAS2R_LOG_CRIT, esas2r_log(ESAS2R_LOG_CRIT,
"Adapter disabled because of hardware failure"); "Adapter disabled because of hardware failure");
} else { } else {
u32 flags = bool alrdyrst = test_and_set_bit(AF_CHPRST_STARTED, &a->flags);
esas2r_lock_set_flags(&a->flags, AF_CHPRST_STARTED);
if (!(flags & AF_CHPRST_STARTED)) if (!alrdyrst)
/* /*
* Only disable interrupts if this is * Only disable interrupts if this is
* the first reset attempt. * the first reset attempt.
*/ */
esas2r_disable_chip_interrupts(a); esas2r_disable_chip_interrupts(a);
if ((a->flags & AF_POWER_MGT) && !(a->flags & AF_FIRST_INIT) && if ((test_bit(AF_POWER_MGT, &a->flags)) &&
!(flags & AF_CHPRST_STARTED)) { !test_bit(AF_FIRST_INIT, &a->flags) && !alrdyrst) {
/* /*
* Don't reset the chip on the first * Don't reset the chip on the first
* deferred power up attempt. * deferred power up attempt.
...@@ -543,10 +543,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) ...@@ -543,10 +543,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
/* Kick off the reinitialization */ /* Kick off the reinitialization */
a->chip_uptime += ESAS2R_CHP_UPTIME_CNT; a->chip_uptime += ESAS2R_CHP_UPTIME_CNT;
a->chip_init_time = jiffies_to_msecs(jiffies); a->chip_init_time = jiffies_to_msecs(jiffies);
if (!(a->flags & AF_POWER_MGT)) { if (!test_bit(AF_POWER_MGT, &a->flags)) {
esas2r_process_adapter_reset(a); esas2r_process_adapter_reset(a);
if (!(flags & AF_CHPRST_STARTED)) { if (!alrdyrst) {
/* Remove devices now that I/O is cleaned up. */ /* Remove devices now that I/O is cleaned up. */
a->prev_dev_cnt = a->prev_dev_cnt =
esas2r_targ_db_get_tgt_cnt(a); esas2r_targ_db_get_tgt_cnt(a);
...@@ -560,38 +560,37 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) ...@@ -560,38 +560,37 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a)
static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a)
{ {
while (a->flags & AF_CHPRST_DETECTED) { while (test_bit(AF_CHPRST_DETECTED, &a->flags)) {
/* /*
* Balance the enable in esas2r_initadapter_hw. * Balance the enable in esas2r_initadapter_hw.
* Esas2r_power_down already took care of it for power * Esas2r_power_down already took care of it for power
* management. * management.
*/ */
if (!(a->flags & AF_DEGRADED_MODE) && !(a->flags & if (!test_bit(AF_DEGRADED_MODE, &a->flags) &&
AF_POWER_MGT)) !test_bit(AF_POWER_MGT, &a->flags))
esas2r_disable_chip_interrupts(a); esas2r_disable_chip_interrupts(a);
/* Reinitialize the chip. */ /* Reinitialize the chip. */
esas2r_check_adapter(a); esas2r_check_adapter(a);
esas2r_init_adapter_hw(a, 0); esas2r_init_adapter_hw(a, 0);
if (a->flags & AF_CHPRST_NEEDED) if (test_bit(AF_CHPRST_NEEDED, &a->flags))
break; break;
if (a->flags & AF_POWER_MGT) { if (test_bit(AF_POWER_MGT, &a->flags)) {
/* Recovery from power management. */ /* Recovery from power management. */
if (a->flags & AF_FIRST_INIT) { if (test_bit(AF_FIRST_INIT, &a->flags)) {
/* Chip reset during normal power up */ /* Chip reset during normal power up */
esas2r_log(ESAS2R_LOG_CRIT, esas2r_log(ESAS2R_LOG_CRIT,
"The firmware was reset during a normal power-up sequence"); "The firmware was reset during a normal power-up sequence");
} else { } else {
/* Deferred power up complete. */ /* Deferred power up complete. */
esas2r_lock_clear_flags(&a->flags, clear_bit(AF_POWER_MGT, &a->flags);
AF_POWER_MGT);
esas2r_send_reset_ae(a, true); esas2r_send_reset_ae(a, true);
} }
} else { } else {
/* Recovery from online chip reset. */ /* Recovery from online chip reset. */
if (a->flags & AF_FIRST_INIT) { if (test_bit(AF_FIRST_INIT, &a->flags)) {
/* Chip reset during driver load */ /* Chip reset during driver load */
} else { } else {
/* Chip reset after driver load */ /* Chip reset after driver load */
...@@ -602,14 +601,14 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) ...@@ -602,14 +601,14 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a)
"Recovering from a chip reset while the chip was online"); "Recovering from a chip reset while the chip was online");
} }
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_STARTED); clear_bit(AF_CHPRST_STARTED, &a->flags);
esas2r_enable_chip_interrupts(a); esas2r_enable_chip_interrupts(a);
/* /*
* Clear this flag last! this indicates that the chip has been * Clear this flag last! this indicates that the chip has been
* reset already during initialization. * reset already during initialization.
*/ */
esas2r_lock_clear_flags(&a->flags, AF_CHPRST_DETECTED); clear_bit(AF_CHPRST_DETECTED, &a->flags);
} }
} }
...@@ -617,26 +616,28 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) ...@@ -617,26 +616,28 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a)
/* Perform deferred tasks when chip interrupts are disabled */ /* Perform deferred tasks when chip interrupts are disabled */
void esas2r_do_tasklet_tasks(struct esas2r_adapter *a) void esas2r_do_tasklet_tasks(struct esas2r_adapter *a)
{ {
if (a->flags & (AF_CHPRST_NEEDED | AF_CHPRST_DETECTED)) {
if (a->flags & AF_CHPRST_NEEDED) if (test_bit(AF_CHPRST_NEEDED, &a->flags) ||
test_bit(AF_CHPRST_DETECTED, &a->flags)) {
if (test_bit(AF_CHPRST_NEEDED, &a->flags))
esas2r_chip_rst_needed_during_tasklet(a); esas2r_chip_rst_needed_during_tasklet(a);
esas2r_handle_chip_rst_during_tasklet(a); esas2r_handle_chip_rst_during_tasklet(a);
} }
if (a->flags & AF_BUSRST_NEEDED) { if (test_bit(AF_BUSRST_NEEDED, &a->flags)) {
esas2r_hdebug("hard resetting bus"); esas2r_hdebug("hard resetting bus");
esas2r_lock_clear_flags(&a->flags, AF_BUSRST_NEEDED); clear_bit(AF_BUSRST_NEEDED, &a->flags);
if (a->flags & AF_FLASHING) if (test_bit(AF_FLASHING, &a->flags))
esas2r_lock_set_flags(&a->flags, AF_BUSRST_DETECTED); set_bit(AF_BUSRST_DETECTED, &a->flags);
else else
esas2r_write_register_dword(a, MU_DOORBELL_IN, esas2r_write_register_dword(a, MU_DOORBELL_IN,
DRBL_RESET_BUS); DRBL_RESET_BUS);
} }
if (a->flags & AF_BUSRST_DETECTED) { if (test_bit(AF_BUSRST_DETECTED, &a->flags)) {
esas2r_process_bus_reset(a); esas2r_process_bus_reset(a);
esas2r_log_dev(ESAS2R_LOG_WARN, esas2r_log_dev(ESAS2R_LOG_WARN,
...@@ -645,14 +646,14 @@ void esas2r_do_tasklet_tasks(struct esas2r_adapter *a) ...@@ -645,14 +646,14 @@ void esas2r_do_tasklet_tasks(struct esas2r_adapter *a)
scsi_report_bus_reset(a->host, 0); scsi_report_bus_reset(a->host, 0);
esas2r_lock_clear_flags(&a->flags, AF_BUSRST_DETECTED); clear_bit(AF_BUSRST_DETECTED, &a->flags);
esas2r_lock_clear_flags(&a->flags, AF_BUSRST_PENDING); clear_bit(AF_BUSRST_PENDING, &a->flags);
esas2r_log(ESAS2R_LOG_WARN, "Bus reset complete"); esas2r_log(ESAS2R_LOG_WARN, "Bus reset complete");
} }
if (a->flags & AF_PORT_CHANGE) { if (test_bit(AF_PORT_CHANGE, &a->flags)) {
esas2r_lock_clear_flags(&a->flags, AF_PORT_CHANGE); clear_bit(AF_PORT_CHANGE, &a->flags);
esas2r_targ_db_report_changes(a); esas2r_targ_db_report_changes(a);
} }
...@@ -672,10 +673,10 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell) ...@@ -672,10 +673,10 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell)
esas2r_write_register_dword(a, MU_DOORBELL_OUT, doorbell); esas2r_write_register_dword(a, MU_DOORBELL_OUT, doorbell);
if (doorbell & DRBL_RESET_BUS) if (doorbell & DRBL_RESET_BUS)
esas2r_lock_set_flags(&a->flags, AF_BUSRST_DETECTED); set_bit(AF_BUSRST_DETECTED, &a->flags);
if (doorbell & DRBL_FORCE_INT) if (doorbell & DRBL_FORCE_INT)
esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT); clear_bit(AF_HEARTBEAT, &a->flags);
if (doorbell & DRBL_PANIC_REASON_MASK) { if (doorbell & DRBL_PANIC_REASON_MASK) {
esas2r_hdebug("*** Firmware Panic ***"); esas2r_hdebug("*** Firmware Panic ***");
...@@ -683,7 +684,7 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell) ...@@ -683,7 +684,7 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell)
} }
if (doorbell & DRBL_FW_RESET) { if (doorbell & DRBL_FW_RESET) {
esas2r_lock_set_flags(&a->flags2, AF2_COREDUMP_AVAIL); set_bit(AF2_COREDUMP_AVAIL, &a->flags2);
esas2r_local_reset_adapter(a); esas2r_local_reset_adapter(a);
} }
...@@ -918,7 +919,7 @@ void esas2r_complete_request(struct esas2r_adapter *a, ...@@ -918,7 +919,7 @@ void esas2r_complete_request(struct esas2r_adapter *a,
{ {
if (rq->vrq->scsi.function == VDA_FUNC_FLASH if (rq->vrq->scsi.function == VDA_FUNC_FLASH
&& rq->vrq->flash.sub_func == VDA_FLASH_COMMIT) && rq->vrq->flash.sub_func == VDA_FLASH_COMMIT)
esas2r_lock_clear_flags(&a->flags, AF_FLASHING); clear_bit(AF_FLASHING, &a->flags);
/* See if we setup a callback to do special processing */ /* See if we setup a callback to do special processing */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -86,7 +86,7 @@ void esas2r_targ_db_report_changes(struct esas2r_adapter *a) ...@@ -86,7 +86,7 @@ void esas2r_targ_db_report_changes(struct esas2r_adapter *a)
esas2r_trace_enter(); esas2r_trace_enter();
if (a->flags & AF_DISC_PENDING) { if (test_bit(AF_DISC_PENDING, &a->flags)) {
esas2r_trace_exit(); esas2r_trace_exit();
return; return;
} }
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -84,7 +84,8 @@ fnic_trace_data_t *fnic_trace_get_buf(void); ...@@ -84,7 +84,8 @@ fnic_trace_data_t *fnic_trace_get_buf(void);
int fnic_get_trace_data(fnic_dbgfs_t *); int fnic_get_trace_data(fnic_dbgfs_t *);
int fnic_trace_buf_init(void); int fnic_trace_buf_init(void);
void fnic_trace_free(void); void fnic_trace_free(void);
int fnic_debugfs_init(void);
void fnic_debugfs_terminate(void);
int fnic_trace_debugfs_init(void); int fnic_trace_debugfs_init(void);
void fnic_trace_debugfs_terminate(void); void fnic_trace_debugfs_terminate(void);
#endif #endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册