#include <gpxe/umalloc.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
-#include <gpxe/process.h>
#include <gpxe/infiniband.h>
#include "hermon.h"
}
}
-/***************************************************************************
- *
- * Infiniband link-layer operations
- *
- ***************************************************************************
- */
-
-/**
- * Initialise Infiniband link
- *
- * @v ibdev Infiniband device
- * @ret rc Return status code
- */
-static int hermon_open ( struct ib_device *ibdev ) {
- struct hermon *hermon = ib_get_drvdata ( ibdev );
- struct hermonprm_init_port init_port;
- int rc;
-
- memset ( &init_port, 0, sizeof ( init_port ) );
- MLX_FILL_2 ( &init_port, 0,
- port_width_cap, 3,
- vl_cap, 1 );
- MLX_FILL_2 ( &init_port, 1,
- mtu, HERMON_MTU_2048,
- max_gid, 1 );
- MLX_FILL_1 ( &init_port, 2, max_pkey, 64 );
- if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port,
- &init_port ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not intialise port: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-/**
- * Close Infiniband link
- *
- * @v ibdev Infiniband device
- */
-static void hermon_close ( struct ib_device *ibdev ) {
- struct hermon *hermon = ib_get_drvdata ( ibdev );
- int rc;
-
- if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not close port: %s\n",
- hermon, strerror ( rc ) );
- /* Nothing we can do about this */
- }
-}
-
-/***************************************************************************
- *
- * Multicast group operations
- *
- ***************************************************************************
- */
-
-/**
- * Attach to multicast group
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v gid Multicast GID
- * @ret rc Return status code
- */
-static int hermon_mcast_attach ( struct ib_device *ibdev,
- struct ib_queue_pair *qp,
- struct ib_gid *gid ) {
- struct hermon *hermon = ib_get_drvdata ( ibdev );
- struct hermonprm_mgm_hash hash;
- struct hermonprm_mcg_entry mcg;
- unsigned int index;
- int rc;
-
- /* Generate hash table index */
- if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
- index = MLX_GET ( &hash, hash );
-
- /* Check for existing hash table entry */
- if ( ( rc = hermon_cmd_read_mcg ( hermon, index, &mcg ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not read MCG %#x: %s\n",
- hermon, index, strerror ( rc ) );
- return rc;
- }
- if ( MLX_GET ( &mcg, hdr.members_count ) != 0 ) {
- /* FIXME: this implementation allows only a single QP
- * per multicast group, and doesn't handle hash
- * collisions. Sufficient for IPoIB but may need to
- * be extended in future.
- */
- DBGC ( hermon, "Hermon %p MGID index %#x already in use\n",
- hermon, index );
- return -EBUSY;
- }
-
- /* Update hash table entry */
- MLX_FILL_1 ( &mcg, 1, hdr.members_count, 1 );
- MLX_FILL_1 ( &mcg, 8, qp[0].qpn, qp->qpn );
- memcpy ( &mcg.u.dwords[4], gid, sizeof ( *gid ) );
- if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
- hermon, index, strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-/**
- * Detach from multicast group
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v gid Multicast GID
- */
-static void hermon_mcast_detach ( struct ib_device *ibdev,
- struct ib_queue_pair *qp __unused,
- struct ib_gid *gid ) {
- struct hermon *hermon = ib_get_drvdata ( ibdev );
- struct hermonprm_mgm_hash hash;
- struct hermonprm_mcg_entry mcg;
- unsigned int index;
- int rc;
-
- /* Generate hash table index */
- if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
- hermon, strerror ( rc ) );
- return;
- }
- index = MLX_GET ( &hash, hash );
-
- /* Clear hash table entry */
- memset ( &mcg, 0, sizeof ( mcg ) );
- if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
- hermon, index, strerror ( rc ) );
- return;
- }
-}
-
-/***************************************************************************
- *
- * MAD operations
- *
- ***************************************************************************
- */
-
-/**
- * Issue management datagram
- *
- * @v ibdev Infiniband device
- * @v mad Management datagram
- * @v len Length of management datagram
- * @ret rc Return status code
- */
-static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
- size_t len ) {
- struct hermon *hermon = ib_get_drvdata ( ibdev );
- union hermonprm_mad mad_ifc;
- int rc;
-
- /* Copy in request packet */
- memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
- assert ( len <= sizeof ( mad_ifc.mad ) );
- memcpy ( &mad_ifc.mad, mad, len );
-
- /* Issue MAD */
- if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
- &mad_ifc ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
-
- /* Copy out reply packet */
- memcpy ( mad, &mad_ifc.mad, len );
-
- if ( mad->status != 0 ) {
- DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
- hermon, ntohs ( mad->status ) );
- return -EIO;
- }
- return 0;
-}
-
-/** Hermon Infiniband operations */
-static struct ib_device_operations hermon_ib_operations = {
- .create_cq = hermon_create_cq,
- .destroy_cq = hermon_destroy_cq,
- .create_qp = hermon_create_qp,
- .modify_qp = hermon_modify_qp,
- .destroy_qp = hermon_destroy_qp,
- .post_send = hermon_post_send,
- .post_recv = hermon_post_recv,
- .poll_cq = hermon_poll_cq,
- .open = hermon_open,
- .close = hermon_close,
- .mcast_attach = hermon_mcast_attach,
- .mcast_detach = hermon_mcast_detach,
- .mad = hermon_mad,
-};
-
/***************************************************************************
*
* Event queues
/**
* Poll event queue
*
- * @v hermon Hermon device
+ * @v ibdev Infiniband device
*/
-static void hermon_poll_eq ( struct hermon *hermon ) {
+static void hermon_poll_eq ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_event_queue *hermon_eq = &hermon->eq;
union hermonprm_event_entry *eqe;
union hermonprm_doorbell_register db_reg;
}
}
+/***************************************************************************
+ *
+ * Infiniband link-layer operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Initialise Infiniband link
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+static int hermon_open ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermonprm_init_port init_port;
+ int rc;
+
+ memset ( &init_port, 0, sizeof ( init_port ) );
+ MLX_FILL_2 ( &init_port, 0,
+ port_width_cap, 3,
+ vl_cap, 1 );
+ MLX_FILL_2 ( &init_port, 1,
+ mtu, HERMON_MTU_2048,
+ max_gid, 1 );
+ MLX_FILL_1 ( &init_port, 2, max_pkey, 64 );
+ if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port,
+ &init_port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not intialise port: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
/**
- * Event queue poll processor
+ * Close Infiniband link
*
- * @v process Hermon event queue process
+ * @v ibdev Infiniband device
*/
-static void hermon_step ( struct process *process ) {
- struct hermon *hermon =
- container_of ( process, struct hermon, event_process );
+static void hermon_close ( struct ib_device *ibdev ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ int rc;
- hermon_poll_eq ( hermon );
+ if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not close port: %s\n",
+ hermon, strerror ( rc ) );
+ /* Nothing we can do about this */
+ }
}
+/***************************************************************************
+ *
+ * Multicast group operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+static int hermon_mcast_attach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_gid *gid ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermonprm_mgm_hash hash;
+ struct hermonprm_mcg_entry mcg;
+ unsigned int index;
+ int rc;
+
+ /* Generate hash table index */
+ if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+ index = MLX_GET ( &hash, hash );
+
+ /* Check for existing hash table entry */
+ if ( ( rc = hermon_cmd_read_mcg ( hermon, index, &mcg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not read MCG %#x: %s\n",
+ hermon, index, strerror ( rc ) );
+ return rc;
+ }
+ if ( MLX_GET ( &mcg, hdr.members_count ) != 0 ) {
+ /* FIXME: this implementation allows only a single QP
+ * per multicast group, and doesn't handle hash
+ * collisions. Sufficient for IPoIB but may need to
+ * be extended in future.
+ */
+ DBGC ( hermon, "Hermon %p MGID index %#x already in use\n",
+ hermon, index );
+ return -EBUSY;
+ }
+
+ /* Update hash table entry */
+ MLX_FILL_1 ( &mcg, 1, hdr.members_count, 1 );
+ MLX_FILL_1 ( &mcg, 8, qp[0].qpn, qp->qpn );
+ memcpy ( &mcg.u.dwords[4], gid, sizeof ( *gid ) );
+ if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
+ hermon, index, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+static void hermon_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_gid *gid ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ struct hermonprm_mgm_hash hash;
+ struct hermonprm_mcg_entry mcg;
+ unsigned int index;
+ int rc;
+
+ /* Generate hash table index */
+ if ( ( rc = hermon_cmd_mgid_hash ( hermon, gid, &hash ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not hash GID: %s\n",
+ hermon, strerror ( rc ) );
+ return;
+ }
+ index = MLX_GET ( &hash, hash );
+
+ /* Clear hash table entry */
+ memset ( &mcg, 0, sizeof ( mcg ) );
+ if ( ( rc = hermon_cmd_write_mcg ( hermon, index, &mcg ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not write MCG %#x: %s\n",
+ hermon, index, strerror ( rc ) );
+ return;
+ }
+}
+
+/***************************************************************************
+ *
+ * MAD operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @v len Length of management datagram
+ * @ret rc Return status code
+ */
+static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
+ size_t len ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ union hermonprm_mad mad_ifc;
+ int rc;
+
+ /* Copy in request packet */
+ memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
+ assert ( len <= sizeof ( mad_ifc.mad ) );
+ memcpy ( &mad_ifc.mad, mad, len );
+
+ /* Issue MAD */
+ if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
+ &mad_ifc ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy out reply packet */
+ memcpy ( mad, &mad_ifc.mad, len );
+
+ if ( mad->status != 0 ) {
+ DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
+ hermon, ntohs ( mad->status ) );
+ return -EIO;
+ }
+ return 0;
+}
+
+/** Hermon Infiniband operations */
+static struct ib_device_operations hermon_ib_operations = {
+ .create_cq = hermon_create_cq,
+ .destroy_cq = hermon_destroy_cq,
+ .create_qp = hermon_create_qp,
+ .modify_qp = hermon_modify_qp,
+ .destroy_qp = hermon_destroy_qp,
+ .post_send = hermon_post_send,
+ .post_recv = hermon_post_recv,
+ .poll_cq = hermon_poll_cq,
+ .poll_eq = hermon_poll_eq,
+ .open = hermon_open,
+ .close = hermon_close,
+ .mcast_attach = hermon_mcast_attach,
+ .mcast_detach = hermon_mcast_detach,
+ .mad = hermon_mad,
+};
+
/***************************************************************************
*
* Firmware control
goto err_alloc_hermon;
}
pci_set_drvdata ( pci, hermon );
- process_init ( &hermon->event_process, hermon_step, NULL );
/* Allocate Infiniband devices */
for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ ) {
i = ( HERMON_NUM_PORTS - 1 );
err_alloc_ibdev:
for ( ; i >= 0 ; i-- )
- free_ibdev ( hermon->ibdev[i] );
- process_del ( &hermon->event_process );
+ ibdev_put ( hermon->ibdev[i] );
free ( hermon );
err_alloc_hermon:
return rc;
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
for ( i = ( HERMON_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
- free_ibdev ( hermon->ibdev[i] );
- process_del ( &hermon->event_process );
+ ibdev_put ( hermon->ibdev[i] );
free ( hermon );
}