ipath_verbs.c
来自「linux 内核源代码」· C语言 代码 · 共 1,887 行 · 第 1/4 页
C
1,887 行
* @hdr: the packet header * @hdrwords: the number of words in the header * @ss: the SGE to send * @len: the length of the packet in bytes */int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr, u32 hdrwords, struct ipath_sge_state *ss, u32 len){ struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd; u32 plen; int ret; u32 dwords = (len + 3) >> 2; /* +1 is for the qword padding of pbc */ plen = hdrwords + dwords + 1; /* Drop non-VL15 packets if we are not in the active state */ if (!(dd->ipath_flags & IPATH_LINKACTIVE) && qp->ibqp.qp_type != IB_QPT_SMI) { if (qp->s_wqe) ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS); ret = 0; } else ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords, ss, len, plen, dwords); return ret;}int ipath_snapshot_counters(struct ipath_devdata *dd, u64 *swords, u64 *rwords, u64 *spkts, u64 *rpkts, u64 *xmit_wait){ int ret; if (!(dd->ipath_flags & IPATH_INITTED)) { /* no hardware, freeze, etc. */ ret = -EINVAL; goto bail; } *swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); *rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); *spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); *rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); *xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt); ret = 0;bail: return ret;}/** * ipath_get_counters - get various chip counters * @dd: the infinipath device * @cntrs: counters are placed here * * Return the counters needed by recv_pma_get_portcounters(). */int ipath_get_counters(struct ipath_devdata *dd, struct ipath_verbs_counters *cntrs){ struct ipath_cregs const *crp = dd->ipath_cregs; int ret; if (!(dd->ipath_flags & IPATH_INITTED)) { /* no hardware, freeze, etc. */ ret = -EINVAL; goto bail; } cntrs->symbol_error_counter = ipath_snap_cntr(dd, crp->cr_ibsymbolerrcnt); cntrs->link_error_recovery_counter = ipath_snap_cntr(dd, crp->cr_iblinkerrrecovcnt); /* * The link downed counter counts when the other side downs the * connection. We add in the number of times we downed the link * due to local link integrity errors to compensate. */ cntrs->link_downed_counter = ipath_snap_cntr(dd, crp->cr_iblinkdowncnt); cntrs->port_rcv_errors = ipath_snap_cntr(dd, crp->cr_rxdroppktcnt) + ipath_snap_cntr(dd, crp->cr_rcvovflcnt) + ipath_snap_cntr(dd, crp->cr_portovflcnt) + ipath_snap_cntr(dd, crp->cr_err_rlencnt) + ipath_snap_cntr(dd, crp->cr_invalidrlencnt) + ipath_snap_cntr(dd, crp->cr_errlinkcnt) + ipath_snap_cntr(dd, crp->cr_erricrccnt) + ipath_snap_cntr(dd, crp->cr_errvcrccnt) + ipath_snap_cntr(dd, crp->cr_errlpcrccnt) + ipath_snap_cntr(dd, crp->cr_badformatcnt) + dd->ipath_rxfc_unsupvl_errs; cntrs->port_rcv_remphys_errors = ipath_snap_cntr(dd, crp->cr_rcvebpcnt); cntrs->port_xmit_discards = ipath_snap_cntr(dd, crp->cr_unsupvlcnt); cntrs->port_xmit_data = ipath_snap_cntr(dd, crp->cr_wordsendcnt); cntrs->port_rcv_data = ipath_snap_cntr(dd, crp->cr_wordrcvcnt); cntrs->port_xmit_packets = ipath_snap_cntr(dd, crp->cr_pktsendcnt); cntrs->port_rcv_packets = ipath_snap_cntr(dd, crp->cr_pktrcvcnt); cntrs->local_link_integrity_errors = (dd->ipath_flags & IPATH_GPIO_ERRINTRS) ? dd->ipath_lli_errs : dd->ipath_lli_errors; cntrs->excessive_buffer_overrun_errors = dd->ipath_overrun_thresh_errs; ret = 0;bail: return ret;}/** * ipath_ib_piobufavail - callback when a PIO buffer is available * @arg: the device pointer * * This is called from ipath_intr() at interrupt level when a PIO buffer is * available after ipath_verbs_send() returned an error that no buffers were * available. Return 1 if we consumed all the PIO buffers and we still have * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and * return zero). */int ipath_ib_piobufavail(struct ipath_ibdev *dev){ struct ipath_qp *qp; unsigned long flags; if (dev == NULL) goto bail; spin_lock_irqsave(&dev->pending_lock, flags); while (!list_empty(&dev->piowait)) { qp = list_entry(dev->piowait.next, struct ipath_qp, piowait); list_del_init(&qp->piowait); clear_bit(IPATH_S_BUSY, &qp->s_busy); tasklet_hi_schedule(&qp->s_task); } spin_unlock_irqrestore(&dev->pending_lock, flags);bail: return 0;}static int ipath_query_device(struct ib_device *ibdev, struct ib_device_attr *props){ struct ipath_ibdev *dev = to_idev(ibdev); memset(props, 0, sizeof(*props)); props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | IB_DEVICE_SYS_IMAGE_GUID; props->page_size_cap = PAGE_SIZE; props->vendor_id = dev->dd->ipath_vendorid; props->vendor_part_id = dev->dd->ipath_deviceid; props->hw_ver = dev->dd->ipath_pcirev; props->sys_image_guid = dev->sys_image_guid; props->max_mr_size = ~0ull; props->max_qp = ib_ipath_max_qps; props->max_qp_wr = ib_ipath_max_qp_wrs; props->max_sge = ib_ipath_max_sges; props->max_cq = ib_ipath_max_cqs; props->max_ah = ib_ipath_max_ahs; props->max_cqe = ib_ipath_max_cqes; props->max_mr = dev->lk_table.max; props->max_fmr = dev->lk_table.max; props->max_map_per_fmr = 32767; props->max_pd = ib_ipath_max_pds; props->max_qp_rd_atom = IPATH_MAX_RDMA_ATOMIC; props->max_qp_init_rd_atom = 255; /* props->max_res_rd_atom */ props->max_srq = ib_ipath_max_srqs; props->max_srq_wr = ib_ipath_max_srq_wrs; props->max_srq_sge = ib_ipath_max_srq_sges; /* props->local_ca_ack_delay */ props->atomic_cap = IB_ATOMIC_GLOB; props->max_pkeys = ipath_get_npkeys(dev->dd); props->max_mcast_grp = ib_ipath_max_mcast_grps; props->max_mcast_qp_attach = ib_ipath_max_mcast_qp_attached; props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * props->max_mcast_grp; return 0;}const u8 ipath_cvt_physportstate[16] = { [INFINIPATH_IBCS_LT_STATE_DISABLED] = 3, [INFINIPATH_IBCS_LT_STATE_LINKUP] = 5, [INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2, [INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2, [INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1, [INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1, [INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4, [INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4, [INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4, [INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4, [INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6, [INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6, [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,};u32 ipath_get_cr_errpkey(struct ipath_devdata *dd){ return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);}static int ipath_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props){ struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_devdata *dd = dev->dd; enum ib_mtu mtu; u16 lid = dd->ipath_lid; u64 ibcstat; memset(props, 0, sizeof(*props)); props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE); props->lmc = dd->ipath_lmc; props->sm_lid = dev->sm_lid; props->sm_sl = dev->sm_sl; ibcstat = dd->ipath_lastibcstat; props->state = ((ibcstat >> 4) & 0x3) + 1; /* See phys_state_show() */ props->phys_state = ipath_cvt_physportstate[ dd->ipath_lastibcstat & 0xf]; props->port_cap_flags = dev->port_cap_flags; props->gid_tbl_len = 1; props->max_msg_sz = 0x80000000; props->pkey_tbl_len = ipath_get_npkeys(dd); props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) - dev->z_pkey_violations; props->qkey_viol_cntr = dev->qkey_violations; props->active_width = IB_WIDTH_4X; /* See rate_show() */ props->active_speed = 1; /* Regular 10Mbs speed. */ props->max_vl_num = 1; /* VLCap = VL0 */ props->init_type_reply = 0; /* * Note: the chip supports a maximum MTU of 4096, but the driver * hasn't implemented this feature yet, so set the maximum value * to 2048. */ props->max_mtu = IB_MTU_2048; switch (dd->ipath_ibmtu) { case 4096: mtu = IB_MTU_4096; break; case 2048: mtu = IB_MTU_2048; break; case 1024: mtu = IB_MTU_1024; break; case 512: mtu = IB_MTU_512; break; case 256: mtu = IB_MTU_256; break; default: mtu = IB_MTU_2048; } props->active_mtu = mtu; props->subnet_timeout = dev->subnet_timeout; return 0;}static int ipath_modify_device(struct ib_device *device, int device_modify_mask, struct ib_device_modify *device_modify){ int ret; if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID | IB_DEVICE_MODIFY_NODE_DESC)) { ret = -EOPNOTSUPP; goto bail; } if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC) memcpy(device->node_desc, device_modify->node_desc, 64); if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID) to_idev(device)->sys_image_guid = cpu_to_be64(device_modify->sys_image_guid); ret = 0;bail: return ret;}static int ipath_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask, struct ib_port_modify *props){ struct ipath_ibdev *dev = to_idev(ibdev); dev->port_cap_flags |= props->set_port_cap_mask; dev->port_cap_flags &= ~props->clr_port_cap_mask; if (port_modify_mask & IB_PORT_SHUTDOWN) ipath_set_linkstate(dev->dd, IPATH_IB_LINKDOWN); if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR) dev->qkey_violations = 0; return 0;}static int ipath_query_gid(struct ib_device *ibdev, u8 port, int index, union ib_gid *gid){ struct ipath_ibdev *dev = to_idev(ibdev); int ret; if (index >= 1) { ret = -EINVAL; goto bail; } gid->global.subnet_prefix = dev->gid_prefix; gid->global.interface_id = dev->dd->ipath_guid; ret = 0;bail: return ret;}static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev, struct ib_ucontext *context, struct ib_udata *udata){ struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_pd *pd; struct ib_pd *ret; /* * This is actually totally arbitrary. Some correctness tests * assume there's a maximum number of PDs that can be allocated. * We don't actually have this limit, but we fail the test if * we allow allocations of more than we report for this value. */ pd = kmalloc(sizeof *pd, GFP_KERNEL); if (!pd) { ret = ERR_PTR(-ENOMEM); goto bail; } spin_lock(&dev->n_pds_lock); if (dev->n_pds_allocated == ib_ipath_max_pds) { spin_unlock(&dev->n_pds_lock); kfree(pd); ret = ERR_PTR(-ENOMEM); goto bail; } dev->n_pds_allocated++; spin_unlock(&dev->n_pds_lock); /* ib_alloc_pd() will initialize pd->ibpd. */ pd->user = udata != NULL; ret = &pd->ibpd;bail: return ret;}static int ipath_dealloc_pd(struct ib_pd *ibpd){ struct ipath_pd *pd = to_ipd(ibpd); struct ipath_ibdev *dev = to_idev(ibpd->device); spin_lock(&dev->n_pds_lock); dev->n_pds_allocated--; spin_unlock(&dev->n_pds_lock); kfree(pd); return 0;}/** * ipath_create_ah - create an address handle * @pd: the protection domain * @ah_attr: the attributes of the AH * * This may be called from interrupt context. */static struct ib_ah *ipath_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr){ struct ipath_ah *ah; struct ib_ah *ret; struct ipath_ibdev *dev = to_idev(pd->device); unsigned long flags; /* A multicast address requires a GRH (see ch. 8.4.1). */ if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && ah_attr->dlid != IPATH_PERMISSIVE_LID && !(ah_attr->ah_flags & IB_AH_GRH)) { ret = ERR_PTR(-EINVAL); goto bail; } if (ah_attr->dlid == 0) { ret = ERR_PTR(-EINVAL); goto bail; } if (ah_attr->port_num < 1 || ah_attr->port_num > pd->device->phys_port_cnt) { ret = ERR_PTR(-EINVAL); goto bail; } ah = kmalloc(sizeof *ah, GFP_ATOMIC); if (!ah) { ret = ERR_PTR(-ENOMEM); goto bail; } spin_lock_irqsave(&dev->n_ahs_lock, flags); if (dev->n_ahs_allocated == ib_ipath_max_ahs) { spin_unlock_irqrestore(&dev->n_ahs_lock, flags); kfree(ah); ret = ERR_PTR(-ENOMEM); goto bail; } dev->n_ahs_allocated++; spin_unlock_irqrestore(&dev->n_ahs_lock, flags); /* ib_create_ah() will initialize ah->ibah. */ ah->attr = *ah_attr; ret = &ah->ibah;bail: return ret;}/** * ipath_destroy_ah - destroy an address handle * @ibah: the AH to destroy * * This may be called from interrupt context. */static int ipath_destroy_ah(struct ib_ah *ibah){ struct ipath_ibdev *dev = to_idev(ibah->device); struct ipath_ah *ah = to_iah(ibah); unsigned long flags; spin_lock_irqsave(&dev->n_ahs_lock, flags); dev->n_ahs_allocated--; spin_unlock_irqrestore(&dev->n_ahs_lock, flags); kfree(ah); return 0;}static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr){ struct ipath_ah *ah = to_iah(ibah); *ah_attr = ah->attr;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?