#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
#include <gpxe/io.h>
#include <gpxe/pci.h>
#include <gpxe/malloc.h>
#include <gpxe/umalloc.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/infiniband.h>
#include <gpxe/ib_smc.h>
#include "arbel.h"
Go to the source code of this file.
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static int | arbel_alloc_qn_offset (arbel_bitmask_t *q_inuse, unsigned int max_inuse) |
| Allocate queue number. | |
| static void | arbel_free_qn_offset (arbel_bitmask_t *q_inuse, int qn_offset) |
| Free queue number. | |
| static int | arbel_cmd_wait (struct arbel *arbel, struct arbelprm_hca_command_register *hcr) |
| Wait for Arbel command completion. | |
| static int | arbel_cmd (struct arbel *arbel, unsigned long command, unsigned int op_mod, const void *in, unsigned int in_mod, void *out) |
| Issue HCA command. | |
| static int | arbel_cmd_query_dev_lim (struct arbel *arbel, struct arbelprm_query_dev_lim *dev_lim) |
| static int | arbel_cmd_query_fw (struct arbel *arbel, struct arbelprm_query_fw *fw) |
| static int | arbel_cmd_init_hca (struct arbel *arbel, const struct arbelprm_init_hca *init_hca) |
| static int | arbel_cmd_close_hca (struct arbel *arbel) |
| static int | arbel_cmd_init_ib (struct arbel *arbel, unsigned int port, const struct arbelprm_init_ib *init_ib) |
| static int | arbel_cmd_close_ib (struct arbel *arbel, unsigned int port) |
| static int | arbel_cmd_sw2hw_mpt (struct arbel *arbel, unsigned int index, const struct arbelprm_mpt *mpt) |
| static int | arbel_cmd_map_eq (struct arbel *arbel, unsigned long index_map, const struct arbelprm_event_mask *mask) |
| static int | arbel_cmd_sw2hw_eq (struct arbel *arbel, unsigned int index, const struct arbelprm_eqc *eqctx) |
| static int | arbel_cmd_hw2sw_eq (struct arbel *arbel, unsigned int index, struct arbelprm_eqc *eqctx) |
| static int | arbel_cmd_sw2hw_cq (struct arbel *arbel, unsigned long cqn, const struct arbelprm_completion_queue_context *cqctx) |
| static int | arbel_cmd_hw2sw_cq (struct arbel *arbel, unsigned long cqn, struct arbelprm_completion_queue_context *cqctx) |
| static int | arbel_cmd_rst2init_qpee (struct arbel *arbel, unsigned long qpn, const struct arbelprm_qp_ee_state_transitions *ctx) |
| static int | arbel_cmd_init2rtr_qpee (struct arbel *arbel, unsigned long qpn, const struct arbelprm_qp_ee_state_transitions *ctx) |
| static int | arbel_cmd_rtr2rts_qpee (struct arbel *arbel, unsigned long qpn, const struct arbelprm_qp_ee_state_transitions *ctx) |
| static int | arbel_cmd_rts2rts_qp (struct arbel *arbel, unsigned long qpn, const struct arbelprm_qp_ee_state_transitions *ctx) |
| static int | arbel_cmd_2rst_qpee (struct arbel *arbel, unsigned long qpn) |
| static int | arbel_cmd_mad_ifc (struct arbel *arbel, unsigned int port, union arbelprm_mad *mad) |
| static int | arbel_cmd_read_mgm (struct arbel *arbel, unsigned int index, struct arbelprm_mgm_entry *mgm) |
| static int | arbel_cmd_write_mgm (struct arbel *arbel, unsigned int index, const struct arbelprm_mgm_entry *mgm) |
| static int | arbel_cmd_mgid_hash (struct arbel *arbel, const struct ib_gid *gid, struct arbelprm_mgm_hash *hash) |
| static int | arbel_cmd_run_fw (struct arbel *arbel) |
| static int | arbel_cmd_disable_lam (struct arbel *arbel) |
| static int | arbel_cmd_enable_lam (struct arbel *arbel, struct arbelprm_access_lam *lam) |
| static int | arbel_cmd_unmap_icm (struct arbel *arbel, unsigned int page_count) |
| static int | arbel_cmd_map_icm (struct arbel *arbel, const struct arbelprm_virtual_physical_mapping *map) |
| static int | arbel_cmd_unmap_icm_aux (struct arbel *arbel) |
| static int | arbel_cmd_map_icm_aux (struct arbel *arbel, const struct arbelprm_virtual_physical_mapping *map) |
| static int | arbel_cmd_set_icm_size (struct arbel *arbel, const struct arbelprm_scalar_parameter *icm_size, struct arbelprm_scalar_parameter *icm_aux_size) |
| static int | arbel_cmd_unmap_fa (struct arbel *arbel) |
| static int | arbel_cmd_map_fa (struct arbel *arbel, const struct arbelprm_virtual_physical_mapping *map) |
| static int | arbel_mad (struct ib_device *ibdev, union ib_mad *mad) |
| Issue management datagram. | |
| static int | arbel_create_cq (struct ib_device *ibdev, struct ib_completion_queue *cq) |
| Create completion queue. | |
| static void | arbel_destroy_cq (struct ib_device *ibdev, struct ib_completion_queue *cq) |
| Destroy completion queue. | |
| static int | arbel_create_send_wq (struct arbel_send_work_queue *arbel_send_wq, unsigned int num_wqes) |
| Create send work queue. | |
| static int | arbel_create_recv_wq (struct arbel_recv_work_queue *arbel_recv_wq, unsigned int num_wqes) |
| Create receive work queue. | |
| static int | arbel_create_qp (struct ib_device *ibdev, struct ib_queue_pair *qp) |
| Create queue pair. | |
| static int | arbel_modify_qp (struct ib_device *ibdev, struct ib_queue_pair *qp) |
| Modify queue pair. | |
| static void | arbel_destroy_qp (struct ib_device *ibdev, struct ib_queue_pair *qp) |
| Destroy queue pair. | |
| static void | arbel_ring_doorbell (struct arbel *arbel, union arbelprm_doorbell_register *db_reg, unsigned int offset) |
| Ring doorbell register in UAR. | |
| static int | arbel_post_send (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *av, struct io_buffer *iobuf) |
| Post send work queue entry. | |
| static int | arbel_post_recv (struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf) |
| Post receive work queue entry. | |
| static int | arbel_complete (struct ib_device *ibdev, struct ib_completion_queue *cq, union arbelprm_completion_entry *cqe) |
| Handle completion. | |
| static void | arbel_poll_cq (struct ib_device *ibdev, struct ib_completion_queue *cq) |
| Poll completion queue. | |
| static int | arbel_create_eq (struct arbel *arbel) |
| Create event queue. | |
| static void | arbel_destroy_eq (struct arbel *arbel) |
| Destroy event queue. | |
| static void | arbel_event_port_state_change (struct arbel *arbel, union arbelprm_event_entry *eqe) |
| Handle port state event. | |
| static void | arbel_poll_eq (struct ib_device *ibdev) |
| Poll event queue. | |
| static int | arbel_open (struct ib_device *ibdev) |
| Initialise Infiniband link. | |
| static void | arbel_close (struct ib_device *ibdev) |
| Close Infiniband link. | |
| static int | arbel_mcast_attach (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *gid) |
| Attach to multicast group. | |
| static void | arbel_mcast_detach (struct ib_device *ibdev, struct ib_queue_pair *qp __unused, struct ib_gid *gid) |
| Detach from multicast group. | |
| static int | arbel_start_firmware (struct arbel *arbel) |
| Start firmware running. | |
| static void | arbel_stop_firmware (struct arbel *arbel) |
| Stop firmware running. | |
| static int | arbel_get_limits (struct arbel *arbel) |
| Get device limits. | |
| static size_t | icm_usage (unsigned int log_num_entries, size_t entry_size) |
| Get ICM usage. | |
| static int | arbel_alloc_icm (struct arbel *arbel, struct arbelprm_init_hca *init_hca) |
| Allocate ICM. | |
| static void | arbel_free_icm (struct arbel *arbel) |
| Free ICM. | |
| static int | arbel_setup_mpt (struct arbel *arbel) |
| Set up memory protection table. | |
| static int | arbel_probe (struct pci_device *pci, const struct pci_device_id *id __unused) |
| Probe PCI device. | |
| static void | arbel_remove (struct pci_device *pci) |
| Remove PCI device. | |
Variables | |
| static struct ib_gid | arbel_no_gid |
| GID used for GID-less send work queue entries. | |
| static struct ib_device_operations | arbel_ib_operations |
| Arbel Infiniband operations. | |
| static struct pci_device_id | arbel_nics [] |
| struct pci_driver arbel_driver | __pci_driver |
Definition in file arbel.c.
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static int arbel_alloc_qn_offset | ( | arbel_bitmask_t * | q_inuse, | |
| unsigned int | max_inuse | |||
| ) | [static] |
Allocate queue number.
| q_inuse | Queue usage bitmask | |
| max_inuse | Maximum number of in-use queues |
| qn_offset | Free queue number offset, or negative error |
Definition at line 63 of file arbel.c.
References ENFILE.
Referenced by arbel_create_cq(), and arbel_create_qp().
00064 { 00065 unsigned int qn_offset = 0; 00066 arbel_bitmask_t mask = 1; 00067 00068 while ( qn_offset < max_inuse ) { 00069 if ( ( mask & *q_inuse ) == 0 ) { 00070 *q_inuse |= mask; 00071 return qn_offset; 00072 } 00073 qn_offset++; 00074 mask <<= 1; 00075 if ( ! mask ) { 00076 mask = 1; 00077 q_inuse++; 00078 } 00079 } 00080 return -ENFILE; 00081 }
| static void arbel_free_qn_offset | ( | arbel_bitmask_t * | q_inuse, | |
| int | qn_offset | |||
| ) | [static] |
Free queue number.
| q_inuse | Queue usage bitmask | |
| qn_offset | Queue number offset |
Definition at line 89 of file arbel.c.
Referenced by arbel_create_cq(), arbel_create_qp(), arbel_destroy_cq(), and arbel_destroy_qp().
00089 { 00090 arbel_bitmask_t mask; 00091 00092 mask = ( 1 << ( qn_offset % ( 8 * sizeof ( mask ) ) ) ); 00093 q_inuse += ( qn_offset / ( 8 * sizeof ( mask ) ) ); 00094 *q_inuse &= ~mask; 00095 }
| static int arbel_cmd_wait | ( | struct arbel * | arbel, | |
| struct arbelprm_hca_command_register * | hcr | |||
| ) | [static] |
Wait for Arbel command completion.
| rc | Return status code |
Definition at line 110 of file arbel.c.
References ARBEL_HCR_MAX_WAIT_MS, ARBEL_HCR_REG, arbel::config, EBUSY, mdelay(), MLX_GET, and readl.
Referenced by arbel_cmd().
00111 { 00112 unsigned int wait; 00113 00114 for ( wait = ARBEL_HCR_MAX_WAIT_MS ; wait ; wait-- ) { 00115 hcr->u.dwords[6] = 00116 readl ( arbel->config + ARBEL_HCR_REG ( 6 ) ); 00117 if ( MLX_GET ( hcr, go ) == 0 ) 00118 return 0; 00119 mdelay ( 1 ); 00120 } 00121 return -EBUSY; 00122 }
| static int arbel_cmd | ( | struct arbel * | arbel, | |
| unsigned long | command, | |||
| unsigned int | op_mod, | |||
| const void * | in, | |||
| unsigned int | in_mod, | |||
| void * | out | |||
| ) | [static] |
Issue HCA command.
| arbel | Arbel device | |
| command | Command opcode, flags and input/output lengths | |
| op_mod | Opcode modifier (0 if no modifier applicable) | |
| in | Input parameters | |
| in_mod | Input modifier (0 if no modifier applicable) | |
| out | Output parameters |
| rc | Return status code |
Definition at line 135 of file arbel.c.
References arbel_cmd_wait(), ARBEL_HCR_IN_LEN, ARBEL_HCR_IN_MBOX, ARBEL_HCR_OPCODE, ARBEL_HCR_OUT_LEN, ARBEL_HCR_OUT_MBOX, ARBEL_HCR_REG, ARBEL_MBOX_SIZE, assert, barrier, arbel::config, DBGC, DBGC2, DBGC2_HD, DBGC_HD, EIO, arbel::mailbox_in, arbel::mailbox_out, memcpy, memset(), MLX_FILL_1, MLX_FILL_3, MLX_GET, readl, virt_to_bus(), and writel.
Referenced by arbel_cmd_2rst_qpee(), arbel_cmd_close_hca(), arbel_cmd_close_ib(), arbel_cmd_disable_lam(), arbel_cmd_enable_lam(), arbel_cmd_hw2sw_cq(), arbel_cmd_hw2sw_eq(), arbel_cmd_init2rtr_qpee(), arbel_cmd_init_hca(), arbel_cmd_init_ib(), arbel_cmd_mad_ifc(), arbel_cmd_map_eq(), arbel_cmd_map_fa(), arbel_cmd_map_icm(), arbel_cmd_map_icm_aux(), arbel_cmd_mgid_hash(), arbel_cmd_query_dev_lim(), arbel_cmd_query_fw(), arbel_cmd_read_mgm(), arbel_cmd_rst2init_qpee(), arbel_cmd_rtr2rts_qpee(), arbel_cmd_rts2rts_qp(), arbel_cmd_run_fw(), arbel_cmd_set_icm_size(), arbel_cmd_sw2hw_cq(), arbel_cmd_sw2hw_eq(), arbel_cmd_sw2hw_mpt(), arbel_cmd_unmap_fa(), arbel_cmd_unmap_icm(), arbel_cmd_unmap_icm_aux(), and arbel_cmd_write_mgm().
00137 { 00138 struct arbelprm_hca_command_register hcr; 00139 unsigned int opcode = ARBEL_HCR_OPCODE ( command ); 00140 size_t in_len = ARBEL_HCR_IN_LEN ( command ); 00141 size_t out_len = ARBEL_HCR_OUT_LEN ( command ); 00142 void *in_buffer; 00143 void *out_buffer; 00144 unsigned int status; 00145 unsigned int i; 00146 int rc; 00147 00148 assert ( in_len <= ARBEL_MBOX_SIZE ); 00149 assert ( out_len <= ARBEL_MBOX_SIZE ); 00150 00151 DBGC2 ( arbel, "Arbel %p command %02x in %zx%s out %zx%s\n", 00152 arbel, opcode, in_len, 00153 ( ( command & ARBEL_HCR_IN_MBOX ) ? "(mbox)" : "" ), out_len, 00154 ( ( command & ARBEL_HCR_OUT_MBOX ) ? "(mbox)" : "" ) ); 00155 00156 /* Check that HCR is free */ 00157 if ( ( rc = arbel_cmd_wait ( arbel, &hcr ) ) != 0 ) { 00158 DBGC ( arbel, "Arbel %p command interface locked\n", arbel ); 00159 return rc; 00160 } 00161 00162 /* Prepare HCR */ 00163 memset ( &hcr, 0, sizeof ( hcr ) ); 00164 in_buffer = &hcr.u.dwords[0]; 00165 if ( in_len && ( command & ARBEL_HCR_IN_MBOX ) ) { 00166 in_buffer = arbel->mailbox_in; 00167 MLX_FILL_1 ( &hcr, 1, in_param_l, virt_to_bus ( in_buffer ) ); 00168 } 00169 memcpy ( in_buffer, in, in_len ); 00170 MLX_FILL_1 ( &hcr, 2, input_modifier, in_mod ); 00171 out_buffer = &hcr.u.dwords[3]; 00172 if ( out_len && ( command & ARBEL_HCR_OUT_MBOX ) ) { 00173 out_buffer = arbel->mailbox_out; 00174 MLX_FILL_1 ( &hcr, 4, out_param_l, 00175 virt_to_bus ( out_buffer ) ); 00176 } 00177 MLX_FILL_3 ( &hcr, 6, 00178 opcode, opcode, 00179 opcode_modifier, op_mod, 00180 go, 1 ); 00181 DBGC2_HD ( arbel, &hcr, sizeof ( hcr ) ); 00182 if ( in_len ) { 00183 DBGC2 ( arbel, "Input:\n" ); 00184 DBGC2_HD ( arbel, in, ( ( in_len < 512 ) ? in_len : 512 ) ); 00185 } 00186 00187 /* Issue command */ 00188 for ( i = 0 ; i < ( sizeof ( hcr ) / sizeof ( hcr.u.dwords[0] ) ) ; 00189 i++ ) { 00190 writel ( hcr.u.dwords[i], 00191 arbel->config + ARBEL_HCR_REG ( i ) ); 00192 barrier(); 00193 } 00194 00195 /* Wait for command completion */ 00196 if ( ( rc = arbel_cmd_wait ( arbel, &hcr ) ) != 0 ) { 00197 DBGC ( arbel, "Arbel %p timed out waiting for command:\n", 00198 arbel ); 00199 DBGC_HD ( arbel, &hcr, sizeof ( hcr ) ); 00200 return rc; 00201 } 00202 00203 /* Check command status */ 00204 status = MLX_GET ( &hcr, status ); 00205 if ( status != 0 ) { 00206 DBGC ( arbel, "Arbel %p command failed with status %02x:\n", 00207 arbel, status ); 00208 DBGC_HD ( arbel, &hcr, sizeof ( hcr ) ); 00209 return -EIO; 00210 } 00211 00212 /* Read output parameters, if any */ 00213 hcr.u.dwords[3] = readl ( arbel->config + ARBEL_HCR_REG ( 3 ) ); 00214 hcr.u.dwords[4] = readl ( arbel->config + ARBEL_HCR_REG ( 4 ) ); 00215 memcpy ( out, out_buffer, out_len ); 00216 if ( out_len ) { 00217 DBGC2 ( arbel, "Output:\n" ); 00218 DBGC2_HD ( arbel, out, ( ( out_len < 512 ) ? out_len : 512 ) ); 00219 } 00220 00221 return 0; 00222 }
| static int arbel_cmd_query_dev_lim | ( | struct arbel * | arbel, | |
| struct arbelprm_query_dev_lim * | dev_lim | |||
| ) | [inline, static] |
Definition at line 225 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_OUT_CMD, ARBEL_HCR_QUERY_DEV_LIM, and NULL.
Referenced by arbel_get_limits().
00226 { 00227 return arbel_cmd ( arbel, 00228 ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_DEV_LIM, 00229 1, sizeof ( *dev_lim ) ), 00230 0, NULL, 0, dev_lim ); 00231 }
| static int arbel_cmd_query_fw | ( | struct arbel * | arbel, | |
| struct arbelprm_query_fw * | fw | |||
| ) | [inline, static] |
Definition at line 234 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_OUT_CMD, ARBEL_HCR_QUERY_FW, and NULL.
Referenced by arbel_start_firmware().
00234 { 00235 return arbel_cmd ( arbel, 00236 ARBEL_HCR_OUT_CMD ( ARBEL_HCR_QUERY_FW, 00237 1, sizeof ( *fw ) ), 00238 0, NULL, 0, fw ); 00239 }
| static int arbel_cmd_init_hca | ( | struct arbel * | arbel, | |
| const struct arbelprm_init_hca * | init_hca | |||
| ) | [inline, static] |
Definition at line 242 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_INIT_HCA, and NULL.
Referenced by arbel_probe().
00243 { 00244 return arbel_cmd ( arbel, 00245 ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT_HCA, 00246 1, sizeof ( *init_hca ) ), 00247 0, init_hca, 0, NULL ); 00248 }
| static int arbel_cmd_close_hca | ( | struct arbel * | arbel | ) | [inline, static] |
Definition at line 251 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_CLOSE_HCA, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_probe(), and arbel_remove().
00251 { 00252 return arbel_cmd ( arbel, 00253 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_CLOSE_HCA ), 00254 0, NULL, 0, NULL ); 00255 }
| static int arbel_cmd_init_ib | ( | struct arbel * | arbel, | |
| unsigned int | port, | |||
| const struct arbelprm_init_ib * | init_ib | |||
| ) | [inline, static] |
Definition at line 258 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_INIT_IB, and NULL.
Referenced by arbel_open().
00259 { 00260 return arbel_cmd ( arbel, 00261 ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT_IB, 00262 1, sizeof ( *init_ib ) ), 00263 0, init_ib, port, NULL ); 00264 }
| static int arbel_cmd_close_ib | ( | struct arbel * | arbel, | |
| unsigned int | port | |||
| ) | [inline, static] |
Definition at line 267 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_CLOSE_IB, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_close().
00267 { 00268 return arbel_cmd ( arbel, 00269 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_CLOSE_IB ), 00270 0, NULL, port, NULL ); 00271 }
| static int arbel_cmd_sw2hw_mpt | ( | struct arbel * | arbel, | |
| unsigned int | index, | |||
| const struct arbelprm_mpt * | mpt | |||
| ) | [inline, static] |
Definition at line 274 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_SW2HW_MPT, and NULL.
Referenced by arbel_setup_mpt().
00275 { 00276 return arbel_cmd ( arbel, 00277 ARBEL_HCR_IN_CMD ( ARBEL_HCR_SW2HW_MPT, 00278 1, sizeof ( *mpt ) ), 00279 0, mpt, index, NULL ); 00280 }
| static int arbel_cmd_map_eq | ( | struct arbel * | arbel, | |
| unsigned long | index_map, | |||
| const struct arbelprm_event_mask * | mask | |||
| ) | [inline, static] |
Definition at line 283 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_MAP_EQ, and NULL.
Referenced by arbel_create_eq(), and arbel_destroy_eq().
00284 { 00285 return arbel_cmd ( arbel, 00286 ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_EQ, 00287 0, sizeof ( *mask ) ), 00288 0, mask, index_map, NULL ); 00289 }
| static int arbel_cmd_sw2hw_eq | ( | struct arbel * | arbel, | |
| unsigned int | index, | |||
| const struct arbelprm_eqc * | eqctx | |||
| ) | [inline, static] |
Definition at line 292 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_SW2HW_EQ, and NULL.
Referenced by arbel_create_eq().
00293 { 00294 return arbel_cmd ( arbel, 00295 ARBEL_HCR_IN_CMD ( ARBEL_HCR_SW2HW_EQ, 00296 1, sizeof ( *eqctx ) ), 00297 0, eqctx, index, NULL ); 00298 }
| static int arbel_cmd_hw2sw_eq | ( | struct arbel * | arbel, | |
| unsigned int | index, | |||
| struct arbelprm_eqc * | eqctx | |||
| ) | [inline, static] |
Definition at line 301 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_HW2SW_EQ, ARBEL_HCR_OUT_CMD, and NULL.
Referenced by arbel_create_eq(), and arbel_destroy_eq().
00302 { 00303 return arbel_cmd ( arbel, 00304 ARBEL_HCR_OUT_CMD ( ARBEL_HCR_HW2SW_EQ, 00305 1, sizeof ( *eqctx ) ), 00306 1, NULL, index, eqctx ); 00307 }
| static int arbel_cmd_sw2hw_cq | ( | struct arbel * | arbel, | |
| unsigned long | cqn, | |||
| const struct arbelprm_completion_queue_context * | cqctx | |||
| ) | [inline, static] |
Definition at line 310 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_SW2HW_CQ, and NULL.
Referenced by arbel_create_cq().
00311 { 00312 return arbel_cmd ( arbel, 00313 ARBEL_HCR_IN_CMD ( ARBEL_HCR_SW2HW_CQ, 00314 1, sizeof ( *cqctx ) ), 00315 0, cqctx, cqn, NULL ); 00316 }
| static int arbel_cmd_hw2sw_cq | ( | struct arbel * | arbel, | |
| unsigned long | cqn, | |||
| struct arbelprm_completion_queue_context * | cqctx | |||
| ) | [inline, static] |
Definition at line 319 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_HW2SW_CQ, ARBEL_HCR_OUT_CMD, and NULL.
Referenced by arbel_destroy_cq().
00320 { 00321 return arbel_cmd ( arbel, 00322 ARBEL_HCR_OUT_CMD ( ARBEL_HCR_HW2SW_CQ, 00323 1, sizeof ( *cqctx ) ), 00324 0, NULL, cqn, cqctx ); 00325 }
| static int arbel_cmd_rst2init_qpee | ( | struct arbel * | arbel, | |
| unsigned long | qpn, | |||
| const struct arbelprm_qp_ee_state_transitions * | ctx | |||
| ) | [inline, static] |
Definition at line 328 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_RST2INIT_QPEE, and NULL.
Referenced by arbel_create_qp().
00329 { 00330 return arbel_cmd ( arbel, 00331 ARBEL_HCR_IN_CMD ( ARBEL_HCR_RST2INIT_QPEE, 00332 1, sizeof ( *ctx ) ), 00333 0, ctx, qpn, NULL ); 00334 }
| static int arbel_cmd_init2rtr_qpee | ( | struct arbel * | arbel, | |
| unsigned long | qpn, | |||
| const struct arbelprm_qp_ee_state_transitions * | ctx | |||
| ) | [inline, static] |
Definition at line 337 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_INIT2RTR_QPEE, and NULL.
Referenced by arbel_create_qp().
00338 { 00339 return arbel_cmd ( arbel, 00340 ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT2RTR_QPEE, 00341 1, sizeof ( *ctx ) ), 00342 0, ctx, qpn, NULL ); 00343 }
| static int arbel_cmd_rtr2rts_qpee | ( | struct arbel * | arbel, | |
| unsigned long | qpn, | |||
| const struct arbelprm_qp_ee_state_transitions * | ctx | |||
| ) | [inline, static] |
Definition at line 346 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_RTR2RTS_QPEE, and NULL.
Referenced by arbel_create_qp().
00347 { 00348 return arbel_cmd ( arbel, 00349 ARBEL_HCR_IN_CMD ( ARBEL_HCR_RTR2RTS_QPEE, 00350 1, sizeof ( *ctx ) ), 00351 0, ctx, qpn, NULL ); 00352 }
| static int arbel_cmd_rts2rts_qp | ( | struct arbel * | arbel, | |
| unsigned long | qpn, | |||
| const struct arbelprm_qp_ee_state_transitions * | ctx | |||
| ) | [inline, static] |
Definition at line 355 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_RTS2RTS_QPEE, and NULL.
Referenced by arbel_modify_qp().
00356 { 00357 return arbel_cmd ( arbel, 00358 ARBEL_HCR_IN_CMD ( ARBEL_HCR_RTS2RTS_QPEE, 00359 1, sizeof ( *ctx ) ), 00360 0, ctx, qpn, NULL ); 00361 }
| static int arbel_cmd_2rst_qpee | ( | struct arbel * | arbel, | |
| unsigned long | qpn | |||
| ) | [inline, static] |
Definition at line 364 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_2RST_QPEE, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_create_qp(), and arbel_destroy_qp().
00364 { 00365 return arbel_cmd ( arbel, 00366 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_2RST_QPEE ), 00367 0x03, NULL, qpn, NULL ); 00368 }
| static int arbel_cmd_mad_ifc | ( | struct arbel * | arbel, | |
| unsigned int | port, | |||
| union arbelprm_mad * | mad | |||
| ) | [inline, static] |
Definition at line 371 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_INOUT_CMD, and ARBEL_HCR_MAD_IFC.
Referenced by arbel_mad().
00372 { 00373 return arbel_cmd ( arbel, 00374 ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_MAD_IFC, 00375 1, sizeof ( *mad ), 00376 1, sizeof ( *mad ) ), 00377 0x03, mad, port, mad ); 00378 }
| static int arbel_cmd_read_mgm | ( | struct arbel * | arbel, | |
| unsigned int | index, | |||
| struct arbelprm_mgm_entry * | mgm | |||
| ) | [inline, static] |
Definition at line 381 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_OUT_CMD, ARBEL_HCR_READ_MGM, and NULL.
Referenced by arbel_mcast_attach().
00382 { 00383 return arbel_cmd ( arbel, 00384 ARBEL_HCR_OUT_CMD ( ARBEL_HCR_READ_MGM, 00385 1, sizeof ( *mgm ) ), 00386 0, NULL, index, mgm ); 00387 }
| static int arbel_cmd_write_mgm | ( | struct arbel * | arbel, | |
| unsigned int | index, | |||
| const struct arbelprm_mgm_entry * | mgm | |||
| ) | [inline, static] |
Definition at line 390 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_WRITE_MGM, and NULL.
Referenced by arbel_mcast_attach(), and arbel_mcast_detach().
00391 { 00392 return arbel_cmd ( arbel, 00393 ARBEL_HCR_IN_CMD ( ARBEL_HCR_WRITE_MGM, 00394 1, sizeof ( *mgm ) ), 00395 0, mgm, index, NULL ); 00396 }
| static int arbel_cmd_mgid_hash | ( | struct arbel * | arbel, | |
| const struct ib_gid * | gid, | |||
| struct arbelprm_mgm_hash * | hash | |||
| ) | [inline, static] |
Definition at line 399 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_INOUT_CMD, and ARBEL_HCR_MGID_HASH.
Referenced by arbel_mcast_attach(), and arbel_mcast_detach().
00400 { 00401 return arbel_cmd ( arbel, 00402 ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_MGID_HASH, 00403 1, sizeof ( *gid ), 00404 0, sizeof ( *hash ) ), 00405 0, gid, 0, hash ); 00406 }
| static int arbel_cmd_run_fw | ( | struct arbel * | arbel | ) | [inline, static] |
Definition at line 409 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_RUN_FW, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_start_firmware().
00409 { 00410 return arbel_cmd ( arbel, 00411 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_RUN_FW ), 00412 0, NULL, 0, NULL ); 00413 }
| static int arbel_cmd_disable_lam | ( | struct arbel * | arbel | ) | [inline, static] |
Definition at line 416 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_DISABLE_LAM, ARBEL_HCR_VOID_CMD, and NULL.
00416 { 00417 return arbel_cmd ( arbel, 00418 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_DISABLE_LAM ), 00419 0, NULL, 0, NULL ); 00420 }
| static int arbel_cmd_enable_lam | ( | struct arbel * | arbel, | |
| struct arbelprm_access_lam * | lam | |||
| ) | [inline, static] |
Definition at line 423 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_ENABLE_LAM, ARBEL_HCR_OUT_CMD, and NULL.
Referenced by arbel_start_firmware().
00423 { 00424 return arbel_cmd ( arbel, 00425 ARBEL_HCR_OUT_CMD ( ARBEL_HCR_ENABLE_LAM, 00426 1, sizeof ( *lam ) ), 00427 1, NULL, 0, lam ); 00428 }
| static int arbel_cmd_unmap_icm | ( | struct arbel * | arbel, | |
| unsigned int | page_count | |||
| ) | [inline, static] |
Definition at line 431 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_UNMAP_ICM, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_alloc_icm(), and arbel_free_icm().
00431 { 00432 return arbel_cmd ( arbel, 00433 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_UNMAP_ICM ), 00434 0, NULL, page_count, NULL ); 00435 }
| static int arbel_cmd_map_icm | ( | struct arbel * | arbel, | |
| const struct arbelprm_virtual_physical_mapping * | map | |||
| ) | [inline, static] |
Definition at line 438 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_MAP_ICM, and NULL.
Referenced by arbel_alloc_icm().
00439 { 00440 return arbel_cmd ( arbel, 00441 ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_ICM, 00442 1, sizeof ( *map ) ), 00443 0, map, 1, NULL ); 00444 }
| static int arbel_cmd_unmap_icm_aux | ( | struct arbel * | arbel | ) | [inline, static] |
Definition at line 447 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_UNMAP_ICM_AUX, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_alloc_icm(), and arbel_free_icm().
00447 { 00448 return arbel_cmd ( arbel, 00449 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_UNMAP_ICM_AUX ), 00450 0, NULL, 0, NULL ); 00451 }
| static int arbel_cmd_map_icm_aux | ( | struct arbel * | arbel, | |
| const struct arbelprm_virtual_physical_mapping * | map | |||
| ) | [inline, static] |
Definition at line 454 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_MAP_ICM_AUX, and NULL.
Referenced by arbel_alloc_icm().
00455 { 00456 return arbel_cmd ( arbel, 00457 ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_ICM_AUX, 00458 1, sizeof ( *map ) ), 00459 0, map, 1, NULL ); 00460 }
| static int arbel_cmd_set_icm_size | ( | struct arbel * | arbel, | |
| const struct arbelprm_scalar_parameter * | icm_size, | |||
| struct arbelprm_scalar_parameter * | icm_aux_size | |||
| ) | [inline, static] |
Definition at line 463 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_INOUT_CMD, and ARBEL_HCR_SET_ICM_SIZE.
Referenced by arbel_alloc_icm().
00465 { 00466 return arbel_cmd ( arbel, 00467 ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_SET_ICM_SIZE, 00468 0, sizeof ( *icm_size ), 00469 0, sizeof ( *icm_aux_size ) ), 00470 0, icm_size, 0, icm_aux_size ); 00471 }
| static int arbel_cmd_unmap_fa | ( | struct arbel * | arbel | ) | [inline, static] |
Definition at line 474 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_UNMAP_FA, ARBEL_HCR_VOID_CMD, and NULL.
Referenced by arbel_start_firmware(), and arbel_stop_firmware().
00474 { 00475 return arbel_cmd ( arbel, 00476 ARBEL_HCR_VOID_CMD ( ARBEL_HCR_UNMAP_FA ), 00477 0, NULL, 0, NULL ); 00478 }
| static int arbel_cmd_map_fa | ( | struct arbel * | arbel, | |
| const struct arbelprm_virtual_physical_mapping * | map | |||
| ) | [inline, static] |
Definition at line 481 of file arbel.c.
References arbel_cmd(), ARBEL_HCR_IN_CMD, ARBEL_HCR_MAP_FA, and NULL.
Referenced by arbel_start_firmware().
00482 { 00483 return arbel_cmd ( arbel, 00484 ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_FA, 00485 1, sizeof ( *map ) ), 00486 0, map, 1, NULL ); 00487 }
Issue management datagram.
| ibdev | Infiniband device | |
| mad | Management datagram |
| rc | Return status code |
Definition at line 503 of file arbel.c.
References arbel_cmd_mad_ifc(), DBGC, EIO, ib_mad::hdr, ib_get_drvdata(), linker_assert, arbelprm_mad::mad, memcpy, ntohs, ib_device::port, ib_mad_hdr::status, and strerror().
Referenced by arbel_event_port_state_change(), arbel_open(), and arbel_probe().
00503 { 00504 struct arbel *arbel = ib_get_drvdata ( ibdev ); 00505 union arbelprm_mad mad_ifc; 00506 int rc; 00507 00508 linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ), 00509 mad_size_mismatch ); 00510 00511 /* Copy in request packet */ 00512 memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) ); 00513 00514 /* Issue MAD */ 00515 if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port, 00516 &mad_ifc ) ) != 0 ) { 00517 DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n", 00518 arbel, strerror ( rc ) ); 00519 return rc; 00520 } 00521 00522 /* Copy out reply packet */ 00523 memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) ); 00524 00525 if ( mad->hdr.status != 0 ) { 00526 DBGC ( arbel, "Arbel %p MAD IFC status %04x\n", 00527 arbel, ntohs ( mad->hdr.status ) ); 00528 return -EIO; 00529 } 00530 return 0; 00531 }
| static int arbel_create_cq | ( | struct ib_device * | ibdev, | |
| struct ib_completion_queue * | cq | |||
| ) | [static] |
Create completion queue.
| ibdev | Infiniband device | |
| cq | Completion queue |
| rc | Return status code |
Definition at line 547 of file arbel.c.
References arbel_alloc_qn_offset(), arbel_cmd_sw2hw_cq(), arbel_cq_arm_doorbell_idx(), arbel_cq_ci_doorbell_idx(), arbel_free_qn_offset(), ARBEL_GLOBAL_PD, ARBEL_MAX_CQS, ARBEL_NO_EQ, ARBEL_UAR_RES_CQ_ARM, ARBEL_UAR_RES_CQ_CI, ARBEL_UAR_RES_NONE, arbel_completion_queue::arm_doorbell_idx, barrier, arbel_completion_queue::ci_doorbell_idx, arbelprm_doorbell_record::cq_arm, arbelprm_doorbell_record::cq_ci, arbel::cq_inuse, arbel_completion_queue::cqe, arbel_completion_queue::cqe_size, ib_completion_queue::cqn, arbel::db_rec, DBGC, ENOMEM, fls, free(), free_dma(), ib_cq_set_drvdata(), ib_get_drvdata(), arbel::limits, malloc_dma(), memset(), MLX_FILL_1, MLX_FILL_2, arbelprm_completion_entry::normal, ib_completion_queue::num_cqes, arbel_dev_limits::reserved_cqs, arbel::reserved_lkey, arbel_dev_limits::reserved_uars, strerror(), virt_to_bus(), and zalloc().
00548 { 00549 struct arbel *arbel = ib_get_drvdata ( ibdev ); 00550 struct arbel_completion_queue *arbel_cq; 00551 struct arbelprm_completion_queue_context cqctx; 00552 struct arbelprm_cq_ci_db_record *ci_db_rec; 00553 struct arbelprm_cq_arm_db_record *arm_db_rec; 00554 int cqn_offset; 00555 unsigned int i; 00556 int rc; 00557 00558 /* Find a free completion queue number */ 00559 cqn_offset = arbel_alloc_qn_offset ( arbel->cq_inuse, ARBEL_MAX_CQS ); 00560 if ( cqn_offset < 0 ) { 00561 DBGC ( arbel, "Arbel %p out of completion queues\n", arbel ); 00562 rc = cqn_offset; 00563 goto err_cqn_offset; 00564 } 00565 cq->cqn = ( arbel->limits.reserved_cqs + cqn_offset ); 00566 00567 /* Allocate control structures */ 00568 arbel_cq = zalloc ( sizeof ( *arbel_cq ) ); 00569 if ( ! arbel_cq ) { 00570 rc = -ENOMEM; 00571 goto err_arbel_cq; 00572 } 00573 arbel_cq->ci_doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset ); 00574 arbel_cq->arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( cqn_offset ); 00575 00576 /* Allocate completion queue itself */ 00577 arbel_cq->cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) ); 00578 arbel_cq->cqe = malloc_dma ( arbel_cq->cqe_size, 00579 sizeof ( arbel_cq->cqe[0] ) ); 00580 if ( ! arbel_cq->cqe ) { 00581 rc = -ENOMEM; 00582 goto err_cqe; 00583 } 00584 memset ( arbel_cq->cqe, 0, arbel_cq->cqe_size ); 00585 for ( i = 0 ; i < cq->num_cqes ; i++ ) { 00586 MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 ); 00587 } 00588 barrier(); 00589 00590 /* Initialise doorbell records */ 00591 ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci; 00592 MLX_FILL_1 ( ci_db_rec, 0, counter, 0 ); 00593 MLX_FILL_2 ( ci_db_rec, 1, 00594 res, ARBEL_UAR_RES_CQ_CI, 00595 cq_number, cq->cqn ); 00596 arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm; 00597 MLX_FILL_1 ( arm_db_rec, 0, counter, 0 ); 00598 MLX_FILL_2 ( arm_db_rec, 1, 00599 res, ARBEL_UAR_RES_CQ_ARM, 00600 cq_number, cq->cqn ); 00601 00602 /* Hand queue over to hardware */ 00603 memset ( &cqctx, 0, sizeof ( cqctx ) ); 00604 MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ ); 00605 MLX_FILL_1 ( &cqctx, 2, start_address_l, 00606 virt_to_bus ( arbel_cq->cqe ) ); 00607 MLX_FILL_2 ( &cqctx, 3, 00608 usr_page, arbel->limits.reserved_uars, 00609 log_cq_size, fls ( cq->num_cqes - 1 ) ); 00610 MLX_FILL_1 ( &cqctx, 5, c_eqn, ARBEL_NO_EQ ); 00611 MLX_FILL_1 ( &cqctx, 6, pd, ARBEL_GLOBAL_PD ); 00612 MLX_FILL_1 ( &cqctx, 7, l_key, arbel->reserved_lkey ); 00613 MLX_FILL_1 ( &cqctx, 12, cqn, cq->cqn ); 00614 MLX_FILL_1 ( &cqctx, 13, 00615 cq_ci_db_record, arbel_cq->ci_doorbell_idx ); 00616 MLX_FILL_1 ( &cqctx, 14, 00617 cq_state_db_record, arbel_cq->arm_doorbell_idx ); 00618 if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) { 00619 DBGC ( arbel, "Arbel %p SW2HW_CQ failed: %s\n", 00620 arbel, strerror ( rc ) ); 00621 goto err_sw2hw_cq; 00622 } 00623 00624 DBGC ( arbel, "Arbel %p CQN %#lx ring at [%p,%p)\n", 00625 arbel, cq->cqn, arbel_cq->cqe, 00626 ( ( ( void * ) arbel_cq->cqe ) + arbel_cq->cqe_size ) ); 00627 ib_cq_set_drvdata ( cq, arbel_cq ); 00628 return 0; 00629 00630 err_sw2hw_cq: 00631 MLX_FILL_1 ( ci_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00632 MLX_FILL_1 ( arm_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00633 free_dma ( arbel_cq->cqe, arbel_cq->cqe_size ); 00634 err_cqe: 00635 free ( arbel_cq ); 00636 err_arbel_cq: 00637 arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset ); 00638 err_cqn_offset: 00639 return rc; 00640 }
| static void arbel_destroy_cq | ( | struct ib_device * | ibdev, | |
| struct ib_completion_queue * | cq | |||
| ) | [static] |
Destroy completion queue.
| ibdev | Infiniband device | |
| cq | Completion queue |
Definition at line 648 of file arbel.c.
References arbel_cmd_hw2sw_cq(), arbel_free_qn_offset(), ARBEL_UAR_RES_NONE, arbel_completion_queue::arm_doorbell_idx, arbel_completion_queue::ci_doorbell_idx, arbelprm_doorbell_record::cq_arm, arbelprm_doorbell_record::cq_ci, arbel::cq_inuse, arbel_completion_queue::cqe, arbel_completion_queue::cqe_size, ib_completion_queue::cqn, arbel::db_rec, DBGC, free(), free_dma(), ib_cq_get_drvdata(), ib_cq_set_drvdata(), ib_get_drvdata(), arbel::limits, MLX_FILL_1, NULL, arbel_dev_limits::reserved_cqs, and strerror().
00649 { 00650 struct arbel *arbel = ib_get_drvdata ( ibdev ); 00651 struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq ); 00652 struct arbelprm_completion_queue_context cqctx; 00653 struct arbelprm_cq_ci_db_record *ci_db_rec; 00654 struct arbelprm_cq_arm_db_record *arm_db_rec; 00655 int cqn_offset; 00656 int rc; 00657 00658 /* Take ownership back from hardware */ 00659 if ( ( rc = arbel_cmd_hw2sw_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) { 00660 DBGC ( arbel, "Arbel %p FATAL HW2SW_CQ failed on CQN %#lx: " 00661 "%s\n", arbel, cq->cqn, strerror ( rc ) ); 00662 /* Leak memory and return; at least we avoid corruption */ 00663 return; 00664 } 00665 00666 /* Clear doorbell records */ 00667 ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci; 00668 arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm; 00669 MLX_FILL_1 ( ci_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00670 MLX_FILL_1 ( arm_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00671 00672 /* Free memory */ 00673 free_dma ( arbel_cq->cqe, arbel_cq->cqe_size ); 00674 free ( arbel_cq ); 00675 00676 /* Mark queue number as free */ 00677 cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs ); 00678 arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset ); 00679 00680 ib_cq_set_drvdata ( cq, NULL ); 00681 }
| static int arbel_create_send_wq | ( | struct arbel_send_work_queue * | arbel_send_wq, | |
| unsigned int | num_wqes | |||
| ) | [static] |
Create send work queue.
| arbel_send_wq | Send work queue | |
| num_wqes | Number of work queue entries |
| rc | Return status code |
Definition at line 697 of file arbel.c.
References ENOMEM, malloc_dma(), memset(), MLX_FILL_1, arbelprm_ud_send_wqe::next, arbelprm_ud_send_wqe::ud, arbel_send_wqe::ud, virt_to_bus(), arbel_send_work_queue::wqe, and arbel_send_work_queue::wqe_size.
Referenced by arbel_create_qp().
00698 { 00699 struct arbelprm_ud_send_wqe *wqe; 00700 struct arbelprm_ud_send_wqe *next_wqe; 00701 unsigned int wqe_idx_mask; 00702 unsigned int i; 00703 00704 /* Allocate work queue */ 00705 arbel_send_wq->wqe_size = ( num_wqes * 00706 sizeof ( arbel_send_wq->wqe[0] ) ); 00707 arbel_send_wq->wqe = malloc_dma ( arbel_send_wq->wqe_size, 00708 sizeof ( arbel_send_wq->wqe[0] ) ); 00709 if ( ! arbel_send_wq->wqe ) 00710 return -ENOMEM; 00711 memset ( arbel_send_wq->wqe, 0, arbel_send_wq->wqe_size ); 00712 00713 /* Link work queue entries */ 00714 wqe_idx_mask = ( num_wqes - 1 ); 00715 for ( i = 0 ; i < num_wqes ; i++ ) { 00716 wqe = &arbel_send_wq->wqe[i].ud; 00717 next_wqe = &arbel_send_wq->wqe[ ( i + 1 ) & wqe_idx_mask ].ud; 00718 MLX_FILL_1 ( &wqe->next, 0, nda_31_6, 00719 ( virt_to_bus ( next_wqe ) >> 6 ) ); 00720 } 00721 00722 return 0; 00723 }
| static int arbel_create_recv_wq | ( | struct arbel_recv_work_queue * | arbel_recv_wq, | |
| unsigned int | num_wqes | |||
| ) | [static] |
Create receive work queue.
| arbel_recv_wq | Receive work queue | |
| num_wqes | Number of work queue entries |
| rc | Return status code |
Definition at line 732 of file arbel.c.
References ARBEL_INVALID_LKEY, arbelprm_recv_wqe::data, ENOMEM, malloc_dma(), memset(), MLX_FILL_1, arbelprm_recv_wqe::next, offsetof, arbel_recv_wqe::recv, virt_to_bus(), arbel_recv_work_queue::wqe, and arbel_recv_work_queue::wqe_size.
Referenced by arbel_create_qp().
00733 { 00734 struct arbelprm_recv_wqe *wqe; 00735 struct arbelprm_recv_wqe *next_wqe; 00736 unsigned int wqe_idx_mask; 00737 size_t nds; 00738 unsigned int i; 00739 unsigned int j; 00740 00741 /* Allocate work queue */ 00742 arbel_recv_wq->wqe_size = ( num_wqes * 00743 sizeof ( arbel_recv_wq->wqe[0] ) ); 00744 arbel_recv_wq->wqe = malloc_dma ( arbel_recv_wq->wqe_size, 00745 sizeof ( arbel_recv_wq->wqe[0] ) ); 00746 if ( ! arbel_recv_wq->wqe ) 00747 return -ENOMEM; 00748 memset ( arbel_recv_wq->wqe, 0, arbel_recv_wq->wqe_size ); 00749 00750 /* Link work queue entries */ 00751 wqe_idx_mask = ( num_wqes - 1 ); 00752 nds = ( ( offsetof ( typeof ( *wqe ), data ) + 00753 sizeof ( wqe->data[0] ) ) >> 4 ); 00754 for ( i = 0 ; i < num_wqes ; i++ ) { 00755 wqe = &arbel_recv_wq->wqe[i].recv; 00756 next_wqe = &arbel_recv_wq->wqe[( i + 1 ) & wqe_idx_mask].recv; 00757 MLX_FILL_1 ( &wqe->next, 0, nda_31_6, 00758 ( virt_to_bus ( next_wqe ) >> 6 ) ); 00759 MLX_FILL_1 ( &wqe->next, 1, nds, ( sizeof ( *wqe ) / 16 ) ); 00760 for ( j = 0 ; ( ( ( void * ) &wqe->data[j] ) < 00761 ( ( void * ) ( wqe + 1 ) ) ) ; j++ ) { 00762 MLX_FILL_1 ( &wqe->data[j], 1, 00763 l_key, ARBEL_INVALID_LKEY ); 00764 } 00765 } 00766 00767 return 0; 00768 }
| static int arbel_create_qp | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair * | qp | |||
| ) | [static] |
Create queue pair.
| ibdev | Infiniband device | |
| qp | Queue pair |
| rc | Return status code |
Definition at line 777 of file arbel.c.
References arbel_alloc_qn_offset(), arbel_cmd_2rst_qpee(), arbel_cmd_init2rtr_qpee(), arbel_cmd_rst2init_qpee(), arbel_cmd_rtr2rts_qpee(), arbel_create_recv_wq(), arbel_create_send_wq(), arbel_free_qn_offset(), ARBEL_GLOBAL_PD, ARBEL_MAX_QPS, ARBEL_MTU_2048, ARBEL_QPN_BASE, arbel_recv_doorbell_idx(), arbel_send_doorbell_idx(), ARBEL_ST_UD, ARBEL_UAR_RES_NONE, ARBEL_UAR_RES_RQ, ARBEL_UAR_RES_SQ, ib_work_queue::cq, ib_completion_queue::cqn, arbel::db_rec, DBGC, arbel_recv_work_queue::doorbell_idx, arbel_send_work_queue::doorbell_idx, ENOMEM, fls, free(), free_dma(), ib_get_drvdata(), ib_qp_set_drvdata(), arbel::limits, memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_3, MLX_FILL_6, ib_work_queue::num_wqes, ib_device::port, arbelprm_doorbell_record::qp, arbel::qp_inuse, ib_queue_pair::qpn, ib_queue_pair::recv, arbel_queue_pair::recv, arbel::reserved_lkey, arbel_dev_limits::reserved_qps, arbel_dev_limits::reserved_uars, ib_queue_pair::send, arbel_queue_pair::send, strerror(), virt_to_bus(), arbel_send_work_queue::wqe, arbel_recv_work_queue::wqe, arbel_recv_work_queue::wqe_size, arbel_send_work_queue::wqe_size, and zalloc().
00778 { 00779 struct arbel *arbel = ib_get_drvdata ( ibdev ); 00780 struct arbel_queue_pair *arbel_qp; 00781 struct arbelprm_qp_ee_state_transitions qpctx; 00782 struct arbelprm_qp_db_record *send_db_rec; 00783 struct arbelprm_qp_db_record *recv_db_rec; 00784 int qpn_offset; 00785 int rc; 00786 00787 /* Find a free queue pair number */ 00788 qpn_offset = arbel_alloc_qn_offset ( arbel->qp_inuse, ARBEL_MAX_QPS ); 00789 if ( qpn_offset < 0 ) { 00790 DBGC ( arbel, "Arbel %p out of queue pairs\n", arbel ); 00791 rc = qpn_offset; 00792 goto err_qpn_offset; 00793 } 00794 qp->qpn = ( ARBEL_QPN_BASE + arbel->limits.reserved_qps + qpn_offset ); 00795 00796 /* Allocate control structures */ 00797 arbel_qp = zalloc ( sizeof ( *arbel_qp ) ); 00798 if ( ! arbel_qp ) { 00799 rc = -ENOMEM; 00800 goto err_arbel_qp; 00801 } 00802 arbel_qp->send.doorbell_idx = arbel_send_doorbell_idx ( qpn_offset ); 00803 arbel_qp->recv.doorbell_idx = arbel_recv_doorbell_idx ( qpn_offset ); 00804 00805 /* Create send and receive work queues */ 00806 if ( ( rc = arbel_create_send_wq ( &arbel_qp->send, 00807 qp->send.num_wqes ) ) != 0 ) 00808 goto err_create_send_wq; 00809 if ( ( rc = arbel_create_recv_wq ( &arbel_qp->recv, 00810 qp->recv.num_wqes ) ) != 0 ) 00811 goto err_create_recv_wq; 00812 00813 /* Initialise doorbell records */ 00814 send_db_rec = &arbel->db_rec[arbel_qp->send.doorbell_idx].qp; 00815 MLX_FILL_1 ( send_db_rec, 0, counter, 0 ); 00816 MLX_FILL_2 ( send_db_rec, 1, 00817 res, ARBEL_UAR_RES_SQ, 00818 qp_number, qp->qpn ); 00819 recv_db_rec = &arbel->db_rec[arbel_qp->recv.doorbell_idx].qp; 00820 MLX_FILL_1 ( recv_db_rec, 0, counter, 0 ); 00821 MLX_FILL_2 ( recv_db_rec, 1, 00822 res, ARBEL_UAR_RES_RQ, 00823 qp_number, qp->qpn ); 00824 00825 /* Hand queue over to hardware */ 00826 memset ( &qpctx, 0, sizeof ( qpctx ) ); 00827 MLX_FILL_3 ( &qpctx, 2, 00828 qpc_eec_data.de, 1, 00829 qpc_eec_data.pm_state, 0x03 /* Always 0x03 for UD */, 00830 qpc_eec_data.st, ARBEL_ST_UD ); 00831 MLX_FILL_6 ( &qpctx, 4, 00832 qpc_eec_data.mtu, ARBEL_MTU_2048, 00833 qpc_eec_data.msg_max, 11 /* 2^11 = 2048 */, 00834 qpc_eec_data.log_rq_size, fls ( qp->recv.num_wqes - 1 ), 00835 qpc_eec_data.log_rq_stride, 00836 ( fls ( sizeof ( arbel_qp->recv.wqe[0] ) - 1 ) - 4 ), 00837 qpc_eec_data.log_sq_size, fls ( qp->send.num_wqes - 1 ), 00838 qpc_eec_data.log_sq_stride, 00839 ( fls ( sizeof ( arbel_qp->send.wqe[0] ) - 1 ) - 4 ) ); 00840 MLX_FILL_1 ( &qpctx, 5, 00841 qpc_eec_data.usr_page, arbel->limits.reserved_uars ); 00842 MLX_FILL_1 ( &qpctx, 10, qpc_eec_data.primary_address_path.port_number, 00843 ibdev->port ); 00844 MLX_FILL_1 ( &qpctx, 27, qpc_eec_data.pd, ARBEL_GLOBAL_PD ); 00845 MLX_FILL_1 ( &qpctx, 29, qpc_eec_data.wqe_lkey, arbel->reserved_lkey ); 00846 MLX_FILL_1 ( &qpctx, 30, qpc_eec_data.ssc, 1 ); 00847 MLX_FILL_1 ( &qpctx, 33, qpc_eec_data.cqn_snd, qp->send.cq->cqn ); 00848 MLX_FILL_1 ( &qpctx, 34, qpc_eec_data.snd_wqe_base_adr_l, 00849 ( virt_to_bus ( arbel_qp->send.wqe ) >> 6 ) ); 00850 MLX_FILL_1 ( &qpctx, 35, qpc_eec_data.snd_db_record_index, 00851 arbel_qp->send.doorbell_idx ); 00852 MLX_FILL_1 ( &qpctx, 38, qpc_eec_data.rsc, 1 ); 00853 MLX_FILL_1 ( &qpctx, 41, qpc_eec_data.cqn_rcv, qp->recv.cq->cqn ); 00854 MLX_FILL_1 ( &qpctx, 42, qpc_eec_data.rcv_wqe_base_adr_l, 00855 ( virt_to_bus ( arbel_qp->recv.wqe ) >> 6 ) ); 00856 MLX_FILL_1 ( &qpctx, 43, qpc_eec_data.rcv_db_record_index, 00857 arbel_qp->recv.doorbell_idx ); 00858 if ( ( rc = arbel_cmd_rst2init_qpee ( arbel, qp->qpn, &qpctx )) != 0 ){ 00859 DBGC ( arbel, "Arbel %p RST2INIT_QPEE failed: %s\n", 00860 arbel, strerror ( rc ) ); 00861 goto err_rst2init_qpee; 00862 } 00863 memset ( &qpctx, 0, sizeof ( qpctx ) ); 00864 MLX_FILL_2 ( &qpctx, 4, 00865 qpc_eec_data.mtu, ARBEL_MTU_2048, 00866 qpc_eec_data.msg_max, 11 /* 2^11 = 2048 */ ); 00867 if ( ( rc = arbel_cmd_init2rtr_qpee ( arbel, qp->qpn, &qpctx )) != 0 ){ 00868 DBGC ( arbel, "Arbel %p INIT2RTR_QPEE failed: %s\n", 00869 arbel, strerror ( rc ) ); 00870 goto err_init2rtr_qpee; 00871 } 00872 memset ( &qpctx, 0, sizeof ( qpctx ) ); 00873 if ( ( rc = arbel_cmd_rtr2rts_qpee ( arbel, qp->qpn, &qpctx ) ) != 0 ){ 00874 DBGC ( arbel, "Arbel %p RTR2RTS_QPEE failed: %s\n", 00875 arbel, strerror ( rc ) ); 00876 goto err_rtr2rts_qpee; 00877 } 00878 00879 DBGC ( arbel, "Arbel %p QPN %#lx send ring at [%p,%p)\n", 00880 arbel, qp->qpn, arbel_qp->send.wqe, 00881 ( ( (void *) arbel_qp->send.wqe ) + arbel_qp->send.wqe_size ) ); 00882 DBGC ( arbel, "Arbel %p QPN %#lx receive ring at [%p,%p)\n", 00883 arbel, qp->qpn, arbel_qp->recv.wqe, 00884 ( ( (void *) arbel_qp->recv.wqe ) + arbel_qp->recv.wqe_size ) ); 00885 ib_qp_set_drvdata ( qp, arbel_qp ); 00886 return 0; 00887 00888 err_rtr2rts_qpee: 00889 err_init2rtr_qpee: 00890 arbel_cmd_2rst_qpee ( arbel, qp->qpn ); 00891 err_rst2init_qpee: 00892 MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00893 MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00894 free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size ); 00895 err_create_recv_wq: 00896 free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size ); 00897 err_create_send_wq: 00898 free ( arbel_qp ); 00899 err_arbel_qp: 00900 arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset ); 00901 err_qpn_offset: 00902 return rc; 00903 }
| static int arbel_modify_qp | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair * | qp | |||
| ) | [static] |
Modify queue pair.
| ibdev | Infiniband device | |
| qp | Queue pair |
| rc | Return status code |
Definition at line 912 of file arbel.c.
References arbel_cmd_rts2rts_qp(), ARBEL_QPEE_OPT_PARAM_QKEY, DBGC, ib_get_drvdata(), memset(), MLX_FILL_1, ib_queue_pair::qkey, ib_queue_pair::qpn, and strerror().
00913 { 00914 struct arbel *arbel = ib_get_drvdata ( ibdev ); 00915 struct arbelprm_qp_ee_state_transitions qpctx; 00916 int rc; 00917 00918 /* Issue RTS2RTS_QP */ 00919 memset ( &qpctx, 0, sizeof ( qpctx ) ); 00920 MLX_FILL_1 ( &qpctx, 0, opt_param_mask, ARBEL_QPEE_OPT_PARAM_QKEY ); 00921 MLX_FILL_1 ( &qpctx, 44, qpc_eec_data.q_key, qp->qkey ); 00922 if ( ( rc = arbel_cmd_rts2rts_qp ( arbel, qp->qpn, &qpctx ) ) != 0 ){ 00923 DBGC ( arbel, "Arbel %p RTS2RTS_QP failed: %s\n", 00924 arbel, strerror ( rc ) ); 00925 return rc; 00926 } 00927 00928 return 0; 00929 }
| static void arbel_destroy_qp | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair * | qp | |||
| ) | [static] |
Destroy queue pair.
| ibdev | Infiniband device | |
| qp | Queue pair |
Definition at line 937 of file arbel.c.
References arbel_cmd_2rst_qpee(), arbel_free_qn_offset(), ARBEL_QPN_BASE, ARBEL_UAR_RES_NONE, arbel::db_rec, DBGC, arbel_recv_work_queue::doorbell_idx, arbel_send_work_queue::doorbell_idx, free(), free_dma(), ib_get_drvdata(), ib_qp_get_drvdata(), ib_qp_set_drvdata(), arbel::limits, MLX_FILL_1, NULL, arbelprm_doorbell_record::qp, arbel::qp_inuse, ib_queue_pair::qpn, arbel_queue_pair::recv, arbel_dev_limits::reserved_qps, arbel_queue_pair::send, strerror(), arbel_recv_work_queue::wqe, arbel_send_work_queue::wqe, arbel_recv_work_queue::wqe_size, and arbel_send_work_queue::wqe_size.
00938 { 00939 struct arbel *arbel = ib_get_drvdata ( ibdev ); 00940 struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); 00941 struct arbelprm_qp_db_record *send_db_rec; 00942 struct arbelprm_qp_db_record *recv_db_rec; 00943 int qpn_offset; 00944 int rc; 00945 00946 /* Take ownership back from hardware */ 00947 if ( ( rc = arbel_cmd_2rst_qpee ( arbel, qp->qpn ) ) != 0 ) { 00948 DBGC ( arbel, "Arbel %p FATAL 2RST_QPEE failed on QPN %#lx: " 00949 "%s\n", arbel, qp->qpn, strerror ( rc ) ); 00950 /* Leak memory and return; at least we avoid corruption */ 00951 return; 00952 } 00953 00954 /* Clear doorbell records */ 00955 send_db_rec = &arbel->db_rec[arbel_qp->send.doorbell_idx].qp; 00956 recv_db_rec = &arbel->db_rec[arbel_qp->recv.doorbell_idx].qp; 00957 MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00958 MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE ); 00959 00960 /* Free memory */ 00961 free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size ); 00962 free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size ); 00963 free ( arbel_qp ); 00964 00965 /* Mark queue number as free */ 00966 qpn_offset = ( qp->qpn - ARBEL_QPN_BASE - arbel->limits.reserved_qps ); 00967 arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset ); 00968 00969 ib_qp_set_drvdata ( qp, NULL ); 00970 }
| static void arbel_ring_doorbell | ( | struct arbel * | arbel, | |
| union arbelprm_doorbell_register * | db_reg, | |||
| unsigned int | offset | |||
| ) | [static] |
Ring doorbell register in UAR.
Definition at line 986 of file arbel.c.
References barrier, DBGC2, arbelprm_doorbell_register::dword, arbel::uar, virt_to_phys(), and writel.
Referenced by arbel_post_send().
00988 { 00989 00990 DBGC2 ( arbel, "Arbel %p ringing doorbell %08x:%08x at %lx\n", 00991 arbel, db_reg->dword[0], db_reg->dword[1], 00992 virt_to_phys ( arbel->uar + offset ) ); 00993 00994 barrier(); 00995 writel ( db_reg->dword[0], ( arbel->uar + offset + 0 ) ); 00996 barrier(); 00997 writel ( db_reg->dword[1], ( arbel->uar + offset + 4 ) ); 00998 }
| static int arbel_post_send | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair * | qp, | |||
| struct ib_address_vector * | av, | |||
| struct io_buffer * | iobuf | |||
| ) | [static] |
Post send work queue entry.
| ibdev | Infiniband device | |
| qp | Queue pair | |
| av | Address vector | |
| iobuf | I/O buffer |
| rc | Return status code |
Definition at line 1014 of file arbel.c.
References ARBEL_DB_POST_SND_OFFSET, ARBEL_GLOBAL_PD, ARBEL_OPCODE_SEND, arbel_ring_doorbell(), barrier, arbelprm_ud_send_wqe::ctrl, io_buffer::data, arbelprm_ud_send_wqe::data, arbel::db_rec, DBGC, arbel_send_work_queue::doorbell_idx, ENOBUFS, ib_address_vector::gid, ib_address_vector::gid_present, ib_get_drvdata(), ib_qp_get_drvdata(), iob_len(), ib_work_queue::iobufs, ib_address_vector::lid, memcpy, memset(), MLX_FILL_1, MLX_FILL_2, MLX_FILL_3, MLX_FILL_4, MLX_SET, arbelprm_ud_send_wqe::next, ib_work_queue::next_idx, ib_work_queue::num_wqes, offsetof, ib_device::port, ib_address_vector::qkey, arbelprm_doorbell_record::qp, ib_queue_pair::qpn, ib_address_vector::qpn, ib_address_vector::rate, arbel::reserved_lkey, arbelprm_doorbell_register::send, arbel_queue_pair::send, ib_queue_pair::send, ib_address_vector::sl, arbelprm_ud_send_wqe::ud, arbel_send_wqe::ud, virt_to_bus(), and arbel_send_work_queue::wqe.
01017 { 01018 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01019 struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); 01020 struct ib_work_queue *wq = &qp->send; 01021 struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send; 01022 struct arbelprm_ud_send_wqe *prev_wqe; 01023 struct arbelprm_ud_send_wqe *wqe; 01024 struct arbelprm_qp_db_record *qp_db_rec; 01025 union arbelprm_doorbell_register db_reg; 01026 const struct ib_gid *gid; 01027 unsigned int wqe_idx_mask; 01028 size_t nds; 01029 01030 /* Allocate work queue entry */ 01031 wqe_idx_mask = ( wq->num_wqes - 1 ); 01032 if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) { 01033 DBGC ( arbel, "Arbel %p send queue full", arbel ); 01034 return -ENOBUFS; 01035 } 01036 wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf; 01037 prev_wqe = &arbel_send_wq->wqe[(wq->next_idx - 1) & wqe_idx_mask].ud; 01038 wqe = &arbel_send_wq->wqe[wq->next_idx & wqe_idx_mask].ud; 01039 01040 /* Construct work queue entry */ 01041 MLX_FILL_1 ( &wqe->next, 1, always1, 1 ); 01042 memset ( &wqe->ctrl, 0, sizeof ( wqe->ctrl ) ); 01043 MLX_FILL_1 ( &wqe->ctrl, 0, always1, 1 ); 01044 memset ( &wqe->ud, 0, sizeof ( wqe->ud ) ); 01045 MLX_FILL_2 ( &wqe->ud, 0, 01046 ud_address_vector.pd, ARBEL_GLOBAL_PD, 01047 ud_address_vector.port_number, ibdev->port ); 01048 MLX_FILL_2 ( &wqe->ud, 1, 01049 ud_address_vector.rlid, av->lid, 01050 ud_address_vector.g, av->gid_present ); 01051 MLX_FILL_2 ( &wqe->ud, 2, 01052 ud_address_vector.max_stat_rate, 01053 ( ( av->rate >= 3 ) ? 0 : 1 ), 01054 ud_address_vector.msg, 3 ); 01055 MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl ); 01056 gid = ( av->gid_present ? &av->gid : &arbel_no_gid ); 01057 memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) ); 01058 MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn ); 01059 MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey ); 01060 MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) ); 01061 MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->reserved_lkey ); 01062 MLX_FILL_1 ( &wqe->data[0], 3, 01063 local_address_l, virt_to_bus ( iobuf->data ) ); 01064 01065 /* Update previous work queue entry's "next" field */ 01066 nds = ( ( offsetof ( typeof ( *wqe ), data ) + 01067 sizeof ( wqe->data[0] ) ) >> 4 ); 01068 MLX_SET ( &prev_wqe->next, nopcode, ARBEL_OPCODE_SEND ); 01069 MLX_FILL_3 ( &prev_wqe->next, 1, 01070 nds, nds, 01071 f, 1, 01072 always1, 1 ); 01073 01074 /* Update doorbell record */ 01075 barrier(); 01076 qp_db_rec = &arbel->db_rec[arbel_send_wq->doorbell_idx].qp; 01077 MLX_FILL_1 ( qp_db_rec, 0, 01078 counter, ( ( wq->next_idx + 1 ) & 0xffff ) ); 01079 01080 /* Ring doorbell register */ 01081 MLX_FILL_4 ( &db_reg.send, 0, 01082 nopcode, ARBEL_OPCODE_SEND, 01083 f, 1, 01084 wqe_counter, ( wq->next_idx & 0xffff ), 01085 wqe_cnt, 1 ); 01086 MLX_FILL_2 ( &db_reg.send, 1, 01087 nds, nds, 01088 qpn, qp->qpn ); 01089 arbel_ring_doorbell ( arbel, &db_reg, ARBEL_DB_POST_SND_OFFSET ); 01090 01091 /* Update work queue's index */ 01092 wq->next_idx++; 01093 01094 return 0; 01095 }
| static int arbel_post_recv | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair * | qp, | |||
| struct io_buffer * | iobuf | |||
| ) | [static] |
Post receive work queue entry.
| ibdev | Infiniband device | |
| qp | Queue pair | |
| iobuf | I/O buffer |
| rc | Return status code |
Definition at line 1105 of file arbel.c.
References barrier, io_buffer::data, arbelprm_recv_wqe::data, arbel::db_rec, DBGC, arbel_recv_work_queue::doorbell_idx, ENOBUFS, ib_get_drvdata(), ib_qp_get_drvdata(), iob_tailroom(), ib_work_queue::iobufs, MLX_FILL_1, ib_work_queue::next_idx, ib_work_queue::num_wqes, arbelprm_doorbell_record::qp, arbel_recv_wqe::recv, arbel_queue_pair::recv, ib_queue_pair::recv, arbel::reserved_lkey, virt_to_bus(), and arbel_recv_work_queue::wqe.
01107 { 01108 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01109 struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); 01110 struct ib_work_queue *wq = &qp->recv; 01111 struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv; 01112 struct arbelprm_recv_wqe *wqe; 01113 union arbelprm_doorbell_record *db_rec; 01114 unsigned int wqe_idx_mask; 01115 01116 /* Allocate work queue entry */ 01117 wqe_idx_mask = ( wq->num_wqes - 1 ); 01118 if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) { 01119 DBGC ( arbel, "Arbel %p receive queue full", arbel ); 01120 return -ENOBUFS; 01121 } 01122 wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf; 01123 wqe = &arbel_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv; 01124 01125 /* Construct work queue entry */ 01126 MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) ); 01127 MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->reserved_lkey ); 01128 MLX_FILL_1 ( &wqe->data[0], 3, 01129 local_address_l, virt_to_bus ( iobuf->data ) ); 01130 01131 /* Update doorbell record */ 01132 barrier(); 01133 db_rec = &arbel->db_rec[arbel_recv_wq->doorbell_idx]; 01134 MLX_FILL_1 ( &db_rec->qp, 0, 01135 counter, ( ( wq->next_idx + 1 ) & 0xffff ) ); 01136 01137 /* Update work queue's index */ 01138 wq->next_idx++; 01139 01140 return 0; 01141 }
| static int arbel_complete | ( | struct ib_device * | ibdev, | |
| struct ib_completion_queue * | cq, | |||
| union arbelprm_completion_entry * | cqe | |||
| ) | [static] |
Handle completion.
| ibdev | Infiniband device | |
| cq | Completion queue | |
| cqe | Hardware completion queue entry |
| rc | Return status code |
Definition at line 1151 of file arbel.c.
References ARBEL_INVALID_LKEY, ARBEL_OPCODE_RECV_ERROR, ARBEL_OPCODE_SEND_ERROR, assert, ib_completion_queue::cqn, io_buffer::data, arbelprm_recv_wqe::data, DBGC, EIO, arbelprm_completion_entry::error, ib_address_vector::gid, ib_address_vector::gid_present, ib_complete_recv(), ib_complete_send(), ib_find_wq(), ib_get_drvdata(), ib_qp_get_drvdata(), iob_len(), iob_pull, iob_put, iob_tailroom(), ib_work_queue::iobufs, ib_address_vector::lid, memcpy, memset(), MLX_FILL_1, MLX_GET, arbelprm_completion_entry::normal, NULL, ib_work_queue::qp, ib_address_vector::qpn, arbel_recv_wqe::recv, arbel_queue_pair::recv, arbel_queue_pair::send, ib_global_route_header::sgid, ib_address_vector::sl, virt_to_bus(), arbel_recv_work_queue::wqe, and arbel_send_work_queue::wqe.
Referenced by arbel_poll_cq().
01153 { 01154 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01155 struct ib_work_queue *wq; 01156 struct ib_queue_pair *qp; 01157 struct arbel_queue_pair *arbel_qp; 01158 struct arbel_send_work_queue *arbel_send_wq; 01159 struct arbel_recv_work_queue *arbel_recv_wq; 01160 struct arbelprm_recv_wqe *recv_wqe; 01161 struct io_buffer *iobuf; 01162 struct ib_address_vector av; 01163 struct ib_global_route_header *grh; 01164 unsigned int opcode; 01165 unsigned long qpn; 01166 int is_send; 01167 unsigned long wqe_adr; 01168 unsigned int wqe_idx; 01169 size_t len; 01170 int rc = 0; 01171 01172 /* Parse completion */ 01173 qpn = MLX_GET ( &cqe->normal, my_qpn ); 01174 is_send = MLX_GET ( &cqe->normal, s ); 01175 wqe_adr = ( MLX_GET ( &cqe->normal, wqe_adr ) << 6 ); 01176 opcode = MLX_GET ( &cqe->normal, opcode ); 01177 if ( opcode >= ARBEL_OPCODE_RECV_ERROR ) { 01178 /* "s" field is not valid for error opcodes */ 01179 is_send = ( opcode == ARBEL_OPCODE_SEND_ERROR ); 01180 DBGC ( arbel, "Arbel %p CPN %lx syndrome %x vendor %x\n", 01181 arbel, cq->cqn, MLX_GET ( &cqe->error, syndrome ), 01182 MLX_GET ( &cqe->error, vendor_code ) ); 01183 rc = -EIO; 01184 /* Don't return immediately; propagate error to completer */ 01185 } 01186 01187 /* Identify work queue */ 01188 wq = ib_find_wq ( cq, qpn, is_send ); 01189 if ( ! wq ) { 01190 DBGC ( arbel, "Arbel %p CQN %lx unknown %s QPN %lx\n", 01191 arbel, cq->cqn, ( is_send ? "send" : "recv" ), qpn ); 01192 return -EIO; 01193 } 01194 qp = wq->qp; 01195 arbel_qp = ib_qp_get_drvdata ( qp ); 01196 arbel_send_wq = &arbel_qp->send; 01197 arbel_recv_wq = &arbel_qp->recv; 01198 01199 /* Identify work queue entry index */ 01200 if ( is_send ) { 01201 wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) / 01202 sizeof ( arbel_send_wq->wqe[0] ) ); 01203 assert ( wqe_idx < qp->send.num_wqes ); 01204 } else { 01205 wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) / 01206 sizeof ( arbel_recv_wq->wqe[0] ) ); 01207 assert ( wqe_idx < qp->recv.num_wqes ); 01208 } 01209 01210 /* Identify I/O buffer */ 01211 iobuf = wq->iobufs[wqe_idx]; 01212 if ( ! iobuf ) { 01213 DBGC ( arbel, "Arbel %p CQN %lx QPN %lx empty WQE %x\n", 01214 arbel, cq->cqn, qpn, wqe_idx ); 01215 return -EIO; 01216 } 01217 wq->iobufs[wqe_idx] = NULL; 01218 01219 if ( is_send ) { 01220 /* Hand off to completion handler */ 01221 ib_complete_send ( ibdev, qp, iobuf, rc ); 01222 } else { 01223 /* Set received length */ 01224 len = MLX_GET ( &cqe->normal, byte_cnt ); 01225 recv_wqe = &arbel_recv_wq->wqe[wqe_idx].recv; 01226 assert ( MLX_GET ( &recv_wqe->data[0], local_address_l ) == 01227 virt_to_bus ( iobuf->data ) ); 01228 assert ( MLX_GET ( &recv_wqe->data[0], byte_count ) == 01229 iob_tailroom ( iobuf ) ); 01230 MLX_FILL_1 ( &recv_wqe->data[0], 0, byte_count, 0 ); 01231 MLX_FILL_1 ( &recv_wqe->data[0], 1, 01232 l_key, ARBEL_INVALID_LKEY ); 01233 assert ( len <= iob_tailroom ( iobuf ) ); 01234 iob_put ( iobuf, len ); 01235 assert ( iob_len ( iobuf ) >= sizeof ( *grh ) ); 01236 grh = iobuf->data; 01237 iob_pull ( iobuf, sizeof ( *grh ) ); 01238 /* Construct address vector */ 01239 memset ( &av, 0, sizeof ( av ) ); 01240 av.qpn = MLX_GET ( &cqe->normal, rqpn ); 01241 av.lid = MLX_GET ( &cqe->normal, rlid ); 01242 av.sl = MLX_GET ( &cqe->normal, sl ); 01243 av.gid_present = MLX_GET ( &cqe->normal, g ); 01244 memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) ); 01245 /* Hand off to completion handler */ 01246 ib_complete_recv ( ibdev, qp, &av, iobuf, rc ); 01247 } 01248 01249 return rc; 01250 }
| static void arbel_poll_cq | ( | struct ib_device * | ibdev, | |
| struct ib_completion_queue * | cq | |||
| ) | [static] |
Poll completion queue.
| ibdev | Infiniband device | |
| cq | Completion queue |
Definition at line 1258 of file arbel.c.
References arbel_complete(), barrier, arbel_completion_queue::ci_doorbell_idx, arbelprm_doorbell_record::cq_ci, arbel_completion_queue::cqe, arbel::db_rec, DBGC, DBGC_HD, ib_cq_get_drvdata(), ib_get_drvdata(), MLX_FILL_1, MLX_GET, ib_completion_queue::next_idx, arbelprm_completion_entry::normal, ib_completion_queue::num_cqes, and strerror().
01259 { 01260 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01261 struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq ); 01262 struct arbelprm_cq_ci_db_record *ci_db_rec; 01263 union arbelprm_completion_entry *cqe; 01264 unsigned int cqe_idx_mask; 01265 int rc; 01266 01267 while ( 1 ) { 01268 /* Look for completion entry */ 01269 cqe_idx_mask = ( cq->num_cqes - 1 ); 01270 cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask]; 01271 if ( MLX_GET ( &cqe->normal, owner ) != 0 ) { 01272 /* Entry still owned by hardware; end of poll */ 01273 break; 01274 } 01275 01276 /* Handle completion */ 01277 if ( ( rc = arbel_complete ( ibdev, cq, cqe ) ) != 0 ) { 01278 DBGC ( arbel, "Arbel %p failed to complete: %s\n", 01279 arbel, strerror ( rc ) ); 01280 DBGC_HD ( arbel, cqe, sizeof ( *cqe ) ); 01281 } 01282 01283 /* Return ownership to hardware */ 01284 MLX_FILL_1 ( &cqe->normal, 7, owner, 1 ); 01285 barrier(); 01286 /* Update completion queue's index */ 01287 cq->next_idx++; 01288 /* Update doorbell record */ 01289 ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci; 01290 MLX_FILL_1 ( ci_db_rec, 0, 01291 counter, ( cq->next_idx & 0xffffffffUL ) ); 01292 } 01293 }
| static int arbel_create_eq | ( | struct arbel * | arbel | ) | [static] |
Create event queue.
| rc | Return status code |
Definition at line 1308 of file arbel.c.
References arbel_cmd_hw2sw_eq(), arbel_cmd_map_eq(), arbel_cmd_sw2hw_eq(), ARBEL_DB_EQ_OFFSET, ARBEL_GLOBAL_PD, ARBEL_MAP_EQ, ARBEL_NUM_EQES, barrier, DBGC, arbel_event_queue::doorbell, ENOMEM, arbel::eq, arbel::eq_ci_doorbells, arbel_event_queue::eqe, arbel_event_queue::eqe_size, arbel_event_queue::eqn, fls, free_dma(), arbelprm_event_entry::generic, arbel::limits, malloc_dma(), memset(), MLX_FILL_1, arbel_dev_limits::reserved_eqs, arbel::reserved_lkey, strerror(), and virt_to_phys().
Referenced by arbel_probe().
01308 { 01309 struct arbel_event_queue *arbel_eq = &arbel->eq; 01310 struct arbelprm_eqc eqctx; 01311 struct arbelprm_event_mask mask; 01312 unsigned int i; 01313 int rc; 01314 01315 /* Select event queue number */ 01316 arbel_eq->eqn = arbel->limits.reserved_eqs; 01317 01318 /* Calculate doorbell address */ 01319 arbel_eq->doorbell = ( arbel->eq_ci_doorbells + 01320 ARBEL_DB_EQ_OFFSET ( arbel_eq->eqn ) ); 01321 01322 /* Allocate event queue itself */ 01323 arbel_eq->eqe_size = 01324 ( ARBEL_NUM_EQES * sizeof ( arbel_eq->eqe[0] ) ); 01325 arbel_eq->eqe = malloc_dma ( arbel_eq->eqe_size, 01326 sizeof ( arbel_eq->eqe[0] ) ); 01327 if ( ! arbel_eq->eqe ) { 01328 rc = -ENOMEM; 01329 goto err_eqe; 01330 } 01331 memset ( arbel_eq->eqe, 0, arbel_eq->eqe_size ); 01332 for ( i = 0 ; i < ARBEL_NUM_EQES ; i++ ) { 01333 MLX_FILL_1 ( &arbel_eq->eqe[i].generic, 7, owner, 1 ); 01334 } 01335 barrier(); 01336 01337 /* Hand queue over to hardware */ 01338 memset ( &eqctx, 0, sizeof ( eqctx ) ); 01339 MLX_FILL_1 ( &eqctx, 0, st, 0xa /* "Fired" */ ); 01340 MLX_FILL_1 ( &eqctx, 2, 01341 start_address_l, virt_to_phys ( arbel_eq->eqe ) ); 01342 MLX_FILL_1 ( &eqctx, 3, log_eq_size, fls ( ARBEL_NUM_EQES - 1 ) ); 01343 MLX_FILL_1 ( &eqctx, 6, pd, ARBEL_GLOBAL_PD ); 01344 MLX_FILL_1 ( &eqctx, 7, lkey, arbel->reserved_lkey ); 01345 if ( ( rc = arbel_cmd_sw2hw_eq ( arbel, arbel_eq->eqn, 01346 &eqctx ) ) != 0 ) { 01347 DBGC ( arbel, "Arbel %p SW2HW_EQ failed: %s\n", 01348 arbel, strerror ( rc ) ); 01349 goto err_sw2hw_eq; 01350 } 01351 01352 /* Map events to this event queue */ 01353 memset ( &mask, 0, sizeof ( mask ) ); 01354 MLX_FILL_1 ( &mask, 1, port_state_change, 1 ); 01355 if ( ( rc = arbel_cmd_map_eq ( arbel, 01356 ( ARBEL_MAP_EQ | arbel_eq->eqn ), 01357 &mask ) ) != 0 ) { 01358 DBGC ( arbel, "Arbel %p MAP_EQ failed: %s\n", 01359 arbel, strerror ( rc ) ); 01360 goto err_map_eq; 01361 } 01362 01363 DBGC ( arbel, "Arbel %p EQN %#lx ring at [%p,%p])\n", 01364 arbel, arbel_eq->eqn, arbel_eq->eqe, 01365 ( ( ( void * ) arbel_eq->eqe ) + arbel_eq->eqe_size ) ); 01366 return 0; 01367 01368 err_map_eq: 01369 arbel_cmd_hw2sw_eq ( arbel, arbel_eq->eqn, &eqctx ); 01370 err_sw2hw_eq: 01371 free_dma ( arbel_eq->eqe, arbel_eq->eqe_size ); 01372 err_eqe: 01373 memset ( arbel_eq, 0, sizeof ( *arbel_eq ) ); 01374 return rc; 01375 }
| static void arbel_destroy_eq | ( | struct arbel * | arbel | ) | [static] |
Destroy event queue.
Definition at line 1382 of file arbel.c.
References arbel_cmd_hw2sw_eq(), arbel_cmd_map_eq(), ARBEL_UNMAP_EQ, DBGC, arbel::eq, arbel_event_queue::eqe, arbel_event_queue::eqe_size, arbel_event_queue::eqn, free_dma(), memset(), MLX_FILL_1, and strerror().
Referenced by arbel_probe(), and arbel_remove().
01382 { 01383 struct arbel_event_queue *arbel_eq = &arbel->eq; 01384 struct arbelprm_eqc eqctx; 01385 struct arbelprm_event_mask mask; 01386 int rc; 01387 01388 /* Unmap events from event queue */ 01389 memset ( &mask, 0, sizeof ( mask ) ); 01390 MLX_FILL_1 ( &mask, 1, port_state_change, 1 ); 01391 if ( ( rc = arbel_cmd_map_eq ( arbel, 01392 ( ARBEL_UNMAP_EQ | arbel_eq->eqn ), 01393 &mask ) ) != 0 ) { 01394 DBGC ( arbel, "Arbel %p FATAL MAP_EQ failed to unmap: %s\n", 01395 arbel, strerror ( rc ) ); 01396 /* Continue; HCA may die but system should survive */ 01397 } 01398 01399 /* Take ownership back from hardware */ 01400 if ( ( rc = arbel_cmd_hw2sw_eq ( arbel, arbel_eq->eqn, 01401 &eqctx ) ) != 0 ) { 01402 DBGC ( arbel, "Arbel %p FATAL HW2SW_EQ failed: %s\n", 01403 arbel, strerror ( rc ) ); 01404 /* Leak memory and return; at least we avoid corruption */ 01405 return; 01406 } 01407 01408 /* Free memory */ 01409 free_dma ( arbel_eq->eqe, arbel_eq->eqe_size ); 01410 memset ( arbel_eq, 0, sizeof ( *arbel_eq ) ); 01411 }
| static void arbel_event_port_state_change | ( | struct arbel * | arbel, | |
| union arbelprm_event_entry * | eqe | |||
| ) | [static] |
Handle port state event.
Definition at line 1419 of file arbel.c.
References arbel_mad(), ARBEL_NUM_PORTS, DBGC, arbelprm_event_entry::generic, ib_link_state_changed(), ib_smc_update(), arbel::ibdev, MLX_GET, and arbelprm_event_entry::port_state_change.
Referenced by arbel_poll_eq().
01420 { 01421 unsigned int port; 01422 int link_up; 01423 01424 /* Get port and link status */ 01425 port = ( MLX_GET ( &eqe->port_state_change, data.p ) - 1 ); 01426 link_up = ( MLX_GET ( &eqe->generic, event_sub_type ) & 0x04 ); 01427 DBGC ( arbel, "Arbel %p port %d link %s\n", arbel, ( port + 1 ), 01428 ( link_up ? "up" : "down" ) ); 01429 01430 /* Sanity check */ 01431 if ( port >= ARBEL_NUM_PORTS ) { 01432 DBGC ( arbel, "Arbel %p port %d does not exist!\n", 01433 arbel, ( port + 1 ) ); 01434 return; 01435 } 01436 01437 /* Update MAD parameters */ 01438 ib_smc_update ( arbel->ibdev[port], arbel_mad ); 01439 01440 /* Notify Infiniband core of link state change */ 01441 ib_link_state_changed ( arbel->ibdev[port] ); 01442 }
| static void arbel_poll_eq | ( | struct ib_device * | ibdev | ) | [static] |
Poll event queue.
| ibdev | Infiniband device |
Definition at line 1449 of file arbel.c.
References ARBEL_EV_PORT_STATE_CHANGE, arbel_event_port_state_change(), ARBEL_NUM_EQES, barrier, arbelprm_eq_doorbell_register::ci, DBGC, DBGC_HD, DBGCP, DBGCP_HD, arbel_event_queue::doorbell, arbelprm_eq_doorbell_register::dword, arbel::eq, arbel_event_queue::eqe, arbelprm_event_entry::generic, ib_get_drvdata(), MLX_FILL_1, MLX_GET, arbel_event_queue::next_idx, virt_to_phys(), and writel.
01449 { 01450 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01451 struct arbel_event_queue *arbel_eq = &arbel->eq; 01452 union arbelprm_event_entry *eqe; 01453 union arbelprm_eq_doorbell_register db_reg; 01454 unsigned int eqe_idx_mask; 01455 unsigned int event_type; 01456 01457 while ( 1 ) { 01458 /* Look for event entry */ 01459 eqe_idx_mask = ( ARBEL_NUM_EQES - 1 ); 01460 eqe = &arbel_eq->eqe[arbel_eq->next_idx & eqe_idx_mask]; 01461 if ( MLX_GET ( &eqe->generic, owner ) != 0 ) { 01462 /* Entry still owned by hardware; end of poll */ 01463 break; 01464 } 01465 DBGCP ( arbel, "Arbel %p event:\n", arbel ); 01466 DBGCP_HD ( arbel, eqe, sizeof ( *eqe ) ); 01467 01468 /* Handle event */ 01469 event_type = MLX_GET ( &eqe->generic, event_type ); 01470 switch ( event_type ) { 01471 case ARBEL_EV_PORT_STATE_CHANGE: 01472 arbel_event_port_state_change ( arbel, eqe ); 01473 break; 01474 default: 01475 DBGC ( arbel, "Arbel %p unrecognised event type " 01476 "%#x:\n", arbel, event_type ); 01477 DBGC_HD ( arbel, eqe, sizeof ( *eqe ) ); 01478 break; 01479 } 01480 01481 /* Return ownership to hardware */ 01482 MLX_FILL_1 ( &eqe->generic, 7, owner, 1 ); 01483 barrier(); 01484 01485 /* Update event queue's index */ 01486 arbel_eq->next_idx++; 01487 01488 /* Ring doorbell */ 01489 MLX_FILL_1 ( &db_reg.ci, 0, ci, arbel_eq->next_idx ); 01490 DBGCP ( arbel, "Ringing doorbell %08lx with %08x\n", 01491 virt_to_phys ( arbel_eq->doorbell ), 01492 db_reg.dword[0] ); 01493 writel ( db_reg.dword[0], arbel_eq->doorbell ); 01494 } 01495 }
| static int arbel_open | ( | struct ib_device * | ibdev | ) | [static] |
Initialise Infiniband link.
| ibdev | Infiniband device |
| rc | Return status code |
Definition at line 1510 of file arbel.c.
References arbel_cmd_init_ib(), arbel_mad(), ARBEL_MTU_2048, DBGC, ib_get_drvdata(), ib_smc_update(), memset(), MLX_FILL_1, MLX_FILL_3, ib_device::port, and strerror().
01510 { 01511 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01512 struct arbelprm_init_ib init_ib; 01513 int rc; 01514 01515 memset ( &init_ib, 0, sizeof ( init_ib ) ); 01516 MLX_FILL_3 ( &init_ib, 0, 01517 mtu_cap, ARBEL_MTU_2048, 01518 port_width_cap, 3, 01519 vl_cap, 1 ); 01520 MLX_FILL_1 ( &init_ib, 1, max_gid, 1 ); 01521 MLX_FILL_1 ( &init_ib, 2, max_pkey, 64 ); 01522 if ( ( rc = arbel_cmd_init_ib ( arbel, ibdev->port, 01523 &init_ib ) ) != 0 ) { 01524 DBGC ( arbel, "Arbel %p could not intialise IB: %s\n", 01525 arbel, strerror ( rc ) ); 01526 return rc; 01527 } 01528 01529 /* Update MAD parameters */ 01530 ib_smc_update ( ibdev, arbel_mad ); 01531 01532 return 0; 01533 }
| static void arbel_close | ( | struct ib_device * | ibdev | ) | [static] |
Close Infiniband link.
| ibdev | Infiniband device |
Definition at line 1540 of file arbel.c.
References arbel_cmd_close_ib(), DBGC, ib_get_drvdata(), ib_device::port, and strerror().
01540 { 01541 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01542 int rc; 01543 01544 if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) { 01545 DBGC ( arbel, "Arbel %p could not close IB: %s\n", 01546 arbel, strerror ( rc ) ); 01547 /* Nothing we can do about this */ 01548 } 01549 }
| static int arbel_mcast_attach | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair * | qp, | |||
| struct ib_gid * | gid | |||
| ) | [static] |
Attach to multicast group.
| ibdev | Infiniband device | |
| qp | Queue pair | |
| gid | Multicast GID |
| rc | Return status code |
Definition at line 1566 of file arbel.c.
References arbel_cmd_mgid_hash(), arbel_cmd_read_mgm(), arbel_cmd_write_mgm(), DBGC, EBUSY, ib_get_drvdata(), index, memcpy, MLX_FILL_2, MLX_GET, ib_queue_pair::qpn, and strerror().
01568 { 01569 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01570 struct arbelprm_mgm_hash hash; 01571 struct arbelprm_mgm_entry mgm; 01572 unsigned int index; 01573 int rc; 01574 01575 /* Generate hash table index */ 01576 if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) { 01577 DBGC ( arbel, "Arbel %p could not hash GID: %s\n", 01578 arbel, strerror ( rc ) ); 01579 return rc; 01580 } 01581 index = MLX_GET ( &hash, hash ); 01582 01583 /* Check for existing hash table entry */ 01584 if ( ( rc = arbel_cmd_read_mgm ( arbel, index, &mgm ) ) != 0 ) { 01585 DBGC ( arbel, "Arbel %p could not read MGM %#x: %s\n", 01586 arbel, index, strerror ( rc ) ); 01587 return rc; 01588 } 01589 if ( MLX_GET ( &mgm, mgmqp_0.qi ) != 0 ) { 01590 /* FIXME: this implementation allows only a single QP 01591 * per multicast group, and doesn't handle hash 01592 * collisions. Sufficient for IPoIB but may need to 01593 * be extended in future. 01594 */ 01595 DBGC ( arbel, "Arbel %p MGID index %#x already in use\n", 01596 arbel, index ); 01597 return -EBUSY; 01598 } 01599 01600 /* Update hash table entry */ 01601 MLX_FILL_2 ( &mgm, 8, 01602 mgmqp_0.qpn_i, qp->qpn, 01603 mgmqp_0.qi, 1 ); 01604 memcpy ( &mgm.u.dwords[4], gid, sizeof ( *gid ) ); 01605 if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) { 01606 DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n", 01607 arbel, index, strerror ( rc ) ); 01608 return rc; 01609 } 01610 01611 return 0; 01612 }
| static void arbel_mcast_detach | ( | struct ib_device * | ibdev, | |
| struct ib_queue_pair *qp | __unused, | |||
| struct ib_gid * | gid | |||
| ) | [static] |
Detach from multicast group.
| ibdev | Infiniband device | |
| qp | Queue pair | |
| gid | Multicast GID |
Definition at line 1621 of file arbel.c.
References arbel_cmd_mgid_hash(), arbel_cmd_write_mgm(), DBGC, ib_get_drvdata(), index, memset(), MLX_GET, and strerror().
01623 { 01624 struct arbel *arbel = ib_get_drvdata ( ibdev ); 01625 struct arbelprm_mgm_hash hash; 01626 struct arbelprm_mgm_entry mgm; 01627 unsigned int index; 01628 int rc; 01629 01630 /* Generate hash table index */ 01631 if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) { 01632 DBGC ( arbel, "Arbel %p could not hash GID: %s\n", 01633 arbel, strerror ( rc ) ); 01634 return; 01635 } 01636 index = MLX_GET ( &hash, hash ); 01637 01638 /* Clear hash table entry */ 01639 memset ( &mgm, 0, sizeof ( mgm ) ); 01640 if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) { 01641 DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n", 01642 arbel, index, strerror ( rc ) ); 01643 return; 01644 } 01645 }
| static int arbel_start_firmware | ( | struct arbel * | arbel | ) | [static] |
Start firmware running.
| rc | Return status code |
Definition at line 1677 of file arbel.c.
References arbel_cmd_enable_lam(), arbel_cmd_map_fa(), arbel_cmd_query_fw(), arbel_cmd_run_fw(), arbel_cmd_unmap_fa(), DBGC, ENOMEM, arbel::eq_ci_doorbells, arbel::firmware_area, fls, ioremap(), memset(), MLX_FILL_2, MLX_GET, strerror(), ufree(), umalloc(), UNULL, and user_to_phys().
Referenced by arbel_probe().
01677 { 01678 struct arbelprm_query_fw fw; 01679 struct arbelprm_access_lam lam; 01680 struct arbelprm_virtual_physical_mapping map_fa; 01681 unsigned int fw_pages; 01682 unsigned int log2_fw_pages; 01683 size_t fw_size; 01684 physaddr_t fw_base; 01685 uint64_t eq_set_ci_base_addr; 01686 int rc; 01687 01688 /* Get firmware parameters */ 01689 if ( ( rc = arbel_cmd_query_fw ( arbel, &fw ) ) != 0 ) { 01690 DBGC ( arbel, "Arbel %p could not query firmware: %s\n", 01691 arbel, strerror ( rc ) ); 01692 goto err_query_fw; 01693 } 01694 DBGC ( arbel, "Arbel %p firmware version %d.%d.%d\n", arbel, 01695 MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ), 01696 MLX_GET ( &fw, fw_rev_subminor ) ); 01697 fw_pages = MLX_GET ( &fw, fw_pages ); 01698 log2_fw_pages = fls ( fw_pages - 1 ); 01699 fw_pages = ( 1 << log2_fw_pages ); 01700 DBGC ( arbel, "Arbel %p requires %d kB for firmware\n", 01701 arbel, ( fw_pages * 4 ) ); 01702 eq_set_ci_base_addr = 01703 ( ( (uint64_t) MLX_GET ( &fw, eq_set_ci_base_addr_h ) << 32 ) | 01704 ( (uint64_t) MLX_GET ( &fw, eq_set_ci_base_addr_l ) ) ); 01705 arbel->eq_ci_doorbells = ioremap ( eq_set_ci_base_addr, 0x200 ); 01706 01707 /* Enable locally-attached memory. Ignore failure; there may 01708 * be no attached memory. 01709 */ 01710 arbel_cmd_enable_lam ( arbel, &lam ); 01711 01712 /* Allocate firmware pages and map firmware area */ 01713 fw_size = ( fw_pages * 4096 ); 01714 arbel->firmware_area = umalloc ( fw_size * 2 ); 01715 if ( ! arbel->firmware_area ) { 01716 rc = -ENOMEM; 01717 goto err_alloc_fa; 01718 } 01719 fw_base = ( user_to_phys ( arbel->firmware_area, fw_size ) & 01720 ~( fw_size - 1 ) ); 01721 DBGC ( arbel, "Arbel %p firmware area at physical [%lx,%lx)\n", 01722 arbel, fw_base, ( fw_base + fw_size ) ); 01723 memset ( &map_fa, 0, sizeof ( map_fa ) ); 01724 MLX_FILL_2 ( &map_fa, 3, 01725 log2size, log2_fw_pages, 01726 pa_l, ( fw_base >> 12 ) ); 01727 if ( ( rc = arbel_cmd_map_fa ( arbel, &map_fa ) ) != 0 ) { 01728 DBGC ( arbel, "Arbel %p could not map firmware: %s\n", 01729 arbel, strerror ( rc ) ); 01730 goto err_map_fa; 01731 } 01732 01733 /* Start firmware */ 01734 if ( ( rc = arbel_cmd_run_fw ( arbel ) ) != 0 ) { 01735 DBGC ( arbel, "Arbel %p could not run firmware: %s\n", 01736 arbel, strerror ( rc ) ); 01737 goto err_run_fw; 01738 } 01739 01740 DBGC ( arbel, "Arbel %p firmware started\n", arbel ); 01741 return 0; 01742 01743 err_run_fw: 01744 arbel_cmd_unmap_fa ( arbel ); 01745 err_map_fa: 01746 ufree ( arbel->firmware_area ); 01747 arbel->firmware_area = UNULL; 01748 err_alloc_fa: 01749 err_query_fw: 01750 return rc; 01751 }
| static void arbel_stop_firmware | ( | struct arbel * | arbel | ) | [static] |
Stop firmware running.
Definition at line 1758 of file arbel.c.
References arbel_cmd_unmap_fa(), DBGC, arbel::firmware_area, strerror(), ufree(), and UNULL.
Referenced by arbel_probe(), and arbel_remove().
01758 { 01759 int rc; 01760 01761 if ( ( rc = arbel_cmd_unmap_fa ( arbel ) ) != 0 ) { 01762 DBGC ( arbel, "Arbel %p FATAL could not stop firmware: %s\n", 01763 arbel, strerror ( rc ) ); 01764 /* Leak memory and return; at least we avoid corruption */ 01765 return; 01766 } 01767 ufree ( arbel->firmware_area ); 01768 arbel->firmware_area = UNULL; 01769 }
| static int arbel_get_limits | ( | struct arbel * | arbel | ) | [static] |
Get device limits.
| rc | Return status code |
Definition at line 1784 of file arbel.c.
References arbel_cmd_query_dev_lim(), arbel_dev_limits::cqc_entry_size, DBGC, arbel_dev_limits::eec_entry_size, arbel_dev_limits::eeec_entry_size, arbel_dev_limits::eqc_entry_size, arbel_dev_limits::eqpc_entry_size, arbel::limits, MLX_GET, arbel_dev_limits::mpt_entry_size, arbel_dev_limits::mtt_entry_size, arbel_dev_limits::qpc_entry_size, arbel_dev_limits::reserved_cqs, arbel_dev_limits::reserved_ees, arbel_dev_limits::reserved_eqs, arbel_dev_limits::reserved_mrws, arbel_dev_limits::reserved_mtts, arbel_dev_limits::reserved_qps, arbel_dev_limits::reserved_rdbs, arbel_dev_limits::reserved_srqs, arbel_dev_limits::reserved_uars, arbel_dev_limits::srqc_entry_size, and strerror().
Referenced by arbel_probe().
01784 { 01785 struct arbelprm_query_dev_lim dev_lim; 01786 int rc; 01787 01788 if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) { 01789 DBGC ( arbel, "Arbel %p could not get device limits: %s\n", 01790 arbel, strerror ( rc ) ); 01791 return rc; 01792 } 01793 01794 arbel->limits.reserved_qps = 01795 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_qps ) ); 01796 arbel->limits.qpc_entry_size = MLX_GET ( &dev_lim, qpc_entry_sz ); 01797 arbel->limits.eqpc_entry_size = MLX_GET ( &dev_lim, eqpc_entry_sz ); 01798 arbel->limits.reserved_srqs = 01799 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_srqs ) ); 01800 arbel->limits.srqc_entry_size = MLX_GET ( &dev_lim, srq_entry_sz ); 01801 arbel->limits.reserved_ees = 01802 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_ees ) ); 01803 arbel->limits.eec_entry_size = MLX_GET ( &dev_lim, eec_entry_sz ); 01804 arbel->limits.eeec_entry_size = MLX_GET ( &dev_lim, eeec_entry_sz ); 01805 arbel->limits.reserved_cqs = 01806 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_cqs ) ); 01807 arbel->limits.cqc_entry_size = MLX_GET ( &dev_lim, cqc_entry_sz ); 01808 arbel->limits.reserved_eqs = MLX_GET ( &dev_lim, num_rsvd_eqs ); 01809 arbel->limits.reserved_mtts = 01810 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_mtts ) ); 01811 arbel->limits.mtt_entry_size = MLX_GET ( &dev_lim, mtt_entry_sz ); 01812 arbel->limits.reserved_mrws = 01813 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_mrws ) ); 01814 arbel->limits.mpt_entry_size = MLX_GET ( &dev_lim, mpt_entry_sz ); 01815 arbel->limits.reserved_rdbs = 01816 ( 1 << MLX_GET ( &dev_lim, log2_rsvd_rdbs ) ); 01817 arbel->limits.eqc_entry_size = MLX_GET ( &dev_lim, eqc_entry_sz ); 01818 arbel->limits.reserved_uars = MLX_GET ( &dev_lim, num_rsvd_uars ); 01819 01820 return 0; 01821 }
Get ICM usage.
| log_num_entries | Log2 of the number of entries | |
| entry_size | Entry size |
| usage | Usage size in ICM |
Definition at line 1830 of file arbel.c.
Referenced by arbel_alloc_icm(), and hermon_alloc_icm().
01830 { 01831 size_t usage; 01832 01833 usage = ( ( 1 << log_num_entries ) * entry_size ); 01834 usage = ( ( usage + 4095 ) & ~4095 ); 01835 return usage; 01836 }
| static int arbel_alloc_icm | ( | struct arbel * | arbel, | |
| struct arbelprm_init_hca * | init_hca | |||
| ) | [static] |
Allocate ICM.
| rc | Return status code |
Definition at line 1845 of file arbel.c.
References arbel_cmd_map_icm(), arbel_cmd_map_icm_aux(), arbel_cmd_set_icm_size(), arbel_cmd_unmap_icm(), arbel_cmd_unmap_icm_aux(), ARBEL_GROUP_SEPARATOR_DOORBELL, ARBEL_MAX_CQS, ARBEL_MAX_EQS, ARBEL_MAX_QPS, ARBEL_PAGE_SIZE, ARBEL_UAR_RES_GROUP_SEP, arbel_dev_limits::cqc_entry_size, arbel::db_rec, DBGC, arbel_dev_limits::eec_entry_size, arbel_dev_limits::eeec_entry_size, ENOMEM, arbel_dev_limits::eqc_entry_size, fls, arbel::icm, arbel::icm_aux_len, arbel::icm_len, icm_usage(), arbel::limits, memset(), MLX_FILL_1, MLX_FILL_2, MLX_GET, arbel_dev_limits::mpt_entry_size, arbel_dev_limits::mtt_entry_size, phys_to_virt(), arbelprm_doorbell_record::qp, arbel_dev_limits::qpc_entry_size, arbel_dev_limits::reserved_cqs, arbel_dev_limits::reserved_ees, arbel_dev_limits::reserved_eqs, arbel_dev_limits::reserved_mrws, arbel_dev_limits::reserved_mtts, arbel_dev_limits::reserved_qps, arbel_dev_limits::reserved_rdbs, arbel_dev_limits::reserved_srqs, arbel_dev_limits::reserved_uars, arbel_dev_limits::srqc_entry_size, strerror(), ufree(), umalloc(), UNULL, and user_to_phys().
Referenced by arbel_probe().
01846 { 01847 struct arbelprm_scalar_parameter icm_size; 01848 struct arbelprm_scalar_parameter icm_aux_size; 01849 struct arbelprm_virtual_physical_mapping map_icm_aux; 01850 struct arbelprm_virtual_physical_mapping map_icm; 01851 union arbelprm_doorbell_record *db_rec; 01852 size_t icm_offset = 0; 01853 unsigned int log_num_qps, log_num_srqs, log_num_ees, log_num_cqs; 01854 unsigned int log_num_mtts, log_num_mpts, log_num_rdbs, log_num_eqs; 01855 int rc; 01856 01857 icm_offset = ( ( arbel->limits.reserved_uars + 1 ) << 12 ); 01858 01859 /* Queue pair contexts */ 01860 log_num_qps = fls ( arbel->limits.reserved_qps + ARBEL_MAX_QPS - 1 ); 01861 MLX_FILL_2 ( init_hca, 13, 01862 qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_l, 01863 ( icm_offset >> 7 ), 01864 qpc_eec_cqc_eqc_rdb_parameters.log_num_of_qp, 01865 log_num_qps ); 01866 DBGC ( arbel, "Arbel %p ICM QPC base = %zx\n", arbel, icm_offset ); 01867 icm_offset += icm_usage ( log_num_qps, arbel->limits.qpc_entry_size ); 01868 01869 /* Extended queue pair contexts */ 01870 MLX_FILL_1 ( init_hca, 25, 01871 qpc_eec_cqc_eqc_rdb_parameters.eqpc_base_addr_l, 01872 icm_offset ); 01873 DBGC ( arbel, "Arbel %p ICM EQPC base = %zx\n", arbel, icm_offset ); 01874 // icm_offset += icm_usage ( log_num_qps, arbel->limits.eqpc_entry_size ); 01875 icm_offset += icm_usage ( log_num_qps, arbel->limits.qpc_entry_size ); 01876 01877 /* Shared receive queue contexts */ 01878 log_num_srqs = fls ( arbel->limits.reserved_srqs - 1 ); 01879 MLX_FILL_2 ( init_hca, 19, 01880 qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_l, 01881 ( icm_offset >> 5 ), 01882 qpc_eec_cqc_eqc_rdb_parameters.log_num_of_srq, 01883 log_num_srqs ); 01884 DBGC ( arbel, "Arbel %p ICM SRQC base = %zx\n", arbel, icm_offset ); 01885 icm_offset += icm_usage ( log_num_srqs, arbel->limits.srqc_entry_size ); 01886 01887 /* End-to-end contexts */ 01888 log_num_ees = fls ( arbel->limits.reserved_ees - 1 ); 01889 MLX_FILL_2 ( init_hca, 17, 01890 qpc_eec_cqc_eqc_rdb_parameters.eec_base_addr_l, 01891 ( icm_offset >> 7 ), 01892 qpc_eec_cqc_eqc_rdb_parameters.log_num_of_ee, 01893 log_num_ees ); 01894 DBGC ( arbel, "Arbel %p ICM EEC base = %zx\n", arbel, icm_offset ); 01895 icm_offset += icm_usage ( log_num_ees, arbel->limits.eec_entry_size ); 01896 01897 /* Extended end-to-end contexts */ 01898 MLX_FILL_1 ( init_hca, 29, 01899 qpc_eec_cqc_eqc_rdb_parameters.eeec_base_addr_l, 01900 icm_offset ); 01901 DBGC ( arbel, "Arbel %p ICM EEEC base = %zx\n", arbel, icm_offset ); 01902 icm_offset += icm_usage ( log_num_ees, arbel->limits.eeec_entry_size ); 01903 01904 /* Completion queue contexts */ 01905 log_num_cqs = fls ( arbel->limits.reserved_cqs + ARBEL_MAX_CQS - 1 ); 01906 MLX_FILL_2 ( init_hca, 21, 01907 qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_l, 01908 ( icm_offset >> 6 ), 01909 qpc_eec_cqc_eqc_rdb_parameters.log_num_of_cq, 01910 log_num_cqs ); 01911 DBGC ( arbel, "Arbel %p ICM CQC base = %zx\n", arbel, icm_offset ); 01912 icm_offset += icm_usage ( log_num_cqs, arbel->limits.cqc_entry_size ); 01913 01914 /* Memory translation table */ 01915 log_num_mtts = fls ( arbel->limits.reserved_mtts - 1 ); 01916 MLX_FILL_1 ( init_hca, 65, 01917 tpt_parameters.mtt_base_addr_l, icm_offset ); 01918 DBGC ( arbel, "Arbel %p ICM MTT base = %zx\n", arbel, icm_offset ); 01919 icm_offset += icm_usage ( log_num_mtts, arbel->limits.mtt_entry_size ); 01920 01921 /* Memory protection table */ 01922 log_num_mpts = fls ( arbel->limits.reserved_mrws + 1 - 1 ); 01923 MLX_FILL_1 ( init_hca, 61, 01924 tpt_parameters.mpt_base_adr_l, icm_offset ); 01925 MLX_FILL_1 ( init_hca, 62, 01926 tpt_parameters.log_mpt_sz, log_num_mpts ); 01927 DBGC ( arbel, "Arbel %p ICM MTT base = %zx\n", arbel, icm_offset ); 01928 icm_offset += icm_usage ( log_num_mpts, arbel->limits.mpt_entry_size ); 01929 01930 /* RDMA something or other */ 01931 log_num_rdbs = fls ( arbel->limits.reserved_rdbs - 1 ); 01932 MLX_FILL_1 ( init_hca, 37, 01933 qpc_eec_cqc_eqc_rdb_parameters.rdb_base_addr_l, 01934 icm_offset ); 01935 DBGC ( arbel, "Arbel %p ICM RDB base = %zx\n", arbel, icm_offset ); 01936 icm_offset += icm_usage ( log_num_rdbs, 32 ); 01937 01938 /* Event queue contexts */ 01939 log_num_eqs = fls ( arbel->limits.reserved_eqs + ARBEL_MAX_EQS - 1 ); 01940 MLX_FILL_2 ( init_hca, 33, 01941 qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_l, 01942 ( icm_offset >> 6 ), 01943 qpc_eec_cqc_eqc_rdb_parameters.log_num_eq, 01944 log_num_eqs ); 01945 DBGC ( arbel, "Arbel %p ICM EQ base = %zx\n", arbel, icm_offset ); 01946 icm_offset += ( ( 1 << log_num_eqs ) * arbel->limits.eqc_entry_size ); 01947 01948 /* Multicast table */ 01949 MLX_FILL_1 ( init_hca, 49, 01950 multicast_parameters.mc_base_addr_l, icm_offset ); 01951 MLX_FILL_1 ( init_hca, 52, 01952 multicast_parameters.log_mc_table_entry_sz, 01953 fls ( sizeof ( struct arbelprm_mgm_entry ) - 1 ) ); 01954 MLX_FILL_1 ( init_hca, 53, 01955 multicast_parameters.mc_table_hash_sz, 8 ); 01956 MLX_FILL_1 ( init_hca, 54, 01957 multicast_parameters.log_mc_table_sz, 3 ); 01958 DBGC ( arbel, "Arbel %p ICM MC base = %zx\n", arbel, icm_offset ); 01959 icm_offset += ( 8 * sizeof ( struct arbelprm_mgm_entry ) ); 01960 01961 arbel->icm_len = icm_offset; 01962 arbel->icm_len = ( ( arbel->icm_len + 4095 ) & ~4095 ); 01963 01964 /* Get ICM auxiliary area size */ 01965 memset ( &icm_size, 0, sizeof ( icm_size ) ); 01966 MLX_FILL_1 ( &icm_size, 1, value, arbel->icm_len ); 01967 if ( ( rc = arbel_cmd_set_icm_size ( arbel, &icm_size, 01968 &icm_aux_size ) ) != 0 ) { 01969 DBGC ( arbel, "Arbel %p could not set ICM size: %s\n", 01970 arbel, strerror ( rc ) ); 01971 goto err_set_icm_size; 01972 } 01973 arbel->icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * 4096 ); 01974 01975 /* Allocate ICM data and auxiliary area */ 01976 DBGC ( arbel, "Arbel %p requires %zd kB ICM and %zd kB AUX ICM\n", 01977 arbel, ( arbel->icm_len / 1024 ), 01978 ( arbel->icm_aux_len / 1024 ) ); 01979 arbel->icm = umalloc ( arbel->icm_len + arbel->icm_aux_len ); 01980 if ( ! arbel->icm ) { 01981 rc = -ENOMEM; 01982 goto err_alloc; 01983 } 01984 01985 /* Map ICM auxiliary area */ 01986 memset ( &map_icm_aux, 0, sizeof ( map_icm_aux ) ); 01987 MLX_FILL_2 ( &map_icm_aux, 3, 01988 log2size, fls ( ( arbel->icm_aux_len / 4096 ) - 1 ), 01989 pa_l, 01990 ( user_to_phys ( arbel->icm, arbel->icm_len ) >> 12 ) ); 01991 if ( ( rc = arbel_cmd_map_icm_aux ( arbel, &map_icm_aux ) ) != 0 ) { 01992 DBGC ( arbel, "Arbel %p could not map AUX ICM: %s\n", 01993 arbel, strerror ( rc ) ); 01994 goto err_map_icm_aux; 01995 } 01996 01997 /* MAP ICM area */ 01998 memset ( &map_icm, 0, sizeof ( map_icm ) ); 01999 MLX_FILL_2 ( &map_icm, 3, 02000 log2size, fls ( ( arbel->icm_len / 4096 ) - 1 ), 02001 pa_l, ( user_to_phys ( arbel->icm, 0 ) >> 12 ) ); 02002 if ( ( rc = arbel_cmd_map_icm ( arbel, &map_icm ) ) != 0 ) { 02003 DBGC ( arbel, "Arbel %p could not map ICM: %s\n", 02004 arbel, strerror ( rc ) ); 02005 goto err_map_icm; 02006 } 02007 02008 /* Initialise UAR context */ 02009 arbel->db_rec = phys_to_virt ( user_to_phys ( arbel->icm, 0 ) + 02010 ( arbel->limits.reserved_uars * 02011 ARBEL_PAGE_SIZE ) ); 02012 memset ( arbel->db_rec, 0, ARBEL_PAGE_SIZE ); 02013 db_rec = &arbel->db_rec[ARBEL_GROUP_SEPARATOR_DOORBELL]; 02014 MLX_FILL_1 ( &db_rec->qp, 1, res, ARBEL_UAR_RES_GROUP_SEP ); 02015 02016 return 0; 02017 02018 arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / 4096 ) ); 02019 err_map_icm: 02020 arbel_cmd_unmap_icm_aux ( arbel ); 02021 err_map_icm_aux: 02022 ufree ( arbel->icm ); 02023 arbel->icm = UNULL; 02024 err_alloc: 02025 err_set_icm_size: 02026 return rc; 02027 }
| static void arbel_free_icm | ( | struct arbel * | arbel | ) | [static] |
Free ICM.
Definition at line 2034 of file arbel.c.
References arbel_cmd_unmap_icm(), arbel_cmd_unmap_icm_aux(), arbel::icm, arbel::icm_len, ufree(), and UNULL.
Referenced by arbel_probe(), and arbel_remove().
02034 { 02035 arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / 4096 ) ); 02036 arbel_cmd_unmap_icm_aux ( arbel ); 02037 ufree ( arbel->icm ); 02038 arbel->icm = UNULL; 02039 }
| static int arbel_setup_mpt | ( | struct arbel * | arbel | ) | [static] |
Set up memory protection table.
| rc | Return status code |
Definition at line 2054 of file arbel.c.
References arbel_cmd_sw2hw_mpt(), ARBEL_GLOBAL_PD, ARBEL_MKEY_PREFIX, DBGC, arbel::limits, memset(), MLX_FILL_1, MLX_FILL_4, arbel::reserved_lkey, arbel_dev_limits::reserved_mrws, and strerror().
Referenced by arbel_probe().
02054 { 02055 struct arbelprm_mpt mpt; 02056 uint32_t key; 02057 int rc; 02058 02059 /* Derive key */ 02060 key = ( arbel->limits.reserved_mrws | ARBEL_MKEY_PREFIX ); 02061 arbel->reserved_lkey = ( ( key << 8 ) | ( key >> 24 ) ); 02062 02063 /* Initialise memory protection table */ 02064 memset ( &mpt, 0, sizeof ( mpt ) ); 02065 MLX_FILL_4 ( &mpt, 0, 02066 r_w, 1, 02067 pa, 1, 02068 lr, 1, 02069 lw, 1 ); 02070 MLX_FILL_1 ( &mpt, 2, mem_key, key ); 02071 MLX_FILL_1 ( &mpt, 3, pd, ARBEL_GLOBAL_PD ); 02072 MLX_FILL_1 ( &mpt, 6, reg_wnd_len_h, 0xffffffffUL ); 02073 MLX_FILL_1 ( &mpt, 7, reg_wnd_len_l, 0xffffffffUL ); 02074 if ( ( rc = arbel_cmd_sw2hw_mpt ( arbel, arbel->limits.reserved_mrws, 02075 &mpt ) ) != 0 ) { 02076 DBGC ( arbel, "Arbel %p could not set up MPT: %s\n", 02077 arbel, strerror ( rc ) ); 02078 return rc; 02079 } 02080 02081 return 0; 02082 }
| static int arbel_probe | ( | struct pci_device * | pci, | |
| const struct pci_device_id *id | __unused | |||
| ) | [static] |
Probe PCI device.
| pci | PCI device | |
| id | PCI ID |
| rc | Return status code |
Definition at line 2091 of file arbel.c.
References adjust_pci_device(), alloc_ibdev(), arbel_alloc_icm(), arbel_cmd_close_hca(), arbel_cmd_init_hca(), arbel_create_eq(), arbel_destroy_eq(), arbel_free_icm(), arbel_get_limits(), arbel_mad(), ARBEL_MBOX_ALIGN, ARBEL_MBOX_SIZE, ARBEL_NUM_PORTS, ARBEL_PCI_CONFIG_BAR, ARBEL_PCI_CONFIG_BAR_SIZE, ARBEL_PCI_UAR_BAR, ARBEL_PCI_UAR_IDX, ARBEL_PCI_UAR_SIZE, ARBEL_PORT_BASE, arbel_setup_mpt(), arbel_start_firmware(), arbel_stop_firmware(), arbel::config, DBGC, pci_device::dev, ib_device::dev, ENOMEM, free(), free_dma(), ib_set_drvdata(), ib_smc_update(), arbel::ibdev, ibdev_put(), ioremap(), arbel::mailbox_in, arbel::mailbox_out, malloc_dma(), memset(), MLX_FILL_1, ib_device::op, pci_bar_start(), pci_set_drvdata(), ib_device::port, register_ibdev(), strerror(), arbel::uar, unregister_ibdev(), and zalloc().
02092 { 02093 struct arbel *arbel; 02094 struct ib_device *ibdev; 02095 struct arbelprm_init_hca init_hca; 02096 int i; 02097 int rc; 02098 02099 /* Allocate Arbel device */ 02100 arbel = zalloc ( sizeof ( *arbel ) ); 02101 if ( ! arbel ) { 02102 rc = -ENOMEM; 02103 goto err_alloc_arbel; 02104 } 02105 pci_set_drvdata ( pci, arbel ); 02106 02107 /* Allocate Infiniband devices */ 02108 for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) { 02109 ibdev = alloc_ibdev ( 0 ); 02110 if ( ! ibdev ) { 02111 rc = -ENOMEM; 02112 goto err_alloc_ibdev; 02113 } 02114 arbel->ibdev[i] = ibdev; 02115 ibdev->op = &arbel_ib_operations; 02116 ibdev->dev = &pci->dev; 02117 ibdev->port = ( ARBEL_PORT_BASE + i ); 02118 ib_set_drvdata ( ibdev, arbel ); 02119 } 02120 02121 /* Fix up PCI device */ 02122 adjust_pci_device ( pci ); 02123 02124 /* Get PCI BARs */ 02125 arbel->config = ioremap ( pci_bar_start ( pci, ARBEL_PCI_CONFIG_BAR ), 02126 ARBEL_PCI_CONFIG_BAR_SIZE ); 02127 arbel->uar = ioremap ( ( pci_bar_start ( pci, ARBEL_PCI_UAR_BAR ) + 02128 ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ), 02129 ARBEL_PCI_UAR_SIZE ); 02130 02131 /* Allocate space for mailboxes */ 02132 arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN ); 02133 if ( ! arbel->mailbox_in ) { 02134 rc = -ENOMEM; 02135 goto err_mailbox_in; 02136 } 02137 arbel->mailbox_out = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN ); 02138 if ( ! arbel->mailbox_out ) { 02139 rc = -ENOMEM; 02140 goto err_mailbox_out; 02141 } 02142 02143 /* Start firmware */ 02144 if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 ) 02145 goto err_start_firmware; 02146 02147 /* Get device limits */ 02148 if ( ( rc = arbel_get_limits ( arbel ) ) != 0 ) 02149 goto err_get_limits; 02150 02151 /* Allocate ICM */ 02152 memset ( &init_hca, 0, sizeof ( init_hca ) ); 02153 if ( ( rc = arbel_alloc_icm ( arbel, &init_hca ) ) != 0 ) 02154 goto err_alloc_icm; 02155 02156 /* Initialise HCA */ 02157 MLX_FILL_1 ( &init_hca, 74, uar_parameters.log_max_uars, 1 ); 02158 if ( ( rc = arbel_cmd_init_hca ( arbel, &init_hca ) ) != 0 ) { 02159 DBGC ( arbel, "Arbel %p could not initialise HCA: %s\n", 02160 arbel, strerror ( rc ) ); 02161 goto err_init_hca; 02162 } 02163 02164 /* Set up memory protection */ 02165 if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 ) 02166 goto err_setup_mpt; 02167 02168 /* Set up event queue */ 02169 if ( ( rc = arbel_create_eq ( arbel ) ) != 0 ) 02170 goto err_create_eq; 02171 02172 /* Update MAD parameters */ 02173 for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) 02174 ib_smc_update ( arbel->ibdev[i], arbel_mad ); 02175 02176 /* Register Infiniband devices */ 02177 for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) { 02178 if ( ( rc = register_ibdev ( arbel->ibdev[i] ) ) != 0 ) { 02179 DBGC ( arbel, "Arbel %p could not register IB " 02180 "device: %s\n", arbel, strerror ( rc ) ); 02181 goto err_register_ibdev; 02182 } 02183 } 02184 02185 return 0; 02186 02187 i = ARBEL_NUM_PORTS; 02188 err_register_ibdev: 02189 for ( i-- ; i >= 0 ; i-- ) 02190 unregister_ibdev ( arbel->ibdev[i] ); 02191 arbel_destroy_eq ( arbel ); 02192 err_create_eq: 02193 err_setup_mpt: 02194 arbel_cmd_close_hca ( arbel ); 02195 err_init_hca: 02196 arbel_free_icm ( arbel ); 02197 err_alloc_icm: 02198 err_get_limits: 02199 arbel_stop_firmware ( arbel ); 02200 err_start_firmware: 02201 free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE ); 02202 err_mailbox_out: 02203 free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); 02204 err_mailbox_in: 02205 i = ARBEL_NUM_PORTS; 02206 err_alloc_ibdev: 02207 for ( i-- ; i >= 0 ; i-- ) 02208 ibdev_put ( arbel->ibdev[i] ); 02209 free ( arbel ); 02210 err_alloc_arbel: 02211 return rc; 02212 }
| static void arbel_remove | ( | struct pci_device * | pci | ) | [static] |
Remove PCI device.
| pci | PCI device |
Definition at line 2219 of file arbel.c.
References arbel_cmd_close_hca(), arbel_destroy_eq(), arbel_free_icm(), ARBEL_MBOX_SIZE, ARBEL_NUM_PORTS, arbel_stop_firmware(), free(), free_dma(), arbel::ibdev, ibdev_put(), arbel::mailbox_in, arbel::mailbox_out, pci_get_drvdata(), and unregister_ibdev().
02219 { 02220 struct arbel *arbel = pci_get_drvdata ( pci ); 02221 int i; 02222 02223 for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) 02224 unregister_ibdev ( arbel->ibdev[i] ); 02225 arbel_destroy_eq ( arbel ); 02226 arbel_cmd_close_hca ( arbel ); 02227 arbel_free_icm ( arbel ); 02228 arbel_stop_firmware ( arbel ); 02229 arbel_stop_firmware ( arbel ); 02230 free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE ); 02231 free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); 02232 for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) 02233 ibdev_put ( arbel->ibdev[i] ); 02234 free ( arbel ); 02235 }
struct ib_gid arbel_no_gid [static] |
struct ib_device_operations arbel_ib_operations [static] |
Initial value:
{
.create_cq = arbel_create_cq,
.destroy_cq = arbel_destroy_cq,
.create_qp = arbel_create_qp,
.modify_qp = arbel_modify_qp,
.destroy_qp = arbel_destroy_qp,
.post_send = arbel_post_send,
.post_recv = arbel_post_recv,
.poll_cq = arbel_poll_cq,
.poll_eq = arbel_poll_eq,
.open = arbel_open,
.close = arbel_close,
.mcast_attach = arbel_mcast_attach,
.mcast_detach = arbel_mcast_detach,
}
struct pci_device_id arbel_nics[] [static] |
| struct pci_driver arbel_driver __pci_driver |
Initial value:
{
.ids = arbel_nics,
.id_count = ( sizeof ( arbel_nics ) / sizeof ( arbel_nics[0] ) ),
.probe = arbel_probe,
.remove = arbel_remove,
}
1.5.7.1