1*d14abf15SRobert Mustacchi /*******************************************************************************
2*d14abf15SRobert Mustacchi  * CDDL HEADER START
3*d14abf15SRobert Mustacchi  *
4*d14abf15SRobert Mustacchi  * The contents of this file are subject to the terms of the
5*d14abf15SRobert Mustacchi  * Common Development and Distribution License (the "License").
6*d14abf15SRobert Mustacchi  * You may not use this file except in compliance with the License.
7*d14abf15SRobert Mustacchi  *
8*d14abf15SRobert Mustacchi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d14abf15SRobert Mustacchi  * or http://www.opensolaris.org/os/licensing.
10*d14abf15SRobert Mustacchi  * See the License for the specific language governing permissions
11*d14abf15SRobert Mustacchi  * and limitations under the License.
12*d14abf15SRobert Mustacchi  *
13*d14abf15SRobert Mustacchi  * When distributing Covered Code, include this CDDL HEADER in each
14*d14abf15SRobert Mustacchi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d14abf15SRobert Mustacchi  * If applicable, add the following below this CDDL HEADER, with the
16*d14abf15SRobert Mustacchi  * fields enclosed by brackets "[]" replaced with your own identifying
17*d14abf15SRobert Mustacchi  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d14abf15SRobert Mustacchi  *
19*d14abf15SRobert Mustacchi  * CDDL HEADER END
20*d14abf15SRobert Mustacchi  *
21*d14abf15SRobert Mustacchi  * Copyright 2014 QLogic Corporation
22*d14abf15SRobert Mustacchi  * The contents of this file are subject to the terms of the
23*d14abf15SRobert Mustacchi  * QLogic End User License (the "License").
24*d14abf15SRobert Mustacchi  * You may not use this file except in compliance with the License.
25*d14abf15SRobert Mustacchi  *
26*d14abf15SRobert Mustacchi  * You can obtain a copy of the License at
27*d14abf15SRobert Mustacchi  * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
28*d14abf15SRobert Mustacchi  * QLogic_End_User_Software_License.txt
29*d14abf15SRobert Mustacchi  * See the License for the specific language governing permissions
30*d14abf15SRobert Mustacchi  * and limitations under the License.
31*d14abf15SRobert Mustacchi  *
32*d14abf15SRobert Mustacchi  *
33*d14abf15SRobert Mustacchi  * Module Description:
34*d14abf15SRobert Mustacchi  *
35*d14abf15SRobert Mustacchi  *
36*d14abf15SRobert Mustacchi  * History:
37*d14abf15SRobert Mustacchi  *    02/05/07 Alon Elhanani    Inception.
38*d14abf15SRobert Mustacchi  ******************************************************************************/
39*d14abf15SRobert Mustacchi 
40*d14abf15SRobert Mustacchi #include "lm5710.h"
41*d14abf15SRobert Mustacchi 
42*d14abf15SRobert Mustacchi 
43*d14abf15SRobert Mustacchi // converts index to DMAE command register name define
lm_dmae_idx_to_go_cmd(u8_t idx)44*d14abf15SRobert Mustacchi u32_t lm_dmae_idx_to_go_cmd( u8_t idx )
45*d14abf15SRobert Mustacchi {
46*d14abf15SRobert Mustacchi     u32_t ret = 0 ;
47*d14abf15SRobert Mustacchi     switch( idx )
48*d14abf15SRobert Mustacchi     {
49*d14abf15SRobert Mustacchi     case 0:  ret = DMAE_REG_GO_C0;  break;
50*d14abf15SRobert Mustacchi     case 1:  ret = DMAE_REG_GO_C1;  break;
51*d14abf15SRobert Mustacchi     case 2:  ret = DMAE_REG_GO_C2;  break;
52*d14abf15SRobert Mustacchi     case 3:  ret = DMAE_REG_GO_C3;  break;
53*d14abf15SRobert Mustacchi     case 4:  ret = DMAE_REG_GO_C4;  break;
54*d14abf15SRobert Mustacchi     case 5:  ret = DMAE_REG_GO_C5;  break;
55*d14abf15SRobert Mustacchi     case 6:  ret = DMAE_REG_GO_C6;  break;
56*d14abf15SRobert Mustacchi     case 7:  ret = DMAE_REG_GO_C7;  break;
57*d14abf15SRobert Mustacchi     case 8:  ret = DMAE_REG_GO_C8;  break;
58*d14abf15SRobert Mustacchi     case 9:  ret = DMAE_REG_GO_C9;  break;
59*d14abf15SRobert Mustacchi     case 10: ret = DMAE_REG_GO_C10; break;
60*d14abf15SRobert Mustacchi     case 11: ret = DMAE_REG_GO_C11; break;
61*d14abf15SRobert Mustacchi     case 12: ret = DMAE_REG_GO_C12; break;
62*d14abf15SRobert Mustacchi     case 13: ret = DMAE_REG_GO_C13; break;
63*d14abf15SRobert Mustacchi     case 14: ret = DMAE_REG_GO_C14; break;
64*d14abf15SRobert Mustacchi     case 15: ret = DMAE_REG_GO_C15; break;
65*d14abf15SRobert Mustacchi     default:
66*d14abf15SRobert Mustacchi         break;
67*d14abf15SRobert Mustacchi     }
68*d14abf15SRobert Mustacchi     return ret ;
69*d14abf15SRobert Mustacchi }
70*d14abf15SRobert Mustacchi 
71*d14abf15SRobert Mustacchi /**
72*d14abf15SRobert Mustacchi  * @defgroup LockingPolicy Locking Policy
73*d14abf15SRobert Mustacchi  * @{
74*d14abf15SRobert Mustacchi  */
75*d14abf15SRobert Mustacchi 
76*d14abf15SRobert Mustacchi /**lm_locking_policy_hwlock_id_for_resource
77*d14abf15SRobert Mustacchi  * Return the hwlock for some protected resource.
78*d14abf15SRobert Mustacchi  *
79*d14abf15SRobert Mustacchi  *
80*d14abf15SRobert Mustacchi  * @param resource the resource
81*d14abf15SRobert Mustacchi  *
82*d14abf15SRobert Mustacchi  * @return u8_t the hwlock for the given resource.
83*d14abf15SRobert Mustacchi  */
lm_dmae_locking_policy_hwlock_id_for_resource(struct _lm_device_t * pdev,IN const u32_t resource)84*d14abf15SRobert Mustacchi static u8_t lm_dmae_locking_policy_hwlock_id_for_resource(struct _lm_device_t* pdev, IN const u32_t resource)
85*d14abf15SRobert Mustacchi {
86*d14abf15SRobert Mustacchi     switch (resource)
87*d14abf15SRobert Mustacchi     {
88*d14abf15SRobert Mustacchi     case LM_PROTECTED_RESOURCE_DMAE_TOE:
89*d14abf15SRobert Mustacchi         {
90*d14abf15SRobert Mustacchi             return HW_LOCK_RESOURCE_PORT0_DMAE_COPY_CMD + PORT_ID(pdev);
91*d14abf15SRobert Mustacchi         }
92*d14abf15SRobert Mustacchi         break;
93*d14abf15SRobert Mustacchi     default:
94*d14abf15SRobert Mustacchi         {
95*d14abf15SRobert Mustacchi             DbgBreakMsg("HW lock for resource does not exist.\n");
96*d14abf15SRobert Mustacchi             return LM_DMAE_NO_HWLOCK;
97*d14abf15SRobert Mustacchi         }
98*d14abf15SRobert Mustacchi         break;
99*d14abf15SRobert Mustacchi     }
100*d14abf15SRobert Mustacchi }
101*d14abf15SRobert Mustacchi 
102*d14abf15SRobert Mustacchi 
lm_dmae_locking_policy_create(struct _lm_device_t * pdev,IN const u32_t resource,IN const lm_dmae_locking_policy_type_t type,OUT lm_dmae_locking_policy_t * policy)103*d14abf15SRobert Mustacchi lm_status_t lm_dmae_locking_policy_create(  struct _lm_device_t* pdev,
104*d14abf15SRobert Mustacchi                                             IN const u32_t resource,
105*d14abf15SRobert Mustacchi                                             IN const lm_dmae_locking_policy_type_t type,
106*d14abf15SRobert Mustacchi                                             OUT lm_dmae_locking_policy_t* policy)
107*d14abf15SRobert Mustacchi {
108*d14abf15SRobert Mustacchi     mm_mem_zero(policy, sizeof(lm_dmae_locking_policy_t));
109*d14abf15SRobert Mustacchi 
110*d14abf15SRobert Mustacchi     if (type > LM_DMAE_LOCKING_POLICY_TYPE_NONE)
111*d14abf15SRobert Mustacchi     {
112*d14abf15SRobert Mustacchi         mm_init_lock(pdev, &policy->spinlock);
113*d14abf15SRobert Mustacchi     }
114*d14abf15SRobert Mustacchi 
115*d14abf15SRobert Mustacchi     if (type == LM_DMAE_LOCKING_POLICY_TYPE_INTER_PF)
116*d14abf15SRobert Mustacchi     {
117*d14abf15SRobert Mustacchi         policy->hwlock = lm_dmae_locking_policy_hwlock_id_for_resource(pdev, resource);
118*d14abf15SRobert Mustacchi     }
119*d14abf15SRobert Mustacchi 
120*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
121*d14abf15SRobert Mustacchi }
122*d14abf15SRobert Mustacchi 
123*d14abf15SRobert Mustacchi #ifdef _VBD_
124*d14abf15SRobert Mustacchi /*28158 is 'No IRQL was saved into '_Param_(2)->spinlock.irql'. The IRQL is saved by the call to mm_acquire_lock.*/
125*d14abf15SRobert Mustacchi #pragma warning(push)
126*d14abf15SRobert Mustacchi #pragma warning(disable:28158)
127*d14abf15SRobert Mustacchi 
128*d14abf15SRobert Mustacchi __drv_maxIRQL(DISPATCH_LEVEL)
129*d14abf15SRobert Mustacchi __drv_at(context->locking_policy->spinlock.irql, __drv_savesIRQL)
__drv_setsIRQL(DISPATCH_LEVEL)130*d14abf15SRobert Mustacchi __drv_setsIRQL(DISPATCH_LEVEL)
131*d14abf15SRobert Mustacchi #endif
132*d14abf15SRobert Mustacchi lm_status_t lm_dmae_locking_policy_lock(struct _lm_device_t* pdev, lm_dmae_locking_policy_t* locking_policy)
133*d14abf15SRobert Mustacchi {
134*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_SUCCESS;
135*d14abf15SRobert Mustacchi 
136*d14abf15SRobert Mustacchi     lm_status = mm_acquire_lock(&locking_policy->spinlock);
137*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
138*d14abf15SRobert Mustacchi     {
139*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire spinlock.\n");
140*d14abf15SRobert Mustacchi         return lm_status;
141*d14abf15SRobert Mustacchi     }
142*d14abf15SRobert Mustacchi 
143*d14abf15SRobert Mustacchi     if (LM_DMAE_NO_HWLOCK != locking_policy->hwlock)
144*d14abf15SRobert Mustacchi     {
145*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, locking_policy->hwlock, TRUE);
146*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS != lm_status)
147*d14abf15SRobert Mustacchi         {
148*d14abf15SRobert Mustacchi             DbgBreakMsg("Failed to acquire HW lock.\n");
149*d14abf15SRobert Mustacchi 
150*d14abf15SRobert Mustacchi             lm_status = mm_release_lock(&locking_policy->spinlock);
151*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
152*d14abf15SRobert Mustacchi             {
153*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to roll-back after locking failure.\n");
154*d14abf15SRobert Mustacchi                 return lm_status;
155*d14abf15SRobert Mustacchi             }
156*d14abf15SRobert Mustacchi 
157*d14abf15SRobert Mustacchi             return lm_status;
158*d14abf15SRobert Mustacchi         }
159*d14abf15SRobert Mustacchi     }
160*d14abf15SRobert Mustacchi 
161*d14abf15SRobert Mustacchi     return lm_status;
162*d14abf15SRobert Mustacchi }
163*d14abf15SRobert Mustacchi #ifdef _VBD_
164*d14abf15SRobert Mustacchi #pragma warning(pop)
165*d14abf15SRobert Mustacchi 
166*d14abf15SRobert Mustacchi /*28157 is 'The IRQL in '_Param_(2)->spinlock.irql' was never restored'. The IRQL is restored by the call to mm_release_lock.*/
167*d14abf15SRobert Mustacchi #pragma warning(push)
168*d14abf15SRobert Mustacchi #pragma warning(disable:28157)
169*d14abf15SRobert Mustacchi #if defined(NTDDI_WIN8)
170*d14abf15SRobert Mustacchi _IRQL_requires_(DISPATCH_LEVEL)
171*d14abf15SRobert Mustacchi __drv_at(context->locking_policy->spinlock.irql, __drv_restoresIRQL )
172*d14abf15SRobert Mustacchi #endif
173*d14abf15SRobert Mustacchi #endif
lm_dmae_locking_policy_unlock(struct _lm_device_t * pdev,lm_dmae_locking_policy_t * locking_policy)174*d14abf15SRobert Mustacchi lm_status_t lm_dmae_locking_policy_unlock(struct _lm_device_t* pdev, lm_dmae_locking_policy_t* locking_policy)
175*d14abf15SRobert Mustacchi {
176*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_SUCCESS;
177*d14abf15SRobert Mustacchi 
178*d14abf15SRobert Mustacchi     if (LM_DMAE_NO_HWLOCK != locking_policy->hwlock)
179*d14abf15SRobert Mustacchi     {
180*d14abf15SRobert Mustacchi         lm_status = lm_hw_unlock(pdev, locking_policy->hwlock);
181*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS != lm_status)
182*d14abf15SRobert Mustacchi         {
183*d14abf15SRobert Mustacchi             DbgBreakMsg("Failed to release HW lock.\n");
184*d14abf15SRobert Mustacchi             return lm_status;
185*d14abf15SRobert Mustacchi         }
186*d14abf15SRobert Mustacchi     }
187*d14abf15SRobert Mustacchi 
188*d14abf15SRobert Mustacchi     lm_status = mm_release_lock(&locking_policy->spinlock);
189*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
190*d14abf15SRobert Mustacchi     {
191*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to release spinlock.\n");
192*d14abf15SRobert Mustacchi 
193*d14abf15SRobert Mustacchi         if (LM_DMAE_NO_HWLOCK != locking_policy->hwlock)
194*d14abf15SRobert Mustacchi         {
195*d14abf15SRobert Mustacchi             //try to re-acquire the HW lock, so at least we'll be in a consistent state.
196*d14abf15SRobert Mustacchi             lm_status = lm_hw_lock(pdev, locking_policy->hwlock, TRUE);
197*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
198*d14abf15SRobert Mustacchi             {
199*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to roll-back after release failure.\n"); //This is a double-fault. Don't try to recover.
200*d14abf15SRobert Mustacchi                 return lm_status;
201*d14abf15SRobert Mustacchi             }
202*d14abf15SRobert Mustacchi         }
203*d14abf15SRobert Mustacchi 
204*d14abf15SRobert Mustacchi         return lm_status;
205*d14abf15SRobert Mustacchi     }
206*d14abf15SRobert Mustacchi 
207*d14abf15SRobert Mustacchi 
208*d14abf15SRobert Mustacchi     return lm_status;
209*d14abf15SRobert Mustacchi }
210*d14abf15SRobert Mustacchi 
211*d14abf15SRobert Mustacchi 
212*d14abf15SRobert Mustacchi #ifdef _VBD_
213*d14abf15SRobert Mustacchi #pragma warning(pop)
214*d14abf15SRobert Mustacchi #endif
215*d14abf15SRobert Mustacchi /**
216*d14abf15SRobert Mustacchi  * @}
217*d14abf15SRobert Mustacchi  */
218*d14abf15SRobert Mustacchi 
219*d14abf15SRobert Mustacchi /**
220*d14abf15SRobert Mustacchi  * @defgroup DMAE_Operation DMAE operation
221*d14abf15SRobert Mustacchi  * @{
222*d14abf15SRobert Mustacchi  */
223*d14abf15SRobert Mustacchi 
224*d14abf15SRobert Mustacchi /**lm_dmae_opcode
225*d14abf15SRobert Mustacchi  * Construct a DMAE command opcode according to HSI and given
226*d14abf15SRobert Mustacchi  * parameters.
227*d14abf15SRobert Mustacchi  *
228*d14abf15SRobert Mustacchi  *
229*d14abf15SRobert Mustacchi  * @param pdev the device to use
230*d14abf15SRobert Mustacchi  * @param source the source of the operation
231*d14abf15SRobert Mustacchi  * @param dest the destination of the operation
232*d14abf15SRobert Mustacchi  * @param b_complete_to_host TRUE if the completion value of the
233*d14abf15SRobert Mustacchi  *                           operation whould be written to host
234*d14abf15SRobert Mustacchi  *                           memory, FALSE if to GRC.
235*d14abf15SRobert Mustacchi  * @param b_resume_prev TRUE if this operation should resume a
236*d14abf15SRobert Mustacchi  *                      previous operation, FALSE if the source
237*d14abf15SRobert Mustacchi  *                      address should be used.
238*d14abf15SRobert Mustacchi  * @param b_change_endianity TRUE if the operation should
239*d14abf15SRobert Mustacchi  *                           byte-swap its data
240*d14abf15SRobert Mustacchi  *
241*d14abf15SRobert Mustacchi  * @return u32_t an opcode according to HSI rules.
242*d14abf15SRobert Mustacchi  */
243*d14abf15SRobert Mustacchi static u32_t
lm_dmae_opcode(struct _lm_device_t * pdev,IN const lm_dmae_address_t source,IN const lm_dmae_address_t dest,IN const u8_t b_complete_to_host,IN const u8_t b_resume_prev,IN const u8_t b_change_endianity)244*d14abf15SRobert Mustacchi lm_dmae_opcode( struct _lm_device_t* pdev,
245*d14abf15SRobert Mustacchi                 IN const lm_dmae_address_t source,
246*d14abf15SRobert Mustacchi                 IN const lm_dmae_address_t dest,
247*d14abf15SRobert Mustacchi                 IN const u8_t b_complete_to_host,
248*d14abf15SRobert Mustacchi                 IN const u8_t b_resume_prev,
249*d14abf15SRobert Mustacchi                 IN const u8_t b_change_endianity)
250*d14abf15SRobert Mustacchi {
251*d14abf15SRobert Mustacchi     u32_t opcode = 0;
252*d14abf15SRobert Mustacchi 
253*d14abf15SRobert Mustacchi     opcode |= ((source.type == LM_DMAE_ADDRESS_GRC)?1:0) <<DMAE_CMD_SRC_SHIFT;
254*d14abf15SRobert Mustacchi     opcode |= ((dest.type == LM_DMAE_ADDRESS_GRC)?2:1) <<DMAE_CMD_DST_SHIFT;
255*d14abf15SRobert Mustacchi     opcode |= (!b_complete_to_host)<< DMAE_CMD_C_DST_SHIFT;
256*d14abf15SRobert Mustacchi     opcode |= 1 << DMAE_CMD_C_TYPE_ENABLE_SHIFT;
257*d14abf15SRobert Mustacchi     opcode |= 0 << DMAE_CMD_C_TYPE_CRC_ENABLE_SHIFT;
258*d14abf15SRobert Mustacchi     opcode |= (b_change_endianity ? 3:2)<<DMAE_CMD_ENDIANITY_SHIFT;
259*d14abf15SRobert Mustacchi     opcode |=  PORT_ID(pdev) << DMAE_CMD_PORT_SHIFT;
260*d14abf15SRobert Mustacchi     opcode |= 0 << DMAE_CMD_CRC_RESET_SHIFT ;
261*d14abf15SRobert Mustacchi     opcode |= (!b_resume_prev) << DMAE_CMD_SRC_RESET_SHIFT;
262*d14abf15SRobert Mustacchi     opcode |= 1 << DMAE_CMD_DST_RESET_SHIFT;
263*d14abf15SRobert Mustacchi     opcode |= VNIC_ID(pdev) << DMAE_CMD_E1HVN_SHIFT;
264*d14abf15SRobert Mustacchi 
265*d14abf15SRobert Mustacchi     return opcode;
266*d14abf15SRobert Mustacchi }
267*d14abf15SRobert Mustacchi 
268*d14abf15SRobert Mustacchi /**lm_dmae_command_set_block
269*d14abf15SRobert Mustacchi  * Set the source, destination and length of a DMAE command HSI
270*d14abf15SRobert Mustacchi  * structure.
271*d14abf15SRobert Mustacchi  *
272*d14abf15SRobert Mustacchi  *
273*d14abf15SRobert Mustacchi  * @param pdev the device to use
274*d14abf15SRobert Mustacchi  * @param command the command to initialize
275*d14abf15SRobert Mustacchi  * @param source the source of the operation
276*d14abf15SRobert Mustacchi  * @param dest the destination of the operation
277*d14abf15SRobert Mustacchi  * @param length the length, in DWORDS, of the operation
278*d14abf15SRobert Mustacchi  */
279*d14abf15SRobert Mustacchi static void
lm_dmae_command_set_block(struct _lm_device_t * pdev,struct dmae_cmd * command,IN const lm_dmae_address_t source,IN const lm_dmae_address_t dest,IN const u16_t length)280*d14abf15SRobert Mustacchi lm_dmae_command_set_block(  struct _lm_device_t* pdev,
281*d14abf15SRobert Mustacchi                             struct dmae_cmd* command,
282*d14abf15SRobert Mustacchi                             IN const lm_dmae_address_t source,
283*d14abf15SRobert Mustacchi                             IN const lm_dmae_address_t dest,
284*d14abf15SRobert Mustacchi                             IN const u16_t length/*in DWORDS*/)
285*d14abf15SRobert Mustacchi {
286*d14abf15SRobert Mustacchi     u64_t source_offset = lm_dmae_address_native_offset(&source);
287*d14abf15SRobert Mustacchi     u64_t dest_offset = lm_dmae_address_native_offset(&dest);
288*d14abf15SRobert Mustacchi 
289*d14abf15SRobert Mustacchi     command->src_addr_hi = U64_HI(source_offset);
290*d14abf15SRobert Mustacchi     command->src_addr_lo = U64_LO(source_offset);
291*d14abf15SRobert Mustacchi 
292*d14abf15SRobert Mustacchi     command->dst_addr_hi = U64_HI(dest_offset);
293*d14abf15SRobert Mustacchi     command->dst_addr_lo = U64_LO(dest_offset);
294*d14abf15SRobert Mustacchi 
295*d14abf15SRobert Mustacchi     command->len = length;
296*d14abf15SRobert Mustacchi }
297*d14abf15SRobert Mustacchi 
298*d14abf15SRobert Mustacchi 
299*d14abf15SRobert Mustacchi /**lm_dmae_initialize_command_by_block
300*d14abf15SRobert Mustacchi  * Initialize an HSI DMAE command struct according to a driver
301*d14abf15SRobert Mustacchi  * DMAE block data structure.
302*d14abf15SRobert Mustacchi  *
303*d14abf15SRobert Mustacchi  * @param pdev the device to use
304*d14abf15SRobert Mustacchi  * @param context the context of the operation
305*d14abf15SRobert Mustacchi  * @param command the command to initialize
306*d14abf15SRobert Mustacchi  * @param block the DMAE block according to which the command
307*d14abf15SRobert Mustacchi  *              will be initialized
308*d14abf15SRobert Mustacchi  * @param completion_value the completion value that should be
309*d14abf15SRobert Mustacchi  *                         written to the context's completion
310*d14abf15SRobert Mustacchi  *                         word when this command completes.
311*d14abf15SRobert Mustacchi  *
312*d14abf15SRobert Mustacchi  * @return lm_status_t LM_STATUS_SUCCESS on success, some other
313*d14abf15SRobert Mustacchi  *         failure value on failure.
314*d14abf15SRobert Mustacchi  */
315*d14abf15SRobert Mustacchi static lm_status_t
lm_dmae_initialize_command_by_block(struct _lm_device_t * pdev,lm_dmae_context_t * context,struct dmae_cmd * command,IN lm_dmae_block_t * block,IN const u32_t completion_value)316*d14abf15SRobert Mustacchi lm_dmae_initialize_command_by_block(struct _lm_device_t* pdev,
317*d14abf15SRobert Mustacchi                                     lm_dmae_context_t* context,
318*d14abf15SRobert Mustacchi                                     struct dmae_cmd* command,
319*d14abf15SRobert Mustacchi                                     IN lm_dmae_block_t* block,
320*d14abf15SRobert Mustacchi                                     IN const u32_t completion_value)
321*d14abf15SRobert Mustacchi {
322*d14abf15SRobert Mustacchi     command->opcode = lm_dmae_opcode(pdev, block->source, block->dest, TRUE, FALSE, context->change_endianity);
323*d14abf15SRobert Mustacchi 
324*d14abf15SRobert Mustacchi     lm_dmae_command_set_block(pdev, command, block->source, block->dest, block->length);
325*d14abf15SRobert Mustacchi 
326*d14abf15SRobert Mustacchi     command->comp_addr_hi = context->completion_word_paddr.as_u32.high;
327*d14abf15SRobert Mustacchi     command->comp_addr_lo = context->completion_word_paddr.as_u32.low;
328*d14abf15SRobert Mustacchi 
329*d14abf15SRobert Mustacchi     command->comp_val = completion_value;
330*d14abf15SRobert Mustacchi 
331*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
332*d14abf15SRobert Mustacchi }
333*d14abf15SRobert Mustacchi 
lm_dmae_operation_create(struct _lm_device_t * pdev,IN const lm_dmae_address_t source,IN const lm_dmae_address_t dest,IN const u16_t length,IN const u8_t replicate_source,IN const u8_t le32_swap,IN lm_dmae_context_t * context,OUT lm_dmae_operation_t * operation)334*d14abf15SRobert Mustacchi lm_status_t lm_dmae_operation_create(   struct _lm_device_t* pdev,
335*d14abf15SRobert Mustacchi                                         IN const lm_dmae_address_t source,
336*d14abf15SRobert Mustacchi                                         IN const lm_dmae_address_t dest,
337*d14abf15SRobert Mustacchi                                         IN const u16_t length,
338*d14abf15SRobert Mustacchi                                         IN const u8_t replicate_source,
339*d14abf15SRobert Mustacchi                                         IN const u8_t le32_swap,
340*d14abf15SRobert Mustacchi                                         IN lm_dmae_context_t* context,
341*d14abf15SRobert Mustacchi                                         OUT lm_dmae_operation_t* operation)
342*d14abf15SRobert Mustacchi {
343*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
344*d14abf15SRobert Mustacchi 
345*d14abf15SRobert Mustacchi     DbgBreakIf(LM_DMAE_MODE_SINGLE_BLOCK != context->mode);
346*d14abf15SRobert Mustacchi     DbgBreakIf(0 == context->completion_word_paddr.as_u64);
347*d14abf15SRobert Mustacchi 
348*d14abf15SRobert Mustacchi     if( (LM_DMAE_ADDRESS_HOST_VIRT == source.type) && (LM_DMAE_ADDRESS_HOST_VIRT == dest.type) )
349*d14abf15SRobert Mustacchi     {
350*d14abf15SRobert Mustacchi         DbgBreakMsg("the intermediate buffer can be used for source or destination but not both.\n");
351*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
352*d14abf15SRobert Mustacchi     }
353*d14abf15SRobert Mustacchi 
354*d14abf15SRobert Mustacchi     mm_mem_zero(operation, sizeof(lm_dmae_operation_t));
355*d14abf15SRobert Mustacchi 
356*d14abf15SRobert Mustacchi     operation->mode = LM_DMAE_MODE_SINGLE_BLOCK;
357*d14abf15SRobert Mustacchi     operation->b_replicate_source = replicate_source;
358*d14abf15SRobert Mustacchi     operation->le32_swap = le32_swap;
359*d14abf15SRobert Mustacchi     operation->context = context;
360*d14abf15SRobert Mustacchi     operation->b_sync = TRUE;
361*d14abf15SRobert Mustacchi 
362*d14abf15SRobert Mustacchi     operation->blocks[0].source = source;
363*d14abf15SRobert Mustacchi     operation->blocks[0].dest = dest;
364*d14abf15SRobert Mustacchi     operation->blocks[0].length = length;
365*d14abf15SRobert Mustacchi 
366*d14abf15SRobert Mustacchi     lm_status = lm_dmae_initialize_command_by_block(pdev,
367*d14abf15SRobert Mustacchi                                                     operation->context,
368*d14abf15SRobert Mustacchi                                                     &operation->main_cmd,
369*d14abf15SRobert Mustacchi                                                     &operation->blocks[0],
370*d14abf15SRobert Mustacchi                                                     DMAE_COMPLETION_VAL);
371*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
372*d14abf15SRobert Mustacchi     {
373*d14abf15SRobert Mustacchi         return lm_status;
374*d14abf15SRobert Mustacchi     }
375*d14abf15SRobert Mustacchi 
376*d14abf15SRobert Mustacchi     return lm_status;
377*d14abf15SRobert Mustacchi }
378*d14abf15SRobert Mustacchi 
379*d14abf15SRobert Mustacchi /**lm_dmae_initialize_sgl_loader_command
380*d14abf15SRobert Mustacchi  * Initialize the DMAE command HSI struct for an SGL loader
381*d14abf15SRobert Mustacchi  * command.
382*d14abf15SRobert Mustacchi  *
383*d14abf15SRobert Mustacchi  * @param pdev the device to use
384*d14abf15SRobert Mustacchi  * @param operation the operation which the command is a part of
385*d14abf15SRobert Mustacchi  * @param command the command to initialize
386*d14abf15SRobert Mustacchi  *
387*d14abf15SRobert Mustacchi  * @return lm_status_t LM_STATUS_SUCCESS on success, some other
388*d14abf15SRobert Mustacchi  *         failure value on failure.
389*d14abf15SRobert Mustacchi  */
390*d14abf15SRobert Mustacchi static lm_status_t
lm_dmae_initialize_sgl_loader_command(struct _lm_device_t * pdev,lm_dmae_operation_t * operation,struct dmae_cmd * command)391*d14abf15SRobert Mustacchi lm_dmae_initialize_sgl_loader_command(  struct _lm_device_t* pdev,
392*d14abf15SRobert Mustacchi                                         lm_dmae_operation_t* operation,
393*d14abf15SRobert Mustacchi                                         struct dmae_cmd* command)
394*d14abf15SRobert Mustacchi {
395*d14abf15SRobert Mustacchi     lm_dmae_address_t source = lm_dmae_address( operation->executer_paddr.as_u64 ,LM_DMAE_ADDRESS_HOST_PHYS);
396*d14abf15SRobert Mustacchi     lm_dmae_address_t dest = lm_dmae_address(   DMAE_REG_CMD_MEM + operation->context->executer_channel*DMAE_CMD_SIZE*sizeof(u32_t),
397*d14abf15SRobert Mustacchi                                                 LM_DMAE_ADDRESS_GRC);
398*d14abf15SRobert Mustacchi 
399*d14abf15SRobert Mustacchi 
400*d14abf15SRobert Mustacchi     command->opcode = lm_dmae_opcode(pdev, source, dest, FALSE, TRUE, operation->context->change_endianity);
401*d14abf15SRobert Mustacchi 
402*d14abf15SRobert Mustacchi     lm_dmae_command_set_block(pdev, command, source, dest, sizeof(struct dmae_cmd) / sizeof(u32_t));
403*d14abf15SRobert Mustacchi 
404*d14abf15SRobert Mustacchi     // Special handling for E1 HW DMAE operation: we give here the size we are writing MINUS 1,
405*d14abf15SRobert Mustacchi     // since when 'no reset' is on (src address is 0 ), the DMAE advance pointer by
406*d14abf15SRobert Mustacchi     // length + 1, so in order to comply, we send length-1
407*d14abf15SRobert Mustacchi     // when relevant data struct we send is not bigger than lnegth-1,
408*d14abf15SRobert Mustacchi     // in this specific case, we send struct size 14 when relevant data is 9
409*d14abf15SRobert Mustacchi     // so even when we send 13 as length, it's ok, since we copy 13, 9 is intersting
410*d14abf15SRobert Mustacchi     // and next time DMAE will read from +14 which is good for us
411*d14abf15SRobert Mustacchi     if( CHIP_IS_E1(pdev) )
412*d14abf15SRobert Mustacchi     {
413*d14abf15SRobert Mustacchi         --command->len;
414*d14abf15SRobert Mustacchi     }
415*d14abf15SRobert Mustacchi 
416*d14abf15SRobert Mustacchi 
417*d14abf15SRobert Mustacchi     command->comp_addr_lo =  lm_dmae_idx_to_go_cmd(operation->context->executer_channel)  / 4;
418*d14abf15SRobert Mustacchi     command->comp_addr_hi = 0;
419*d14abf15SRobert Mustacchi 
420*d14abf15SRobert Mustacchi     command->comp_val = DMAE_GO_VALUE;
421*d14abf15SRobert Mustacchi 
422*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
423*d14abf15SRobert Mustacchi }
424*d14abf15SRobert Mustacchi 
lm_dmae_operation_create_sgl(struct _lm_device_t * pdev,IN const u8_t b_sync,IN lm_dmae_context_t * context)425*d14abf15SRobert Mustacchi lm_dmae_operation_t* lm_dmae_operation_create_sgl(  struct _lm_device_t* pdev,
426*d14abf15SRobert Mustacchi                                                     IN const u8_t b_sync,
427*d14abf15SRobert Mustacchi                                                     IN lm_dmae_context_t* context)
428*d14abf15SRobert Mustacchi {
429*d14abf15SRobert Mustacchi     lm_dmae_operation_t* operation = NULL;
430*d14abf15SRobert Mustacchi     lm_address_t operation_phys_addr = {{0}};
431*d14abf15SRobert Mustacchi     lm_address_t executer_phys_addr = {{0}};
432*d14abf15SRobert Mustacchi 
433*d14abf15SRobert Mustacchi     DbgBreakIf(LM_DMAE_MODE_SGL != context->mode);
434*d14abf15SRobert Mustacchi     DbgBreakIf(0 == context->completion_word_paddr.as_u64);
435*d14abf15SRobert Mustacchi 
436*d14abf15SRobert Mustacchi     operation = mm_alloc_phys_mem(pdev, sizeof(lm_dmae_operation_t), &operation_phys_addr, PHYS_MEM_TYPE_NONCACHED, LM_RESOURCE_COMMON);
437*d14abf15SRobert Mustacchi 
438*d14abf15SRobert Mustacchi     if (CHK_NULL(operation))
439*d14abf15SRobert Mustacchi     {
440*d14abf15SRobert Mustacchi         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
441*d14abf15SRobert Mustacchi         return NULL;
442*d14abf15SRobert Mustacchi     }
443*d14abf15SRobert Mustacchi 
444*d14abf15SRobert Mustacchi     mm_mem_zero(operation, sizeof(lm_dmae_operation_t));
445*d14abf15SRobert Mustacchi 
446*d14abf15SRobert Mustacchi     operation->mode = LM_DMAE_MODE_SGL;
447*d14abf15SRobert Mustacchi     operation->context = context;
448*d14abf15SRobert Mustacchi     operation->b_sync = b_sync;
449*d14abf15SRobert Mustacchi 
450*d14abf15SRobert Mustacchi     executer_phys_addr = operation_phys_addr;
451*d14abf15SRobert Mustacchi     LM_INC64(&executer_phys_addr, OFFSETOF(lm_dmae_operation_t, executer_cmd[0]));
452*d14abf15SRobert Mustacchi     operation->executer_paddr = executer_phys_addr;
453*d14abf15SRobert Mustacchi 
454*d14abf15SRobert Mustacchi     lm_dmae_initialize_sgl_loader_command(pdev, operation, &operation->main_cmd);
455*d14abf15SRobert Mustacchi     return operation;
456*d14abf15SRobert Mustacchi }
457*d14abf15SRobert Mustacchi 
lm_dmae_operation_add_sge(struct _lm_device_t * pdev,lm_dmae_operation_t * operation,IN const lm_dmae_address_t source,IN const lm_dmae_address_t dest,IN const u16_t length)458*d14abf15SRobert Mustacchi lm_status_t lm_dmae_operation_add_sge(  struct _lm_device_t* pdev,
459*d14abf15SRobert Mustacchi                                         lm_dmae_operation_t* operation,
460*d14abf15SRobert Mustacchi                                         IN const lm_dmae_address_t source,
461*d14abf15SRobert Mustacchi                                         IN const lm_dmae_address_t dest,
462*d14abf15SRobert Mustacchi                                         IN const u16_t length)
463*d14abf15SRobert Mustacchi {
464*d14abf15SRobert Mustacchi     u8_t last_sge_idx = 0;
465*d14abf15SRobert Mustacchi     u8_t new_sge_idx = 0;
466*d14abf15SRobert Mustacchi     struct dmae_cmd* last_sge = NULL;
467*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
468*d14abf15SRobert Mustacchi 
469*d14abf15SRobert Mustacchi     if( (LM_DMAE_ADDRESS_HOST_VIRT == source.type) && (LM_DMAE_ADDRESS_HOST_VIRT == dest.type) )
470*d14abf15SRobert Mustacchi     {
471*d14abf15SRobert Mustacchi         DbgBreakMsg("the intermediate buffer can be used for source or destination but not both.\n");
472*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
473*d14abf15SRobert Mustacchi     }
474*d14abf15SRobert Mustacchi 
475*d14abf15SRobert Mustacchi     new_sge_idx = operation->next_free_block;
476*d14abf15SRobert Mustacchi 
477*d14abf15SRobert Mustacchi     if (new_sge_idx >= ARRSIZE(operation->blocks))
478*d14abf15SRobert Mustacchi     {
479*d14abf15SRobert Mustacchi         DbgBreakMsg("Too many SGEs in DMAE operation");
480*d14abf15SRobert Mustacchi         return LM_STATUS_INVALID_PARAMETER;
481*d14abf15SRobert Mustacchi     }
482*d14abf15SRobert Mustacchi 
483*d14abf15SRobert Mustacchi     if (0 != operation->next_free_block)
484*d14abf15SRobert Mustacchi     {
485*d14abf15SRobert Mustacchi         last_sge_idx = operation->next_free_block-1;
486*d14abf15SRobert Mustacchi         last_sge = &operation->executer_cmd[last_sge_idx];
487*d14abf15SRobert Mustacchi 
488*d14abf15SRobert Mustacchi         SET_FLAGS(last_sge->opcode, 1<<DMAE_CMD_C_DST_SHIFT);
489*d14abf15SRobert Mustacchi 
490*d14abf15SRobert Mustacchi         last_sge->comp_addr_lo = lm_dmae_idx_to_go_cmd(operation->context->main_channel) / 4;
491*d14abf15SRobert Mustacchi         last_sge->comp_addr_hi = 0;
492*d14abf15SRobert Mustacchi 
493*d14abf15SRobert Mustacchi         last_sge->comp_val = DMAE_GO_VALUE;
494*d14abf15SRobert Mustacchi     }
495*d14abf15SRobert Mustacchi 
496*d14abf15SRobert Mustacchi     operation->blocks[new_sge_idx].source = source;
497*d14abf15SRobert Mustacchi     operation->blocks[new_sge_idx].dest = dest;
498*d14abf15SRobert Mustacchi     operation->blocks[new_sge_idx].length = length;
499*d14abf15SRobert Mustacchi 
500*d14abf15SRobert Mustacchi     lm_status = lm_dmae_initialize_command_by_block(pdev,
501*d14abf15SRobert Mustacchi                                                     operation->context,
502*d14abf15SRobert Mustacchi                                                     &operation->executer_cmd[new_sge_idx],
503*d14abf15SRobert Mustacchi                                                     &operation->blocks[new_sge_idx],
504*d14abf15SRobert Mustacchi                                                     DMAE_SGL_COMPLETION_VAL);
505*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
506*d14abf15SRobert Mustacchi     {
507*d14abf15SRobert Mustacchi         return lm_status;
508*d14abf15SRobert Mustacchi     }
509*d14abf15SRobert Mustacchi 
510*d14abf15SRobert Mustacchi     operation->next_free_block++;
511*d14abf15SRobert Mustacchi 
512*d14abf15SRobert Mustacchi     return lm_status;
513*d14abf15SRobert Mustacchi }
514*d14abf15SRobert Mustacchi 
lm_dmae_operation_clear_all_sges(lm_dmae_operation_t * operation)515*d14abf15SRobert Mustacchi void lm_dmae_operation_clear_all_sges(lm_dmae_operation_t* operation)
516*d14abf15SRobert Mustacchi {
517*d14abf15SRobert Mustacchi     DbgBreakIf(LM_DMAE_MODE_SGL != operation->mode);
518*d14abf15SRobert Mustacchi 
519*d14abf15SRobert Mustacchi     operation->next_free_block = 0;
520*d14abf15SRobert Mustacchi }
521*d14abf15SRobert Mustacchi 
lm_dmae_operation_is_complete(IN lm_dmae_operation_t * operation)522*d14abf15SRobert Mustacchi u8_t lm_dmae_operation_is_complete(IN lm_dmae_operation_t* operation)
523*d14abf15SRobert Mustacchi {
524*d14abf15SRobert Mustacchi     return operation->context->completion_word != operation->command_id;
525*d14abf15SRobert Mustacchi }
526*d14abf15SRobert Mustacchi 
527*d14abf15SRobert Mustacchi /**lm_dmae_operation_wait
528*d14abf15SRobert Mustacchi  * Wait for an operation to finish. Note that this function
529*d14abf15SRobert Mustacchi  * busy-waits and does not yield the CPU, so it can be used in
530*d14abf15SRobert Mustacchi  * high IRQLs.
531*d14abf15SRobert Mustacchi  *
532*d14abf15SRobert Mustacchi  * @param pdev the device to use
533*d14abf15SRobert Mustacchi  * @param operation the operation to wait for
534*d14abf15SRobert Mustacchi  *
535*d14abf15SRobert Mustacchi  * @return lm_status_t LM_STATUS_SUCCESS on success,
536*d14abf15SRobert Mustacchi  *         LM_STATUS_TIMEOUT if the operation did not finish in
537*d14abf15SRobert Mustacchi  *         reasonable time, LM_STATUS_ABORTED if reset is in
538*d14abf15SRobert Mustacchi  *         progress.
539*d14abf15SRobert Mustacchi  */
540*d14abf15SRobert Mustacchi static lm_status_t
lm_dmae_operation_wait(struct _lm_device_t * pdev,lm_dmae_operation_t * operation)541*d14abf15SRobert Mustacchi lm_dmae_operation_wait(struct _lm_device_t* pdev, lm_dmae_operation_t* operation)
542*d14abf15SRobert Mustacchi {
543*d14abf15SRobert Mustacchi     u32_t wait_cnt = 0;
544*d14abf15SRobert Mustacchi     u32_t wait_cnt_limit = 10000 * pdev->vars.clk_factor;
545*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_SUCCESS;
546*d14abf15SRobert Mustacchi 
547*d14abf15SRobert Mustacchi     while (!lm_dmae_operation_is_complete(operation))
548*d14abf15SRobert Mustacchi     {
549*d14abf15SRobert Mustacchi         mm_wait(pdev, 20);
550*d14abf15SRobert Mustacchi         if (++wait_cnt > wait_cnt_limit)
551*d14abf15SRobert Mustacchi         {
552*d14abf15SRobert Mustacchi             DbgMessage(pdev,
553*d14abf15SRobert Mustacchi                        FATAL,
554*d14abf15SRobert Mustacchi                       "Timed-out waiting for operation %d to complete. Completion word is 0x%x expected 0x%x.\n",(u64_t)operation->command_id,
555*d14abf15SRobert Mustacchi                        (u64_t)operation->context->completion_word,
556*d14abf15SRobert Mustacchi                        (u64_t)operation->context->completion_value);
557*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_TIMEOUT;
558*d14abf15SRobert Mustacchi             break;
559*d14abf15SRobert Mustacchi         }
560*d14abf15SRobert Mustacchi 
561*d14abf15SRobert Mustacchi         if (lm_reset_is_inprogress(pdev))
562*d14abf15SRobert Mustacchi         {
563*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_ABORTED;
564*d14abf15SRobert Mustacchi             break;
565*d14abf15SRobert Mustacchi         }
566*d14abf15SRobert Mustacchi     }
567*d14abf15SRobert Mustacchi 
568*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
569*d14abf15SRobert Mustacchi     {
570*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS != lm_dmae_context_reset(operation->context))
571*d14abf15SRobert Mustacchi         {
572*d14abf15SRobert Mustacchi             DbgBreakMsg("Unable to clean up after a DMAE error. DMAE context is unusable.\n");
573*d14abf15SRobert Mustacchi         }
574*d14abf15SRobert Mustacchi     }
575*d14abf15SRobert Mustacchi 
576*d14abf15SRobert Mustacchi     return lm_status;
577*d14abf15SRobert Mustacchi }
578*d14abf15SRobert Mustacchi 
579*d14abf15SRobert Mustacchi /**
580*d14abf15SRobert Mustacchi  * @}
581*d14abf15SRobert Mustacchi  */
582*d14abf15SRobert Mustacchi 
583*d14abf15SRobert Mustacchi /**
584*d14abf15SRobert Mustacchi  * @defgroup DMAE_Context DMAE Context
585*d14abf15SRobert Mustacchi  * @{
586*d14abf15SRobert Mustacchi  */
587*d14abf15SRobert Mustacchi 
lm_dmae_context_create(struct _lm_device_t * pdev,IN const u8_t channel_idx,IN lm_dmae_locking_policy_t * locking_policy,IN const u8_t change_endianity)588*d14abf15SRobert Mustacchi lm_dmae_context_t* lm_dmae_context_create(  struct _lm_device_t* pdev,
589*d14abf15SRobert Mustacchi                                             IN const u8_t channel_idx,
590*d14abf15SRobert Mustacchi                                             IN lm_dmae_locking_policy_t* locking_policy,
591*d14abf15SRobert Mustacchi                                             IN const u8_t change_endianity)
592*d14abf15SRobert Mustacchi {
593*d14abf15SRobert Mustacchi     lm_dmae_context_t* context = NULL;
594*d14abf15SRobert Mustacchi     lm_address_t context_paddr = {{0}};
595*d14abf15SRobert Mustacchi     lm_address_t completion_word_paddr = {{0}};
596*d14abf15SRobert Mustacchi     lm_address_t intermediate_buffer_paddr = {{0}};
597*d14abf15SRobert Mustacchi 
598*d14abf15SRobert Mustacchi     context = mm_alloc_phys_mem(pdev, sizeof(lm_dmae_context_t), &context_paddr, PHYS_MEM_TYPE_NONCACHED, LM_RESOURCE_COMMON);
599*d14abf15SRobert Mustacchi 
600*d14abf15SRobert Mustacchi     if (CHK_NULL(context))
601*d14abf15SRobert Mustacchi     {
602*d14abf15SRobert Mustacchi         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
603*d14abf15SRobert Mustacchi         return NULL;
604*d14abf15SRobert Mustacchi     }
605*d14abf15SRobert Mustacchi 
606*d14abf15SRobert Mustacchi     context->mode = LM_DMAE_MODE_SINGLE_BLOCK;
607*d14abf15SRobert Mustacchi     context->main_channel = channel_idx;
608*d14abf15SRobert Mustacchi     context->executer_channel = (u8_t)-1;
609*d14abf15SRobert Mustacchi     context->locking_policy = locking_policy;
610*d14abf15SRobert Mustacchi     context->change_endianity = change_endianity;
611*d14abf15SRobert Mustacchi     context->next_command_id = 1;
612*d14abf15SRobert Mustacchi 
613*d14abf15SRobert Mustacchi #ifndef __BIG_ENDIAN
614*d14abf15SRobert Mustacchi     // if we changed the endianity, the completion word should be swapped
615*d14abf15SRobert Mustacchi     context->completion_value = context->change_endianity ? DMAE_COMPLETION_VAL_SWAPPED : DMAE_COMPLETION_VAL ;
616*d14abf15SRobert Mustacchi #else
617*d14abf15SRobert Mustacchi     context->completion_value = DMAE_COMPLETION_VAL;
618*d14abf15SRobert Mustacchi #endif // !__BIG_ENDIAN
619*d14abf15SRobert Mustacchi 
620*d14abf15SRobert Mustacchi     context->completion_word = context->completion_value;
621*d14abf15SRobert Mustacchi 
622*d14abf15SRobert Mustacchi     completion_word_paddr = context_paddr;
623*d14abf15SRobert Mustacchi     LM_INC64(&completion_word_paddr, OFFSETOF(lm_dmae_context_t, completion_word));
624*d14abf15SRobert Mustacchi     context->completion_word_paddr = completion_word_paddr;
625*d14abf15SRobert Mustacchi 
626*d14abf15SRobert Mustacchi     intermediate_buffer_paddr = context_paddr;
627*d14abf15SRobert Mustacchi     LM_INC64(&intermediate_buffer_paddr, OFFSETOF(lm_dmae_context_t, intermediate_buffer));
628*d14abf15SRobert Mustacchi     context->intermediate_buffer_paddr = intermediate_buffer_paddr;
629*d14abf15SRobert Mustacchi 
630*d14abf15SRobert Mustacchi     return context;
631*d14abf15SRobert Mustacchi }
632*d14abf15SRobert Mustacchi 
633*d14abf15SRobert Mustacchi 
lm_dmae_context_create_sgl(struct _lm_device_t * pdev,IN const u8_t loader_channel_idx,IN const u8_t executer_channel_idx,IN lm_dmae_locking_policy_t * locking_policy,IN const u8_t change_endianity)634*d14abf15SRobert Mustacchi lm_dmae_context_t* lm_dmae_context_create_sgl(  struct _lm_device_t* pdev,
635*d14abf15SRobert Mustacchi                                                 IN const u8_t loader_channel_idx,
636*d14abf15SRobert Mustacchi                                                 IN const u8_t executer_channel_idx,
637*d14abf15SRobert Mustacchi                                                 IN lm_dmae_locking_policy_t* locking_policy,
638*d14abf15SRobert Mustacchi                                                 IN const u8_t change_endianity)
639*d14abf15SRobert Mustacchi {
640*d14abf15SRobert Mustacchi     lm_dmae_context_t* context = NULL;
641*d14abf15SRobert Mustacchi     lm_address_t context_paddr = {{0}};
642*d14abf15SRobert Mustacchi     lm_address_t completion_word_paddr = {{0}};
643*d14abf15SRobert Mustacchi     lm_address_t intermediate_buffer_paddr = {{0}};
644*d14abf15SRobert Mustacchi 
645*d14abf15SRobert Mustacchi     context = mm_alloc_phys_mem(pdev, sizeof(lm_dmae_context_t), &context_paddr, PHYS_MEM_TYPE_NONCACHED, LM_RESOURCE_COMMON);
646*d14abf15SRobert Mustacchi 
647*d14abf15SRobert Mustacchi     if (CHK_NULL(context))
648*d14abf15SRobert Mustacchi     {
649*d14abf15SRobert Mustacchi         DbgMessage(NULL, FATAL, "Failed to allocate SGL DMAE context.\n");
650*d14abf15SRobert Mustacchi         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
651*d14abf15SRobert Mustacchi         return NULL;
652*d14abf15SRobert Mustacchi     }
653*d14abf15SRobert Mustacchi 
654*d14abf15SRobert Mustacchi     context->mode = LM_DMAE_MODE_SGL;
655*d14abf15SRobert Mustacchi     context->main_channel = loader_channel_idx;
656*d14abf15SRobert Mustacchi     context->executer_channel = executer_channel_idx;
657*d14abf15SRobert Mustacchi     context->locking_policy = locking_policy;
658*d14abf15SRobert Mustacchi     context->change_endianity = change_endianity;
659*d14abf15SRobert Mustacchi     context->next_command_id = 1;
660*d14abf15SRobert Mustacchi 
661*d14abf15SRobert Mustacchi     context->completion_value = DMAE_SGL_COMPLETION_VAL;
662*d14abf15SRobert Mustacchi 
663*d14abf15SRobert Mustacchi     context->completion_word = context->completion_value;
664*d14abf15SRobert Mustacchi 
665*d14abf15SRobert Mustacchi     completion_word_paddr = context_paddr;
666*d14abf15SRobert Mustacchi     LM_INC64(&completion_word_paddr, OFFSETOF(lm_dmae_context_t, completion_word));
667*d14abf15SRobert Mustacchi     context->completion_word_paddr = completion_word_paddr;
668*d14abf15SRobert Mustacchi 
669*d14abf15SRobert Mustacchi     intermediate_buffer_paddr = context_paddr;
670*d14abf15SRobert Mustacchi     LM_INC64(&intermediate_buffer_paddr, OFFSETOF(lm_dmae_context_t, intermediate_buffer));
671*d14abf15SRobert Mustacchi     context->intermediate_buffer_paddr = intermediate_buffer_paddr;
672*d14abf15SRobert Mustacchi 
673*d14abf15SRobert Mustacchi     return context;
674*d14abf15SRobert Mustacchi }
675*d14abf15SRobert Mustacchi 
676*d14abf15SRobert Mustacchi /**lm_dmae_context_reset
677*d14abf15SRobert Mustacchi  * Bring a DMAE context to a known-good state. This function
678*d14abf15SRobert Mustacchi  * must be used on an acquired context. It should be used if for
679*d14abf15SRobert Mustacchi  * some reason the context is left in an invalid state (e.g an
680*d14abf15SRobert Mustacchi  * error occured during a DMAE transaction using this context).
681*d14abf15SRobert Mustacchi  *
682*d14abf15SRobert Mustacchi  * @param context the context to reset.
683*d14abf15SRobert Mustacchi  *
684*d14abf15SRobert Mustacchi  * @return lm_status LM_STATUS_SUCCESS on success, some other
685*d14abf15SRobert Mustacchi  *         failure code on failure.
686*d14abf15SRobert Mustacchi  */
lm_dmae_context_reset(lm_dmae_context_t * context)687*d14abf15SRobert Mustacchi lm_status_t lm_dmae_context_reset(lm_dmae_context_t *context)
688*d14abf15SRobert Mustacchi {
689*d14abf15SRobert Mustacchi     context->completion_word = context->completion_value;
690*d14abf15SRobert Mustacchi 
691*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
692*d14abf15SRobert Mustacchi }
693*d14abf15SRobert Mustacchi 
694*d14abf15SRobert Mustacchi #ifdef _VBD_
695*d14abf15SRobert Mustacchi __drv_maxIRQL(DISPATCH_LEVEL)
696*d14abf15SRobert Mustacchi __drv_at(context->locking_policy->spinlock.irql, __drv_savesIRQL)
__drv_setsIRQL(DISPATCH_LEVEL)697*d14abf15SRobert Mustacchi __drv_setsIRQL(DISPATCH_LEVEL)
698*d14abf15SRobert Mustacchi #endif
699*d14abf15SRobert Mustacchi lm_status_t lm_dmae_context_acquire(struct _lm_device_t* pdev, lm_dmae_context_t *context)
700*d14abf15SRobert Mustacchi {
701*d14abf15SRobert Mustacchi     return lm_dmae_locking_policy_lock(pdev, context->locking_policy);
702*d14abf15SRobert Mustacchi }
703*d14abf15SRobert Mustacchi 
704*d14abf15SRobert Mustacchi #ifdef _VBD_
705*d14abf15SRobert Mustacchi #if defined(NTDDI_WIN8)
706*d14abf15SRobert Mustacchi _IRQL_requires_(DISPATCH_LEVEL)
707*d14abf15SRobert Mustacchi __drv_at(context->locking_policy->spinlock.irql, __drv_restoresIRQL )
708*d14abf15SRobert Mustacchi #endif
709*d14abf15SRobert Mustacchi #endif
lm_dmae_context_release(struct _lm_device_t * pdev,lm_dmae_context_t * context)710*d14abf15SRobert Mustacchi lm_status_t lm_dmae_context_release(struct _lm_device_t* pdev, lm_dmae_context_t *context)
711*d14abf15SRobert Mustacchi {
712*d14abf15SRobert Mustacchi     return lm_dmae_locking_policy_unlock(pdev, context->locking_policy);
713*d14abf15SRobert Mustacchi }
714*d14abf15SRobert Mustacchi 
lm_dmae_context_execute(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_dmae_operation_t * operation)715*d14abf15SRobert Mustacchi lm_status_t lm_dmae_context_execute(struct _lm_device_t* pdev, lm_dmae_context_t *context, lm_dmae_operation_t *operation)
716*d14abf15SRobert Mustacchi {
717*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
718*d14abf15SRobert Mustacchi 
719*d14abf15SRobert Mustacchi     lm_status = lm_dmae_context_acquire(pdev,context);
720*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
721*d14abf15SRobert Mustacchi     {
722*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire context.\n");
723*d14abf15SRobert Mustacchi         return lm_status;
724*d14abf15SRobert Mustacchi     }
725*d14abf15SRobert Mustacchi 
726*d14abf15SRobert Mustacchi     lm_status = lm_dmae_context_execute_unsafe(pdev, context,operation);
727*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
728*d14abf15SRobert Mustacchi     {
729*d14abf15SRobert Mustacchi         DbgMessage(pdev, FATAL, "lm_dmae_context_execute_unsafe returned %d\n", lm_status);
730*d14abf15SRobert Mustacchi         if (LM_STATUS_ABORTED != lm_status)
731*d14abf15SRobert Mustacchi         {
732*d14abf15SRobert Mustacchi             //we'll let the caller decide if DbgBreak should be called when lm_reset_is_inprogress interrupts a DMAE operation.
733*d14abf15SRobert Mustacchi             DbgBreakMsg("DMAE execution failed.\n");
734*d14abf15SRobert Mustacchi         }
735*d14abf15SRobert Mustacchi 
736*d14abf15SRobert Mustacchi         //don't return - release the context first.
737*d14abf15SRobert Mustacchi     }
738*d14abf15SRobert Mustacchi 
739*d14abf15SRobert Mustacchi     //no need to check the return code, since we can't really recover from
740*d14abf15SRobert Mustacchi     //not being able to release the context anyway.
741*d14abf15SRobert Mustacchi     lm_dmae_context_release(pdev,context);
742*d14abf15SRobert Mustacchi 
743*d14abf15SRobert Mustacchi     return lm_status;
744*d14abf15SRobert Mustacchi }
745*d14abf15SRobert Mustacchi 
746*d14abf15SRobert Mustacchi /**lm_dmae_context_advance_command_id
747*d14abf15SRobert Mustacchi  * DMAE context has a 'private' variable of the next command ID
748*d14abf15SRobert Mustacchi  * to use. This function returns the next valid value for this
749*d14abf15SRobert Mustacchi  * context's command ID in a thread-safe manner.
750*d14abf15SRobert Mustacchi  *
751*d14abf15SRobert Mustacchi  * @param context the context to change
752*d14abf15SRobert Mustacchi  *
753*d14abf15SRobert Mustacchi  * @return u32_t the new command ID for the context.
754*d14abf15SRobert Mustacchi  */
755*d14abf15SRobert Mustacchi static u32_t
lm_dmae_context_advance_command_id(lm_dmae_context_t * context)756*d14abf15SRobert Mustacchi lm_dmae_context_advance_command_id(lm_dmae_context_t* context)
757*d14abf15SRobert Mustacchi {
758*d14abf15SRobert Mustacchi     u32_t cmd_id = mm_atomic_inc(&context->next_command_id);
759*d14abf15SRobert Mustacchi 
760*d14abf15SRobert Mustacchi     if ((0 == cmd_id)||
761*d14abf15SRobert Mustacchi         (context->completion_value == cmd_id))
762*d14abf15SRobert Mustacchi     {
763*d14abf15SRobert Mustacchi         cmd_id = mm_atomic_inc(&context->next_command_id);
764*d14abf15SRobert Mustacchi     }
765*d14abf15SRobert Mustacchi 
766*d14abf15SRobert Mustacchi     return cmd_id;
767*d14abf15SRobert Mustacchi }
768*d14abf15SRobert Mustacchi 
769*d14abf15SRobert Mustacchi // Copy the loader command to DMAE - need to do it before every call - for source/dest address no reset...
770*d14abf15SRobert Mustacchi // Due to parity checks error, we write zero for last 5 registers of command (9-13, zero based)
771*d14abf15SRobert Mustacchi static void
lm_dmae_post_command(IN struct _lm_device_t * pdev,IN const u8_t idx_cmd,IN const struct dmae_cmd * command)772*d14abf15SRobert Mustacchi lm_dmae_post_command(   IN struct _lm_device_t*   pdev,
773*d14abf15SRobert Mustacchi                         IN const u8_t             idx_cmd,
774*d14abf15SRobert Mustacchi                         IN const struct dmae_cmd* command  )
775*d14abf15SRobert Mustacchi {
776*d14abf15SRobert Mustacchi     u8_t i = 0 ;
777*d14abf15SRobert Mustacchi 
778*d14abf15SRobert Mustacchi     DbgBreakIf(IS_VFDEV(pdev));
779*d14abf15SRobert Mustacchi 
780*d14abf15SRobert Mustacchi     if ( CHK_NULL(pdev) || CHK_NULL(command))
781*d14abf15SRobert Mustacchi     {
782*d14abf15SRobert Mustacchi         return;
783*d14abf15SRobert Mustacchi     }
784*d14abf15SRobert Mustacchi 
785*d14abf15SRobert Mustacchi     // verify address is not NULL
786*d14abf15SRobert Mustacchi     if ERR_IF( ( ( 0 == command->dst_addr_lo ) && ( command->dst_addr_hi == command->dst_addr_lo ) ) ||
787*d14abf15SRobert Mustacchi                ( ( 0 == command->src_addr_lo ) && ( command->src_addr_hi == command->src_addr_lo ) ) )
788*d14abf15SRobert Mustacchi 
789*d14abf15SRobert Mustacchi     {
790*d14abf15SRobert Mustacchi             DbgMessage(pdev,
791*d14abf15SRobert Mustacchi                        FATAL,
792*d14abf15SRobert Mustacchi                        "lm_dmae_command: idx_cmd=%d opcode = 0x%x opcode_iov=0x%x len=0x%x src=0x%x:%x dst=0x%x:%x\n",
793*d14abf15SRobert Mustacchi                        idx_cmd,
794*d14abf15SRobert Mustacchi                        (int)command->opcode,
795*d14abf15SRobert Mustacchi                        (int)command->opcode_iov,
796*d14abf15SRobert Mustacchi                        (int)command->len,
797*d14abf15SRobert Mustacchi                        (int)command->src_addr_hi,
798*d14abf15SRobert Mustacchi                        (int)command->src_addr_lo,
799*d14abf15SRobert Mustacchi                        (int)command->dst_addr_hi,
800*d14abf15SRobert Mustacchi                        (int)command->dst_addr_lo );
801*d14abf15SRobert Mustacchi             DbgBreakMsg("lm_dmae_command: Trying to write/read to NULL address\n");
802*d14abf15SRobert Mustacchi     }
803*d14abf15SRobert Mustacchi 
804*d14abf15SRobert Mustacchi     // Copy the command to DMAE - need to do it before every call - for source/dest address no reset...
805*d14abf15SRobert Mustacchi     // Due to parity checks error, we write zero for last 5 registers of command (9-13, zero based)
806*d14abf15SRobert Mustacchi     for( i = 0 ; i < 14 ; i++ )
807*d14abf15SRobert Mustacchi     {
808*d14abf15SRobert Mustacchi         REG_WR( pdev,
809*d14abf15SRobert Mustacchi                 DMAE_REG_CMD_MEM+(idx_cmd*DMAE_CMD_SIZE*sizeof(u32_t))+i*sizeof(u32_t),
810*d14abf15SRobert Mustacchi                 i < 9 ? *(((u32_t*)command)+i) : 0 ) ;
811*d14abf15SRobert Mustacchi     }
812*d14abf15SRobert Mustacchi 
813*d14abf15SRobert Mustacchi     REG_WR(pdev, lm_dmae_idx_to_go_cmd(idx_cmd), DMAE_GO_VALUE) ;
814*d14abf15SRobert Mustacchi }
815*d14abf15SRobert Mustacchi 
816*d14abf15SRobert Mustacchi 
817*d14abf15SRobert Mustacchi /**lm_dmae_context_execute_single_block
818*d14abf15SRobert Mustacchi  * Execute an SGL operation without acquiring the
819*d14abf15SRobert Mustacchi  * context.
820*d14abf15SRobert Mustacchi  *
821*d14abf15SRobert Mustacchi  *
822*d14abf15SRobert Mustacchi  * @param pdev the device to use
823*d14abf15SRobert Mustacchi  * @param context the context that executes the operation
824*d14abf15SRobert Mustacchi  * @param operation the operation to execute
825*d14abf15SRobert Mustacchi  *
826*d14abf15SRobert Mustacchi  * @return lm_status_t LM_STATUS_SUCCESS on success,
827*d14abf15SRobert Mustacchi  *         LM_STATUS_TIMEOUT if the operation did not finish in
828*d14abf15SRobert Mustacchi  *         reasonable time, some other failure value on failure.
829*d14abf15SRobert Mustacchi  */
lm_dmae_context_execute_sgl(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_dmae_operation_t * operation)830*d14abf15SRobert Mustacchi lm_status_t lm_dmae_context_execute_sgl(struct _lm_device_t* pdev, lm_dmae_context_t *context, lm_dmae_operation_t *operation)
831*d14abf15SRobert Mustacchi {
832*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_SUCCESS;
833*d14abf15SRobert Mustacchi 
834*d14abf15SRobert Mustacchi     context->completion_word = operation->command_id;
835*d14abf15SRobert Mustacchi 
836*d14abf15SRobert Mustacchi     lm_dmae_post_command(pdev, context->main_channel, &operation->main_cmd);
837*d14abf15SRobert Mustacchi 
838*d14abf15SRobert Mustacchi     if (operation->b_sync)
839*d14abf15SRobert Mustacchi     {
840*d14abf15SRobert Mustacchi         lm_status = lm_dmae_operation_wait(pdev, operation);
841*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS != lm_status)
842*d14abf15SRobert Mustacchi         {
843*d14abf15SRobert Mustacchi             DbgMessage(pdev, FATAL, "lm_dmae_operation_wait returned %d\n", lm_status);
844*d14abf15SRobert Mustacchi         }
845*d14abf15SRobert Mustacchi     }
846*d14abf15SRobert Mustacchi 
847*d14abf15SRobert Mustacchi     return lm_status;
848*d14abf15SRobert Mustacchi }
849*d14abf15SRobert Mustacchi 
850*d14abf15SRobert Mustacchi /**lm_dmae_context_execute_sub_operation
851*d14abf15SRobert Mustacchi  * lm_dmae_context_execute_single_block splits every command to
852*d14abf15SRobert Mustacchi  * sub-operations, each with a length that is less the the HW
853*d14abf15SRobert Mustacchi  * limit for DMAE lengths. This function executes one of these
854*d14abf15SRobert Mustacchi  * sub-operations.
855*d14abf15SRobert Mustacchi  * Note: This function modifies operation->main_cmd.
856*d14abf15SRobert Mustacchi  *
857*d14abf15SRobert Mustacchi  *
858*d14abf15SRobert Mustacchi  * @param pdev the device to use
859*d14abf15SRobert Mustacchi  * @param context the context that executes the operation
860*d14abf15SRobert Mustacchi  * @param operation the operation to execute
861*d14abf15SRobert Mustacchi  * @param src_offset the source offset of the current
862*d14abf15SRobert Mustacchi  *                   sub-operation. This value overrides
863*d14abf15SRobert Mustacchi  *                   whatever is stored in operation
864*d14abf15SRobert Mustacchi  * @param dst_offset the destination offset of the current
865*d14abf15SRobert Mustacchi  *                   sub-operation. This value overrides
866*d14abf15SRobert Mustacchi  *                   whatever is stored in operation
867*d14abf15SRobert Mustacchi  * @param length the length of the current sub-operation. This
868*d14abf15SRobert Mustacchi  *               value overrides whatever is stored in operation
869*d14abf15SRobert Mustacchi  *
870*d14abf15SRobert Mustacchi  * @return lm_status_t LM_STATUS_SUCCESS on success,
871*d14abf15SRobert Mustacchi  *         LM_STATUS_TIMEOUT if the operation did not finish in
872*d14abf15SRobert Mustacchi  *         reasonable time, some other failure value on failure.
873*d14abf15SRobert Mustacchi  */
874*d14abf15SRobert Mustacchi static lm_status_t
lm_dmae_context_execute_sub_operation(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_dmae_operation_t * operation,IN const u64_t src_offset,IN const u64_t dst_offset,IN const u16_t length)875*d14abf15SRobert Mustacchi lm_dmae_context_execute_sub_operation(  struct _lm_device_t* pdev,
876*d14abf15SRobert Mustacchi                                         lm_dmae_context_t *context,
877*d14abf15SRobert Mustacchi                                         lm_dmae_operation_t *operation,
878*d14abf15SRobert Mustacchi                                         IN const u64_t src_offset,
879*d14abf15SRobert Mustacchi                                         IN const u64_t dst_offset,
880*d14abf15SRobert Mustacchi                                         IN const u16_t length)
881*d14abf15SRobert Mustacchi {
882*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_SUCCESS;
883*d14abf15SRobert Mustacchi 
884*d14abf15SRobert Mustacchi     lm_address_t src_addr = {{0}};
885*d14abf15SRobert Mustacchi     lm_address_t dst_addr = {{0}};
886*d14abf15SRobert Mustacchi 
887*d14abf15SRobert Mustacchi     u16_t i = 0;
888*d14abf15SRobert Mustacchi 
889*d14abf15SRobert Mustacchi     src_addr.as_u64 = src_offset;
890*d14abf15SRobert Mustacchi     dst_addr.as_u64 = dst_offset;
891*d14abf15SRobert Mustacchi 
892*d14abf15SRobert Mustacchi     switch (operation->blocks[0].source.type)
893*d14abf15SRobert Mustacchi     {
894*d14abf15SRobert Mustacchi         case LM_DMAE_ADDRESS_GRC://fallthrough
895*d14abf15SRobert Mustacchi         case LM_DMAE_ADDRESS_HOST_PHYS:
896*d14abf15SRobert Mustacchi             {
897*d14abf15SRobert Mustacchi                 operation->main_cmd.src_addr_hi = src_addr.as_u32.high;
898*d14abf15SRobert Mustacchi                 operation->main_cmd.src_addr_lo = src_addr.as_u32.low;
899*d14abf15SRobert Mustacchi             }
900*d14abf15SRobert Mustacchi             break;
901*d14abf15SRobert Mustacchi         case LM_DMAE_ADDRESS_HOST_VIRT: //for virtual source addresses we use the intermediate buffer.
902*d14abf15SRobert Mustacchi             {
903*d14abf15SRobert Mustacchi                 operation->main_cmd.src_addr_hi = context->intermediate_buffer_paddr.as_u32.high;
904*d14abf15SRobert Mustacchi                 operation->main_cmd.src_addr_lo = context->intermediate_buffer_paddr.as_u32.low;
905*d14abf15SRobert Mustacchi 
906*d14abf15SRobert Mustacchi                 mm_memcpy( &context->intermediate_buffer[0], src_addr.as_ptr, length*sizeof(u32_t));
907*d14abf15SRobert Mustacchi                 if (operation->le32_swap)
908*d14abf15SRobert Mustacchi                 {
909*d14abf15SRobert Mustacchi                     for (i=0; i < length; ++i)
910*d14abf15SRobert Mustacchi                     {
911*d14abf15SRobert Mustacchi                         context->intermediate_buffer[i] = mm_cpu_to_le32(context->intermediate_buffer[i]);
912*d14abf15SRobert Mustacchi                     }
913*d14abf15SRobert Mustacchi                 }
914*d14abf15SRobert Mustacchi             }
915*d14abf15SRobert Mustacchi             break;
916*d14abf15SRobert Mustacchi         default:
917*d14abf15SRobert Mustacchi             {
918*d14abf15SRobert Mustacchi                 DbgBreakMsg("Unknown source address type for DMAE operation.\n");
919*d14abf15SRobert Mustacchi                 return LM_STATUS_INVALID_PARAMETER;
920*d14abf15SRobert Mustacchi             }
921*d14abf15SRobert Mustacchi             break;
922*d14abf15SRobert Mustacchi     }
923*d14abf15SRobert Mustacchi 
924*d14abf15SRobert Mustacchi     switch (operation->blocks[0].dest.type)
925*d14abf15SRobert Mustacchi     {
926*d14abf15SRobert Mustacchi         case LM_DMAE_ADDRESS_GRC://fallthrough
927*d14abf15SRobert Mustacchi         case LM_DMAE_ADDRESS_HOST_PHYS:
928*d14abf15SRobert Mustacchi             {
929*d14abf15SRobert Mustacchi                 operation->main_cmd.dst_addr_hi = dst_addr.as_u32.high;
930*d14abf15SRobert Mustacchi                 operation->main_cmd.dst_addr_lo = dst_addr.as_u32.low;
931*d14abf15SRobert Mustacchi             }
932*d14abf15SRobert Mustacchi             break;
933*d14abf15SRobert Mustacchi         case LM_DMAE_ADDRESS_HOST_VIRT: //for virtual source addresses we use the intermediate buffer.
934*d14abf15SRobert Mustacchi             {
935*d14abf15SRobert Mustacchi                 operation->main_cmd.dst_addr_hi = context->intermediate_buffer_paddr.as_u32.high;
936*d14abf15SRobert Mustacchi                 operation->main_cmd.dst_addr_lo = context->intermediate_buffer_paddr.as_u32.low;
937*d14abf15SRobert Mustacchi             }
938*d14abf15SRobert Mustacchi             break;
939*d14abf15SRobert Mustacchi         default:
940*d14abf15SRobert Mustacchi             {
941*d14abf15SRobert Mustacchi                 DbgBreakMsg("Unknown destination address type for DMAE operation.\n");
942*d14abf15SRobert Mustacchi                 return LM_STATUS_INVALID_PARAMETER;
943*d14abf15SRobert Mustacchi             }
944*d14abf15SRobert Mustacchi             break;
945*d14abf15SRobert Mustacchi     }
946*d14abf15SRobert Mustacchi 
947*d14abf15SRobert Mustacchi     DbgBreakIf(context->completion_word != context->completion_value);
948*d14abf15SRobert Mustacchi 
949*d14abf15SRobert Mustacchi     context->completion_word = operation->command_id;
950*d14abf15SRobert Mustacchi 
951*d14abf15SRobert Mustacchi     operation->main_cmd.len = length;
952*d14abf15SRobert Mustacchi 
953*d14abf15SRobert Mustacchi     lm_dmae_post_command(pdev, context->main_channel, &operation->main_cmd);
954*d14abf15SRobert Mustacchi 
955*d14abf15SRobert Mustacchi     lm_status = lm_dmae_operation_wait(pdev, operation);
956*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
957*d14abf15SRobert Mustacchi     {
958*d14abf15SRobert Mustacchi         return lm_status;
959*d14abf15SRobert Mustacchi     }
960*d14abf15SRobert Mustacchi 
961*d14abf15SRobert Mustacchi     DbgBreakIf(context->completion_word != context->completion_value);
962*d14abf15SRobert Mustacchi 
963*d14abf15SRobert Mustacchi     if (operation->blocks[0].dest.type == LM_DMAE_ADDRESS_HOST_VIRT)
964*d14abf15SRobert Mustacchi     {
965*d14abf15SRobert Mustacchi         mm_memcpy( dst_addr.as_ptr, &context->intermediate_buffer[0], length*sizeof(u32_t));
966*d14abf15SRobert Mustacchi     }
967*d14abf15SRobert Mustacchi 
968*d14abf15SRobert Mustacchi     return lm_status;
969*d14abf15SRobert Mustacchi }
970*d14abf15SRobert Mustacchi 
971*d14abf15SRobert Mustacchi /**lm_dmae_context_execute_single_block
972*d14abf15SRobert Mustacchi  * Execute a single-block operation without acquiring the
973*d14abf15SRobert Mustacchi  * context.
974*d14abf15SRobert Mustacchi  *
975*d14abf15SRobert Mustacchi  *
976*d14abf15SRobert Mustacchi  * @param pdev the device to use
977*d14abf15SRobert Mustacchi  * @param context the context that executes the operation
978*d14abf15SRobert Mustacchi  * @param operation the operation to execute
979*d14abf15SRobert Mustacchi  *
980*d14abf15SRobert Mustacchi  * @return lm_status_t LM_STATUS_SUCCESS on success,
981*d14abf15SRobert Mustacchi  *         LM_STATUS_TIMEOUT if the operation did not finish in
982*d14abf15SRobert Mustacchi  *         reasonable time, some other failure value on failure.
983*d14abf15SRobert Mustacchi  */
984*d14abf15SRobert Mustacchi static lm_status_t
lm_dmae_context_execute_single_block(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_dmae_operation_t * operation)985*d14abf15SRobert Mustacchi lm_dmae_context_execute_single_block(struct _lm_device_t* pdev, lm_dmae_context_t *context, lm_dmae_operation_t *operation)
986*d14abf15SRobert Mustacchi {
987*d14abf15SRobert Mustacchi     lm_status_t        lm_status       = LM_STATUS_SUCCESS ;
988*d14abf15SRobert Mustacchi     u16_t              length_current  = 0 ;
989*d14abf15SRobert Mustacchi     u16_t              i               = 0 ;
990*d14abf15SRobert Mustacchi     u32_t              offset          = 0 ;
991*d14abf15SRobert Mustacchi     lm_address_t       src_addr        = {{0}};
992*d14abf15SRobert Mustacchi     lm_address_t       dst_addr        = {{0}};
993*d14abf15SRobert Mustacchi     u64_t              src_addr_split  = 0;
994*d14abf15SRobert Mustacchi     u64_t              dst_addr_split  = 0;
995*d14abf15SRobert Mustacchi 
996*d14abf15SRobert Mustacchi 
997*d14abf15SRobert Mustacchi     const u16_t        length_limit    = (operation->blocks[0].dest.type != LM_DMAE_ADDRESS_GRC) ? min( DMAE_MAX_READ_SIZE, DMAE_MAX_RW_SIZE(pdev) ) : DMAE_MAX_RW_SIZE(pdev) ;
998*d14abf15SRobert Mustacchi     u16_t        cnt_split       = 0; // number of chunks of splits
999*d14abf15SRobert Mustacchi     u16_t        length_mod      = 0;
1000*d14abf15SRobert Mustacchi 
1001*d14abf15SRobert Mustacchi     DbgBreakIf(0 == length_limit); //to avoid divide-by-0. can't do static assert because it depends on CHIP_ID
1002*d14abf15SRobert Mustacchi 
1003*d14abf15SRobert Mustacchi     cnt_split = operation->blocks[0].length / length_limit;
1004*d14abf15SRobert Mustacchi     length_mod = operation->blocks[0].length % length_limit;
1005*d14abf15SRobert Mustacchi 
1006*d14abf15SRobert Mustacchi     src_addr.as_u64 = lm_dmae_address_native_offset(&operation->blocks[0].source);
1007*d14abf15SRobert Mustacchi     src_addr_split = src_addr.as_u64;
1008*d14abf15SRobert Mustacchi 
1009*d14abf15SRobert Mustacchi     dst_addr.as_u64 = lm_dmae_address_native_offset(&operation->blocks[0].dest);
1010*d14abf15SRobert Mustacchi     dst_addr_split  = dst_addr.as_u64;
1011*d14abf15SRobert Mustacchi 
1012*d14abf15SRobert Mustacchi 
1013*d14abf15SRobert Mustacchi     DbgBreakIf(IS_VFDEV(pdev));
1014*d14abf15SRobert Mustacchi 
1015*d14abf15SRobert Mustacchi     if ( CHK_NULL(pdev) || ERR_IF( 0 == operation->blocks[0].length ) )
1016*d14abf15SRobert Mustacchi     {
1017*d14abf15SRobert Mustacchi        return LM_STATUS_INVALID_PARAMETER ;
1018*d14abf15SRobert Mustacchi     }
1019*d14abf15SRobert Mustacchi 
1020*d14abf15SRobert Mustacchi     for( i = 0; i <= cnt_split; i++ )
1021*d14abf15SRobert Mustacchi     {
1022*d14abf15SRobert Mustacchi         offset = length_limit*i ;
1023*d14abf15SRobert Mustacchi 
1024*d14abf15SRobert Mustacchi         if( !operation->b_replicate_source )
1025*d14abf15SRobert Mustacchi         {
1026*d14abf15SRobert Mustacchi             if (operation->blocks[0].source.type == LM_DMAE_ADDRESS_GRC)
1027*d14abf15SRobert Mustacchi             {
1028*d14abf15SRobert Mustacchi                 src_addr_split = src_addr.as_u64 + offset;
1029*d14abf15SRobert Mustacchi             }
1030*d14abf15SRobert Mustacchi             else
1031*d14abf15SRobert Mustacchi             {
1032*d14abf15SRobert Mustacchi                 src_addr_split = src_addr.as_u64 + (offset*4);
1033*d14abf15SRobert Mustacchi             }
1034*d14abf15SRobert Mustacchi         }
1035*d14abf15SRobert Mustacchi 
1036*d14abf15SRobert Mustacchi         if (operation->blocks[0].dest.type == LM_DMAE_ADDRESS_GRC)
1037*d14abf15SRobert Mustacchi         {
1038*d14abf15SRobert Mustacchi             dst_addr_split = dst_addr.as_u64 + offset;
1039*d14abf15SRobert Mustacchi         }
1040*d14abf15SRobert Mustacchi         else
1041*d14abf15SRobert Mustacchi         {
1042*d14abf15SRobert Mustacchi             dst_addr_split = dst_addr.as_u64 + (offset*4);
1043*d14abf15SRobert Mustacchi         }
1044*d14abf15SRobert Mustacchi 
1045*d14abf15SRobert Mustacchi         length_current = (cnt_split==i)? length_mod : length_limit ;
1046*d14abf15SRobert Mustacchi 
1047*d14abf15SRobert Mustacchi         // might be zero on last iteration
1048*d14abf15SRobert Mustacchi         if( 0 != length_current )
1049*d14abf15SRobert Mustacchi         {
1050*d14abf15SRobert Mustacchi             lm_status = lm_dmae_context_execute_sub_operation(pdev, context, operation, src_addr_split, dst_addr_split, length_current);
1051*d14abf15SRobert Mustacchi             if( LM_STATUS_SUCCESS != lm_status )
1052*d14abf15SRobert Mustacchi             {
1053*d14abf15SRobert Mustacchi                 return lm_status ;
1054*d14abf15SRobert Mustacchi             }
1055*d14abf15SRobert Mustacchi         }
1056*d14abf15SRobert Mustacchi     }
1057*d14abf15SRobert Mustacchi 
1058*d14abf15SRobert Mustacchi     return lm_status ;
1059*d14abf15SRobert Mustacchi }
1060*d14abf15SRobert Mustacchi 
lm_dmae_context_execute_unsafe(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_dmae_operation_t * operation)1061*d14abf15SRobert Mustacchi lm_status_t lm_dmae_context_execute_unsafe(struct _lm_device_t* pdev, lm_dmae_context_t *context, lm_dmae_operation_t *operation)
1062*d14abf15SRobert Mustacchi {
1063*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
1064*d14abf15SRobert Mustacchi 
1065*d14abf15SRobert Mustacchi     if (context->completion_word != context->completion_value)
1066*d14abf15SRobert Mustacchi     {
1067*d14abf15SRobert Mustacchi         return LM_STATUS_BUSY;
1068*d14abf15SRobert Mustacchi     }
1069*d14abf15SRobert Mustacchi 
1070*d14abf15SRobert Mustacchi     DbgBreakIf(context->mode != operation->mode);
1071*d14abf15SRobert Mustacchi 
1072*d14abf15SRobert Mustacchi     operation->command_id = lm_dmae_context_advance_command_id(context);
1073*d14abf15SRobert Mustacchi 
1074*d14abf15SRobert Mustacchi     switch (context->mode)
1075*d14abf15SRobert Mustacchi     {
1076*d14abf15SRobert Mustacchi     case LM_DMAE_MODE_SINGLE_BLOCK:
1077*d14abf15SRobert Mustacchi         {
1078*d14abf15SRobert Mustacchi             lm_status = lm_dmae_context_execute_single_block(pdev, context, operation);
1079*d14abf15SRobert Mustacchi         }
1080*d14abf15SRobert Mustacchi         break;
1081*d14abf15SRobert Mustacchi     case LM_DMAE_MODE_SGL:
1082*d14abf15SRobert Mustacchi         {
1083*d14abf15SRobert Mustacchi             lm_status = lm_dmae_context_execute_sgl(pdev, context, operation);
1084*d14abf15SRobert Mustacchi         }
1085*d14abf15SRobert Mustacchi         break;
1086*d14abf15SRobert Mustacchi     default:
1087*d14abf15SRobert Mustacchi         {
1088*d14abf15SRobert Mustacchi             DbgBreakMsg("Unknown context mode.\n");
1089*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_INVALID_PARAMETER;
1090*d14abf15SRobert Mustacchi         }
1091*d14abf15SRobert Mustacchi         break;
1092*d14abf15SRobert Mustacchi     }
1093*d14abf15SRobert Mustacchi 
1094*d14abf15SRobert Mustacchi     return lm_status;
1095*d14abf15SRobert Mustacchi }
1096*d14abf15SRobert Mustacchi 
1097*d14abf15SRobert Mustacchi /**
1098*d14abf15SRobert Mustacchi  * @}
1099*d14abf15SRobert Mustacchi  */
1100*d14abf15SRobert Mustacchi 
1101*d14abf15SRobert Mustacchi 
1102*d14abf15SRobert Mustacchi /**
1103*d14abf15SRobert Mustacchi  * @defgroup DMAE_Address DMAE address
1104*d14abf15SRobert Mustacchi  * @{
1105*d14abf15SRobert Mustacchi  */
1106*d14abf15SRobert Mustacchi 
lm_dmae_address_native_offset(IN const lm_dmae_address_t * address)1107*d14abf15SRobert Mustacchi u64_t lm_dmae_address_native_offset(IN const lm_dmae_address_t* address)
1108*d14abf15SRobert Mustacchi {
1109*d14abf15SRobert Mustacchi     switch (address->type)
1110*d14abf15SRobert Mustacchi     {
1111*d14abf15SRobert Mustacchi     case LM_DMAE_ADDRESS_GRC:
1112*d14abf15SRobert Mustacchi         {
1113*d14abf15SRobert Mustacchi             return address->u.grc_offset / sizeof(u32_t);
1114*d14abf15SRobert Mustacchi         }
1115*d14abf15SRobert Mustacchi         break;
1116*d14abf15SRobert Mustacchi     case LM_DMAE_ADDRESS_HOST_PHYS:
1117*d14abf15SRobert Mustacchi         {
1118*d14abf15SRobert Mustacchi             return address->u.host_phys_address.as_u64;
1119*d14abf15SRobert Mustacchi         }
1120*d14abf15SRobert Mustacchi         break;
1121*d14abf15SRobert Mustacchi     case LM_DMAE_ADDRESS_HOST_VIRT:
1122*d14abf15SRobert Mustacchi         {
1123*d14abf15SRobert Mustacchi             lm_address_t temp;
1124*d14abf15SRobert Mustacchi             temp.as_ptr = address->u.host_virt_address;
1125*d14abf15SRobert Mustacchi             return temp.as_u64;
1126*d14abf15SRobert Mustacchi         }
1127*d14abf15SRobert Mustacchi         break;
1128*d14abf15SRobert Mustacchi     default:
1129*d14abf15SRobert Mustacchi         {
1130*d14abf15SRobert Mustacchi             DbgBreakMsg("Unknown address type.\n");
1131*d14abf15SRobert Mustacchi             return 0;
1132*d14abf15SRobert Mustacchi         }
1133*d14abf15SRobert Mustacchi         break;
1134*d14abf15SRobert Mustacchi 
1135*d14abf15SRobert Mustacchi     }
1136*d14abf15SRobert Mustacchi }
1137*d14abf15SRobert Mustacchi 
lm_dmae_address(IN const u64_t offset,IN const lm_dmae_address_type_t type)1138*d14abf15SRobert Mustacchi lm_dmae_address_t lm_dmae_address(IN const u64_t offset, IN const lm_dmae_address_type_t type)
1139*d14abf15SRobert Mustacchi {
1140*d14abf15SRobert Mustacchi     lm_dmae_address_t address = {{0}};
1141*d14abf15SRobert Mustacchi 
1142*d14abf15SRobert Mustacchi     address.type = type;
1143*d14abf15SRobert Mustacchi 
1144*d14abf15SRobert Mustacchi     switch (type)
1145*d14abf15SRobert Mustacchi     {
1146*d14abf15SRobert Mustacchi     case LM_DMAE_ADDRESS_GRC:
1147*d14abf15SRobert Mustacchi         {
1148*d14abf15SRobert Mustacchi             ASSERT_STATIC(sizeof(address.u.grc_offset) == sizeof(u32_t));
1149*d14abf15SRobert Mustacchi             DbgBreakIf (offset > MAX_VARIABLE_VALUE(address.u.grc_offset));
1150*d14abf15SRobert Mustacchi 
1151*d14abf15SRobert Mustacchi             address.u.grc_offset = (u32_t)offset;
1152*d14abf15SRobert Mustacchi         }
1153*d14abf15SRobert Mustacchi         break;
1154*d14abf15SRobert Mustacchi     case LM_DMAE_ADDRESS_HOST_PHYS:
1155*d14abf15SRobert Mustacchi         {
1156*d14abf15SRobert Mustacchi             address.u.host_phys_address.as_u64 = offset;
1157*d14abf15SRobert Mustacchi         }
1158*d14abf15SRobert Mustacchi         break;
1159*d14abf15SRobert Mustacchi     case LM_DMAE_ADDRESS_HOST_VIRT:
1160*d14abf15SRobert Mustacchi         {
1161*d14abf15SRobert Mustacchi             lm_address_t temp;
1162*d14abf15SRobert Mustacchi             temp.as_u64 = offset;
1163*d14abf15SRobert Mustacchi 
1164*d14abf15SRobert Mustacchi             address.u.host_virt_address = temp.as_ptr;
1165*d14abf15SRobert Mustacchi         }
1166*d14abf15SRobert Mustacchi         break;
1167*d14abf15SRobert Mustacchi     default:
1168*d14abf15SRobert Mustacchi         {
1169*d14abf15SRobert Mustacchi             DbgBreakMsg("Unknown address type.\n");
1170*d14abf15SRobert Mustacchi         }
1171*d14abf15SRobert Mustacchi         break;
1172*d14abf15SRobert Mustacchi     }
1173*d14abf15SRobert Mustacchi 
1174*d14abf15SRobert Mustacchi     return address;
1175*d14abf15SRobert Mustacchi }
1176*d14abf15SRobert Mustacchi 
1177*d14abf15SRobert Mustacchi /**
1178*d14abf15SRobert Mustacchi  * @}
1179*d14abf15SRobert Mustacchi  */
1180*d14abf15SRobert Mustacchi 
1181*d14abf15SRobert Mustacchi 
1182*d14abf15SRobert Mustacchi /**
1183*d14abf15SRobert Mustacchi  * @defgroup DMAE_User DMAE users API
1184*d14abf15SRobert Mustacchi  * @{
1185*d14abf15SRobert Mustacchi  */
1186*d14abf15SRobert Mustacchi 
lm_dmae_get(struct _lm_device_t * pdev,IN const lm_dmae_type_t type)1187*d14abf15SRobert Mustacchi lm_dmae_context_info_t* lm_dmae_get(struct _lm_device_t* pdev, IN const lm_dmae_type_t type)
1188*d14abf15SRobert Mustacchi {
1189*d14abf15SRobert Mustacchi     ASSERT_STATIC(LM_DMAE_MAX_TYPE == ARRSIZE(pdev->dmae_info.ctx_arr));
1190*d14abf15SRobert Mustacchi 
1191*d14abf15SRobert Mustacchi     if (type >= LM_DMAE_MAX_TYPE)
1192*d14abf15SRobert Mustacchi     {
1193*d14abf15SRobert Mustacchi         DbgBreakMsg("Invalid DMAE user index.\n");
1194*d14abf15SRobert Mustacchi         return NULL;
1195*d14abf15SRobert Mustacchi     }
1196*d14abf15SRobert Mustacchi 
1197*d14abf15SRobert Mustacchi     return &pdev->dmae_info.ctx_arr[type];
1198*d14abf15SRobert Mustacchi }
1199*d14abf15SRobert Mustacchi 
1200*d14abf15SRobert Mustacchi static const u32_t MAX_GRC_OFFSET = 0x00400000; //GRC space is 4MB for 57710-578xx
1201*d14abf15SRobert Mustacchi 
lm_dmae_reg_wr(struct _lm_device_t * pdev,lm_dmae_context_t * context,void * source_vaddr,u32_t dest_offset,u16_t length,u8_t replicate_source,u8_t le32_swap)1202*d14abf15SRobert Mustacchi lm_status_t lm_dmae_reg_wr(struct _lm_device_t* pdev, lm_dmae_context_t* context, void* source_vaddr, u32_t dest_offset, u16_t length, u8_t replicate_source, u8_t le32_swap)
1203*d14abf15SRobert Mustacchi {
1204*d14abf15SRobert Mustacchi     lm_address_t source_offset = {{0}};
1205*d14abf15SRobert Mustacchi     lm_dmae_address_t source = {{0}};
1206*d14abf15SRobert Mustacchi     lm_dmae_address_t dest = lm_dmae_address(dest_offset, LM_DMAE_ADDRESS_GRC);
1207*d14abf15SRobert Mustacchi     lm_dmae_operation_t operation = {0};
1208*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
1209*d14abf15SRobert Mustacchi 
1210*d14abf15SRobert Mustacchi     DbgBreakIf(dest_offset > MAX_GRC_OFFSET); //make sure dest_offset is a valid GRC offset
1211*d14abf15SRobert Mustacchi 
1212*d14abf15SRobert Mustacchi     source_offset.as_ptr = source_vaddr;
1213*d14abf15SRobert Mustacchi     source = lm_dmae_address(source_offset.as_u64, LM_DMAE_ADDRESS_HOST_VIRT);
1214*d14abf15SRobert Mustacchi 
1215*d14abf15SRobert Mustacchi     lm_status = lm_dmae_operation_create(pdev, source, dest, length, replicate_source, le32_swap, context, &operation);
1216*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1217*d14abf15SRobert Mustacchi     {
1218*d14abf15SRobert Mustacchi         return lm_status;
1219*d14abf15SRobert Mustacchi     }
1220*d14abf15SRobert Mustacchi 
1221*d14abf15SRobert Mustacchi     lm_status = lm_dmae_context_execute(pdev, context, &operation);
1222*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1223*d14abf15SRobert Mustacchi     {
1224*d14abf15SRobert Mustacchi         return lm_status;
1225*d14abf15SRobert Mustacchi     }
1226*d14abf15SRobert Mustacchi 
1227*d14abf15SRobert Mustacchi     return lm_status;
1228*d14abf15SRobert Mustacchi }
1229*d14abf15SRobert Mustacchi 
lm_dmae_reg_wr_phys(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_address_t source_paddr,u32_t dest_offset,u16_t length)1230*d14abf15SRobert Mustacchi lm_status_t lm_dmae_reg_wr_phys(struct _lm_device_t* pdev, lm_dmae_context_t* context, lm_address_t source_paddr, u32_t dest_offset, u16_t length)
1231*d14abf15SRobert Mustacchi {
1232*d14abf15SRobert Mustacchi     lm_dmae_address_t source =lm_dmae_address(source_paddr.as_u64, LM_DMAE_ADDRESS_HOST_PHYS);
1233*d14abf15SRobert Mustacchi     lm_dmae_address_t dest = lm_dmae_address(dest_offset, LM_DMAE_ADDRESS_GRC);
1234*d14abf15SRobert Mustacchi     lm_dmae_operation_t operation = {0};
1235*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
1236*d14abf15SRobert Mustacchi 
1237*d14abf15SRobert Mustacchi     DbgBreakIf(dest_offset > MAX_GRC_OFFSET); //make sure dest_offset is a valid GRC offset
1238*d14abf15SRobert Mustacchi 
1239*d14abf15SRobert Mustacchi     lm_status = lm_dmae_operation_create(pdev, source, dest, length, FALSE, FALSE, context, &operation);
1240*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1241*d14abf15SRobert Mustacchi     {
1242*d14abf15SRobert Mustacchi         return lm_status;
1243*d14abf15SRobert Mustacchi     }
1244*d14abf15SRobert Mustacchi 
1245*d14abf15SRobert Mustacchi     lm_status = lm_dmae_context_execute(pdev, context, &operation);
1246*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1247*d14abf15SRobert Mustacchi     {
1248*d14abf15SRobert Mustacchi         return lm_status;
1249*d14abf15SRobert Mustacchi     }
1250*d14abf15SRobert Mustacchi 
1251*d14abf15SRobert Mustacchi     return lm_status;
1252*d14abf15SRobert Mustacchi }
1253*d14abf15SRobert Mustacchi 
lm_dmae_reg_rd(struct _lm_device_t * pdev,lm_dmae_context_t * context,u32_t source_offset,void * dest_vaddr,u16_t length,u8_t le32_swap)1254*d14abf15SRobert Mustacchi lm_status_t lm_dmae_reg_rd(struct _lm_device_t* pdev, lm_dmae_context_t* context, u32_t source_offset, void* dest_vaddr, u16_t length, u8_t le32_swap)
1255*d14abf15SRobert Mustacchi {
1256*d14abf15SRobert Mustacchi     lm_address_t dest_offset = {{0}};
1257*d14abf15SRobert Mustacchi     lm_dmae_address_t source = lm_dmae_address(source_offset, LM_DMAE_ADDRESS_GRC);
1258*d14abf15SRobert Mustacchi     lm_dmae_address_t dest = {{0}};
1259*d14abf15SRobert Mustacchi     lm_dmae_operation_t operation = {0};
1260*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
1261*d14abf15SRobert Mustacchi 
1262*d14abf15SRobert Mustacchi     DbgBreakIf(source_offset > MAX_GRC_OFFSET); //make sure source_offset is a valid GRC offset
1263*d14abf15SRobert Mustacchi 
1264*d14abf15SRobert Mustacchi     dest_offset.as_ptr = dest_vaddr;
1265*d14abf15SRobert Mustacchi     dest = lm_dmae_address(dest_offset.as_u64, LM_DMAE_ADDRESS_HOST_VIRT);
1266*d14abf15SRobert Mustacchi 
1267*d14abf15SRobert Mustacchi     lm_status = lm_dmae_operation_create(pdev, source, dest, length, FALSE, le32_swap, context, &operation);
1268*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1269*d14abf15SRobert Mustacchi     {
1270*d14abf15SRobert Mustacchi         return lm_status;
1271*d14abf15SRobert Mustacchi     }
1272*d14abf15SRobert Mustacchi 
1273*d14abf15SRobert Mustacchi     lm_status = lm_dmae_context_execute(pdev, context, &operation);
1274*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1275*d14abf15SRobert Mustacchi     {
1276*d14abf15SRobert Mustacchi         return lm_status;
1277*d14abf15SRobert Mustacchi     }
1278*d14abf15SRobert Mustacchi 
1279*d14abf15SRobert Mustacchi     return lm_status;
1280*d14abf15SRobert Mustacchi }
1281*d14abf15SRobert Mustacchi 
lm_dmae_copy_phys_buffer_unsafe(struct _lm_device_t * pdev,lm_dmae_context_t * context,lm_address_t source_paddr,lm_address_t dest_paddr,u16_t length)1282*d14abf15SRobert Mustacchi lm_status_t lm_dmae_copy_phys_buffer_unsafe(struct _lm_device_t* pdev, lm_dmae_context_t* context, lm_address_t source_paddr, lm_address_t dest_paddr, u16_t length)
1283*d14abf15SRobert Mustacchi {
1284*d14abf15SRobert Mustacchi     lm_dmae_address_t source = lm_dmae_address(source_paddr.as_u64, LM_DMAE_ADDRESS_HOST_PHYS);
1285*d14abf15SRobert Mustacchi     lm_dmae_address_t dest = lm_dmae_address(dest_paddr.as_u64, LM_DMAE_ADDRESS_HOST_PHYS);
1286*d14abf15SRobert Mustacchi     lm_dmae_operation_t operation = {0};
1287*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
1288*d14abf15SRobert Mustacchi 
1289*d14abf15SRobert Mustacchi     lm_status = lm_dmae_operation_create(pdev, source, dest, length, FALSE, FALSE, context, &operation);
1290*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1291*d14abf15SRobert Mustacchi     {
1292*d14abf15SRobert Mustacchi         return lm_status;
1293*d14abf15SRobert Mustacchi     }
1294*d14abf15SRobert Mustacchi 
1295*d14abf15SRobert Mustacchi     lm_status = lm_dmae_context_execute_unsafe(pdev, context, &operation);
1296*d14abf15SRobert Mustacchi     if (LM_STATUS_ABORTED == lm_status)
1297*d14abf15SRobert Mustacchi     {
1298*d14abf15SRobert Mustacchi         //if the operation failed due to lm_reset_is_inprogress, treat it as success.
1299*d14abf15SRobert Mustacchi         lm_status = LM_STATUS_SUCCESS;
1300*d14abf15SRobert Mustacchi     }
1301*d14abf15SRobert Mustacchi 
1302*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS != lm_status)
1303*d14abf15SRobert Mustacchi     {
1304*d14abf15SRobert Mustacchi         return lm_status;
1305*d14abf15SRobert Mustacchi     }
1306*d14abf15SRobert Mustacchi 
1307*d14abf15SRobert Mustacchi     return lm_status;
1308*d14abf15SRobert Mustacchi }
1309*d14abf15SRobert Mustacchi 
1310*d14abf15SRobert Mustacchi 
1311*d14abf15SRobert Mustacchi /**
1312*d14abf15SRobert Mustacchi  * @}
1313*d14abf15SRobert Mustacchi  */
1314*d14abf15SRobert Mustacchi 
1315