struct tid_queue { struct list_head queue_head; /* queue head for QP TID resource waiters */
u32 enqueue; /* count of tid enqueues */
u32 dequeue; /* count of tid dequeues */
};
struct hfi1_ctxtdata { /* rcvhdrq base, needs mmap before useful */ void *rcvhdrq; /* kernel virtual address where hdrqtail is updated */ volatile __le64 *rcvhdrtail_kvaddr; /* so functions that need physical port can get it easily */ struct hfi1_pportdata *ppd; /* so file ops can get at unit */ struct hfi1_devdata *dd; /* this receive context's assigned PIO ACK send context */ struct send_context *sc; /* per context recv functions */ const rhf_rcv_function_ptr *rhf_rcv_function_map; /* *Theinterrupthandlerforaparticularreceivecontextcanvary *throughoutit'slifetime.Thisisnotalockprotecteddatamemberso *itmustbeupdatedatomicallyandtheprevandnewvaluemustalways *bevalid.Worstcaseisweprocessanextrainterruptandupto64 *packetswiththewronginterrupthandler.
*/
intr_handler do_interrupt; /** fast handler after autoactive */
intr_handler fast_handler; /** slow handler */
intr_handler slow_handler; /* napi pointer assiociated with netdev */ struct napi_struct *napi; /* verbs rx_stats per rcd */ struct hfi1_opcode_stats_perctx *opstats; /* clear interrupt mask */
u64 imask; /* ctxt rcvhdrq head offset */
u32 head; /* number of rcvhdrq entries */
u16 rcvhdrq_cnt;
u8 ireg; /* clear interrupt register */ /* receive packet sequence counter */
u8 seq_cnt; /* size of each of the rcvhdrq entries */
u8 rcvhdrqentsize; /* offset of RHF within receive header entry */
u8 rhf_offset; /* dynamic receive available interrupt timeout */
u8 rcvavail_timeout; /* Indicates that this is vnic context */ bool is_vnic; /* vnic queue index this context is mapped to */
u8 vnic_q_idx; /* Is ASPM interrupt supported for this context */ bool aspm_intr_supported; /* ASPM state (enabled/disabled) for this context */ bool aspm_enabled; /* Is ASPM processing enabled for this context (in intr context) */ bool aspm_intr_enable; struct ctxt_eager_bufs egrbufs; /* QPs waiting for context processing */ struct list_head qp_wait_list; /* tid allocation lists */ struct exp_tid_set tid_group_list; struct exp_tid_set tid_used_list; struct exp_tid_set tid_full_list;
/* Timer for re-enabling ASPM if interrupt activity quiets down */ struct timer_list aspm_timer; /* per-context configuration flags */ unsignedlong flags; /* array of tid_groups */ struct tid_group *groups; /* mmap of hdrq, must fit in 44 bits */
dma_addr_t rcvhdrq_dma;
dma_addr_t rcvhdrqtailaddr_dma; /* Last interrupt timestamp */
ktime_t aspm_ts_last_intr; /* Last timestamp at which we scheduled a timer for this context */
ktime_t aspm_ts_timer_sched; /* Lock to serialize between intr, timer intr and user threads */
spinlock_t aspm_lock; /* Reference count the base context usage */ struct kref kref; /* numa node of this context */ int numa_id; /* associated msix interrupt. */
s16 msix_intr; /* job key */
u16 jkey; /* number of RcvArray groups for this context. */
u16 rcv_array_groups; /* index of first eager TID entry. */
u16 eager_base; /* number of expected TID entries */
u16 expected_count; /* index of first expected TID entry. */
u16 expected_base; /* Device context index */
u8 ctxt;
/* PSM Specific fields */ /* lock protecting all Expected TID data */ struct mutex exp_mutex; /* lock protecting all Expected TID data of kernel contexts */
spinlock_t exp_lock; /* Queue for QP's waiting for HW TID flows */ struct tid_queue flow_queue; /* Queue for QP's waiting for HW receive array entries */ struct tid_queue rarr_queue; /* when waiting for rcv or pioavail */
wait_queue_head_t wait; /* uuid from PSM */
u8 uuid[16]; /* same size as task_struct .comm[], command that opened context */ char comm[TASK_COMM_LEN]; /* Bitmask of in use context(s) */
DECLARE_BITMAP(in_use_ctxts, HFI1_MAX_SHARED_CTXTS); /* per-context event flags for fileops/intr communication */ unsignedlong event_flags; /* A page of memory for rcvhdrhead, rcvegrhead, rcvegrtail * N */ void *subctxt_uregbase; /* An array of pages for the eager receive buffers * N */ void *subctxt_rcvegrbuf; /* An array of pages for the eager header queue entries * N */ void *subctxt_rcvhdr_base; /* total number of polled urgent packets */
u32 urgent; /* saved total number of polled urgent packets for poll edge trigger */
u32 urgent_poll; /* Type of packets or conditions we want to poll for */
u16 poll_type; /* non-zero if ctxt is being shared. */
u16 subctxt_id; /* The version of the library which opened this ctxt */
u32 userversion; /* *non-zeroifctxtcanbeshared,anddefinesthemaximumnumberof *sub-contextsforthisdevicecontext.
*/
u8 subctxt_cnt;
/* Bit mask to track free TID RDMA HW flows */ unsignedlong flow_mask; struct tid_flow_state flows[RXE_NUM_TID_FLOWS];
};
/* use this MTU size if none other is given */ #define HFI1_DEFAULT_ACTIVE_MTU 10240 /* use this MTU size as the default maximum */ #define HFI1_DEFAULT_MAX_MTU 10240 /* default partition key */ #define DEFAULT_PKEY 0xffff
/* *Possiblefabricmanagerconfigparametersforfm_{get,set}_table()
*/ #define FM_TBL_VL_HIGH_ARB 1/* Get/set VL high prio weights */ #define FM_TBL_VL_LOW_ARB 2/* Get/set VL low prio weights */ #define FM_TBL_BUFFER_CONTROL 3/* Get/set Buffer Control */ #define FM_TBL_SC2VLNT 4/* Get/set SC->VLnt */ #define FM_TBL_VL_PREEMPT_ELEMS 5/* Get (no set) VL preempt elems */ #define FM_TBL_VL_PREEMPT_MATRIX 6/* Get (no set) VL preempt matrix */
u32 ibmtu; /* The MTU programmed for this unit */ /* *CurrentmaxsizeIBpacket(inbytes)includingIBheaders,that *wecansend.Changeswhenibmtuchanges.
*/
u32 ibmaxlen;
u32 current_egress_rate; /* units [10^6 bits/sec] */ /* LID programmed for this instance */
u32 lid; /* list of pkeys programmed; 0 if not set */
u16 pkeys[MAX_PKEY_VALUES];
u16 link_width_supported;
u16 link_width_downgrade_supported;
u16 link_speed_supported;
u16 link_width_enabled;
u16 link_width_downgrade_enabled;
u16 link_speed_enabled;
u16 link_width_active;
u16 link_width_downgrade_tx_active;
u16 link_width_downgrade_rx_active;
u16 link_speed_active;
u8 vls_supported;
u8 vls_operational;
u8 actual_vls_operational; /* LID mask control */
u8 lmc; /* Rx Polarity inversion (compensate for ~tx on partner) */
u8 rx_pol_inv;
u8 hw_pidx; /* physical port index */
u32 port; /* IB port number and index into dd->pports - 1 */ /* type of neighbor node */
u8 neighbor_type;
u8 neighbor_normal;
u8 neighbor_fm_security; /* 1 if firmware checking is disabled */
u8 neighbor_port_number;
u8 is_sm_config_started;
u8 offline_disabled_reason;
u8 is_active_optimize_enabled;
u8 driver_link_ready; /* driver ready for active link */
u8 link_enabled; /* link enabled? */
u8 linkinit_reason;
u8 local_tx_rate; /* rate given to 8051 firmware */
u8 qsfp_retry_count;
/* Used to override LED behavior for things like maintenance beaconing*/ /* *Alternatesperphaseofblink *[0]holdsLEDoffduration,[1]holdsLEDonduration
*/ unsignedlong led_override_vals[2];
u8 led_override_phase; /* LSB picks from vals[] */
atomic_t led_override_timer_active; /* Used to flash LEDs in override mode */ struct timer_list led_override_timer;
/* Total number of congestion control table entries */
u16 total_cct_entry;
/* Bit map identifying service level */
u32 cc_sl_control_map;
/* CA's max number of 64 entry units in the congestion control table */
u8 cc_max_table_entries;
/* *begincongestionlogrelatedentries *cc_log_lockprotectsallcongestionlogrelateddata
*/
spinlock_t cc_log_lock ____cacheline_aligned_in_smp;
u8 threshold_cong_event_map[OPA_MAX_SLS / 8];
u16 threshold_event_counter; struct opa_hfi1_cong_log_event_internal cc_events[OPA_CONG_LOG_ELEMS]; int cc_log_idx; /* index for logging events */ int cc_mad_idx; /* index for reporting events */ /* end congestion log related entries */
struct vl_arb_cache vl_arb_cache[MAX_PRIO_TABLE];
/* port relative counter buffer */
u64 *cntrs; /* port relative synthetic counter buffer */
u64 *scntrs; /* port_xmit_discards are synthesized from different egress errors */
u64 port_xmit_discards;
u64 port_xmit_discards_vl[C_VL_COUNT];
u64 port_xmit_constraint_errors;
u64 port_rcv_constraint_errors; /* count of 'link_err' interrupts from DC */
u64 link_downed; /* number of times link retrained successfully */
u64 link_up; /* number of times a link unknown frame was reported */
u64 unknown_frame_count; /* port_ltp_crc_mode is returned in 'portinfo' MADs */
u16 port_ltp_crc_mode; /* port_crc_mode_enabled is the crc we support */
u8 port_crc_mode_enabled; /* mgmt_allowed is also returned in 'portinfo' MADs */
u8 mgmt_allowed;
u8 part_enforce; /* partition enforcement flags */ struct link_down_reason local_link_down_reason; struct link_down_reason neigh_link_down_reason; /* Value to be sent to link peer on LinkDown .*/
u8 remote_link_down_reason; /* Error events that will cause a port bounce. */
u32 port_error_action; struct work_struct linkstate_active_work; /* Does this port need to prescan for FECNs */ bool cc_prescan; /* *SamplesendWaitCnt&sendWaitVlCntduringlinktransition *andcounterrequest.
*/
u64 port_vl_xmit_wait_last[C_VL_COUNT + 1];
u16 prev_link_width;
u64 vl_xmit_flit_cnt[C_VL_COUNT + 1];
};
struct hfi1_temp { unsignedint curr; /* current temperature */ unsignedint lo_lim; /* low temperature limit */ unsignedint hi_lim; /* high temperature limit */ unsignedint crit_lim; /* critical temperature limit */
u8 triggers; /* temperature triggers */
};
struct hfi1_i2c_bus { struct hfi1_devdata *controlling_dd; /* current controlling device */ struct i2c_adapter adapter; /* bus details */ struct i2c_algo_bit_data algo; /* bus algorithm details */ int num; /* bus number, 0 or 1 */
};
/* common data between shared ASIC HFIs */ struct hfi1_asic_data { struct hfi1_devdata *dds[2]; /* back pointers */ struct mutex asic_resource_mutex; struct hfi1_i2c_bus *i2c_bus0; struct hfi1_i2c_bus *i2c_bus1;
};
/* sizes for both the QP and RSM map tables */ #define NUM_MAP_ENTRIES 256 #define NUM_MAP_REGS 32
/* Virtual NIC information */ struct hfi1_vnic_data { struct kmem_cache *txreq_cache;
u8 num_vports;
};
struct hfi1_vnic_vport_info;
/* device data struct now contains only "general per-device" info. *fieldsrelatedtoaphysicalIBportareinahfi1_pportdatastruct.
*/ struct sdma_engine; struct sdma_vl_map;
#define BOARD_VERS_MAX 96/* how long the version string can be */ #define SERIAL_MAX 16/* length of the serial number */
typedefint (*send_routine)(struct rvt_qp *, struct hfi1_pkt_state *, u64); struct hfi1_netdev_rx; struct hfi1_devdata { struct hfi1_ibdev verbs_dev; /* must be first */ /* pointers to related structs for this device */ /* pci access data structure */ struct pci_dev *pcidev; struct cdev user_cdev; struct cdev diag_cdev; struct cdev ui_cdev; struct device *user_device; struct device *diag_device; struct device *ui_device;
/* first mapping up to RcvArray */
u8 __iomem *kregbase1;
resource_size_t physaddr;
/* second uncached mapping from RcvArray to pio send buffers */
u8 __iomem *kregbase2; /* for detecting offset above kregbase2 address */
u32 base2_start;
/* Per VL data. Enough for all VLs but not all elements are set/used. */ struct per_vl_data vld[PER_VL_SEND_CONTEXTS]; /* send context data */ struct send_context_info *send_contexts; /* map hardware send contexts to software index */
u8 *hw_to_sw; /* spinlock for allocating and releasing send context resources */
spinlock_t sc_lock; /* lock for pio_map */
spinlock_t pio_map_lock; /* Send Context initialization lock. */
spinlock_t sc_init_lock; /* lock for sdma_map */
spinlock_t sde_map_lock; /* array of kernel send contexts */ struct send_context **kernel_send_context; /* array of vl maps */ struct pio_vl_map __rcu *pio_map; /* default flags to last descriptor */
u64 default_desc1;
/* fields common to all SDMA engines */
volatile __le64 *sdma_heads_dma; /* DMA'ed by chip */
dma_addr_t sdma_heads_phys; void *sdma_pad_dma; /* DMA'ed by chip */
dma_addr_t sdma_pad_phys; /* for deallocation */
size_t sdma_heads_size; /* num used */
u32 num_sdma; /* array of engines sized by num_sdma */ struct sdma_engine *per_sdma; /* array of vl maps */ struct sdma_vl_map __rcu *sdma_map; /* SPC freeze waitqueue and variable */
wait_queue_head_t sdma_unfreeze_wq;
atomic_t sdma_unfreeze_count;
u32 lcb_access_count; /* count of LCB users */
/* common data between shared ASIC HFIs in this OS */ struct hfi1_asic_data *asic_data;
/* mem-mapped pointer to base of PIO buffers */ void __iomem *piobase; /* *write-combiningmem-mappedpointertobaseofRcvArray *memory.
*/ void __iomem *rcvarray_wc; /* *creditreturnbase-aper-NUMArangeofDMAaddressthat *thechipwillusetoupdatetheper-contextfreecounter
*/ struct credit_return_base *cr_base;
/* send context numbers and sizes for each type */ struct sc_config_sizes sc_sizes[SC_MAX];
char *boardname; /* human readable board info */
u64 ctx0_seq_drop;
/* reset value */
u64 z_int_counter;
u64 z_rcv_limit;
u64 z_send_schedule;
u64 __percpu *send_schedule; /* number of reserved contexts for netdev usage */
u16 num_netdev_contexts; /* number of receive contexts in use by the driver */
u32 num_rcv_contexts; /* number of pio send contexts in use by the driver */
u32 num_send_contexts; /* *numberofctxtsavailableforPSMopen
*/
u32 freectxts; /* total number of available user/PSM contexts */
u32 num_user_contexts; /* base receive interrupt timeout, in CSR units */
u32 rcv_intr_timeout_csr;
spinlock_t sendctrl_lock; /* protect changes to SendCtrl */
spinlock_t rcvctrl_lock; /* protect changes to RcvCtrl */
spinlock_t uctxt_lock; /* protect rcd changes */ struct mutex dc8051_lock; /* exclusive access to 8051 */ struct workqueue_struct *update_cntr_wq; struct work_struct update_cntr_work; /* exclusive access to 8051 memory */
spinlock_t dc8051_memlock; int dc8051_timed_out; /* remember if the 8051 timed out */ /* *Apagethatwillholdeventnotificationbitmapsforall *contexts.Thispagewillbemappedintoallprocesses.
*/ unsignedlong *events; /* *perunitstatus,seealsoportdatastatusp *mappedread-onlyintouserprocessessotheycangetunitand *IBlinkstatuscheaply
*/ struct hfi1_status *status;
/* revision register shadow */
u64 revision; /* Base GUID for device (network order) */
u64 base_guid;
/* both sides of the PCIe link are gen3 capable */
u8 link_gen3_capable;
u8 dc_shutdown; /* localbus width (1, 2,4,8,16,32) from config space */
u32 lbus_width; /* localbus speed in MHz */
u32 lbus_speed; int unit; /* unit # of this chip */ int node; /* home node of this chip */
/* save these PCI fields to restore after a reset */
u32 pcibar0;
u32 pcibar1;
u32 pci_rom;
u16 pci_command;
u16 pcie_devctl;
u16 pcie_lnkctl;
u16 pcie_devctl2;
u32 pci_msix0;
u32 pci_tph2;
/* *ASCIIserialnumber,fromflash,largeenoughfororiginal *alldigitstrings,andlongerserialnumberformat
*/
u8 serial[SERIAL_MAX]; /* human readable board version */
u8 boardversion[BOARD_VERS_MAX];
u8 lbus_info[32]; /* human readable localbus info */ /* chip major rev, from CceRevision */
u8 majrev; /* chip minor rev, from CceRevision */
u8 minrev; /* hardware ID */
u8 hfi1_id; /* implementation code */
u8 icode; /* vAU of this device */
u8 vau; /* vCU of this device */
u8 vcu; /* link credits of this device */
u16 link_credits; /* initial vl15 credits to use */
u16 vl15_init;
/* Software counter that spans all contexts */
u64 sw_ctxt_err_status_cnt[NUM_SEND_CTXT_ERR_STATUS_COUNTERS]; /* Software counter that spans all DMA engines */
u64 sw_send_dma_eng_err_status_cnt[
NUM_SEND_DMA_ENG_ERR_STATUS_COUNTERS]; /* Software counter that aggregates all cce_err_status errors */
u64 sw_cce_err_status_aggregate; /* Software counter that aggregates all bypass packet rcv errors */
u64 sw_rcv_bypass_packet_errors;
/* Save the enabled LCB error bits */
u64 lcb_err_en; struct cpu_mask_set *comp_vect; int *comp_vect_mappings;
u32 comp_vect_possible_cpus;
/* *Capabilitytohavedifferentsendenginessimplybychanginga *pointervalue.
*/
send_routine process_pio_send ____cacheline_aligned_in_smp;
send_routine process_dma_send; void (*pio_inline_send)(struct hfi1_devdata *dd, struct pio_buf *pbuf,
u64 pbc, constvoid *from, size_t count); int (*process_vnic_dma_send)(struct hfi1_devdata *dd, u8 q_idx, struct hfi1_vnic_vport_info *vinfo, struct sk_buff *skb, u64 pbc, u8 plen); /* hfi1_pportdata, points to array of (physical) port-specific *datastructs,indexedbypidx(0..n-1)
*/ struct hfi1_pportdata *pport; /* receive context data */ struct hfi1_ctxtdata **rcd;
u64 __percpu *int_counter; /* verbs tx opcode stats */ struct hfi1_opcode_stats_perctx __percpu *tx_opstats; /* device (not port) flags, basically device capabilities */
u16 flags; /* Number of physical ports available */
u8 num_pports; /* Lowest context number which can be used by user processes or VNIC */
u8 first_dyn_alloc_ctxt; /* adding a new field here would make it part of this cacheline */
/* seqlock for sc2vl */
seqlock_t sc2vl_lock ____cacheline_aligned_in_smp;
u64 sc2vl[4];
u64 __percpu *rcv_limit; /* adding a new field here would make it part of this cacheline */
/* OUI comes from the HW. Used everywhere as 3 separate bytes. */
u8 oui1;
u8 oui2;
u8 oui3;
/* Timer and counter used to detect RcvBufOvflCnt changes */ struct timer_list rcverr_timer;
u32 rcv_ovfl_cnt; /* Serialize ASPM enable/disable between multiple verbs contexts */
spinlock_t aspm_lock; /* Number of verbs contexts which have disabled ASPM */
atomic_t aspm_disabled_cnt; /* Keeps track of user space clients */
refcount_t user_refcount; /* Used to wait for outstanding user space clients before dev removal */ struct completion user_comp;
bool eprom_available; /* true if EPROM is available for this device */ bool aspm_supported; /* Does HW support ASPM */ bool aspm_enabled; /* ASPM state: enabled/disabled */ struct rhashtable *sdma_rht;
/* vnic data */ struct hfi1_vnic_data vnic; /* Lock to protect IRQ SRC register access */
spinlock_t irq_src_lock; int vnic_num_vports; struct hfi1_netdev_rx *netdev_rx; struct hfi1_affinity_node *affinity_entry;
/* *valuesfordd->flags(_device_relatedflags)
*/ #define HFI1_INITTED 0x1 /* chip and driver up and initted */ #define HFI1_PRESENT 0x2 /* chip accesses can be done */ #define HFI1_FROZEN 0x4 /* chip in SPC freeze */ #define HFI1_HAS_SDMA_TIMEOUT 0x8 #define HFI1_HAS_SEND_DMA 0x10 /* Supports Send DMA */ #define HFI1_FORCED_FREEZE 0x80 /* driver forced freeze mode */ #define HFI1_SHUTDOWN 0x100 /* device is shutting down */
/* IB dword length mask in PBC (lower 11 bits); same for all chips */ #define HFI1_PBC_LENGTH_MASK ((1 << 11) - 1)
/* ctxt_flag bit offsets */ /* base context has not finished initializing */ #define HFI1_CTXT_BASE_UNINIT 1 /* base context initaliation failed */ #define HFI1_CTXT_BASE_FAILED 2 /* waiting for a packet to arrive */ #define HFI1_CTXT_WAITING_RCV 3 /* waiting for an urgent packet to arrive */ #define HFI1_CTXT_WAITING_URG 4
/* free up any allocated data at closes */ int hfi1_init_dd(struct hfi1_devdata *dd); void hfi1_free_devdata(struct hfi1_devdata *dd);
int hfi1_device_create(struct hfi1_devdata *dd); void hfi1_device_remove(struct hfi1_devdata *dd);
int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd); void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd); /* Hook for sysfs read of QSFP */ int qsfp_dump(struct hfi1_pportdata *ppd, char *buf, int len);
int hfi1_pcie_init(struct hfi1_devdata *dd); void hfi1_pcie_cleanup(struct pci_dev *pdev); int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev); void hfi1_pcie_ddcleanup(struct hfi1_devdata *); int pcie_speeds(struct hfi1_devdata *dd); int restore_pci_variables(struct hfi1_devdata *dd); int save_pci_variables(struct hfi1_devdata *dd); int do_pcie_gen3_transition(struct hfi1_devdata *dd); void tune_pcie_caps(struct hfi1_devdata *dd); int parse_platform_config(struct hfi1_devdata *dd); int get_platform_config_field(struct hfi1_devdata *dd, enum platform_config_table_type_encoding
table_type, int table_index, int field_index,
u32 *data, u32 len);
ppd = (struct hfi1_pportdata *)(dd + 1);
for (i = 0; i < dd->num_pports; i++, ppd++) {
ppd->ibport_data.rvp.z_rc_acks =
get_all_cpu_total(ppd->ibport_data.rvp.rc_acks);
ppd->ibport_data.rvp.z_rc_qacks =
get_all_cpu_total(ppd->ibport_data.rvp.rc_qacks);
}
}
/* Control LED state */
static inline void setextled(struct hfi1_devdata *dd, u32 on)
{
if (on)
write_csr(dd, DCC_CFG_LED_CNTRL, 0x1F);
else
write_csr(dd, DCC_CFG_LED_CNTRL, 0x10);
}
/* return the i2c resource given the target */
static inline u32 i2c_target(u32 target)
{
return target ? CR_I2C2 : CR_I2C1;
}
/* return the i2c chain chip resource that this HFI uses for QSFP */
static inline u32 qsfp_resource(struct hfi1_devdata *dd)
{
return i2c_target(dd->hfi1_id);
}
/* Is this device integrated or discrete? */
static inline bool is_integrated(struct hfi1_devdata *dd)
{
return dd->pcidev->device == PCI_DEVICE_ID_INTEL1;
}
/**
* hfi1_need_drop - detect need for drop
* @dd: - the device
*
* In some cases, the first packet needs to be dropped.
*
* Return true is the current packet needs to be dropped and false otherwise.
*/
static inline bool hfi1_need_drop(struct hfi1_devdata *dd)
{
if (unlikely(dd->do_drop &&
atomic_xchg(&dd->drop_packet, DROP_PACKET_OFF) ==
DROP_PACKET_ON)) {
dd->do_drop = false;
return true;
}
return false;
}
int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp);
/*
* Kernel clients may not have setup GRH information
* Set that here.
*/
ibp = to_iport(ibdev, rdma_ah_get_port_num(attr));
ppd = ppd_from_ibp(ibp);
if ((((dlid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) ||
(ppd->lid >= be16_to_cpu(IB_MULTICAST_LID_BASE))) &&
(dlid != be32_to_cpu(OPA_LID_PERMISSIVE)) &&
(dlid != be16_to_cpu(IB_LID_PERMISSIVE)) &&
(!(rdma_ah_get_ah_flags(attr) & IB_AH_GRH))) ||
(rdma_ah_get_make_grd(attr))) {
rdma_ah_set_ah_flags(attr, IB_AH_GRH);
rdma_ah_set_interface_id(attr, OPA_MAKE_ID(dlid));
rdma_ah_set_subnet_prefix(attr, ibp->rvp.gid_prefix);
}
}
/*
* hfi1_check_mcast- Check if the given lid is
* in the OPA multicast range.
*
* The LID might either reside in ah.dlid or might be
* in the GRH of the address handle as DGID if extended
* addresses are in use.
*/
static inline bool hfi1_check_mcast(u32 lid)
{
return ((lid >= opa_get_mcast_base(OPA_MCAST_NR)) &&
(lid != be32_to_cpu(OPA_LID_PERMISSIVE)));
}
/* Convert a lid to a specific lid space */
static inline u32 __opa_get_lid(u32 lid, u8 format)
{
bool is_mcast = hfi1_check_mcast(lid);
switch (format) {
case OPA_PORT_PACKET_FORMAT_8B:
case OPA_PORT_PACKET_FORMAT_10B:
if (is_mcast)
return (lid - opa_get_mcast_base(OPA_MCAST_NR) + 0xF0000);
return lid & 0xFFFFF;
case OPA_PORT_PACKET_FORMAT_16B:
if (is_mcast)
return (lid - opa_get_mcast_base(OPA_MCAST_NR) + 0xF00000);
return lid & 0xFFFFFF;
case OPA_PORT_PACKET_FORMAT_9B:
if (is_mcast)
return (lid -
opa_get_mcast_base(OPA_MCAST_NR) +
be16_to_cpu(IB_MULTICAST_LID_BASE));
else
return lid & 0xFFFF;
default:
return lid;
}
}
/* Return true if the given lid is the OPA 16B multicast range */
static inline bool hfi1_is_16B_mcast(u32 lid)
{
return ((lid >=
opa_get_lid(opa_get_mcast_base(OPA_MCAST_NR), 16B)) &&
(lid != opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE), 16B)));
}
/* Modify ah_attr.dlid to be in the 32 bit LID space.
* This is how the address will be laid out:
* Assuming MCAST_NR to be 4,
* 32 bit permissive LID = 0xFFFFFFFF
* Multicast LID range = 0xFFFFFFFE to 0xF0000000
* Unicast LID range = 0xEFFFFFFF to 1
* Invalid LID = 0
*/
if (ib_is_opa_gid(&grh->dgid))
dlid = opa_get_lid_from_gid(&grh->dgid);
else if ((dlid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
(dlid != be16_to_cpu(IB_LID_PERMISSIVE)) &&
(dlid != be32_to_cpu(OPA_LID_PERMISSIVE)))
dlid = dlid - be16_to_cpu(IB_MULTICAST_LID_BASE) +
opa_get_mcast_base(OPA_MCAST_NR);
else if (dlid == be16_to_cpu(IB_LID_PERMISSIVE))
dlid = be32_to_cpu(OPA_LID_PERMISSIVE);
rdma_ah_set_dlid(attr, dlid);
}
static inline u8 hfi1_get_packet_type(u32 lid)
{
/* 9B if lid > 0xF0000000 */
if (lid >= opa_get_mcast_base(OPA_MCAST_NR))
return HFI1_PKT_TYPE_9B;
/* 16B if lid > 0xC000 */
if (lid >= opa_get_lid(opa_get_mcast_base(OPA_MCAST_NR), 9B))
return HFI1_PKT_TYPE_16B;
return HFI1_PKT_TYPE_9B;
}
static inline bool hfi1_get_hdr_type(u32 lid, struct rdma_ah_attr *attr)
{
/*
* If there was an incoming 16B packet with permissive
* LIDs, OPA GIDs would have been programmed when those
* packets were received. A 16B packet will have to
* be sent in response to that packet. Return a 16B
* header type if that's the case.
*/
if (rdma_ah_get_dlid(attr) == be32_to_cpu(OPA_LID_PERMISSIVE))
return (ib_is_opa_gid(&rdma_ah_read_grh(attr)->dgid)) ?
HFI1_PKT_TYPE_16B : HFI1_PKT_TYPE_9B;
/*
* Return a 16B header type if either the destination
* or source lid is extended.
*/
if (hfi1_get_packet_type(rdma_ah_get_dlid(attr)) == HFI1_PKT_TYPE_16B)
return HFI1_PKT_TYPE_16B;
/*
* Upper layers (like mad) may compare the dgid in the
* wc that is obtained here with the sgid_index in
* the wr. Since sgid_index in wr is always 0 for
* extended lids, set the dgid here to the default
* IB gid.
*/
grh->dgid.global.subnet_prefix = ibp->rvp.gid_prefix;
grh->dgid.global.interface_id =
cpu_to_be64(ppd->guids[HFI1_PORT_GUID_INDEX]);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.