|
@@ -36,6 +36,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
36
|
36
|
#include <ipxe/netdevice.h>
|
37
|
37
|
#include <ipxe/infiniband.h>
|
38
|
38
|
#include <ipxe/ib_smc.h>
|
|
39
|
+#include <ipxe/if_ether.h>
|
|
40
|
+#include <ipxe/ethernet.h>
|
39
|
41
|
#include "hermon.h"
|
40
|
42
|
|
41
|
43
|
/**
|
|
@@ -304,12 +306,13 @@ hermon_cmd_close_port ( struct hermon *hermon, unsigned int port ) {
|
304
|
306
|
}
|
305
|
307
|
|
306
|
308
|
static inline int
|
307
|
|
-hermon_cmd_set_port ( struct hermon *hermon, unsigned int port,
|
308
|
|
- union hermonprm_set_port *set_port ) {
|
|
309
|
+hermon_cmd_set_port ( struct hermon *hermon, int is_ethernet,
|
|
310
|
+ unsigned int port_selector,
|
|
311
|
+ const union hermonprm_set_port *set_port ) {
|
309
|
312
|
return hermon_cmd ( hermon,
|
310
|
313
|
HERMON_HCR_IN_CMD ( HERMON_HCR_SET_PORT,
|
311
|
314
|
1, sizeof ( *set_port ) ),
|
312
|
|
- 0, set_port, port, NULL );
|
|
315
|
+ is_ethernet, set_port, port_selector, NULL );
|
313
|
316
|
}
|
314
|
317
|
|
315
|
318
|
static inline int
|
|
@@ -491,6 +494,24 @@ hermon_cmd_mgid_hash ( struct hermon *hermon, const union ib_gid *gid,
|
491
|
494
|
0, gid, 0, hash );
|
492
|
495
|
}
|
493
|
496
|
|
|
497
|
+static inline int
|
|
498
|
+hermon_cmd_query_port ( struct hermon *hermon, unsigned int port,
|
|
499
|
+ struct hermonprm_query_port_cap *query_port ) {
|
|
500
|
+ return hermon_cmd ( hermon,
|
|
501
|
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_QUERY_PORT,
|
|
502
|
+ 1, sizeof ( *query_port ) ),
|
|
503
|
+ 0, NULL, port, query_port );
|
|
504
|
+}
|
|
505
|
+
|
|
506
|
+static inline int
|
|
507
|
+hermon_cmd_sense_port ( struct hermon *hermon, unsigned int port,
|
|
508
|
+ struct hermonprm_sense_port *port_type ) {
|
|
509
|
+ return hermon_cmd ( hermon,
|
|
510
|
+ HERMON_HCR_OUT_CMD ( HERMON_HCR_SENSE_PORT,
|
|
511
|
+ 1, sizeof ( *port_type ) ),
|
|
512
|
+ 0, NULL, port, port_type );
|
|
513
|
+}
|
|
514
|
+
|
494
|
515
|
static inline int
|
495
|
516
|
hermon_cmd_run_fw ( struct hermon *hermon ) {
|
496
|
517
|
return hermon_cmd ( hermon,
|
|
@@ -559,16 +580,6 @@ hermon_cmd_map_fa ( struct hermon *hermon,
|
559
|
580
|
0, map, 1, NULL );
|
560
|
581
|
}
|
561
|
582
|
|
562
|
|
-static inline int
|
563
|
|
-hermon_cmd_sense_port ( struct hermon *hermon, unsigned int port,
|
564
|
|
- struct hermonprm_sense_port *port_type ) {
|
565
|
|
- return hermon_cmd ( hermon,
|
566
|
|
- HERMON_HCR_OUT_CMD ( HERMON_HCR_SENSE_PORT,
|
567
|
|
- 1, sizeof ( *port_type ) ),
|
568
|
|
- 0, NULL, port, port_type );
|
569
|
|
-}
|
570
|
|
-
|
571
|
|
-
|
572
|
583
|
/***************************************************************************
|
573
|
584
|
*
|
574
|
585
|
* Memory translation table operations
|
|
@@ -916,6 +927,7 @@ static int hermon_alloc_qpn ( struct ib_device *ibdev,
|
916
|
927
|
return 0;
|
917
|
928
|
case IB_QPT_UD:
|
918
|
929
|
case IB_QPT_RC:
|
|
930
|
+ case IB_QPT_ETH:
|
919
|
931
|
/* Find a free queue pair number */
|
920
|
932
|
qpn_offset = hermon_bitmask_alloc ( hermon->qp_inuse,
|
921
|
933
|
HERMON_MAX_QPS, 1 );
|
|
@@ -982,6 +994,7 @@ static uint8_t hermon_qp_st[] = {
|
982
|
994
|
[IB_QPT_GSI] = HERMON_ST_MLX,
|
983
|
995
|
[IB_QPT_UD] = HERMON_ST_UD,
|
984
|
996
|
[IB_QPT_RC] = HERMON_ST_RC,
|
|
997
|
+ [IB_QPT_ETH] = HERMON_ST_MLX,
|
985
|
998
|
};
|
986
|
999
|
|
987
|
1000
|
/**
|
|
@@ -1163,7 +1176,9 @@ static int hermon_modify_qp ( struct ib_device *ibdev,
|
1163
|
1176
|
if ( hermon_qp->state < HERMON_QP_ST_RTR ) {
|
1164
|
1177
|
memset ( &qpctx, 0, sizeof ( qpctx ) );
|
1165
|
1178
|
MLX_FILL_2 ( &qpctx, 4,
|
1166
|
|
- qpc_eec_data.mtu, HERMON_MTU_2048,
|
|
1179
|
+ qpc_eec_data.mtu,
|
|
1180
|
+ ( ( qp->type == IB_QPT_ETH ) ?
|
|
1181
|
+ HERMON_MTU_ETH : HERMON_MTU_2048 ),
|
1167
|
1182
|
qpc_eec_data.msg_max, 31 );
|
1168
|
1183
|
MLX_FILL_1 ( &qpctx, 7,
|
1169
|
1184
|
qpc_eec_data.remote_qpn_een, qp->av.qpn );
|
|
@@ -1402,6 +1417,38 @@ hermon_fill_rc_send_wqe ( struct ib_device *ibdev,
|
1402
|
1417
|
return HERMON_OPCODE_SEND;
|
1403
|
1418
|
}
|
1404
|
1419
|
|
|
1420
|
+/**
|
|
1421
|
+ * Construct Ethernet send work queue entry
|
|
1422
|
+ *
|
|
1423
|
+ * @v ibdev Infiniband device
|
|
1424
|
+ * @v qp Queue pair
|
|
1425
|
+ * @v av Address vector
|
|
1426
|
+ * @v iobuf I/O buffer
|
|
1427
|
+ * @v wqe Send work queue entry
|
|
1428
|
+ * @ret opcode Control opcode
|
|
1429
|
+ */
|
|
1430
|
+static unsigned int
|
|
1431
|
+hermon_fill_eth_send_wqe ( struct ib_device *ibdev,
|
|
1432
|
+ struct ib_queue_pair *qp __unused,
|
|
1433
|
+ struct ib_address_vector *av __unused,
|
|
1434
|
+ struct io_buffer *iobuf,
|
|
1435
|
+ union hermon_send_wqe *wqe ) {
|
|
1436
|
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
|
|
1437
|
+
|
|
1438
|
+ /* Fill work queue entry */
|
|
1439
|
+ MLX_FILL_1 ( &wqe->eth.ctrl, 1, ds,
|
|
1440
|
+ ( ( offsetof ( typeof ( wqe->mlx ), data[1] ) / 16 ) ) );
|
|
1441
|
+ MLX_FILL_2 ( &wqe->eth.ctrl, 2,
|
|
1442
|
+ c, 0x03 /* generate completion */,
|
|
1443
|
+ s, 1 /* inhibit ICRC */ );
|
|
1444
|
+ MLX_FILL_1 ( &wqe->eth.data[0], 0,
|
|
1445
|
+ byte_count, iob_len ( iobuf ) );
|
|
1446
|
+ MLX_FILL_1 ( &wqe->eth.data[0], 1, l_key, hermon->lkey );
|
|
1447
|
+ MLX_FILL_1 ( &wqe->eth.data[0], 3,
|
|
1448
|
+ local_address_l, virt_to_bus ( iobuf->data ) );
|
|
1449
|
+ return HERMON_OPCODE_SEND;
|
|
1450
|
+}
|
|
1451
|
+
|
1405
|
1452
|
/** Work queue entry constructors */
|
1406
|
1453
|
static unsigned int
|
1407
|
1454
|
( * hermon_fill_send_wqe[] ) ( struct ib_device *ibdev,
|
|
@@ -1413,6 +1460,7 @@ static unsigned int
|
1413
|
1460
|
[IB_QPT_GSI] = hermon_fill_mlx_send_wqe,
|
1414
|
1461
|
[IB_QPT_UD] = hermon_fill_ud_send_wqe,
|
1415
|
1462
|
[IB_QPT_RC] = hermon_fill_rc_send_wqe,
|
|
1463
|
+ [IB_QPT_ETH] = hermon_fill_eth_send_wqe,
|
1416
|
1464
|
};
|
1417
|
1465
|
|
1418
|
1466
|
/**
|
|
@@ -1618,6 +1666,9 @@ static int hermon_complete ( struct ib_device *ibdev,
|
1618
|
1666
|
case IB_QPT_RC:
|
1619
|
1667
|
av = &qp->av;
|
1620
|
1668
|
break;
|
|
1669
|
+ case IB_QPT_ETH:
|
|
1670
|
+ av = NULL;
|
|
1671
|
+ break;
|
1621
|
1672
|
default:
|
1622
|
1673
|
assert ( 0 );
|
1623
|
1674
|
return -EINVAL;
|
|
@@ -1826,8 +1877,9 @@ static void hermon_event_port_state_change ( struct hermon *hermon,
|
1826
|
1877
|
return;
|
1827
|
1878
|
}
|
1828
|
1879
|
|
1829
|
|
- /* Update MAD parameters */
|
1830
|
|
- ib_smc_update ( hermon->ibdev[port], hermon_mad );
|
|
1880
|
+ /* Notify device of port state change */
|
|
1881
|
+ hermon->port[port].type->state_change ( hermon, &hermon->port[port],
|
|
1882
|
+ link_up );
|
1831
|
1883
|
}
|
1832
|
1884
|
|
1833
|
1885
|
/**
|
|
@@ -1898,39 +1950,6 @@ static void hermon_poll_eq ( struct ib_device *ibdev ) {
|
1898
|
1950
|
***************************************************************************
|
1899
|
1951
|
*/
|
1900
|
1952
|
|
1901
|
|
-/**
|
1902
|
|
- * Sense port type
|
1903
|
|
- *
|
1904
|
|
- * @v ibdev Infiniband device
|
1905
|
|
- * @ret port_type Port type, or negative error
|
1906
|
|
- */
|
1907
|
|
-static int hermon_sense_port_type ( struct ib_device *ibdev ) {
|
1908
|
|
- struct hermon *hermon = ib_get_drvdata ( ibdev );
|
1909
|
|
- struct hermonprm_sense_port sense_port;
|
1910
|
|
- int port_type;
|
1911
|
|
- int rc;
|
1912
|
|
-
|
1913
|
|
- /* If DPDP is not supported, always assume Infiniband */
|
1914
|
|
- if ( ! hermon->cap.dpdp ) {
|
1915
|
|
- DBGC ( hermon, "Hermon %p does not support DPDP; assuming "
|
1916
|
|
- "Infiniband\n", hermon );
|
1917
|
|
- return HERMON_PORT_TYPE_IB;
|
1918
|
|
- }
|
1919
|
|
-
|
1920
|
|
- /* Sense the port type */
|
1921
|
|
- if ( ( rc = hermon_cmd_sense_port ( hermon, ibdev->port,
|
1922
|
|
- &sense_port ) ) != 0 ) {
|
1923
|
|
- DBGC ( hermon, "Hermon %p port %d sense failed: %s\n",
|
1924
|
|
- hermon, ibdev->port, strerror ( rc ) );
|
1925
|
|
- return rc;
|
1926
|
|
- }
|
1927
|
|
- port_type = MLX_GET ( &sense_port, port_type );
|
1928
|
|
-
|
1929
|
|
- DBGC ( hermon, "Hermon %p port %d type %d\n",
|
1930
|
|
- hermon, ibdev->port, port_type );
|
1931
|
|
- return port_type;
|
1932
|
|
-}
|
1933
|
|
-
|
1934
|
1953
|
/**
|
1935
|
1954
|
* Initialise Infiniband link
|
1936
|
1955
|
*
|
|
@@ -1940,18 +1959,8 @@ static int hermon_sense_port_type ( struct ib_device *ibdev ) {
|
1940
|
1959
|
static int hermon_open ( struct ib_device *ibdev ) {
|
1941
|
1960
|
struct hermon *hermon = ib_get_drvdata ( ibdev );
|
1942
|
1961
|
union hermonprm_set_port set_port;
|
1943
|
|
- int port_type;
|
1944
|
1962
|
int rc;
|
1945
|
1963
|
|
1946
|
|
- /* Check we are connected to an Infiniband network */
|
1947
|
|
- if ( ( rc = port_type = hermon_sense_port_type ( ibdev ) ) < 0 )
|
1948
|
|
- return rc;
|
1949
|
|
- if ( port_type != HERMON_PORT_TYPE_IB ) {
|
1950
|
|
- DBGC ( hermon, "Hermon %p port %d not connected to an "
|
1951
|
|
- "Infiniband network", hermon, ibdev->port );
|
1952
|
|
- return -ENOTCONN;
|
1953
|
|
- }
|
1954
|
|
-
|
1955
|
1964
|
/* Set port parameters */
|
1956
|
1965
|
memset ( &set_port, 0, sizeof ( set_port ) );
|
1957
|
1966
|
MLX_FILL_7 ( &set_port.ib, 0,
|
|
@@ -1965,7 +1974,7 @@ static int hermon_open ( struct ib_device *ibdev ) {
|
1965
|
1974
|
MLX_FILL_2 ( &set_port.ib, 10,
|
1966
|
1975
|
max_pkey, 1,
|
1967
|
1976
|
max_gid, 1 );
|
1968
|
|
- if ( ( rc = hermon_cmd_set_port ( hermon, ibdev->port,
|
|
1977
|
+ if ( ( rc = hermon_cmd_set_port ( hermon, 0, ibdev->port,
|
1969
|
1978
|
&set_port ) ) != 0 ) {
|
1970
|
1979
|
DBGC ( hermon, "Hermon %p port %d could not set port: %s\n",
|
1971
|
1980
|
hermon, ibdev->port, strerror ( rc ) );
|
|
@@ -2136,6 +2145,530 @@ static struct ib_device_operations hermon_ib_operations = {
|
2136
|
2145
|
.set_pkey_table = hermon_inform_sma,
|
2137
|
2146
|
};
|
2138
|
2147
|
|
|
2148
|
+/**
|
|
2149
|
+ * Register Hermon Infiniband device
|
|
2150
|
+ *
|
|
2151
|
+ * @v hermon Hermon device
|
|
2152
|
+ * @v port Hermon port
|
|
2153
|
+ * @ret rc Return status code
|
|
2154
|
+ */
|
|
2155
|
+static int hermon_register_ibdev ( struct hermon *hermon,
|
|
2156
|
+ struct hermon_port *port ) {
|
|
2157
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2158
|
+ int rc;
|
|
2159
|
+
|
|
2160
|
+ /* Initialise parameters using SMC */
|
|
2161
|
+ ib_smc_init ( ibdev, hermon_mad );
|
|
2162
|
+
|
|
2163
|
+ /* Register Infiniband device */
|
|
2164
|
+ if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
|
|
2165
|
+ DBGC ( hermon, "Hermon %p port %d could not register IB "
|
|
2166
|
+ "device: %s\n", hermon, ibdev->port, strerror ( rc ) );
|
|
2167
|
+ return rc;
|
|
2168
|
+ }
|
|
2169
|
+
|
|
2170
|
+ return 0;
|
|
2171
|
+}
|
|
2172
|
+
|
|
2173
|
+/**
|
|
2174
|
+ * Handle Hermon Infiniband device port state change
|
|
2175
|
+ *
|
|
2176
|
+ * @v hermon Hermon device
|
|
2177
|
+ * @v port Hermon port
|
|
2178
|
+ * @v link_up Link is up
|
|
2179
|
+ */
|
|
2180
|
+static void hermon_state_change_ibdev ( struct hermon *hermon __unused,
|
|
2181
|
+ struct hermon_port *port,
|
|
2182
|
+ int link_up __unused ) {
|
|
2183
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2184
|
+
|
|
2185
|
+ /* Update MAD parameters */
|
|
2186
|
+ ib_smc_update ( ibdev, hermon_mad );
|
|
2187
|
+}
|
|
2188
|
+
|
|
2189
|
+/**
|
|
2190
|
+ * Unregister Hermon Infiniband device
|
|
2191
|
+ *
|
|
2192
|
+ * @v hermon Hermon device
|
|
2193
|
+ * @v port Hermon port
|
|
2194
|
+ */
|
|
2195
|
+static void hermon_unregister_ibdev ( struct hermon *hermon __unused,
|
|
2196
|
+ struct hermon_port *port ) {
|
|
2197
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2198
|
+
|
|
2199
|
+ unregister_ibdev ( ibdev );
|
|
2200
|
+}
|
|
2201
|
+
|
|
2202
|
+/** Hermon Infiniband port type */
|
|
2203
|
+static struct hermon_port_type hermon_port_type_ib = {
|
|
2204
|
+ .register_dev = hermon_register_ibdev,
|
|
2205
|
+ .state_change = hermon_state_change_ibdev,
|
|
2206
|
+ .unregister_dev = hermon_unregister_ibdev,
|
|
2207
|
+};
|
|
2208
|
+
|
|
2209
|
+/***************************************************************************
|
|
2210
|
+ *
|
|
2211
|
+ * Ethernet operation
|
|
2212
|
+ *
|
|
2213
|
+ ***************************************************************************
|
|
2214
|
+ */
|
|
2215
|
+
|
|
2216
|
+/** Number of Hermon Ethernet send work queue entries */
|
|
2217
|
+#define HERMON_ETH_NUM_SEND_WQES 2
|
|
2218
|
+
|
|
2219
|
+/** Number of Hermon Ethernet receive work queue entries */
|
|
2220
|
+#define HERMON_ETH_NUM_RECV_WQES 4
|
|
2221
|
+
|
|
2222
|
+/** Number of Hermon Ethernet completion entries */
|
|
2223
|
+#define HERMON_ETH_NUM_CQES 8
|
|
2224
|
+
|
|
2225
|
+/**
|
|
2226
|
+ * Transmit packet via Hermon Ethernet device
|
|
2227
|
+ *
|
|
2228
|
+ * @v netdev Network device
|
|
2229
|
+ * @v iobuf I/O buffer
|
|
2230
|
+ * @ret rc Return status code
|
|
2231
|
+ */
|
|
2232
|
+static int hermon_eth_transmit ( struct net_device *netdev,
|
|
2233
|
+ struct io_buffer *iobuf ) {
|
|
2234
|
+ struct hermon_port *port = netdev->priv;
|
|
2235
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2236
|
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
|
|
2237
|
+ int rc;
|
|
2238
|
+
|
|
2239
|
+ /* Transmit packet */
|
|
2240
|
+ if ( ( rc = ib_post_send ( ibdev, port->eth_qp, NULL,
|
|
2241
|
+ iobuf ) ) != 0 ) {
|
|
2242
|
+ DBGC ( hermon, "Hermon %p port %d could not transmit: %s\n",
|
|
2243
|
+ hermon, ibdev->port, strerror ( rc ) );
|
|
2244
|
+ return rc;
|
|
2245
|
+ }
|
|
2246
|
+
|
|
2247
|
+ return 0;
|
|
2248
|
+}
|
|
2249
|
+
|
|
2250
|
+/**
|
|
2251
|
+ * Handle Hermon Ethernet device send completion
|
|
2252
|
+ *
|
|
2253
|
+ * @v ibdev Infiniband device
|
|
2254
|
+ * @v qp Queue pair
|
|
2255
|
+ * @v iobuf I/O buffer
|
|
2256
|
+ * @v rc Completion status code
|
|
2257
|
+ */
|
|
2258
|
+static void hermon_eth_complete_send ( struct ib_device *ibdev __unused,
|
|
2259
|
+ struct ib_queue_pair *qp,
|
|
2260
|
+ struct io_buffer *iobuf, int rc ) {
|
|
2261
|
+ struct net_device *netdev = ib_qp_get_ownerdata ( qp );
|
|
2262
|
+
|
|
2263
|
+ netdev_tx_complete_err ( netdev, iobuf, rc );
|
|
2264
|
+}
|
|
2265
|
+
|
|
2266
|
+/**
|
|
2267
|
+ * Handle Hermon Ethernet device receive completion
|
|
2268
|
+ *
|
|
2269
|
+ * @v ibdev Infiniband device
|
|
2270
|
+ * @v qp Queue pair
|
|
2271
|
+ * @v av Address vector, or NULL
|
|
2272
|
+ * @v iobuf I/O buffer
|
|
2273
|
+ * @v rc Completion status code
|
|
2274
|
+ */
|
|
2275
|
+static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused,
|
|
2276
|
+ struct ib_queue_pair *qp,
|
|
2277
|
+ struct ib_address_vector *av __unused,
|
|
2278
|
+ struct io_buffer *iobuf, int rc ) {
|
|
2279
|
+ struct net_device *netdev = ib_qp_get_ownerdata ( qp );
|
|
2280
|
+
|
|
2281
|
+ /* Hand off to network layer */
|
|
2282
|
+ if ( rc == 0 ) {
|
|
2283
|
+ netdev_rx ( netdev, iobuf );
|
|
2284
|
+ } else {
|
|
2285
|
+ netdev_rx_err ( netdev, iobuf, rc );
|
|
2286
|
+ }
|
|
2287
|
+}
|
|
2288
|
+
|
|
2289
|
+/** Hermon Ethernet device completion operations */
|
|
2290
|
+static struct ib_completion_queue_operations hermon_eth_cq_op = {
|
|
2291
|
+ .complete_send = hermon_eth_complete_send,
|
|
2292
|
+ .complete_recv = hermon_eth_complete_recv,
|
|
2293
|
+};
|
|
2294
|
+
|
|
2295
|
+/**
|
|
2296
|
+ * Poll Hermon Ethernet device
|
|
2297
|
+ *
|
|
2298
|
+ * @v netdev Network device
|
|
2299
|
+ */
|
|
2300
|
+static void hermon_eth_poll ( struct net_device *netdev ) {
|
|
2301
|
+ struct hermon_port *port = netdev->priv;
|
|
2302
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2303
|
+
|
|
2304
|
+ ib_poll_eq ( ibdev );
|
|
2305
|
+}
|
|
2306
|
+
|
|
2307
|
+/**
|
|
2308
|
+ * Enable/disable interrupts on Hermon Ethernet device
|
|
2309
|
+ *
|
|
2310
|
+ * @v netdev Network device
|
|
2311
|
+ * @v enable Interrupts should be enabled
|
|
2312
|
+ */
|
|
2313
|
+static void hermon_eth_irq ( struct net_device *netdev __unused,
|
|
2314
|
+ int enable __unused ) {
|
|
2315
|
+ /* No implementation */
|
|
2316
|
+}
|
|
2317
|
+
|
|
2318
|
+/**
|
|
2319
|
+ * Open Hermon Ethernet device
|
|
2320
|
+ *
|
|
2321
|
+ * @v netdev Network device
|
|
2322
|
+ * @ret rc Return status code
|
|
2323
|
+ */
|
|
2324
|
+static int hermon_eth_open ( struct net_device *netdev ) {
|
|
2325
|
+ struct hermon_port *port = netdev->priv;
|
|
2326
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2327
|
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
|
|
2328
|
+ union hermonprm_set_port set_port;
|
|
2329
|
+ int rc;
|
|
2330
|
+
|
|
2331
|
+ /* Allocate completion queue */
|
|
2332
|
+ port->eth_cq = ib_create_cq ( ibdev, HERMON_ETH_NUM_CQES,
|
|
2333
|
+ &hermon_eth_cq_op );
|
|
2334
|
+ if ( ! port->eth_cq ) {
|
|
2335
|
+ DBGC ( hermon, "Hermon %p port %d could not create completion "
|
|
2336
|
+ "queue\n", hermon, ibdev->port );
|
|
2337
|
+ rc = -ENOMEM;
|
|
2338
|
+ goto err_create_cq;
|
|
2339
|
+ }
|
|
2340
|
+
|
|
2341
|
+ /* Allocate queue pair */
|
|
2342
|
+ port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH,
|
|
2343
|
+ HERMON_ETH_NUM_SEND_WQES, port->eth_cq,
|
|
2344
|
+ HERMON_ETH_NUM_RECV_WQES, port->eth_cq );
|
|
2345
|
+ if ( ! port->eth_qp ) {
|
|
2346
|
+ DBGC ( hermon, "Hermon %p port %d could not create queue "
|
|
2347
|
+ "pair\n", hermon, ibdev->port );
|
|
2348
|
+ rc = -ENOMEM;
|
|
2349
|
+ goto err_create_qp;
|
|
2350
|
+ }
|
|
2351
|
+ ib_qp_set_ownerdata ( port->eth_qp, netdev );
|
|
2352
|
+
|
|
2353
|
+ /* Activate queue pair */
|
|
2354
|
+ if ( ( rc = ib_modify_qp ( ibdev, port->eth_qp ) ) != 0 ) {
|
|
2355
|
+ DBGC ( hermon, "Hermon %p port %d could not modify queue "
|
|
2356
|
+ "pair: %s\n", hermon, ibdev->port, strerror ( rc ) );
|
|
2357
|
+ goto err_modify_qp;
|
|
2358
|
+ }
|
|
2359
|
+
|
|
2360
|
+ /* Fill receive rings */
|
|
2361
|
+ ib_refill_recv ( ibdev, port->eth_qp );
|
|
2362
|
+
|
|
2363
|
+ /* Set port general parameters */
|
|
2364
|
+ memset ( &set_port, 0, sizeof ( set_port ) );
|
|
2365
|
+ MLX_FILL_3 ( &set_port.general, 0,
|
|
2366
|
+ v_mtu, 1,
|
|
2367
|
+ v_pprx, 1,
|
|
2368
|
+ v_pptx, 1 );
|
|
2369
|
+ MLX_FILL_1 ( &set_port.general, 1,
|
|
2370
|
+ mtu, ( ETH_FRAME_LEN + 40 /* Used by card */ ) );
|
|
2371
|
+ MLX_FILL_1 ( &set_port.general, 2, pptx, 1 );
|
|
2372
|
+ MLX_FILL_1 ( &set_port.general, 3, pprx, 1 );
|
|
2373
|
+ if ( ( rc = hermon_cmd_set_port ( hermon, 1,
|
|
2374
|
+ ( HERMON_SET_PORT_GENERAL_PARAM |
|
|
2375
|
+ ibdev->port ),
|
|
2376
|
+ &set_port ) ) != 0 ) {
|
|
2377
|
+ DBGC ( hermon, "Hermon %p port %d could not set port general "
|
|
2378
|
+ "parameters: %s\n",
|
|
2379
|
+ hermon, ibdev->port, strerror ( rc ) );
|
|
2380
|
+ goto err_set_port_general_params;
|
|
2381
|
+ }
|
|
2382
|
+
|
|
2383
|
+ /* Set port receive QP */
|
|
2384
|
+ memset ( &set_port, 0, sizeof ( set_port ) );
|
|
2385
|
+ MLX_FILL_1 ( &set_port.rqp_calc, 0, base_qpn, port->eth_qp->qpn );
|
|
2386
|
+ MLX_FILL_1 ( &set_port.rqp_calc, 2,
|
|
2387
|
+ mac_miss_index, 128 /* MAC misses go to promisc QP */ );
|
|
2388
|
+ MLX_FILL_2 ( &set_port.rqp_calc, 3,
|
|
2389
|
+ vlan_miss_index, 127 /* VLAN misses go to promisc QP */,
|
|
2390
|
+ no_vlan_index, 126 /* VLAN-free go to promisc QP */ );
|
|
2391
|
+ MLX_FILL_2 ( &set_port.rqp_calc, 5,
|
|
2392
|
+ promisc_qpn, port->eth_qp->qpn,
|
|
2393
|
+ en_uc_promisc, 1 );
|
|
2394
|
+ MLX_FILL_2 ( &set_port.rqp_calc, 6,
|
|
2395
|
+ def_mcast_qpn, port->eth_qp->qpn,
|
|
2396
|
+ mc_promisc_mode, 2 /* Receive all multicasts */ );
|
|
2397
|
+ if ( ( rc = hermon_cmd_set_port ( hermon, 1,
|
|
2398
|
+ ( HERMON_SET_PORT_RECEIVE_QP |
|
|
2399
|
+ ibdev->port ),
|
|
2400
|
+ &set_port ) ) != 0 ) {
|
|
2401
|
+ DBGC ( hermon, "Hermon %p port %d could not set port receive "
|
|
2402
|
+ "QP: %s\n", hermon, ibdev->port, strerror ( rc ) );
|
|
2403
|
+ goto err_set_port_receive_qp;
|
|
2404
|
+ }
|
|
2405
|
+
|
|
2406
|
+ /* Initialise port */
|
|
2407
|
+ if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
|
|
2408
|
+ DBGC ( hermon, "Hermon %p port %d could not initialise port: "
|
|
2409
|
+ "%s\n", hermon, ibdev->port, strerror ( rc ) );
|
|
2410
|
+ goto err_init_port;
|
|
2411
|
+ }
|
|
2412
|
+
|
|
2413
|
+ return 0;
|
|
2414
|
+
|
|
2415
|
+ err_init_port:
|
|
2416
|
+ err_set_port_receive_qp:
|
|
2417
|
+ err_set_port_general_params:
|
|
2418
|
+ err_modify_qp:
|
|
2419
|
+ ib_destroy_qp ( ibdev, port->eth_qp );
|
|
2420
|
+ err_create_qp:
|
|
2421
|
+ ib_destroy_cq ( ibdev, port->eth_cq );
|
|
2422
|
+ err_create_cq:
|
|
2423
|
+ return rc;
|
|
2424
|
+}
|
|
2425
|
+
|
|
2426
|
+/**
|
|
2427
|
+ * Close Hermon Ethernet device
|
|
2428
|
+ *
|
|
2429
|
+ * @v netdev Network device
|
|
2430
|
+ */
|
|
2431
|
+static void hermon_eth_close ( struct net_device *netdev ) {
|
|
2432
|
+ struct hermon_port *port = netdev->priv;
|
|
2433
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2434
|
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
|
|
2435
|
+ int rc;
|
|
2436
|
+
|
|
2437
|
+ /* Close port */
|
|
2438
|
+ if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
|
|
2439
|
+ DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
|
|
2440
|
+ hermon, ibdev->port, strerror ( rc ) );
|
|
2441
|
+ /* Nothing we can do about this */
|
|
2442
|
+ }
|
|
2443
|
+
|
|
2444
|
+ /* Tear down the queues */
|
|
2445
|
+ ib_destroy_qp ( ibdev, port->eth_qp );
|
|
2446
|
+ ib_destroy_cq ( ibdev, port->eth_cq );
|
|
2447
|
+}
|
|
2448
|
+
|
|
2449
|
+/** Hermon Ethernet network device operations */
|
|
2450
|
+static struct net_device_operations hermon_eth_operations = {
|
|
2451
|
+ .open = hermon_eth_open,
|
|
2452
|
+ .close = hermon_eth_close,
|
|
2453
|
+ .transmit = hermon_eth_transmit,
|
|
2454
|
+ .poll = hermon_eth_poll,
|
|
2455
|
+ .irq = hermon_eth_irq,
|
|
2456
|
+};
|
|
2457
|
+
|
|
2458
|
+/**
|
|
2459
|
+ * Register Hermon Ethernet device
|
|
2460
|
+ *
|
|
2461
|
+ * @v hermon Hermon device
|
|
2462
|
+ * @v port Hermon port
|
|
2463
|
+ * @ret rc Return status code
|
|
2464
|
+ */
|
|
2465
|
+static int hermon_register_netdev ( struct hermon *hermon,
|
|
2466
|
+ struct hermon_port *port ) {
|
|
2467
|
+ struct net_device *netdev = port->netdev;
|
|
2468
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2469
|
+ struct hermonprm_query_port_cap query_port;
|
|
2470
|
+ union {
|
|
2471
|
+ uint8_t bytes[8];
|
|
2472
|
+ uint32_t dwords[2];
|
|
2473
|
+ } mac;
|
|
2474
|
+ int rc;
|
|
2475
|
+
|
|
2476
|
+ /* Retrieve MAC address */
|
|
2477
|
+ if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
|
|
2478
|
+ &query_port ) ) != 0 ) {
|
|
2479
|
+ DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
|
|
2480
|
+ hermon, ibdev->port, strerror ( rc ) );
|
|
2481
|
+ return rc;
|
|
2482
|
+ }
|
|
2483
|
+ mac.dwords[0] = htonl ( MLX_GET ( &query_port, mac_47_32 ) );
|
|
2484
|
+ mac.dwords[1] = htonl ( MLX_GET ( &query_port, mac_31_0 ) );
|
|
2485
|
+ memcpy ( netdev->hw_addr,
|
|
2486
|
+ &mac.bytes[ sizeof ( mac.bytes ) - ETH_ALEN ], ETH_ALEN );
|
|
2487
|
+
|
|
2488
|
+ /* Register network device */
|
|
2489
|
+ if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
|
|
2490
|
+ DBGC ( hermon, "Hermon %p port %d could not register network "
|
|
2491
|
+ "device: %s\n", hermon, ibdev->port, strerror ( rc ) );
|
|
2492
|
+ return rc;
|
|
2493
|
+ }
|
|
2494
|
+
|
|
2495
|
+ return 0;
|
|
2496
|
+}
|
|
2497
|
+
|
|
2498
|
+/**
|
|
2499
|
+ * Handle Hermon Ethernet device port state change
|
|
2500
|
+ *
|
|
2501
|
+ * @v hermon Hermon device
|
|
2502
|
+ * @v port Hermon port
|
|
2503
|
+ * @v link_up Link is up
|
|
2504
|
+ */
|
|
2505
|
+static void hermon_state_change_netdev ( struct hermon *hermon __unused,
|
|
2506
|
+ struct hermon_port *port,
|
|
2507
|
+ int link_up ) {
|
|
2508
|
+ struct net_device *netdev = port->netdev;
|
|
2509
|
+
|
|
2510
|
+ if ( link_up ) {
|
|
2511
|
+ netdev_link_up ( netdev );
|
|
2512
|
+ } else {
|
|
2513
|
+ netdev_link_down ( netdev );
|
|
2514
|
+ }
|
|
2515
|
+}
|
|
2516
|
+
|
|
2517
|
+/**
|
|
2518
|
+ * Unregister Hermon Ethernet device
|
|
2519
|
+ *
|
|
2520
|
+ * @v hermon Hermon device
|
|
2521
|
+ * @v port Hermon port
|
|
2522
|
+ */
|
|
2523
|
+static void hermon_unregister_netdev ( struct hermon *hermon __unused,
|
|
2524
|
+ struct hermon_port *port ) {
|
|
2525
|
+ struct net_device *netdev = port->netdev;
|
|
2526
|
+
|
|
2527
|
+ unregister_netdev ( netdev );
|
|
2528
|
+}
|
|
2529
|
+
|
|
2530
|
+/** Hermon Ethernet port type */
|
|
2531
|
+static struct hermon_port_type hermon_port_type_eth = {
|
|
2532
|
+ .register_dev = hermon_register_netdev,
|
|
2533
|
+ .state_change = hermon_state_change_netdev,
|
|
2534
|
+ .unregister_dev = hermon_unregister_netdev,
|
|
2535
|
+};
|
|
2536
|
+
|
|
2537
|
+/***************************************************************************
|
|
2538
|
+ *
|
|
2539
|
+ * Port type detection
|
|
2540
|
+ *
|
|
2541
|
+ ***************************************************************************
|
|
2542
|
+ */
|
|
2543
|
+
|
|
2544
|
+/** Timeout for port sensing */
|
|
2545
|
+#define HERMON_SENSE_PORT_TIMEOUT ( TICKS_PER_SEC / 2 )
|
|
2546
|
+
|
|
2547
|
+/**
|
|
2548
|
+ * Name port type
|
|
2549
|
+ *
|
|
2550
|
+ * @v port_type Port type
|
|
2551
|
+ * @v port_type_name Port type name
|
|
2552
|
+ */
|
|
2553
|
+static inline const char * hermon_name_port_type ( unsigned int port_type ) {
|
|
2554
|
+ switch ( port_type ) {
|
|
2555
|
+ case HERMON_PORT_TYPE_UNKNOWN: return "unknown";
|
|
2556
|
+ case HERMON_PORT_TYPE_IB: return "Infiniband";
|
|
2557
|
+ case HERMON_PORT_TYPE_ETH: return "Ethernet";
|
|
2558
|
+ default: return "INVALID";
|
|
2559
|
+ }
|
|
2560
|
+}
|
|
2561
|
+
|
|
2562
|
+/**
|
|
2563
|
+ * Sense port type
|
|
2564
|
+ *
|
|
2565
|
+ * @v hermon Hermon device
|
|
2566
|
+ * @v port Hermon port
|
|
2567
|
+ * @ret port_type Port type, or negative error
|
|
2568
|
+ */
|
|
2569
|
+static int hermon_sense_port_type ( struct hermon *hermon,
|
|
2570
|
+ struct hermon_port *port ) {
|
|
2571
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2572
|
+ struct hermonprm_sense_port sense_port;
|
|
2573
|
+ int port_type;
|
|
2574
|
+ int rc;
|
|
2575
|
+
|
|
2576
|
+ /* If DPDP is not supported, always assume Infiniband */
|
|
2577
|
+ if ( ! hermon->cap.dpdp ) {
|
|
2578
|
+ port_type = HERMON_PORT_TYPE_IB;
|
|
2579
|
+ DBGC ( hermon, "Hermon %p port %d does not support DPDP; "
|
|
2580
|
+ "assuming an %s network\n", hermon, ibdev->port,
|
|
2581
|
+ hermon_name_port_type ( port_type ) );
|
|
2582
|
+ return port_type;
|
|
2583
|
+ }
|
|
2584
|
+
|
|
2585
|
+ /* Sense the port type */
|
|
2586
|
+ if ( ( rc = hermon_cmd_sense_port ( hermon, ibdev->port,
|
|
2587
|
+ &sense_port ) ) != 0 ) {
|
|
2588
|
+ DBGC ( hermon, "Hermon %p port %d sense failed: %s\n",
|
|
2589
|
+ hermon, ibdev->port, strerror ( rc ) );
|
|
2590
|
+ return rc;
|
|
2591
|
+ }
|
|
2592
|
+ port_type = MLX_GET ( &sense_port, port_type );
|
|
2593
|
+
|
|
2594
|
+ DBGC ( hermon, "Hermon %p port %d sensed an %s network\n",
|
|
2595
|
+ hermon, ibdev->port, hermon_name_port_type ( port_type ) );
|
|
2596
|
+ return port_type;
|
|
2597
|
+}
|
|
2598
|
+
|
|
2599
|
+/**
|
|
2600
|
+ * Set port type
|
|
2601
|
+ *
|
|
2602
|
+ * @v hermon Hermon device
|
|
2603
|
+ * @v port Hermon port
|
|
2604
|
+ * @ret rc Return status code
|
|
2605
|
+ */
|
|
2606
|
+static int hermon_set_port_type ( struct hermon *hermon,
|
|
2607
|
+ struct hermon_port *port ) {
|
|
2608
|
+ struct ib_device *ibdev = port->ibdev;
|
|
2609
|
+ struct hermonprm_query_port_cap query_port;
|
|
2610
|
+ int ib_supported;
|
|
2611
|
+ int eth_supported;
|
|
2612
|
+ int port_type;
|
|
2613
|
+ unsigned long start;
|
|
2614
|
+ unsigned long elapsed;
|
|
2615
|
+ int rc;
|
|
2616
|
+
|
|
2617
|
+ /* Check to see which types are supported */
|
|
2618
|
+ if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
|
|
2619
|
+ &query_port ) ) != 0 ) {
|
|
2620
|
+ DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
|
|
2621
|
+ hermon, ibdev->port, strerror ( rc ) );
|
|
2622
|
+ return rc;
|
|
2623
|
+ }
|
|
2624
|
+ ib_supported = MLX_GET ( &query_port, ib );
|
|
2625
|
+ eth_supported = MLX_GET ( &query_port, eth );
|
|
2626
|
+ DBGC ( hermon, "Hermon %p port %d supports%s%s%s\n",
|
|
2627
|
+ hermon, ibdev->port, ( ib_supported ? " Infiniband" : "" ),
|
|
2628
|
+ ( ( ib_supported && eth_supported ) ? " and" : "" ),
|
|
2629
|
+ ( eth_supported ? " Ethernet" : "" ) );
|
|
2630
|
+
|
|
2631
|
+ /* Sense network, if applicable */
|
|
2632
|
+ if ( ib_supported && eth_supported ) {
|
|
2633
|
+
|
|
2634
|
+ /* Both types are supported; try sensing network */
|
|
2635
|
+ start = currticks();
|
|
2636
|
+ do {
|
|
2637
|
+ /* Try sensing port */
|
|
2638
|
+ port_type = hermon_sense_port_type ( hermon, port );
|
|
2639
|
+ if ( port_type < 0 ) {
|
|
2640
|
+ rc = port_type;
|
|
2641
|
+ return rc;
|
|
2642
|
+ }
|
|
2643
|
+ } while ( ( port_type == HERMON_PORT_TYPE_UNKNOWN ) &&
|
|
2644
|
+ ( ( elapsed = ( currticks() - start ) ) <
|
|
2645
|
+ HERMON_SENSE_PORT_TIMEOUT ) );
|
|
2646
|
+
|
|
2647
|
+ /* Set port type based on sensed network, defaulting
|
|
2648
|
+ * to Infiniband if nothing was sensed.
|
|
2649
|
+ */
|
|
2650
|
+ switch ( port_type ) {
|
|
2651
|
+ case HERMON_PORT_TYPE_ETH:
|
|
2652
|
+ port->type = &hermon_port_type_eth;
|
|
2653
|
+ break;
|
|
2654
|
+ case HERMON_PORT_TYPE_IB:
|
|
2655
|
+ case HERMON_PORT_TYPE_UNKNOWN:
|
|
2656
|
+ port->type = &hermon_port_type_ib;
|
|
2657
|
+ break;
|
|
2658
|
+ default:
|
|
2659
|
+ return -EINVAL;
|
|
2660
|
+ }
|
|
2661
|
+
|
|
2662
|
+ } else if ( eth_supported ) {
|
|
2663
|
+ port->type = &hermon_port_type_eth;
|
|
2664
|
+ } else {
|
|
2665
|
+ port->type = &hermon_port_type_ib;
|
|
2666
|
+ }
|
|
2667
|
+
|
|
2668
|
+ assert ( port->type != NULL );
|
|
2669
|
+ return 0;
|
|
2670
|
+}
|
|
2671
|
+
|
2139
|
2672
|
/***************************************************************************
|
2140
|
2673
|
*
|
2141
|
2674
|
* Firmware control
|
|
@@ -2789,6 +3322,8 @@ static int hermon_probe ( struct pci_device *pci,
|
2789
|
3322
|
const struct pci_device_id *id __unused ) {
|
2790
|
3323
|
struct hermon *hermon;
|
2791
|
3324
|
struct ib_device *ibdev;
|
|
3325
|
+ struct net_device *netdev;
|
|
3326
|
+ struct hermon_port *port;
|
2792
|
3327
|
struct hermonprm_init_hca init_hca;
|
2793
|
3328
|
unsigned int i;
|
2794
|
3329
|
int rc;
|
|
@@ -2842,13 +3377,26 @@ static int hermon_probe ( struct pci_device *pci,
|
2842
|
3377
|
rc = -ENOMEM;
|
2843
|
3378
|
goto err_alloc_ibdev;
|
2844
|
3379
|
}
|
2845
|
|
- hermon->ibdev[i] = ibdev;
|
|
3380
|
+ hermon->port[i].ibdev = ibdev;
|
2846
|
3381
|
ibdev->op = &hermon_ib_operations;
|
2847
|
3382
|
ibdev->dev = &pci->dev;
|
2848
|
3383
|
ibdev->port = ( HERMON_PORT_BASE + i );
|
2849
|
3384
|
ib_set_drvdata ( ibdev, hermon );
|
2850
|
3385
|
}
|
2851
|
3386
|
|
|
3387
|
+ /* Allocate network devices */
|
|
3388
|
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
|
|
3389
|
+ netdev = alloc_etherdev ( 0 );
|
|
3390
|
+ if ( ! netdev ) {
|
|
3391
|
+ rc = -ENOMEM;
|
|
3392
|
+ goto err_alloc_netdev;
|
|
3393
|
+ }
|
|
3394
|
+ hermon->port[i].netdev = netdev;
|
|
3395
|
+ netdev_init ( netdev, &hermon_eth_operations );
|
|
3396
|
+ netdev->dev = &pci->dev;
|
|
3397
|
+ netdev->priv = &hermon->port[i];
|
|
3398
|
+ }
|
|
3399
|
+
|
2852
|
3400
|
/* Allocate ICM */
|
2853
|
3401
|
memset ( &init_hca, 0, sizeof ( init_hca ) );
|
2854
|
3402
|
if ( ( rc = hermon_alloc_icm ( hermon, &init_hca ) ) != 0 )
|
|
@@ -2868,7 +3416,7 @@ static int hermon_probe ( struct pci_device *pci,
|
2868
|
3416
|
if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
|
2869
|
3417
|
goto err_setup_mpt;
|
2870
|
3418
|
for ( i = 0 ; i < hermon->cap.num_ports ; i++ )
|
2871
|
|
- hermon->ibdev[i]->rdma_key = hermon->lkey;
|
|
3419
|
+ hermon->port[i].ibdev->rdma_key = hermon->lkey;
|
2872
|
3420
|
|
2873
|
3421
|
/* Set up event queue */
|
2874
|
3422
|
if ( ( rc = hermon_create_eq ( hermon ) ) != 0 )
|
|
@@ -2878,26 +3426,29 @@ static int hermon_probe ( struct pci_device *pci,
|
2878
|
3426
|
if ( ( rc = hermon_configure_special_qps ( hermon ) ) != 0 )
|
2879
|
3427
|
goto err_conf_special_qps;
|
2880
|
3428
|
|
2881
|
|
- /* Initialise parameters using SMC */
|
2882
|
|
- for ( i = 0 ; i < hermon->cap.num_ports ; i++ )
|
2883
|
|
- ib_smc_init ( hermon->ibdev[i], hermon_mad );
|
|
3429
|
+ /* Determine port types */
|
|
3430
|
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
|
|
3431
|
+ port = &hermon->port[i];
|
|
3432
|
+ if ( ( rc = hermon_set_port_type ( hermon, port ) ) != 0 )
|
|
3433
|
+ goto err_set_port_type;
|
|
3434
|
+ }
|
2884
|
3435
|
|
2885
|
|
- /* Register Infiniband devices */
|
|
3436
|
+ /* Register devices */
|
2886
|
3437
|
for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
|
2887
|
|
- if ( ( rc = register_ibdev ( hermon->ibdev[i] ) ) != 0 ) {
|
2888
|
|
- DBGC ( hermon, "Hermon %p port %d could not register "
|
2889
|
|
- "IB device: %s\n", hermon,
|
2890
|
|
- hermon->ibdev[i]->port, strerror ( rc ) );
|
2891
|
|
- goto err_register_ibdev;
|
2892
|
|
- }
|
|
3438
|
+ port = &hermon->port[i];
|
|
3439
|
+ if ( ( rc = port->type->register_dev ( hermon, port ) ) != 0 )
|
|
3440
|
+ goto err_register;
|
2893
|
3441
|
}
|
2894
|
3442
|
|
2895
|
3443
|
return 0;
|
2896
|
3444
|
|
2897
|
3445
|
i = hermon->cap.num_ports;
|
2898
|
|
- err_register_ibdev:
|
2899
|
|
- for ( i-- ; ( signed int ) i >= 0 ; i-- )
|
2900
|
|
- unregister_ibdev ( hermon->ibdev[i] );
|
|
3446
|
+ err_register:
|
|
3447
|
+ for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
|
|
3448
|
+ port = &hermon->port[i];
|
|
3449
|
+ port->type->unregister_dev ( hermon, port );
|
|
3450
|
+ }
|
|
3451
|
+ err_set_port_type:
|
2901
|
3452
|
err_conf_special_qps:
|
2902
|
3453
|
hermon_destroy_eq ( hermon );
|
2903
|
3454
|
err_create_eq:
|
|
@@ -2907,9 +3458,15 @@ static int hermon_probe ( struct pci_device *pci,
|
2907
|
3458
|
hermon_free_icm ( hermon );
|
2908
|
3459
|
err_alloc_icm:
|
2909
|
3460
|
i = hermon->cap.num_ports;
|
|
3461
|
+ err_alloc_netdev:
|
|
3462
|
+ for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
|
|
3463
|
+ netdev_nullify ( hermon->port[i].netdev );
|
|
3464
|
+ netdev_put ( hermon->port[i].netdev );
|
|
3465
|
+ }
|
|
3466
|
+ i = hermon->cap.num_ports;
|
2910
|
3467
|
err_alloc_ibdev:
|
2911
|
3468
|
for ( i-- ; ( signed int ) i >= 0 ; i-- )
|
2912
|
|
- ibdev_put ( hermon->ibdev[i] );
|
|
3469
|
+ ibdev_put ( hermon->port[i].ibdev );
|
2913
|
3470
|
err_get_cap:
|
2914
|
3471
|
hermon_stop_firmware ( hermon );
|
2915
|
3472
|
err_start_firmware:
|
|
@@ -2929,10 +3486,13 @@ static int hermon_probe ( struct pci_device *pci,
|
2929
|
3486
|
*/
|
2930
|
3487
|
static void hermon_remove ( struct pci_device *pci ) {
|
2931
|
3488
|
struct hermon *hermon = pci_get_drvdata ( pci );
|
|
3489
|
+ struct hermon_port *port;
|
2932
|
3490
|
int i;
|
2933
|
3491
|
|
2934
|
|
- for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- )
|
2935
|
|
- unregister_ibdev ( hermon->ibdev[i] );
|
|
3492
|
+ for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
|
|
3493
|
+ port = &hermon->port[i];
|
|
3494
|
+ port->type->unregister_dev ( hermon, port );
|
|
3495
|
+ }
|
2936
|
3496
|
hermon_destroy_eq ( hermon );
|
2937
|
3497
|
hermon_cmd_close_hca ( hermon );
|
2938
|
3498
|
hermon_free_icm ( hermon );
|
|
@@ -2940,8 +3500,12 @@ static void hermon_remove ( struct pci_device *pci ) {
|
2940
|
3500
|
hermon_stop_firmware ( hermon );
|
2941
|
3501
|
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
|
2942
|
3502
|
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
|
|
3503
|
+ for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
|
|
3504
|
+ netdev_nullify ( hermon->port[i].netdev );
|
|
3505
|
+ netdev_put ( hermon->port[i].netdev );
|
|
3506
|
+ }
|
2943
|
3507
|
for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- )
|
2944
|
|
- ibdev_put ( hermon->ibdev[i] );
|
|
3508
|
+ ibdev_put ( hermon->port[i].ibdev );
|
2945
|
3509
|
free ( hermon );
|
2946
|
3510
|
}
|
2947
|
3511
|
|
|
@@ -2950,6 +3514,14 @@ static struct pci_device_id hermon_nics[] = {
|
2950
|
3514
|
PCI_ROM ( 0x15b3, 0x634a, "mt25418", "MT25418 HCA driver", 0 ),
|
2951
|
3515
|
PCI_ROM ( 0x15b3, 0x6732, "mt26418", "MT26418 HCA driver", 0 ),
|
2952
|
3516
|
PCI_ROM ( 0x15b3, 0x673c, "mt26428", "MT26428 HCA driver", 0 ),
|
|
3517
|
+ PCI_ROM ( 0x15b3, 0x6746, "mt26438", "MT26438 HCA driver", 0 ),
|
|
3518
|
+ PCI_ROM ( 0x15b3, 0x6778, "mt26488", "MT26488 HCA driver", 0 ),
|
|
3519
|
+ PCI_ROM ( 0x15b3, 0x6368, "mt25448", "MT25448 HCA driver", 0 ),
|
|
3520
|
+ PCI_ROM ( 0x15b3, 0x6750, "mt26448", "MT26448 HCA driver", 0 ),
|
|
3521
|
+ PCI_ROM ( 0x15b3, 0x6372, "mt25458", "MT25458 HCA driver", 0 ),
|
|
3522
|
+ PCI_ROM ( 0x15b3, 0x675a, "mt26458", "MT26458 HCA driver", 0 ),
|
|
3523
|
+ PCI_ROM ( 0x15b3, 0x6764, "mt26468", "MT26468 HCA driver", 0 ),
|
|
3524
|
+ PCI_ROM ( 0x15b3, 0x676e, "mt26478", "MT26478 HCA driver", 0 ),
|
2953
|
3525
|
};
|
2954
|
3526
|
|
2955
|
3527
|
struct pci_driver hermon_driver __pci_driver = {
|