david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[Infiniband] Add preliminary support for multi-port devices.

Arbel and Hermon cards both have multiple ports.  Add the
infrastructure required to register each port as a separate IB
device.  Don't yet register more than one port, since registration
will currently fail unless a valid link is detected.

Use ib_*_{set,get}_{drv,owner}data wrappers to access driver- and
owner-private data on Infiniband structures.
This commit is contained in:
Michael Brown 2008-02-27 13:59:56 +00:00
parent 6570203571
commit bc3f0a25c6
7 changed files with 284 additions and 119 deletions

View File

@ -43,9 +43,6 @@
* *
*/ */
/* Port to use */
#define PXE_IB_PORT 1
/*************************************************************************** /***************************************************************************
* *
* Queue number allocation * Queue number allocation
@ -482,7 +479,7 @@ arbel_cmd_map_fa ( struct arbel *arbel,
*/ */
static int arbel_create_cq ( struct ib_device *ibdev, static int arbel_create_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) { struct ib_completion_queue *cq ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_completion_queue *arbel_cq; struct arbel_completion_queue *arbel_cq;
struct arbelprm_completion_queue_context cqctx; struct arbelprm_completion_queue_context cqctx;
struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_ci_db_record *ci_db_rec;
@ -560,7 +557,7 @@ static int arbel_create_cq ( struct ib_device *ibdev,
DBGC ( arbel, "Arbel %p CQN %#lx ring at [%p,%p)\n", DBGC ( arbel, "Arbel %p CQN %#lx ring at [%p,%p)\n",
arbel, cq->cqn, arbel_cq->cqe, arbel, cq->cqn, arbel_cq->cqe,
( ( ( void * ) arbel_cq->cqe ) + arbel_cq->cqe_size ) ); ( ( ( void * ) arbel_cq->cqe ) + arbel_cq->cqe_size ) );
cq->dev_priv = arbel_cq; ib_cq_set_drvdata ( cq, arbel_cq );
return 0; return 0;
err_sw2hw_cq: err_sw2hw_cq:
@ -583,8 +580,8 @@ static int arbel_create_cq ( struct ib_device *ibdev,
*/ */
static void arbel_destroy_cq ( struct ib_device *ibdev, static void arbel_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) { struct ib_completion_queue *cq ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_completion_queue *arbel_cq = cq->dev_priv; struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
struct arbelprm_completion_queue_context cqctx; struct arbelprm_completion_queue_context cqctx;
struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_ci_db_record *ci_db_rec;
struct arbelprm_cq_arm_db_record *arm_db_rec; struct arbelprm_cq_arm_db_record *arm_db_rec;
@ -613,7 +610,7 @@ static void arbel_destroy_cq ( struct ib_device *ibdev,
cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs ); cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs );
arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset ); arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset );
cq->dev_priv = NULL; ib_cq_set_drvdata ( cq, NULL );
} }
/*************************************************************************** /***************************************************************************
@ -712,7 +709,7 @@ static int arbel_create_recv_wq ( struct arbel_recv_work_queue *arbel_recv_wq,
*/ */
static int arbel_create_qp ( struct ib_device *ibdev, static int arbel_create_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp ) { struct ib_queue_pair *qp ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_queue_pair *arbel_qp; struct arbel_queue_pair *arbel_qp;
struct arbelprm_qp_ee_state_transitions qpctx; struct arbelprm_qp_ee_state_transitions qpctx;
struct arbelprm_qp_db_record *send_db_rec; struct arbelprm_qp_db_record *send_db_rec;
@ -819,7 +816,7 @@ static int arbel_create_qp ( struct ib_device *ibdev,
DBGC ( arbel, "Arbel %p QPN %#lx receive ring at [%p,%p)\n", DBGC ( arbel, "Arbel %p QPN %#lx receive ring at [%p,%p)\n",
arbel, qp->qpn, arbel_qp->recv.wqe, arbel, qp->qpn, arbel_qp->recv.wqe,
( ( (void *) arbel_qp->recv.wqe ) + arbel_qp->recv.wqe_size ) ); ( ( (void *) arbel_qp->recv.wqe ) + arbel_qp->recv.wqe_size ) );
qp->dev_priv = arbel_qp; ib_qp_set_drvdata ( qp, arbel_qp );
return 0; return 0;
err_rtr2rts_qpee: err_rtr2rts_qpee:
@ -847,8 +844,8 @@ static int arbel_create_qp ( struct ib_device *ibdev,
*/ */
static void arbel_destroy_qp ( struct ib_device *ibdev, static void arbel_destroy_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp ) { struct ib_queue_pair *qp ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_queue_pair *arbel_qp = qp->dev_priv; struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
struct arbelprm_qp_db_record *send_db_rec; struct arbelprm_qp_db_record *send_db_rec;
struct arbelprm_qp_db_record *recv_db_rec; struct arbelprm_qp_db_record *recv_db_rec;
int qpn_offset; int qpn_offset;
@ -877,7 +874,7 @@ static void arbel_destroy_qp ( struct ib_device *ibdev,
qpn_offset = ( qp->qpn - ARBEL_QPN_BASE - arbel->limits.reserved_qps ); qpn_offset = ( qp->qpn - ARBEL_QPN_BASE - arbel->limits.reserved_qps );
arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset ); arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset );
qp->dev_priv = NULL; ib_qp_set_drvdata ( qp, NULL );
} }
/*************************************************************************** /***************************************************************************
@ -926,8 +923,8 @@ static int arbel_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_address_vector *av, struct ib_address_vector *av,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_queue_pair *arbel_qp = qp->dev_priv; struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
struct ib_work_queue *wq = &qp->send; struct ib_work_queue *wq = &qp->send;
struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send; struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send;
struct arbelprm_ud_send_wqe *prev_wqe; struct arbelprm_ud_send_wqe *prev_wqe;
@ -1016,8 +1013,8 @@ static int arbel_post_send ( struct ib_device *ibdev,
static int arbel_post_recv ( struct ib_device *ibdev, static int arbel_post_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_queue_pair *arbel_qp = qp->dev_priv; struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
struct ib_work_queue *wq = &qp->recv; struct ib_work_queue *wq = &qp->recv;
struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv; struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv;
struct arbelprm_recv_wqe *wqe; struct arbelprm_recv_wqe *wqe;
@ -1066,7 +1063,7 @@ static int arbel_complete ( struct ib_device *ibdev,
union arbelprm_completion_entry *cqe, union arbelprm_completion_entry *cqe,
ib_completer_t complete_send, ib_completer_t complete_send,
ib_completer_t complete_recv ) { ib_completer_t complete_recv ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct ib_completion completion; struct ib_completion completion;
struct ib_work_queue *wq; struct ib_work_queue *wq;
struct ib_queue_pair *qp; struct ib_queue_pair *qp;
@ -1108,7 +1105,7 @@ static int arbel_complete ( struct ib_device *ibdev,
return -EIO; return -EIO;
} }
qp = wq->qp; qp = wq->qp;
arbel_qp = qp->dev_priv; arbel_qp = ib_qp_get_drvdata ( qp );
arbel_send_wq = &arbel_qp->send; arbel_send_wq = &arbel_qp->send;
arbel_recv_wq = &arbel_qp->recv; arbel_recv_wq = &arbel_qp->recv;
@ -1170,8 +1167,8 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq, struct ib_completion_queue *cq,
ib_completer_t complete_send, ib_completer_t complete_send,
ib_completer_t complete_recv ) { ib_completer_t complete_recv ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_completion_queue *arbel_cq = cq->dev_priv; struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_ci_db_record *ci_db_rec;
union arbelprm_completion_entry *cqe; union arbelprm_completion_entry *cqe;
unsigned int cqe_idx_mask; unsigned int cqe_idx_mask;
@ -1220,7 +1217,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
* @ret rc Return status code * @ret rc Return status code
*/ */
static int arbel_open ( struct ib_device *ibdev ) { static int arbel_open ( struct ib_device *ibdev ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbelprm_init_ib init_ib; struct arbelprm_init_ib init_ib;
int rc; int rc;
@ -1247,7 +1244,7 @@ static int arbel_open ( struct ib_device *ibdev ) {
* @v ibdev Infiniband device * @v ibdev Infiniband device
*/ */
static void arbel_close ( struct ib_device *ibdev ) { static void arbel_close ( struct ib_device *ibdev ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
int rc; int rc;
if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) { if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) {
@ -1275,7 +1272,7 @@ static void arbel_close ( struct ib_device *ibdev ) {
static int arbel_mcast_attach ( struct ib_device *ibdev, static int arbel_mcast_attach ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_gid *gid ) { struct ib_gid *gid ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbelprm_mgm_hash hash; struct arbelprm_mgm_hash hash;
struct arbelprm_mgm_entry mgm; struct arbelprm_mgm_entry mgm;
unsigned int index; unsigned int index;
@ -1330,7 +1327,7 @@ static int arbel_mcast_attach ( struct ib_device *ibdev,
static void arbel_mcast_detach ( struct ib_device *ibdev, static void arbel_mcast_detach ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused, struct ib_queue_pair *qp __unused,
struct ib_gid *gid ) { struct ib_gid *gid ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbelprm_mgm_hash hash; struct arbelprm_mgm_hash hash;
struct arbelprm_mgm_entry mgm; struct arbelprm_mgm_entry mgm;
unsigned int index; unsigned int index;
@ -1370,7 +1367,7 @@ static void arbel_mcast_detach ( struct ib_device *ibdev,
*/ */
static int arbel_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, static int arbel_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
size_t len ) { size_t len ) {
struct arbel *arbel = ibdev->dev_priv; struct arbel *arbel = ib_get_drvdata ( ibdev );
union arbelprm_mad mad_ifc; union arbelprm_mad mad_ifc;
int rc; int rc;
@ -1837,23 +1834,33 @@ static int arbel_setup_mpt ( struct arbel *arbel ) {
*/ */
static int arbel_probe ( struct pci_device *pci, static int arbel_probe ( struct pci_device *pci,
const struct pci_device_id *id __unused ) { const struct pci_device_id *id __unused ) {
struct ib_device *ibdev;
struct arbel *arbel; struct arbel *arbel;
struct ib_device *ibdev;
struct arbelprm_init_hca init_hca; struct arbelprm_init_hca init_hca;
int i;
int rc; int rc;
/* Allocate Infiniband device */ /* Allocate Arbel device */
ibdev = alloc_ibdev ( sizeof ( *arbel ) ); arbel = zalloc ( sizeof ( *arbel ) );
if ( ! ibdev ) { if ( ! arbel ) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_ibdev; goto err_alloc_arbel;
}
pci_set_drvdata ( pci, arbel );
/* Allocate Infiniband devices */
for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) {
ibdev = alloc_ibdev ( 0 );
if ( ! ibdev ) {
rc = -ENOMEM;
goto err_alloc_ibdev;
}
arbel->ibdev[i] = ibdev;
ibdev->op = &arbel_ib_operations;
ibdev->dev = &pci->dev;
ibdev->port = ( ARBEL_PORT_BASE + i );
ib_set_drvdata ( ibdev, arbel );
} }
ibdev->op = &arbel_ib_operations;
pci_set_drvdata ( pci, ibdev );
ibdev->dev = &pci->dev;
ibdev->port = PXE_IB_PORT;
arbel = ibdev->dev_priv;
memset ( arbel, 0, sizeof ( *arbel ) );
/* Fix up PCI device */ /* Fix up PCI device */
adjust_pci_device ( pci ); adjust_pci_device ( pci );
@ -1902,16 +1909,21 @@ static int arbel_probe ( struct pci_device *pci,
if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 ) if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 )
goto err_setup_mpt; goto err_setup_mpt;
/* Register Infiniband device */ /* Register Infiniband devices */
if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) {
DBGC ( arbel, "Arbel %p could not register IB device: %s\n", if ( ( rc = register_ibdev ( arbel->ibdev[i] ) ) != 0 ) {
arbel, strerror ( rc ) ); DBGC ( arbel, "Arbel %p could not register IB "
goto err_register_ibdev; "device: %s\n", arbel, strerror ( rc ) );
goto err_register_ibdev;
}
} }
return 0; return 0;
i = ( ARBEL_NUM_PORTS - 1 );
err_register_ibdev: err_register_ibdev:
for ( ; i >= 0 ; i-- )
unregister_ibdev ( arbel->ibdev[i] );
err_setup_mpt: err_setup_mpt:
arbel_cmd_close_hca ( arbel ); arbel_cmd_close_hca ( arbel );
err_init_hca: err_init_hca:
@ -1924,8 +1936,12 @@ static int arbel_probe ( struct pci_device *pci,
err_mailbox_out: err_mailbox_out:
free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
err_mailbox_in: err_mailbox_in:
free_ibdev ( ibdev ); i = ( ARBEL_NUM_PORTS - 1 );
err_ibdev: err_alloc_ibdev:
for ( ; i >= 0 ; i-- )
free_ibdev ( arbel->ibdev[i] );
free ( arbel );
err_alloc_arbel:
return rc; return rc;
} }
@ -1935,17 +1951,20 @@ static int arbel_probe ( struct pci_device *pci,
* @v pci PCI device * @v pci PCI device
*/ */
static void arbel_remove ( struct pci_device *pci ) { static void arbel_remove ( struct pci_device *pci ) {
struct ib_device *ibdev = pci_get_drvdata ( pci ); struct arbel *arbel = pci_get_drvdata ( pci );
struct arbel *arbel = ibdev->dev_priv; int i;
unregister_ibdev ( ibdev ); for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
unregister_ibdev ( arbel->ibdev[i] );
arbel_cmd_close_hca ( arbel ); arbel_cmd_close_hca ( arbel );
arbel_free_icm ( arbel ); arbel_free_icm ( arbel );
arbel_stop_firmware ( arbel ); arbel_stop_firmware ( arbel );
arbel_stop_firmware ( arbel ); arbel_stop_firmware ( arbel );
free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE ); free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
free_ibdev ( ibdev ); for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
free_ibdev ( arbel->ibdev[i] );
free ( arbel );
} }
static struct pci_device_id arbel_nics[] = { static struct pci_device_id arbel_nics[] = {

View File

@ -17,6 +17,10 @@
* *
*/ */
/* Ports in existence */
#define ARBEL_NUM_PORTS 1
#define ARBEL_PORT_BASE 1
/* PCI BARs */ /* PCI BARs */
#define ARBEL_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0 #define ARBEL_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0
#define ARBEL_PCI_CONFIG_BAR_SIZE 0x100000 #define ARBEL_PCI_CONFIG_BAR_SIZE 0x100000
@ -344,6 +348,9 @@ struct arbel {
/** Device limits */ /** Device limits */
struct arbel_dev_limits limits; struct arbel_dev_limits limits;
/** Infiniband devices */
struct ib_device *ibdev[ARBEL_NUM_PORTS];
}; };
/** Global protection domain */ /** Global protection domain */

View File

@ -41,9 +41,6 @@
* *
*/ */
/* Port to use */
#define PXE_IB_PORT 1
/*************************************************************************** /***************************************************************************
* *
* Queue number allocation * Queue number allocation
@ -599,7 +596,7 @@ static void hermon_free_mtt ( struct hermon *hermon,
*/ */
static int hermon_create_cq ( struct ib_device *ibdev, static int hermon_create_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) { struct ib_completion_queue *cq ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_completion_queue *hermon_cq; struct hermon_completion_queue *hermon_cq;
struct hermonprm_completion_queue_context cqctx; struct hermonprm_completion_queue_context cqctx;
int cqn_offset; int cqn_offset;
@ -665,7 +662,7 @@ static int hermon_create_cq ( struct ib_device *ibdev,
DBGC ( hermon, "Hermon %p CQN %#lx ring at [%p,%p)\n", DBGC ( hermon, "Hermon %p CQN %#lx ring at [%p,%p)\n",
hermon, cq->cqn, hermon_cq->cqe, hermon, cq->cqn, hermon_cq->cqe,
( ( ( void * ) hermon_cq->cqe ) + hermon_cq->cqe_size ) ); ( ( ( void * ) hermon_cq->cqe ) + hermon_cq->cqe_size ) );
cq->dev_priv = hermon_cq; ib_cq_set_drvdata ( cq, hermon_cq );
return 0; return 0;
err_sw2hw_cq: err_sw2hw_cq:
@ -688,8 +685,8 @@ static int hermon_create_cq ( struct ib_device *ibdev,
*/ */
static void hermon_destroy_cq ( struct ib_device *ibdev, static void hermon_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) { struct ib_completion_queue *cq ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_completion_queue *hermon_cq = cq->dev_priv; struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
struct hermonprm_completion_queue_context cqctx; struct hermonprm_completion_queue_context cqctx;
int cqn_offset; int cqn_offset;
int rc; int rc;
@ -713,7 +710,7 @@ static void hermon_destroy_cq ( struct ib_device *ibdev,
cqn_offset = ( cq->cqn - hermon->cap.reserved_cqs ); cqn_offset = ( cq->cqn - hermon->cap.reserved_cqs );
hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 ); hermon_bitmask_free ( hermon->cq_inuse, cqn_offset, 1 );
cq->dev_priv = NULL; ib_cq_set_drvdata ( cq, NULL );
} }
/*************************************************************************** /***************************************************************************
@ -732,7 +729,7 @@ static void hermon_destroy_cq ( struct ib_device *ibdev,
*/ */
static int hermon_create_qp ( struct ib_device *ibdev, static int hermon_create_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp ) { struct ib_queue_pair *qp ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_queue_pair *hermon_qp; struct hermon_queue_pair *hermon_qp;
struct hermonprm_qp_ee_state_transitions qpctx; struct hermonprm_qp_ee_state_transitions qpctx;
int qpn_offset; int qpn_offset;
@ -845,7 +842,7 @@ static int hermon_create_qp ( struct ib_device *ibdev,
DBGC ( hermon, "Hermon %p QPN %#lx receive ring at [%p,%p)\n", DBGC ( hermon, "Hermon %p QPN %#lx receive ring at [%p,%p)\n",
hermon, qp->qpn, hermon_qp->recv.wqe, hermon, qp->qpn, hermon_qp->recv.wqe,
( ((void *)hermon_qp->recv.wqe ) + hermon_qp->recv.wqe_size ) ); ( ((void *)hermon_qp->recv.wqe ) + hermon_qp->recv.wqe_size ) );
qp->dev_priv = hermon_qp; ib_qp_set_drvdata ( qp, hermon_qp );
return 0; return 0;
err_rtr2rts_qp: err_rtr2rts_qp:
@ -871,8 +868,8 @@ static int hermon_create_qp ( struct ib_device *ibdev,
*/ */
static void hermon_destroy_qp ( struct ib_device *ibdev, static void hermon_destroy_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp ) { struct ib_queue_pair *qp ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_queue_pair *hermon_qp = qp->dev_priv; struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
int qpn_offset; int qpn_offset;
int rc; int rc;
@ -896,7 +893,7 @@ static void hermon_destroy_qp ( struct ib_device *ibdev,
hermon->cap.reserved_qps ); hermon->cap.reserved_qps );
hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 ); hermon_bitmask_free ( hermon->qp_inuse, qpn_offset, 1 );
qp->dev_priv = NULL; ib_qp_set_drvdata ( qp, NULL );
} }
/*************************************************************************** /***************************************************************************
@ -924,8 +921,8 @@ static int hermon_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_address_vector *av, struct ib_address_vector *av,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_queue_pair *hermon_qp = qp->dev_priv; struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
struct ib_work_queue *wq = &qp->send; struct ib_work_queue *wq = &qp->send;
struct hermon_send_work_queue *hermon_send_wq = &hermon_qp->send; struct hermon_send_work_queue *hermon_send_wq = &hermon_qp->send;
struct hermonprm_ud_send_wqe *wqe; struct hermonprm_ud_send_wqe *wqe;
@ -1000,8 +997,8 @@ static int hermon_post_send ( struct ib_device *ibdev,
static int hermon_post_recv ( struct ib_device *ibdev, static int hermon_post_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_queue_pair *hermon_qp = qp->dev_priv; struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
struct ib_work_queue *wq = &qp->recv; struct ib_work_queue *wq = &qp->recv;
struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv; struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv;
struct hermonprm_recv_wqe *wqe; struct hermonprm_recv_wqe *wqe;
@ -1048,7 +1045,7 @@ static int hermon_complete ( struct ib_device *ibdev,
union hermonprm_completion_entry *cqe, union hermonprm_completion_entry *cqe,
ib_completer_t complete_send, ib_completer_t complete_send,
ib_completer_t complete_recv ) { ib_completer_t complete_recv ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct ib_completion completion; struct ib_completion completion;
struct ib_work_queue *wq; struct ib_work_queue *wq;
struct ib_queue_pair *qp; struct ib_queue_pair *qp;
@ -1085,7 +1082,7 @@ static int hermon_complete ( struct ib_device *ibdev,
return -EIO; return -EIO;
} }
qp = wq->qp; qp = wq->qp;
hermon_qp = qp->dev_priv; hermon_qp = ib_qp_get_drvdata ( qp );
/* Identify I/O buffer */ /* Identify I/O buffer */
wqe_idx = ( MLX_GET ( &cqe->normal, wqe_counter ) & wqe_idx = ( MLX_GET ( &cqe->normal, wqe_counter ) &
@ -1128,8 +1125,8 @@ static void hermon_poll_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq, struct ib_completion_queue *cq,
ib_completer_t complete_send, ib_completer_t complete_send,
ib_completer_t complete_recv ) { ib_completer_t complete_recv ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_completion_queue *hermon_cq = cq->dev_priv; struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
union hermonprm_completion_entry *cqe; union hermonprm_completion_entry *cqe;
unsigned int cqe_idx_mask; unsigned int cqe_idx_mask;
int rc; int rc;
@ -1177,7 +1174,7 @@ static void hermon_poll_cq ( struct ib_device *ibdev,
* @ret rc Return status code * @ret rc Return status code
*/ */
static int hermon_open ( struct ib_device *ibdev ) { static int hermon_open ( struct ib_device *ibdev ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermonprm_init_port init_port; struct hermonprm_init_port init_port;
int rc; int rc;
@ -1205,7 +1202,7 @@ static int hermon_open ( struct ib_device *ibdev ) {
* @v ibdev Infiniband device * @v ibdev Infiniband device
*/ */
static void hermon_close ( struct ib_device *ibdev ) { static void hermon_close ( struct ib_device *ibdev ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
int rc; int rc;
if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) { if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
@ -1233,7 +1230,7 @@ static void hermon_close ( struct ib_device *ibdev ) {
static int hermon_mcast_attach ( struct ib_device *ibdev, static int hermon_mcast_attach ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_gid *gid ) { struct ib_gid *gid ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermonprm_mgm_hash hash; struct hermonprm_mgm_hash hash;
struct hermonprm_mcg_entry mcg; struct hermonprm_mcg_entry mcg;
unsigned int index; unsigned int index;
@ -1287,7 +1284,7 @@ static int hermon_mcast_attach ( struct ib_device *ibdev,
static void hermon_mcast_detach ( struct ib_device *ibdev, static void hermon_mcast_detach ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused, struct ib_queue_pair *qp __unused,
struct ib_gid *gid ) { struct ib_gid *gid ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermonprm_mgm_hash hash; struct hermonprm_mgm_hash hash;
struct hermonprm_mcg_entry mcg; struct hermonprm_mcg_entry mcg;
unsigned int index; unsigned int index;
@ -1327,7 +1324,7 @@ static void hermon_mcast_detach ( struct ib_device *ibdev,
*/ */
static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
size_t len ) { size_t len ) {
struct hermon *hermon = ibdev->dev_priv; struct hermon *hermon = ib_get_drvdata ( ibdev );
union hermonprm_mad mad_ifc; union hermonprm_mad mad_ifc;
int rc; int rc;
@ -1870,23 +1867,33 @@ static int hermon_setup_mpt ( struct hermon *hermon ) {
*/ */
static int hermon_probe ( struct pci_device *pci, static int hermon_probe ( struct pci_device *pci,
const struct pci_device_id *id __unused ) { const struct pci_device_id *id __unused ) {
struct ib_device *ibdev;
struct hermon *hermon; struct hermon *hermon;
struct ib_device *ibdev;
struct hermonprm_init_hca init_hca; struct hermonprm_init_hca init_hca;
int i;
int rc; int rc;
/* Allocate Infiniband device */ /* Allocate Hermon device */
ibdev = alloc_ibdev ( sizeof ( *hermon ) ); hermon = zalloc ( sizeof ( *hermon ) );
if ( ! ibdev ) { if ( ! hermon ) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_ibdev; goto err_alloc_hermon;
}
pci_set_drvdata ( pci, hermon );
/* Allocate Infiniband devices */
for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ ) {
ibdev = alloc_ibdev ( 0 );
if ( ! ibdev ) {
rc = -ENOMEM;
goto err_alloc_ibdev;
}
hermon->ibdev[i] = ibdev;
ibdev->op = &hermon_ib_operations;
ibdev->dev = &pci->dev;
ibdev->port = ( HERMON_PORT_BASE + i );
ib_set_drvdata ( ibdev, hermon );
} }
ibdev->op = &hermon_ib_operations;
pci_set_drvdata ( pci, ibdev );
ibdev->dev = &pci->dev;
ibdev->port = PXE_IB_PORT;
hermon = ibdev->dev_priv;
memset ( hermon, 0, sizeof ( *hermon ) );
/* Fix up PCI device */ /* Fix up PCI device */
adjust_pci_device ( pci ); adjust_pci_device ( pci );
@ -1939,16 +1946,21 @@ static int hermon_probe ( struct pci_device *pci,
if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 ) if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
goto err_setup_mpt; goto err_setup_mpt;
/* Register Infiniband device */ /* Register Infiniband devices */
if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) { for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ ) {
DBGC ( hermon, "Hermon %p could not register IB device: %s\n", if ( ( rc = register_ibdev ( hermon->ibdev[i] ) ) != 0 ) {
hermon, strerror ( rc ) ); DBGC ( hermon, "Hermon %p could not register IB "
goto err_register_ibdev; "device: %s\n", hermon, strerror ( rc ) );
goto err_register_ibdev;
}
} }
return 0; return 0;
i = ( HERMON_NUM_PORTS - 1 );
err_register_ibdev: err_register_ibdev:
for ( ; i >= 0 ; i-- )
unregister_ibdev ( hermon->ibdev[i] );
err_setup_mpt: err_setup_mpt:
hermon_cmd_close_hca ( hermon ); hermon_cmd_close_hca ( hermon );
err_init_hca: err_init_hca:
@ -1961,8 +1973,12 @@ static int hermon_probe ( struct pci_device *pci,
err_mailbox_out: err_mailbox_out:
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE ); free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
err_mailbox_in: err_mailbox_in:
free_ibdev ( ibdev ); i = ( HERMON_NUM_PORTS - 1 );
err_ibdev: err_alloc_ibdev:
for ( ; i >= 0 ; i-- )
free_ibdev ( hermon->ibdev[i] );
free ( hermon );
err_alloc_hermon:
return rc; return rc;
} }
@ -1972,17 +1988,20 @@ static int hermon_probe ( struct pci_device *pci,
* @v pci PCI device * @v pci PCI device
*/ */
static void hermon_remove ( struct pci_device *pci ) { static void hermon_remove ( struct pci_device *pci ) {
struct ib_device *ibdev = pci_get_drvdata ( pci ); struct hermon *hermon = pci_get_drvdata ( pci );
struct hermon *hermon = ibdev->dev_priv; int i;
unregister_ibdev ( ibdev ); for ( i = ( HERMON_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
unregister_ibdev ( hermon->ibdev[i] );
hermon_cmd_close_hca ( hermon ); hermon_cmd_close_hca ( hermon );
hermon_free_icm ( hermon ); hermon_free_icm ( hermon );
hermon_stop_firmware ( hermon ); hermon_stop_firmware ( hermon );
hermon_stop_firmware ( hermon ); hermon_stop_firmware ( hermon );
free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE ); free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE ); free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
free_ibdev ( ibdev ); for ( i = ( HERMON_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
free_ibdev ( hermon->ibdev[i] );
free ( hermon );
} }
static struct pci_device_id hermon_nics[] = { static struct pci_device_id hermon_nics[] = {

View File

@ -17,6 +17,10 @@
* *
*/ */
/* Ports in existence */
#define HERMON_NUM_PORTS 1
#define HERMON_PORT_BASE 1
/* PCI BARs */ /* PCI BARs */
#define HERMON_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0 #define HERMON_PCI_CONFIG_BAR PCI_BASE_ADDRESS_0
#define HERMON_PCI_CONFIG_BAR_SIZE 0x100000 #define HERMON_PCI_CONFIG_BAR_SIZE 0x100000
@ -402,6 +406,9 @@ struct hermon {
/** Device capabilities */ /** Device capabilities */
struct hermon_dev_cap cap; struct hermon_dev_cap cap;
/** Infiniband devices */
struct ib_device *ibdev[HERMON_NUM_PORTS];
}; };
/** Global protection domain */ /** Global protection domain */

View File

@ -294,7 +294,7 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib,
rc = -ENOMEM; rc = -ENOMEM;
goto err; goto err;
} }
qset->qp->owner_priv = ipoib->netdev; ib_qp_set_ownerdata ( qset->qp, ipoib->netdev );
return 0; return 0;
@ -506,7 +506,7 @@ static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_completion *completion, struct ib_completion *completion,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct net_device *netdev = qp->owner_priv; struct net_device *netdev = ib_qp_get_ownerdata ( qp );
netdev_tx_complete_err ( netdev, iobuf, netdev_tx_complete_err ( netdev, iobuf,
( completion->syndrome ? -EIO : 0 ) ); ( completion->syndrome ? -EIO : 0 ) );
@ -524,7 +524,7 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_completion *completion, struct ib_completion *completion,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct net_device *netdev = qp->owner_priv; struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct ipoib_device *ipoib = netdev->priv; struct ipoib_device *ipoib = netdev->priv;
struct ipoib_pseudo_hdr *ipoib_pshdr; struct ipoib_pseudo_hdr *ipoib_pshdr;
@ -572,7 +572,7 @@ static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_completion *completion, struct ib_completion *completion,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct net_device *netdev = qp->owner_priv; struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct ipoib_device *ipoib = netdev->priv; struct ipoib_device *ipoib = netdev->priv;
if ( completion->syndrome ) { if ( completion->syndrome ) {
@ -640,7 +640,7 @@ static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_completion *completion, struct ib_completion *completion,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct net_device *netdev = qp->owner_priv; struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct ipoib_device *ipoib = netdev->priv; struct ipoib_device *ipoib = netdev->priv;
union ib_mad *mad; union ib_mad *mad;

View File

@ -75,8 +75,8 @@ struct ib_work_queue {
unsigned long next_idx; unsigned long next_idx;
/** I/O buffers assigned to work queue */ /** I/O buffers assigned to work queue */
struct io_buffer **iobufs; struct io_buffer **iobufs;
/** Device private data */ /** Driver private data */
void *dev_priv; void *drv_priv;
}; };
/** An Infiniband Queue Pair */ /** An Infiniband Queue Pair */
@ -89,8 +89,8 @@ struct ib_queue_pair {
struct ib_work_queue send; struct ib_work_queue send;
/** Receive queue */ /** Receive queue */
struct ib_work_queue recv; struct ib_work_queue recv;
/** Device private data */ /** Driver private data */
void *dev_priv; void *drv_priv;
/** Queue owner private data */ /** Queue owner private data */
void *owner_priv; void *owner_priv;
}; };
@ -111,8 +111,8 @@ struct ib_completion_queue {
unsigned long next_idx; unsigned long next_idx;
/** List of work queues completing to this queue */ /** List of work queues completing to this queue */
struct list_head work_queues; struct list_head work_queues;
/** Device private data */ /** Driver private data */
void *dev_priv; void *drv_priv;
}; };
/** An Infiniband completion */ /** An Infiniband completion */
@ -297,8 +297,8 @@ struct ib_device {
unsigned long sm_lid; unsigned long sm_lid;
/** Partition key */ /** Partition key */
unsigned int pkey; unsigned int pkey;
/** Device private data */ /** Driver private data */
void *dev_priv; void *drv_priv;
/** Owner private data */ /** Owner private data */
void *owner_priv; void *owner_priv;
}; };
@ -425,20 +425,130 @@ ib_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) {
} }
/** /**
* Set Infiniband owner-private data * Set Infiniband work queue driver-private data
* *
* @v pci Infiniband device * @v wq Work queue
* @v priv Private data * @v priv Private data
*/ */
static inline __attribute__ (( always_inline )) void static inline __attribute__ (( always_inline )) void
ib_set_ownerdata ( struct ib_device *ibdev, void *owner_priv ) { ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) {
ibdev->owner_priv = owner_priv; wq->drv_priv = priv;
} }
/** /**
* Get Infiniband owner-private data * Get Infiniband work queue driver-private data
* *
* @v pci Infiniband device * @v wq Work queue
* @ret priv Private data
*/
static inline __attribute__ (( always_inline )) void *
ib_wq_get_drvdata ( struct ib_work_queue *wq ) {
return wq->drv_priv;
}
/**
* Set Infiniband queue pair driver-private data
*
* @v qp Queue pair
* @v priv Private data
*/
static inline __attribute__ (( always_inline )) void
ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) {
qp->drv_priv = priv;
}
/**
* Get Infiniband queue pair driver-private data
*
* @v qp Queue pair
* @ret priv Private data
*/
static inline __attribute__ (( always_inline )) void *
ib_qp_get_drvdata ( struct ib_queue_pair *qp ) {
return qp->drv_priv;
}
/**
* Set Infiniband queue pair owner-private data
*
* @v qp Queue pair
* @v priv Private data
*/
static inline __attribute__ (( always_inline )) void
ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) {
qp->owner_priv = priv;
}
/**
* Get Infiniband queue pair owner-private data
*
* @v qp Queue pair
* @ret priv Private data
*/
static inline __attribute__ (( always_inline )) void *
ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) {
return qp->owner_priv;
}
/**
* Set Infiniband completion queue driver-private data
*
* @v cq Completion queue
* @v priv Private data
*/
static inline __attribute__ (( always_inline )) void
ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) {
cq->drv_priv = priv;
}
/**
* Get Infiniband completion queue driver-private data
*
* @v cq Completion queue
* @ret priv Private data
*/
static inline __attribute__ (( always_inline )) void *
ib_cq_get_drvdata ( struct ib_completion_queue *cq ) {
return cq->drv_priv;
}
/**
* Set Infiniband device driver-private data
*
* @v ibdev Infiniband device
* @v priv Private data
*/
static inline __attribute__ (( always_inline )) void
ib_set_drvdata ( struct ib_device *ibdev, void *priv ) {
ibdev->drv_priv = priv;
}
/**
* Get Infiniband device driver-private data
*
* @v ibdev Infiniband device
* @ret priv Private data
*/
static inline __attribute__ (( always_inline )) void *
ib_get_drvdata ( struct ib_device *ibdev ) {
return ibdev->drv_priv;
}
/**
* Set Infiniband device owner-private data
*
* @v ibdev Infiniband device
* @v priv Private data
*/
static inline __attribute__ (( always_inline )) void
ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) {
ibdev->owner_priv = priv;
}
/**
* Get Infiniband device owner-private data
*
* @v ibdev Infiniband device
* @ret priv Private data * @ret priv Private data
*/ */
static inline __attribute__ (( always_inline )) void * static inline __attribute__ (( always_inline )) void *

View File

@ -67,7 +67,8 @@ struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
} }
DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) " DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
"with CQN %#lx\n", ibdev, num_cqes, cq, cq->dev_priv, cq->cqn ); "with CQN %#lx\n", ibdev, num_cqes, cq,
ib_cq_get_drvdata ( cq ), cq->cqn );
return cq; return cq;
} }
@ -141,7 +142,7 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
} }
DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n", DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
ibdev, qp, qp->dev_priv, qp->qpn ); ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n", DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
ibdev, qp->qpn, num_send_wqes, qp->send.iobufs, ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
qp->recv.iobufs ); qp->recv.iobufs );
@ -360,17 +361,19 @@ static int ib_get_mad_params ( struct ib_device *ibdev ) {
/** /**
* Allocate Infiniband device * Allocate Infiniband device
* *
* @v priv_size Size of private data area * @v priv_size Size of driver private data area
* @ret ibdev Infiniband device, or NULL * @ret ibdev Infiniband device, or NULL
*/ */
struct ib_device * alloc_ibdev ( size_t priv_size ) { struct ib_device * alloc_ibdev ( size_t priv_size ) {
struct ib_device *ibdev; struct ib_device *ibdev;
void *drv_priv;
size_t total_len; size_t total_len;
total_len = ( sizeof ( *ibdev ) + priv_size ); total_len = ( sizeof ( *ibdev ) + priv_size );
ibdev = zalloc ( total_len ); ibdev = zalloc ( total_len );
if ( ibdev ) { if ( ibdev ) {
ibdev->dev_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) ); drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
ib_set_drvdata ( ibdev, drv_priv );
} }
return ibdev; return ibdev;
} }