aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi/be_cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/be2iscsi/be_cmds.c')
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c88
1 files changed, 76 insertions, 12 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index f008708f1b08..67098578fba4 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -1,5 +1,5 @@
1/** 1/**
2 * Copyright (C) 2005 - 2009 ServerEngines 2 * Copyright (C) 2005 - 2010 ServerEngines
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -19,7 +19,7 @@
19#include "be_mgmt.h" 19#include "be_mgmt.h"
20#include "be_main.h" 20#include "be_main.h"
21 21
22static void be_mcc_notify(struct beiscsi_hba *phba) 22void be_mcc_notify(struct beiscsi_hba *phba)
23{ 23{
24 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; 24 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
25 u32 val = 0; 25 u32 val = 0;
@@ -29,6 +29,52 @@ static void be_mcc_notify(struct beiscsi_hba *phba)
29 iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); 29 iowrite32(val, phba->db_va + DB_MCCQ_OFFSET);
30} 30}
31 31
32unsigned int alloc_mcc_tag(struct beiscsi_hba *phba)
33{
34 unsigned int tag = 0;
35 unsigned int num = 0;
36
37mcc_tag_rdy:
38 if (phba->ctrl.mcc_tag_available) {
39 tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index];
40 phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0;
41 phba->ctrl.mcc_numtag[tag] = 0;
42 } else {
43 udelay(100);
44 num++;
45 if (num < mcc_timeout)
46 goto mcc_tag_rdy;
47 }
48 if (tag) {
49 phba->ctrl.mcc_tag_available--;
50 if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1))
51 phba->ctrl.mcc_alloc_index = 0;
52 else
53 phba->ctrl.mcc_alloc_index++;
54 }
55 return tag;
56}
57
58void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag)
59{
60 spin_lock(&ctrl->mbox_lock);
61 tag = tag & 0x000000FF;
62 ctrl->mcc_tag[ctrl->mcc_free_index] = tag;
63 if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1))
64 ctrl->mcc_free_index = 0;
65 else
66 ctrl->mcc_free_index++;
67 ctrl->mcc_tag_available++;
68 spin_unlock(&ctrl->mbox_lock);
69}
70
71bool is_link_state_evt(u32 trailer)
72{
73 return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
74 ASYNC_TRAILER_EVENT_CODE_MASK) ==
75 ASYNC_EVENT_CODE_LINK_STATE);
76}
77
32static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) 78static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
33{ 79{
34 if (compl->flags != 0) { 80 if (compl->flags != 0) {
@@ -64,12 +110,30 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
64 return 0; 110 return 0;
65} 111}
66 112
67 113int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl,
68static inline bool is_link_state_evt(u32 trailer) 114 struct be_mcc_compl *compl)
69{ 115{
70 return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & 116 u16 compl_status, extd_status;
71 ASYNC_TRAILER_EVENT_CODE_MASK) == 117 unsigned short tag;
72 ASYNC_EVENT_CODE_LINK_STATE); 118
119 be_dws_le_to_cpu(compl, 4);
120
121 compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
122 CQE_STATUS_COMPL_MASK;
123 /* The ctrl.mcc_numtag[tag] is filled with
124 * [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status,
125 * [7:0] = compl_status
126 */
127 tag = (compl->tag0 & 0x000000FF);
128 extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
129 CQE_STATUS_EXTD_MASK;
130
131 ctrl->mcc_numtag[tag] = 0x80000000;
132 ctrl->mcc_numtag[tag] |= (compl->tag0 & 0x00FF0000);
133 ctrl->mcc_numtag[tag] |= (extd_status & 0x000000FF) << 8;
134 ctrl->mcc_numtag[tag] |= (compl_status & 0x000000FF);
135 wake_up_interruptible(&ctrl->mcc_wait[tag]);
136 return 0;
73} 137}
74 138
75static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) 139static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba)
@@ -89,7 +153,7 @@ static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session)
89 iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); 153 iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
90} 154}
91 155
92static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, 156void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
93 struct be_async_event_link_state *evt) 157 struct be_async_event_link_state *evt)
94{ 158{
95 switch (evt->port_link_status) { 159 switch (evt->port_link_status) {
@@ -97,13 +161,13 @@ static void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
97 SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d \n", 161 SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d \n",
98 evt->physical_port); 162 evt->physical_port);
99 phba->state |= BE_ADAPTER_LINK_DOWN; 163 phba->state |= BE_ADAPTER_LINK_DOWN;
164 iscsi_host_for_each_session(phba->shost,
165 be2iscsi_fail_session);
100 break; 166 break;
101 case ASYNC_EVENT_LINK_UP: 167 case ASYNC_EVENT_LINK_UP:
102 phba->state = BE_ADAPTER_UP; 168 phba->state = BE_ADAPTER_UP;
103 SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d \n", 169 SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d \n",
104 evt->physical_port); 170 evt->physical_port);
105 iscsi_host_for_each_session(phba->shost,
106 be2iscsi_fail_session);
107 break; 171 break;
108 default: 172 default:
109 SE_DEBUG(DBG_LVL_1, "Unexpected Async Notification %d on" 173 SE_DEBUG(DBG_LVL_1, "Unexpected Async Notification %d on"
@@ -162,7 +226,6 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
162/* Wait till no more pending mcc requests are present */ 226/* Wait till no more pending mcc requests are present */
163static int be_mcc_wait_compl(struct beiscsi_hba *phba) 227static int be_mcc_wait_compl(struct beiscsi_hba *phba)
164{ 228{
165#define mcc_timeout 120000 /* 5s timeout */
166 int i, status; 229 int i, status;
167 for (i = 0; i < mcc_timeout; i++) { 230 for (i = 0; i < mcc_timeout; i++) {
168 status = beiscsi_process_mcc(phba); 231 status = beiscsi_process_mcc(phba);
@@ -372,9 +435,10 @@ struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba)
372 435
373 BUG_ON(atomic_read(&mccq->used) >= mccq->len); 436 BUG_ON(atomic_read(&mccq->used) >= mccq->len);
374 wrb = queue_head_node(mccq); 437 wrb = queue_head_node(mccq);
438 memset(wrb, 0, sizeof(*wrb));
439 wrb->tag0 = (mccq->head & 0x000000FF) << 16;
375 queue_head_inc(mccq); 440 queue_head_inc(mccq);
376 atomic_inc(&mccq->used); 441 atomic_inc(&mccq->used);
377 memset(wrb, 0, sizeof(*wrb));
378 return wrb; 442 return wrb;
379} 443}
380 444