aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/drivers/infiniband/linda.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/drivers/infiniband/linda.c')
-rw-r--r--gpxe/src/drivers/infiniband/linda.c99
1 files changed, 67 insertions, 32 deletions
diff --git a/gpxe/src/drivers/infiniband/linda.c b/gpxe/src/drivers/infiniband/linda.c
index c5d13177..b9a7ba58 100644
--- a/gpxe/src/drivers/infiniband/linda.c
+++ b/gpxe/src/drivers/infiniband/linda.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
@@ -28,7 +30,6 @@
#include <gpxe/bitbash.h>
#include <gpxe/malloc.h>
#include <gpxe/iobuf.h>
-#include <gpxe/ib_sma.h>
#include "linda.h"
/**
@@ -95,9 +96,6 @@ struct linda {
struct i2c_bit_basher i2c;
/** I2C serial EEPROM */
struct i2c_device eeprom;
-
- /** Subnet management agent */
- struct ib_sma sma;
};
/***************************************************************************
@@ -233,22 +231,48 @@ static void linda_link_state_changed ( struct ib_device *ibdev ) {
/* Notify Infiniband core of link state change */
ibdev->port_state = ( link_state + 1 );
- ibdev->link_width =
+ ibdev->link_width_active =
( link_width ? IB_LINK_WIDTH_4X : IB_LINK_WIDTH_1X );
- ibdev->link_speed =
+ ibdev->link_speed_active =
( link_speed ? IB_LINK_SPEED_DDR : IB_LINK_SPEED_SDR );
ib_link_state_changed ( ibdev );
}
/**
+ * Wait for link state change to take effect
+ *
+ * @v linda Linda device
+ * @v new_link_state Expected link state
+ * @ret rc Return status code
+ */
+static int linda_link_state_check ( struct linda *linda,
+ unsigned int new_link_state ) {
+ struct QIB_7220_IBCStatus ibcstatus;
+ unsigned int link_state;
+ unsigned int i;
+
+ for ( i = 0 ; i < LINDA_LINK_STATE_MAX_WAIT_US ; i++ ) {
+ linda_readq ( linda, &ibcstatus, QIB_7220_IBCStatus_offset );
+ link_state = BIT_GET ( &ibcstatus, LinkState );
+ if ( link_state == new_link_state )
+ return 0;
+ udelay ( 1 );
+ }
+
+ DBGC ( linda, "Linda %p timed out waiting for link state %s\n",
+ linda, linda_link_state_text ( link_state ) );
+ return -ETIMEDOUT;
+}
+
+/**
* Set port information
*
* @v ibdev Infiniband device
- * @v port_info New port information
+ * @v mad Set port information MAD
*/
-static int linda_set_port_info ( struct ib_device *ibdev,
- const struct ib_port_info *port_info ) {
+static int linda_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
struct linda *linda = ib_get_drvdata ( ibdev );
+ struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
struct QIB_7220_IBCCtrl ibcctrl;
unsigned int port_state;
unsigned int link_state;
@@ -262,6 +286,12 @@ static int linda_set_port_info ( struct ib_device *ibdev,
linda_readq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
BIT_SET ( &ibcctrl, LinkCmd, link_state );
linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
+
+ /* Wait for link state change to take effect. Ignore
+ * errors; the current link state will be returned via
+ * the GetResponse MAD.
+ */
+ linda_link_state_check ( linda, link_state );
}
/* Detect and report link state change */
@@ -270,10 +300,17 @@ static int linda_set_port_info ( struct ib_device *ibdev,
return 0;
}
-/** Linda subnet management operations */
-static struct ib_sma_operations linda_sma_operations = {
- .set_port_info = linda_set_port_info,
-};
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ */
+static int linda_set_pkey_table ( struct ib_device *ibdev __unused,
+ union ib_mad *mad __unused ) {
+ /* Nothing to do */
+ return 0;
+}
/***************************************************************************
*
@@ -859,12 +896,10 @@ static int linda_create_qp ( struct ib_device *ibdev,
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v mod_list Modification list
* @ret rc Return status code
*/
static int linda_modify_qp ( struct ib_device *ibdev,
- struct ib_queue_pair *qp,
- unsigned long mod_list __unused ) {
+ struct ib_queue_pair *qp ) {
struct linda *linda = ib_get_drvdata ( ibdev );
/* Nothing to do; the hardware doesn't have a notion of queue
@@ -1462,6 +1497,8 @@ static struct ib_device_operations linda_ib_operations = {
.close = linda_close,
.mcast_attach = linda_mcast_attach,
.mcast_detach = linda_mcast_detach,
+ .set_port_info = linda_set_port_info,
+ .set_pkey_table = linda_set_pkey_table,
};
/***************************************************************************
@@ -1601,15 +1638,15 @@ static int linda_read_eeprom ( struct linda *linda,
/* Read GUID */
if ( ( rc = i2c->read ( i2c, &linda->eeprom, LINDA_EEPROM_GUID_OFFSET,
- guid->bytes, sizeof ( *guid ) ) ) != 0 ) {
+ guid->u.bytes, sizeof ( *guid ) ) ) != 0 ) {
DBGC ( linda, "Linda %p could not read GUID: %s\n",
linda, strerror ( rc ) );
return rc;
}
DBGC2 ( linda, "Linda %p has GUID %02x:%02x:%02x:%02x:%02x:%02x:"
- "%02x:%02x\n", linda, guid->bytes[0], guid->bytes[1],
- guid->bytes[2], guid->bytes[3], guid->bytes[4],
- guid->bytes[5], guid->bytes[6], guid->bytes[7] );
+ "%02x:%02x\n", linda, guid->u.bytes[0], guid->u.bytes[1],
+ guid->u.bytes[2], guid->u.bytes[3], guid->u.bytes[4],
+ guid->u.bytes[5], guid->u.bytes[6], guid->u.bytes[7] );
/* Read serial number (debug only) */
if ( DBG_LOG ) {
@@ -2219,7 +2256,7 @@ static int linda_init_ib_serdes ( struct linda *linda ) {
linda_writeq ( linda, &ibcctrl, QIB_7220_IBCCtrl_offset );
/* Force SDR only to avoid needing all the DDR tuning,
- * Mellanox compatibiltiy hacks etc. SDR is plenty for
+ * Mellanox compatibility hacks etc. SDR is plenty for
* boot-time operation.
*/
linda_readq ( linda, &ibcddrctrl, QIB_7220_IBCDDRCtrl_offset );
@@ -2317,6 +2354,14 @@ static int linda_probe ( struct pci_device *pci,
BIT_GET ( &revision, R_ChipRevMajor ),
BIT_GET ( &revision, R_ChipRevMinor ) );
+ /* Record link capabilities. Note that we force SDR only to
+ * avoid having to carry extra code for DDR tuning etc.
+ */
+ ibdev->link_width_enabled = ibdev->link_width_supported =
+ ( IB_LINK_WIDTH_4X | IB_LINK_WIDTH_1X );
+ ibdev->link_speed_enabled = ibdev->link_speed_supported =
+ IB_LINK_SPEED_SDR;
+
/* Initialise I2C subsystem */
if ( ( rc = linda_init_i2c ( linda ) ) != 0 )
goto err_init_i2c;
@@ -2337,13 +2382,6 @@ static int linda_probe ( struct pci_device *pci,
if ( ( rc = linda_init_ib_serdes ( linda ) ) != 0 )
goto err_init_ib_serdes;
- /* Create the SMA */
- if ( ( rc = ib_create_sma ( &linda->sma, ibdev,
- &linda_sma_operations ) ) != 0 )
- goto err_create_sma;
- /* If the SMA doesn't get context 0, we're screwed */
- assert ( linda_qpn_to_ctx ( linda->sma.qp->qpn ) == 0 );
-
/* Register Infiniband device */
if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
DBGC ( linda, "Linda %p could not register IB "
@@ -2355,8 +2393,6 @@ static int linda_probe ( struct pci_device *pci,
unregister_ibdev ( ibdev );
err_register_ibdev:
- ib_destroy_sma ( &linda->sma );
- err_create_sma:
linda_fini_recv ( linda );
err_init_recv:
linda_fini_send ( linda );
@@ -2379,14 +2415,13 @@ static void linda_remove ( struct pci_device *pci ) {
struct linda *linda = ib_get_drvdata ( ibdev );
unregister_ibdev ( ibdev );
- ib_destroy_sma ( &linda->sma );
linda_fini_recv ( linda );
linda_fini_send ( linda );
ibdev_put ( ibdev );
}
static struct pci_device_id linda_nics[] = {
- PCI_ROM ( 0x1077, 0x7220, "iba7220", "QLE7240/7280 HCA driver" ),
+ PCI_ROM ( 0x1077, 0x7220, "iba7220", "QLE7240/7280 HCA driver", 0 ),
};
struct pci_driver linda_driver __pci_driver = {