[MLX4] Soft Reset: (bugfix in error flow) handling a case when MLX4_BUS fails during...
[mirror/winof/.git] / hw / mlx4 / kernel / bus / drv / pdo.c
1 #include "precomp.h"\r
2 #include <initguid.h>\r
3 #include <wdmguid.h>\r
4 \r
5 #if defined (EVENT_TRACING)\r
6 #ifdef offsetof\r
7 #undef offsetof\r
8 #endif\r
9 #include "pdo.tmh"\r
10 #endif \r
11 \r
12 #ifdef ALLOC_PRAGMA\r
13 #pragma alloc_text(PAGE, create_pdo)\r
14 #endif\r
15 \r
16 #define MAX_ID_LEN 80\r
17 \r
18 NTSTATUS\r
19 EvtDeviceProcessQueryInterfaceRequest(\r
20         IN WDFDEVICE  Device,\r
21         IN LPGUID  InterfaceType,\r
22         IN OUT PINTERFACE  ExposedInterface,\r
23         IN OUT PVOID  ExposedInterfaceSpecificData\r
24         )\r
25 {\r
26         PPDO_DEVICE_DATA p_pdo = PdoGetData(Device);\r
27         PFDO_DEVICE_DATA p_fdo  = p_pdo->p_fdo;\r
28         PMLX4_BUS_IB_INTERFACE p_ib_ifc = (PMLX4_BUS_IB_INTERFACE)ExposedInterface;\r
29 \r
30         UNUSED_PARAM(InterfaceType);\r
31         UNUSED_PARAM(ExposedInterfaceSpecificData);\r
32 \r
33         if (p_fdo->pci_dev.dev) {\r
34                 p_ib_ifc->p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;\r
35                 p_ib_ifc->pmlx4_dev = p_fdo->bus_ib_ifc.pmlx4_dev;\r
36                 p_ib_ifc->is_livefish = p_fdo->bus_ib_ifc.is_livefish;\r
37                 return STATUS_SUCCESS;\r
38         }\r
39         else {\r
40                 p_ib_ifc->p_ibdev = NULL;\r
41                 p_ib_ifc->pmlx4_dev = NULL;\r
42                 p_ib_ifc->is_livefish = FALSE;\r
43                 return STATUS_UNSUCCESSFUL;\r
44         }\r
45 \r
46 }\r
47 \r
48 NTSTATUS\r
49 create_pdo(\r
50         __in WDFDEVICE  Device,\r
51         __in PWCHAR     HardwareIds,\r
52         __in PWCHAR     DeviceDescription,\r
53         __in ULONG      SerialNo\r
54 )\r
55 /*++\r
56 \r
57 Routine Description:\r
58 \r
59     This routine creates and initialize a PDO.\r
60 \r
61 Arguments:\r
62 \r
63 Return Value:\r
64 \r
65     NT Status code.\r
66 \r
67 --*/\r
68 {\r
69         NTSTATUS                    status;\r
70         PWDFDEVICE_INIT             pDeviceInit = NULL;\r
71         PPDO_DEVICE_DATA            p_pdo = NULL;\r
72         PFDO_DEVICE_DATA            p_fdo;\r
73         WDFDEVICE                   hChild = NULL;\r
74         WDF_OBJECT_ATTRIBUTES       pdoAttributes;\r
75         WDF_DEVICE_PNP_CAPABILITIES pnpCaps;\r
76         WDF_DEVICE_POWER_CAPABILITIES powerCaps;\r
77         UNICODE_STRING compatId;\r
78         DECLARE_CONST_UNICODE_STRING(deviceLocation, L"MLX4 Bus 0");\r
79         UNICODE_STRING deviceId;\r
80         DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);\r
81 \r
82         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("Entered CreatePdo\n"));\r
83 \r
84         RtlInitUnicodeString(&compatId, HardwareIds);\r
85         PAGED_CODE();\r
86 \r
87         //\r
88         // Allocate a WDFDEVICE_INIT structure and set the properties\r
89         // so that we can create a device object for the child.\r
90         //\r
91         pDeviceInit = WdfPdoInitAllocate(Device);\r
92 \r
93         if (pDeviceInit == NULL) {\r
94                 status = STATUS_INSUFFICIENT_RESOURCES;\r
95                 goto Cleanup;\r
96         }\r
97 \r
98         //\r
99         // Set DeviceType\r
100         //\r
101         WdfDeviceInitSetDeviceType(pDeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
102 \r
103         //\r
104         // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId\r
105         //\r
106         RtlInitUnicodeString(&deviceId,HardwareIds);\r
107 \r
108         status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);\r
109         if (!NT_SUCCESS(status)) {\r
110                 goto Cleanup;\r
111         }\r
112 \r
113         //\r
114         // Note same string  is used to initialize hardware id too\r
115         //\r
116         status = WdfPdoInitAddHardwareID(pDeviceInit, &deviceId);\r
117         if (!NT_SUCCESS(status)) {\r
118                 goto Cleanup;\r
119         }\r
120 \r
121         status = WdfPdoInitAddCompatibleID(pDeviceInit, &compatId);\r
122         if (!NT_SUCCESS(status)) {\r
123                 goto Cleanup;\r
124         }\r
125 \r
126         status =  RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo);\r
127         if (!NT_SUCCESS(status)) {\r
128                 goto Cleanup;\r
129         }\r
130 \r
131         status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);\r
132         if (!NT_SUCCESS(status)) {\r
133                 goto Cleanup;\r
134         }\r
135 \r
136         //\r
137         // Provide a description about the device. This text is usually read from\r
138         // the device. In the case of USB device, this text comes from the string\r
139         // descriptor. This text is displayed momentarily by the PnP manager while\r
140         // it's looking for a matching INF. If it finds one, it uses the Device\r
141         // Description from the INF file or the friendly name created by\r
142         // coinstallers to display in the device manager. FriendlyName takes\r
143         // precedence over the DeviceDesc from the INF file.\r
144         //\r
145         status = RtlUnicodeStringPrintf(&buffer,DeviceDescription  , SerialNo );\r
146         \r
147         if (!NT_SUCCESS(status)) {\r
148                 goto Cleanup;\r
149         }\r
150 \r
151         //\r
152         // You can call WdfPdoInitAddDeviceText multiple times, adding device\r
153         // text for multiple locales. When the system displays the text, it\r
154         // chooses the text that matches the current locale, if available.\r
155         // Otherwise it will use the string for the default locale.\r
156         // The driver can specify the driver's default locale by calling\r
157         // WdfPdoInitSetDefaultLocale.\r
158         //\r
159         status = WdfPdoInitAddDeviceText(pDeviceInit,\r
160                 &buffer, &deviceLocation, 0x409);\r
161         if (!NT_SUCCESS(status)) {\r
162                 goto Cleanup;\r
163         }\r
164 \r
165         WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);\r
166 \r
167         //\r
168         // Initialize the attributes to specify the size of PDO device extension.\r
169         // All the state information private to the PDO will be tracked here.\r
170         //\r
171         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA);\r
172 \r
173         status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);\r
174         if (!NT_SUCCESS(status)) {\r
175                 goto Cleanup;\r
176         }\r
177 \r
178         //\r
179         // Once the device is created successfully, framework frees the\r
180         // DeviceInit memory and sets the pDeviceInit to NULL. So don't\r
181         // call any WdfDeviceInit functions after that.\r
182         //\r
183         // Get the device context.\r
184         //\r
185         p_pdo = PdoGetData(hChild);\r
186         p_fdo = FdoGetData(Device);\r
187 \r
188         p_pdo->p_fdo = p_fdo;\r
189         p_pdo->SerialNo = SerialNo;\r
190         p_pdo->PdoDevice = hChild;\r
191 \r
192         //\r
193         // Set PnP properties for the child device.\r
194         //\r
195         WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);\r
196         pnpCaps.Removable         = WdfTrue;\r
197         pnpCaps.EjectSupported    = WdfTrue;\r
198         pnpCaps.SurpriseRemovalOK = WdfTrue;\r
199 \r
200         pnpCaps.Address  = SerialNo;\r
201         pnpCaps.UINumber = SerialNo;\r
202 \r
203         WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);\r
204 \r
205         //\r
206         // Set Power properties for the child device\r
207         //\r
208         WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);\r
209 \r
210         powerCaps.DeviceD1 = WdfTrue;\r
211         powerCaps.WakeFromD1 = WdfTrue;\r
212         powerCaps.DeviceWake = PowerDeviceD1;\r
213 \r
214         powerCaps.DeviceState[PowerSystemWorking]   = PowerDeviceD0;\r
215         powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;\r
216         powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
217         powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
218         powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
219         powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
220 \r
221         WdfDeviceSetPowerCapabilities(hChild, &powerCaps);\r
222 \r
223         //\r
224         // Set bus IB interface\r
225         //\r
226         p_fdo->bus_ib_ifc.port_id = (u8) SerialNo;\r
227         p_fdo->bus_ib_ifc.pVipBusIfc = &p_fdo->mtnic_Ifc;\r
228         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_pd_alloc = mlx4_pd_alloc;\r
229         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_pd_free = mlx4_pd_free;\r
230         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_uar_alloc = mlx4_uar_alloc;\r
231         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_uar_free = mlx4_uar_free;\r
232         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_mr_alloc = mlx4_mr_alloc;\r
233         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_mr_free = mlx4_mr_free;\r
234         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_mr_enable = mlx4_mr_enable;\r
235         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_get_region = mlx4_qp_get_region;\r
236         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_alloc_hwq_res = mlx4_alloc_hwq_res;\r
237         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_free_hwq_res = mlx4_free_hwq_res;\r
238 \r
239         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cq_alloc = mlx4_cq_alloc;\r
240         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cq_free = mlx4_cq_free;\r
241         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cq_modify = mlx4_cq_modify;\r
242         \r
243         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_register_mac = mlx4_register_mac;\r
244         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_unregister_mac = mlx4_unregister_mac;\r
245         \r
246         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_alloc = mlx4_srq_alloc;\r
247         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_free = mlx4_srq_free;\r
248         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_invalidate = mlx4_srq_invalidate;\r
249         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_remove = mlx4_srq_remove;\r
250 \r
251         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_alloc = mlx4_qp_alloc;\r
252         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_free = mlx4_qp_free;\r
253         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_remove = mlx4_qp_remove;\r
254         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_modify = mlx4_qp_modify;\r
255         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_to_ready = mlx4_qp_to_ready;\r
256         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_reserve_range = mlx4_qp_reserve_range;\r
257         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_release_range = mlx4_qp_release_range;\r
258 \r
259         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_alloc_cmd_mailbox = mlx4_alloc_cmd_mailbox;\r
260         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_free_cmd_mailbox = mlx4_free_cmd_mailbox;\r
261         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cmd = imlx4_cmd;\r
262 \r
263         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_INIT_PORT = mlx4_INIT_PORT;\r
264         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_CLOSE_PORT = mlx4_CLOSE_PORT;\r
265         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_add_eq = mlx4_add_eq;\r
266         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_remove_eq = mlx4_remove_eq;\r
267         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_register_ev_cb = mlx4_reset_cb_register;\r
268         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_unregister_ev_cb = mlx4_reset_cb_unregister;\r
269         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_reset_request = mlx4_reset_request;\r
270         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_reset_execute = mlx4_reset_execute;\r
271         \r
272         //\r
273         // Create a custom interface so that other drivers can\r
274         // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly.\r
275         //\r
276         p_fdo->bus_ib_ifc.i.Context = p_pdo;\r
277 \r
278         WDF_QUERY_INTERFACE_CONFIG_INIT( &p_pdo->qiMlx4Bus,\r
279                 (PINTERFACE) &p_fdo->bus_ib_ifc,\r
280                 &MLX4_BUS_IB_INTERFACE_GUID, EvtDeviceProcessQueryInterfaceRequest);\r
281 \r
282         status = WdfDeviceAddQueryInterface( hChild, &p_pdo->qiMlx4Bus );\r
283         if (!NT_SUCCESS(status))\r
284                 goto Cleanup;\r
285 \r
286         //\r
287         // Expose also PCI.SYS interface for MLX4_HCA\r
288         //\r
289         WDF_QUERY_INTERFACE_CONFIG_INIT( &p_pdo->qiPciBus,\r
290                 (PINTERFACE) &p_fdo->pci_dev.bus_pci_ifc,\r
291                 &GUID_BUS_INTERFACE_STANDARD, NULL);\r
292 \r
293         // TODO: Soft Reset - how tobar getting interface during RESET_IN_PROGRESS\r
294         // maybe - using EvtDeviceProcessQueryInterfaceRequest\r
295         status = WdfDeviceAddQueryInterface( hChild, &p_pdo->qiPciBus );\r
296         if (!NT_SUCCESS(status))\r
297                 goto Cleanup;\r
298 \r
299         //\r
300         // Add this device to the FDO's collection of children.\r
301         // After the child device is added to the static collection successfully,\r
302         // driver must call WdfPdoMarkMissing to get the device deleted. It\r
303         // shouldn't delete the child device directly by calling WdfObjectDelete.\r
304         //\r
305         status = WdfFdoAddStaticChild(Device, hChild);\r
306         if (!NT_SUCCESS(status)) {\r
307                 goto Cleanup;\r
308         }\r
309 \r
310         return status;\r
311 \r
312 Cleanup:\r
313         KdPrint(("BusEnum: Bus_CreatePdo failed %x\n", status));\r
314 \r
315         //\r
316         // Call WdfDeviceInitFree if you encounter an error before the\r
317         // device is created. Once the device is created, framework\r
318         // NULLs the pDeviceInit value.\r
319         //\r
320         if (pDeviceInit != NULL) {\r
321                 WdfDeviceInitFree(pDeviceInit);\r
322         }\r
323 \r
324         if(hChild) {\r
325                 WdfObjectDelete(hChild);\r
326         }\r
327 \r
328         return status;\r
329 }\r
330 \r
331 \r