|
@@ -10,6 +10,15 @@ Skeleton NIC driver for Etherboot
|
10
|
10
|
* your option) any later version.
|
11
|
11
|
*/
|
12
|
12
|
|
|
13
|
+#include <errno.h>
|
|
14
|
+#include <gpxe/pci.h>
|
|
15
|
+#include <gpxe/iobuf.h>
|
|
16
|
+#include <gpxe/netdevice.h>
|
|
17
|
+#include <gpxe/infiniband.h>
|
|
18
|
+
|
|
19
|
+struct mlx_nic {
|
|
20
|
+};
|
|
21
|
+
|
13
|
22
|
|
14
|
23
|
#include "etherboot.h"
|
15
|
24
|
|
|
@@ -145,6 +154,131 @@ static void mt25218_transmit(struct nic *nic, const char *dest,
|
145
|
154
|
}
|
146
|
155
|
}
|
147
|
156
|
|
|
157
|
+
|
|
158
|
+ * Open network device
|
|
159
|
+ *
|
|
160
|
+ * @v netdev Network device
|
|
161
|
+ * @ret rc Return status code
|
|
162
|
+ */
|
|
163
|
+static int mlx_open ( struct net_device *netdev ) {
|
|
164
|
+ return 0;
|
|
165
|
+}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+ * Close network device
|
|
169
|
+ *
|
|
170
|
+ * @v netdev Network device
|
|
171
|
+ */
|
|
172
|
+static void mlx_close ( struct net_device *netdev ) {
|
|
173
|
+}
|
|
174
|
+
|
|
175
|
+#warning "Broadcast address?"
|
|
176
|
+static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+ * Transmit packet
|
|
181
|
+ *
|
|
182
|
+ * @v netdev Network device
|
|
183
|
+ * @v iobuf I/O buffer
|
|
184
|
+ * @ret rc Return status code
|
|
185
|
+ */
|
|
186
|
+static int mlx_transmit ( struct net_device *netdev,
|
|
187
|
+ struct io_buffer *iobuf ) {
|
|
188
|
+ struct ibhdr *ibhdr = iobuf->data;
|
|
189
|
+
|
|
190
|
+ DBG ( "Sending packet:\n" );
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+ DBG ( "Peer:\n" );
|
|
194
|
+ DBG_HD ( &ibhdr->peer[0], IB_ALEN );
|
|
195
|
+ DBG ( "Bcast:\n" );
|
|
196
|
+ DBG_HD ( &ib_broadcast[0], IB_ALEN );
|
|
197
|
+
|
|
198
|
+ iob_pull ( iobuf, sizeof ( *ibhdr ) );
|
|
199
|
+
|
|
200
|
+ if ( memcmp ( ibhdr->peer, ib_broadcast, IB_ALEN ) == 0 ) {
|
|
201
|
+ printf ( "Sending broadcast packet\n" );
|
|
202
|
+ return send_bcast_packet ( ibhdr->proto, iobuf->data,
|
|
203
|
+ iob_len ( iobuf ) );
|
|
204
|
+ } else {
|
|
205
|
+ printf ( "Sending unicast packet\n" );
|
|
206
|
+ return send_ucast_packet ( ibhdr->peer, ibhdr->proto,
|
|
207
|
+ iobuf->data, iob_len ( iobuf ) );
|
|
208
|
+ }
|
|
209
|
+}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+ * Poll for completed and received packets
|
|
213
|
+ *
|
|
214
|
+ * @v netdev Network device
|
|
215
|
+ */
|
|
216
|
+static void mlx_poll ( struct net_device *netdev ) {
|
|
217
|
+ struct ib_cqe_st ib_cqe;
|
|
218
|
+ uint8_t num_cqes;
|
|
219
|
+ unsigned int len;
|
|
220
|
+ struct io_buffer *iobuf;
|
|
221
|
+ void *buf;
|
|
222
|
+ int rc;
|
|
223
|
+
|
|
224
|
+ if ( ( rc = poll_error_buf() ) != 0 ) {
|
|
225
|
+ DBG ( "poll_error_buf() failed: %s\n", strerror ( rc ) );
|
|
226
|
+ return;
|
|
227
|
+ }
|
|
228
|
+
|
|
229
|
+ if ( ( rc = drain_eq() ) != 0 ) {
|
|
230
|
+ DBG ( "drain_eq() failed: %s\n", strerror ( rc ) );
|
|
231
|
+ return;
|
|
232
|
+ }
|
|
233
|
+
|
|
234
|
+ if ( ( rc = ib_poll_cq ( ipoib_data.rcv_cqh, &ib_cqe,
|
|
235
|
+ &num_cqes ) ) != 0 ) {
|
|
236
|
+ DBG ( "ib_poll_cq() failed: %s\n", strerror ( rc ) );
|
|
237
|
+ return;
|
|
238
|
+ }
|
|
239
|
+
|
|
240
|
+ if ( ! num_cqes )
|
|
241
|
+ return;
|
|
242
|
+
|
|
243
|
+ if ( ib_cqe.is_error ) {
|
|
244
|
+ DBG ( "cqe error\n" );
|
|
245
|
+ free_wqe ( ib_cqe.wqe );
|
|
246
|
+ return;
|
|
247
|
+ }
|
|
248
|
+
|
|
249
|
+ len = ib_cqe.count;
|
|
250
|
+ iobuf = alloc_iob ( len );
|
|
251
|
+ if ( ! iobuf ) {
|
|
252
|
+ DBG ( "out of memory\n" );
|
|
253
|
+ free_wqe ( ib_cqe.wqe );
|
|
254
|
+ return;
|
|
255
|
+ }
|
|
256
|
+ memcpy ( iob_put ( iobuf, len ), buf, len );
|
|
257
|
+ DBG ( "Received packet:\n" );
|
|
258
|
+ DBG_HD ( iobuf->data, iob_len ( iobuf ) );
|
|
259
|
+
|
|
260
|
+ netdev_rx ( netdev, iobuf );
|
|
261
|
+
|
|
262
|
+ free_wqe ( ib_cqe.wqe );
|
|
263
|
+}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+ * Enable or disable interrupts
|
|
267
|
+ *
|
|
268
|
+ * @v netdev Network device
|
|
269
|
+ * @v enable Interrupts should be enabled
|
|
270
|
+ */
|
|
271
|
+static void mlx_irq ( struct net_device *netdev, int enable ) {
|
|
272
|
+}
|
|
273
|
+
|
|
274
|
+static struct net_device_operations mlx_operations = {
|
|
275
|
+ .open = mlx_open,
|
|
276
|
+ .close = mlx_close,
|
|
277
|
+ .transmit = mlx_transmit,
|
|
278
|
+ .poll = mlx_poll,
|
|
279
|
+ .irq = mlx_irq,
|
|
280
|
+};
|
|
281
|
+
|
148
|
282
|
|
149
|
283
|
DISABLE - Turn off ethernet interface
|
150
|
284
|
***************************************************************************/
|
|
@@ -165,6 +299,21 @@ static void mt25218_disable(struct nic *nic)
|
165
|
299
|
}
|
166
|
300
|
}
|
167
|
301
|
|
|
302
|
+
|
|
303
|
+ * Remove PCI device
|
|
304
|
+ *
|
|
305
|
+ * @v pci PCI device
|
|
306
|
+ */
|
|
307
|
+static void mlx_remove ( struct pci_device *pci ) {
|
|
308
|
+ struct net_device *netdev = pci_get_drvdata ( pci );
|
|
309
|
+ struct mlx_nic *mlx = netdev->priv;
|
|
310
|
+
|
|
311
|
+ unregister_netdev ( netdev );
|
|
312
|
+ ipoib_close(0);
|
|
313
|
+ netdev_nullify ( netdev );
|
|
314
|
+ netdev_put ( netdev );
|
|
315
|
+}
|
|
316
|
+
|
168
|
317
|
static struct nic_operations mt25218_operations = {
|
169
|
318
|
.connect = dummy_connect,
|
170
|
319
|
.poll = mt25218_poll,
|
|
@@ -233,12 +382,59 @@ static int mt25218_probe(struct nic *nic, struct pci_device *pci)
|
233
|
382
|
return 0;
|
234
|
383
|
}
|
235
|
384
|
|
236
|
|
-static struct pci_device_id mt25218_nics[] = {
|
|
385
|
+
|
|
386
|
+ * Probe PCI device
|
|
387
|
+ *
|
|
388
|
+ * @v pci PCI device
|
|
389
|
+ * @v id PCI ID
|
|
390
|
+ * @ret rc Return status code
|
|
391
|
+ */
|
|
392
|
+static int mlx_probe ( struct pci_device *pci,
|
|
393
|
+ const struct pci_device_id *id __unused ) {
|
|
394
|
+ struct net_device *netdev;
|
|
395
|
+ struct mlx_nic *mlx;
|
|
396
|
+ int rc;
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+ netdev = alloc_ibdev ( sizeof ( *mlx ) );
|
|
400
|
+ if ( ! netdev )
|
|
401
|
+ return -ENOMEM;
|
|
402
|
+ netdev_init ( netdev, &mlx_operations );
|
|
403
|
+ mlx = netdev->priv;
|
|
404
|
+ pci_set_drvdata ( pci, netdev );
|
|
405
|
+ netdev->dev = &pci->dev;
|
|
406
|
+ memset ( mlx, 0, sizeof ( *mlx ) );
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+ adjust_pci_device ( pci );
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+ if ( ( rc = ipoib_init ( pci ) ) != 0 )
|
|
413
|
+ goto err_ipoib_init;
|
|
414
|
+ memcpy ( netdev->ll_addr, ipoib_data.port_gid_raw, IB_ALEN );
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
|
418
|
+ goto err_register_netdev;
|
|
419
|
+
|
|
420
|
+ return 0;
|
|
421
|
+
|
|
422
|
+ err_register_netdev:
|
|
423
|
+ err_ipoib_init:
|
|
424
|
+ ipoib_close(0);
|
|
425
|
+ netdev_nullify ( netdev );
|
|
426
|
+ netdev_put ( netdev );
|
|
427
|
+ return rc;
|
|
428
|
+}
|
|
429
|
+
|
|
430
|
+static struct pci_device_id mlx_nics[] = {
|
237
|
431
|
PCI_ROM(0x15b3, 0x6282, "MT25218", "MT25218 HCA driver"),
|
238
|
432
|
PCI_ROM(0x15b3, 0x6274, "MT25204", "MT25204 HCA driver"),
|
239
|
433
|
};
|
240
|
434
|
|
241
|
|
-PCI_DRIVER ( mt25218_driver, mt25218_nics, PCI_NO_CLASS );
|
242
|
|
-
|
243
|
|
-DRIVER ( "MT25218", nic_driver, pci_driver, mt25218_driver,
|
244
|
|
- mt25218_probe, mt25218_disable );
|
|
435
|
+struct pci_driver mlx_driver __pci_driver = {
|
|
436
|
+ .ids = mlx_nics,
|
|
437
|
+ .id_count = ( sizeof ( mlx_nics ) / sizeof ( mlx_nics[0] ) ),
|
|
438
|
+ .probe = mlx_probe,
|
|
439
|
+ .remove = mlx_remove,
|
|
440
|
+};
|