1 
2 
3 #include "lm5710.h"
4 #include "command.h"
5 #include "everest_l5cm_constants.h"
6 #include "lm_l5if.h"
7 
8 static lm_status_t lm_sc_post_init_request(
9     IN  struct _lm_device_t *pdev,
10     IN  lm_iscsi_state_t *iscsi,
11     IN  lm_iscsi_slow_path_request_t *sp_req,
12     OUT u8_t *command,
13     OUT u64_t *data)
14 {
15     DbgMessage(pdev, VERBOSEl5sp, "##lm__post_initiate_offload_request\n");
16     DbgBreakIf(iscsi->hdr.status != STATE_STATUS_INIT_CONTEXT);
17 
18     *command = ISCSI_RAMROD_CMD_ID_INIT;
19     *data = iscsi->ctx_phys.as_u64;
20 
21     return LM_STATUS_PENDING;
22 }
23 
24 
25 
26 static lm_status_t lm_sc_post_update_request(
27     IN  struct _lm_device_t *pdev,
28     IN  lm_iscsi_state_t *iscsi,
29     IN  lm_iscsi_slow_path_request_t *sp_req,
30     OUT u8_t *command,
31     OUT u64_t *data)
32 {
33     struct protocol_common_spe     spe       = {0};
34 
35     DbgMessage(pdev, VERBOSEl5sp, "##lm__post_initiate_offload_request\n");
36     DbgBreakIf(iscsi->hdr.status != STATE_STATUS_NORMAL);
37 
38     *command = ISCSI_RAMROD_CMD_ID_UPDATE_CONN;
39     spe.data.phy_address.hi = iscsi->sp_req_data.phys_addr.as_u32.high;
40     spe.data.phy_address.lo = iscsi->sp_req_data.phys_addr.as_u32.low;
41     *data = *((u64_t*)(&(spe.data.phy_address)));
42 
43     return LM_STATUS_PENDING;
44 }
45 
46 
47 
48 /* Desciption:
49  *  post slow path request of given type for given iscsi state
50  * Assumptions:
51  *  - caller initialized request->type according to his specific request
52  *  - caller allocated space for request->data, according to the specific request type
53  *  - all previous slow path requests for given tcp state are already completed
54  * Returns:
55  *  PENDING, SUCCESS or any failure */
56 lm_status_t lm_sc_post_slow_path_request(
57     IN  struct _lm_device_t *pdev,
58     IN  lm_iscsi_state_t *iscsi,
59     IN  lm_iscsi_slow_path_request_t *request)
60 {
61     lm_status_t lm_status = LM_STATUS_SUCCESS;
62     u64_t       data      = 0;
63     u8_t        command   = 0;
64 
65     DbgBreakIf(!(pdev && iscsi && request));
66     DbgMessage(pdev, VERBOSEl5sp, "### lm_sc_post_slow_path_request cid=%d, type=%d\n", iscsi->cid, request->type);
67 
68     switch (request->type)
69     {
70     /* NirV: called under lock, iscsi_state is being changed */
71     case SP_REQUEST_SC_INIT:
72         lm_status = lm_sc_post_init_request(pdev, iscsi, request, &command, &data);
73         break;
74 
75     case SP_REQUEST_SC_UPDATE:
76         lm_status = lm_sc_post_update_request(pdev, iscsi, request, &command, &data);
77         break;
78 
79     default:
80         lm_status = LM_STATUS_FAILURE;
81         DbgBreakMsg("Illegal slow path request type!\n");
82         break;
83     }
84 
85     if (lm_status == LM_STATUS_PENDING)
86     {
87         DbgMessage(pdev, VERBOSEl5sp,
88                    "calling lm_command_post, cid=%d, command=%d, con_type=%d, data=%lx\n",
89                    iscsi->cid, command, ISCSI_CONNECTION_TYPE, data);
90         lm_command_post(pdev, iscsi->cid, command, CMD_PRIORITY_NORMAL, ISCSI_CONNECTION_TYPE/*ulp*/, data);
91     }
92 
93     request->status = lm_status;
94     return lm_status;
95 }
96 
97 
98 
99 /* Desciption:
100  *  initiate a caller allocated lm iscsi state
101  * Assumptions:
102  *  - caller already zeroed given iscsi state
103  * Returns:
104  *  SUCCESS or any failure */
105 lm_status_t lm_sc_init_iscsi_state(
106     struct _lm_device_t *pdev,
107     lm_state_block_t *state_blk,
108     lm_iscsi_state_t *iscsi)
109 {
110     DbgMessage(pdev, VERBOSEl5sp, "###lm_sc_init_iscsi_state, ptr=%p\n", iscsi);
111     DbgBreakIf(!(pdev && state_blk && iscsi));
112 
113     iscsi->hdr.state_blk     = state_blk;
114     iscsi->hdr.state_id      = STATE_ID_UNKNOWN;
115     iscsi->hdr.status        = STATE_STATUS_INIT;
116     d_list_push_tail(&pdev->iscsi_info.run_time.iscsi_list, &iscsi->hdr.link);
117 
118     // NirV: sc: future statistics update
119 
120     /* the rest of the iscsi state's fields that require initialization value other than 0,
121      * will be initialized later (when lm_sc_init_iscsi_context is called) */
122 
123     return LM_STATUS_SUCCESS;
124 }
125 
126 
127 
128 /* Desciption:
129  *  delete iscsi state from lm _except_ from actual freeing of memory.
130  *  the task of freeing of memory is done in lm_sc_free_iscsi_state()
131  * Assumptions:
132  *  global toe lock is taken by the caller
133  */
134 void lm_sc_del_iscsi_state(
135     struct _lm_device_t *pdev,
136     lm_iscsi_state_t *iscsi)
137 {
138     u8_t notify_fw = 1;
139 
140     DbgMessage(pdev, VERBOSEl5sp, "###lm_sc_del_iscsi_state\n");
141     DbgBreakIf(!(pdev && iscsi));
142     DbgBreakIf(iscsi->hdr.status >= STATE_STATUS_OFFLOAD_PENDING &&
143                iscsi->hdr.status < STATE_STATUS_UPLOAD_DONE);
144 
145     /* just a moment before we delete this connection, lets take it's info... */
146     /*lm_tcp_collect_stats(pdev, tcp);*/
147 
148     d_list_remove_entry(
149         &pdev->iscsi_info.run_time.iscsi_list,
150         &iscsi->hdr.link);
151     /*pdev->iscsi_info.stats.total_upld++;*/
152 
153 
154   /* tcp->cid could have not been initialized if delete of state
155      is a result of a failed initialization */
156     DbgBreakIf(iscsi->hdr.status != STATE_STATUS_UPLOAD_DONE &&
157                iscsi->hdr.status != STATE_STATUS_INIT_OFFLOAD_ERR);
158 
159     if (iscsi->hdr.status == STATE_STATUS_INIT_OFFLOAD_ERR) {
160         notify_fw = 0;
161     }
162 
163     lm_free_cid_resc(pdev, ISCSI_CONNECTION_TYPE, iscsi->cid, notify_fw);
164 
165     iscsi->hdr.state_blk     = NULL;
166     iscsi->cid = 0;
167     iscsi->ctx_virt = NULL;
168     iscsi->ctx_phys.as_u64 = 0;
169 } /* lm_sc_del_iscsi_state */
170 
171 
172 /* clean up the lm_fcoe_state */
173 void
174 lm_fc_del_fcoe_state(
175     struct _lm_device_t             *pdev,
176     lm_fcoe_state_t                 *fcoe)
177 {
178     DbgMessage(pdev, VERBOSEl5sp, "###lm_fc_del_fcoe_state\n");
179     DbgBreakIf(!(pdev && fcoe));
180     /*
181     DbgBreakIf(fcoe->hdr.status >= STATE_STATUS_OFFLOAD_PENDING &&
182                fcoe->hdr.status < STATE_STATUS_UPLOAD_DONE);
183     */
184 
185     /* remove the lm_fcoe_state from the state list */
186     d_list_remove_entry(&pdev->fcoe_info.run_time.fcoe_list, &fcoe->hdr.link);
187 
188   /* tcp->cid could have not been initialized if delete of state
189      is a result of a failed initialization */
190 
191     /*
192     DbgBreakIf(fcoe->hdr.status != STATE_STATUS_UPLOAD_DONE &&
193                fcoe->hdr.status != STATE_STATUS_INIT_OFFLOAD_ERR);
194     */
195 } /* lm_fc_del_fcoe_state */
196 
197 
198 
199 lm_status_t
200 lm_fc_init_fcoe_state(
201     struct _lm_device_t             *pdev,
202     lm_state_block_t                *state_blk,
203     lm_fcoe_state_t                 *fcoe)
204 {
205     DbgMessage(pdev, VERBOSEl5sp, "###lm_fc_init_fcoe_state, ptr=%p\n", fcoe);
206     DbgBreakIf(!(pdev && state_blk && fcoe));
207 
208     fcoe->hdr.state_blk     = state_blk;
209     fcoe->hdr.state_id      = STATE_ID_UNKNOWN;
210     fcoe->hdr.status        = STATE_STATUS_INIT;
211     d_list_push_tail(&pdev->fcoe_info.run_time.fcoe_list, &fcoe->hdr.link);
212 
213     /* the rest of the fcoe state's fields that require initialization value other than 0,
214      * will be initialized later (when lm_fc_init_fcoe_context is called) */
215 
216     return LM_STATUS_SUCCESS;
217 }
218 
219 
220 
221 void lm_sc_init_sp_req_type(
222     struct _lm_device_t          * pdev,
223     lm_iscsi_state_t             * iscsi,
224     lm_iscsi_slow_path_request_t * lm_req,
225     void                         * req_input_data)
226 {
227     void *update_kwqe_virt;
228     struct protocol_common_spe spe = {0};
229 
230     switch(lm_req->type) {
231     case SP_REQUEST_SC_INIT:
232         break;
233     case SP_REQUEST_SC_UPDATE:
234 
235         spe.data.phy_address.hi = iscsi->sp_req_data.phys_addr.as_u32.high;
236         spe.data.phy_address.lo = iscsi->sp_req_data.phys_addr.as_u32.low;
237 
238         update_kwqe_virt = &iscsi->sp_req_data.virt_addr->update_ctx.kwqe;
239         mm_memcpy(update_kwqe_virt, req_input_data, sizeof(struct iscsi_kwqe_conn_update));
240 
241         break;
242     default:
243         DbgBreakMsg("lm_sc_init_sp_req_type: Illegal slow path request type!\n");
244     }
245 } /* lm_init_sp_req_type */
246