mirror of
https://github.com/joel16/android_kernel_sony_msm8994_rework.git
synced 2024-11-23 20:09:51 +00:00
RDMA/nes: Support for Packed And Unaligned fpdus
Support for Packed and Unaligned (PAU) FPDUs is needed for interoperability between NES and non-NES nodes. When the NES hardware detects a PAU frame, it will pass it to the driver to process the frame. NES driver creates a new frame for each FPDU and forwards it to the hardware to be sent to its associated qp. Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com> Signed-off-by: Faisal Latif <Faisal.Latif@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
6224c7eeff
commit
0f0bee8bbc
@ -1,3 +1,3 @@
|
||||
obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
|
||||
|
||||
iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
|
||||
iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
|
||||
|
@ -84,7 +84,7 @@ module_param(send_first, int, 0644);
|
||||
MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
|
||||
|
||||
|
||||
unsigned int nes_drv_opt = 0;
|
||||
unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
|
||||
module_param(nes_drv_opt, int, 0644);
|
||||
MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
|
||||
|
||||
@ -130,9 +130,6 @@ static struct notifier_block nes_net_notifier = {
|
||||
.notifier_call = nes_net_event
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* nes_inetaddr_event
|
||||
*/
|
||||
@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
|
||||
}
|
||||
|
||||
if (atomic_dec_and_test(&nesqp->refcount)) {
|
||||
if (nesqp->pau_mode)
|
||||
nes_destroy_pau_qp(nesdev, nesqp);
|
||||
|
||||
/* Destroy the QP */
|
||||
cqp_request = nes_get_cqp_request(nesdev);
|
||||
if (cqp_request == NULL) {
|
||||
|
@ -102,6 +102,7 @@
|
||||
#define NES_DRV_OPT_NO_INLINE_DATA 0x00000080
|
||||
#define NES_DRV_OPT_DISABLE_INT_MOD 0x00000100
|
||||
#define NES_DRV_OPT_DISABLE_VIRT_WQ 0x00000200
|
||||
#define NES_DRV_OPT_ENABLE_PAU 0x00000400
|
||||
|
||||
#define NES_AEQ_EVENT_TIMEOUT 2500
|
||||
#define NES_DISCONNECT_EVENT_TIMEOUT 2000
|
||||
@ -128,6 +129,7 @@
|
||||
#define NES_DBG_IW_RX 0x00020000
|
||||
#define NES_DBG_IW_TX 0x00040000
|
||||
#define NES_DBG_SHUTDOWN 0x00080000
|
||||
#define NES_DBG_PAU 0x00100000
|
||||
#define NES_DBG_RSVD1 0x10000000
|
||||
#define NES_DBG_RSVD2 0x20000000
|
||||
#define NES_DBG_RSVD3 0x40000000
|
||||
@ -162,6 +164,7 @@ do { \
|
||||
#include "nes_context.h"
|
||||
#include "nes_user.h"
|
||||
#include "nes_cm.h"
|
||||
#include "nes_mgt.h"
|
||||
|
||||
extern int max_mtu;
|
||||
#define max_frame_len (max_mtu+ETH_HLEN)
|
||||
@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created;
|
||||
extern atomic_t cm_nodes_destroyed;
|
||||
extern atomic_t cm_accel_dropped_pkts;
|
||||
extern atomic_t cm_resets_recvd;
|
||||
extern atomic_t pau_qps_created;
|
||||
extern atomic_t pau_qps_destroyed;
|
||||
|
||||
extern u32 int_mod_timer_init;
|
||||
extern u32 int_mod_cq_depth_256;
|
||||
@ -273,6 +278,14 @@ struct nes_device {
|
||||
u8 link_recheck;
|
||||
};
|
||||
|
||||
/* Receive skb private area - must fit in skb->cb area */
|
||||
struct nes_rskb_cb {
|
||||
u64 busaddr;
|
||||
u32 maplen;
|
||||
u32 seqnum;
|
||||
u8 *data_start;
|
||||
struct nes_qp *nesqp;
|
||||
};
|
||||
|
||||
static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
|
||||
{
|
||||
@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value)
|
||||
static inline void
|
||||
nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
|
||||
{
|
||||
set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
|
||||
(u64)((unsigned long) &nesdev->cqp));
|
||||
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX] = 0;
|
||||
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
|
||||
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0;
|
||||
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0;
|
||||
cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
|
||||
|
@ -159,6 +159,15 @@ atomic_t cm_connecteds;
|
||||
atomic_t cm_connect_reqs;
|
||||
atomic_t cm_rejects;
|
||||
|
||||
int nes_add_ref_cm_node(struct nes_cm_node *cm_node)
|
||||
{
|
||||
return add_ref_cm_node(cm_node);
|
||||
}
|
||||
|
||||
int nes_rem_ref_cm_node(struct nes_cm_node *cm_node)
|
||||
{
|
||||
return rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* create_event
|
||||
@ -2331,9 +2340,13 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
|
||||
}
|
||||
add_ref_cm_node(cm_node);
|
||||
} else if (cm_node->state == NES_CM_STATE_TSA) {
|
||||
rem_ref_cm_node(cm_core, cm_node);
|
||||
atomic_inc(&cm_accel_dropped_pkts);
|
||||
dev_kfree_skb_any(skb);
|
||||
if (cm_node->nesqp->pau_mode)
|
||||
nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp);
|
||||
else {
|
||||
rem_ref_cm_node(cm_core, cm_node);
|
||||
atomic_inc(&cm_accel_dropped_pkts);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
skb_reset_network_header(skb);
|
||||
|
@ -422,5 +422,7 @@ int nes_destroy_listen(struct iw_cm_id *);
|
||||
int nes_cm_recv(struct sk_buff *, struct net_device *);
|
||||
int nes_cm_start(void);
|
||||
int nes_cm_stop(void);
|
||||
int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
|
||||
int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
|
||||
|
||||
#endif /* NES_CM_H */
|
||||
|
@ -1563,6 +1563,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
|
||||
struct nes_hw_nic_rq_wqe *nic_rqe;
|
||||
struct nes_hw_nic *nesnic;
|
||||
struct nes_device *nesdev;
|
||||
struct nes_rskb_cb *cb;
|
||||
u32 rx_wqes_posted = 0;
|
||||
|
||||
nesnic = &nesvnic->nic;
|
||||
@ -1588,6 +1589,9 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
|
||||
|
||||
bus_address = pci_map_single(nesdev->pcidev,
|
||||
skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
|
||||
cb = (struct nes_rskb_cb *)&skb->cb[0];
|
||||
cb->busaddr = bus_address;
|
||||
cb->maplen = nesvnic->max_frame_size;
|
||||
|
||||
nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
|
||||
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
|
||||
@ -1677,6 +1681,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
|
||||
u32 cqp_head;
|
||||
u32 counter;
|
||||
u32 wqe_count;
|
||||
struct nes_rskb_cb *cb;
|
||||
u8 jumbomode=0;
|
||||
|
||||
/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
|
||||
@ -1853,6 +1858,9 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
|
||||
|
||||
pmem = pci_map_single(nesdev->pcidev, skb->data,
|
||||
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
|
||||
cb = (struct nes_rskb_cb *)&skb->cb[0];
|
||||
cb->busaddr = pmem;
|
||||
cb->maplen = nesvnic->max_frame_size;
|
||||
|
||||
nic_rqe = &nesvnic->nic.rq_vbase[counter];
|
||||
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
|
||||
@ -1881,6 +1889,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
|
||||
jumbomode = 1;
|
||||
nes_nic_init_timer_defaults(nesdev, jumbomode);
|
||||
}
|
||||
if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
|
||||
(nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
|
||||
nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
|
||||
nes_destroy_nic_qp(nesvnic);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
|
||||
nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
|
||||
nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
|
||||
@ -1903,28 +1918,29 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
|
||||
struct nes_device *nesdev = nesvnic->nesdev;
|
||||
struct nes_hw_cqp_wqe *cqp_wqe;
|
||||
struct nes_hw_nic_sq_wqe *nic_sqe;
|
||||
struct nes_hw_nic_rq_wqe *nic_rqe;
|
||||
__le16 *wqe_fragment_length;
|
||||
u16 wqe_fragment_index;
|
||||
u64 wqe_frag;
|
||||
u32 cqp_head;
|
||||
u32 wqm_cfg0;
|
||||
unsigned long flags;
|
||||
struct sk_buff *rx_skb;
|
||||
struct nes_rskb_cb *cb;
|
||||
int ret;
|
||||
|
||||
if (nesdev->nesadapter->allow_unaligned_fpdus)
|
||||
nes_destroy_mgt(nesvnic);
|
||||
|
||||
/* clear wqe stall before destroying NIC QP */
|
||||
wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
|
||||
nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
|
||||
|
||||
/* Free remaining NIC receive buffers */
|
||||
while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
|
||||
nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
|
||||
wqe_frag = (u64)le32_to_cpu(
|
||||
nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
|
||||
wqe_frag |= ((u64)le32_to_cpu(
|
||||
nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
|
||||
pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
|
||||
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
|
||||
rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
|
||||
cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
|
||||
pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
|
||||
nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
|
||||
}
|
||||
@ -2783,6 +2799,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
||||
struct nes_hw_nic_sq_wqe *nic_sqe;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *rx_skb;
|
||||
struct nes_rskb_cb *cb;
|
||||
__le16 *wqe_fragment_length;
|
||||
u32 head;
|
||||
u32 cq_size;
|
||||
@ -2867,6 +2884,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
||||
bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
|
||||
pci_unmap_single(nesdev->pcidev, bus_address,
|
||||
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
|
||||
cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
|
||||
cb->busaddr = 0;
|
||||
/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
|
||||
/* rx_skb->len = rx_pkt_size; */
|
||||
rx_skb->len = 0; /* TODO: see if this is necessary */
|
||||
@ -2991,6 +3010,7 @@ skip_rx_indicate0:
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* nes_cqp_ce_handler
|
||||
*/
|
||||
@ -3005,6 +3025,8 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
|
||||
u32 cq_size;
|
||||
u32 cqe_count=0;
|
||||
u32 error_code;
|
||||
u32 opcode;
|
||||
u32 ctx_index;
|
||||
/* u32 counter; */
|
||||
|
||||
head = cq->cq_head;
|
||||
@ -3015,12 +3037,9 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
|
||||
/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
|
||||
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
|
||||
|
||||
if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
|
||||
u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
|
||||
cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
|
||||
((u64)(le32_to_cpu(cq->cq_vbase[head].
|
||||
cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
|
||||
cqp = *((struct nes_hw_cqp **)&u64temp);
|
||||
opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
|
||||
if (opcode & NES_CQE_VALID) {
|
||||
cqp = &nesdev->cqp;
|
||||
|
||||
error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
|
||||
if (error_code) {
|
||||
@ -3029,15 +3048,14 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
|
||||
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
|
||||
(u16)(error_code >> 16),
|
||||
(u16)error_code);
|
||||
nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
|
||||
cqp->qp_id, cqp->sq_head, cqp->sq_tail);
|
||||
}
|
||||
|
||||
u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
|
||||
wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
|
||||
((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
|
||||
wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
|
||||
cqp_request = *((struct nes_cqp_request **)&u64temp);
|
||||
u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
|
||||
cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
|
||||
((u64)(le32_to_cpu(cq->cq_vbase[head].
|
||||
cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
|
||||
|
||||
cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
|
||||
if (cqp_request) {
|
||||
if (cqp_request->waiting) {
|
||||
/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
|
||||
@ -3083,9 +3101,15 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
|
||||
cqp_wqe = &nesdev->cqp.sq_vbase[head];
|
||||
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
|
||||
barrier();
|
||||
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
|
||||
|
||||
opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
|
||||
if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
|
||||
ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
|
||||
else
|
||||
ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
|
||||
cqp_wqe->wqe_words[ctx_index] =
|
||||
cpu_to_le32((u32)((unsigned long)cqp_request));
|
||||
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
|
||||
cqp_wqe->wqe_words[ctx_index + 1] =
|
||||
cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
|
||||
nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
|
||||
cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
|
||||
@ -3101,7 +3125,6 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
|
||||
nes_read32(nesdev->regs+NES_CQE_ALLOC);
|
||||
}
|
||||
|
||||
|
||||
static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
|
||||
{
|
||||
if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
|
||||
|
@ -47,6 +47,11 @@
|
||||
#define NES_MULTICAST_PF_MAX 8
|
||||
#define NES_A0 3
|
||||
|
||||
#define NES_ENABLE_PAU 0x07000001
|
||||
#define NES_DISABLE_PAU 0x07000000
|
||||
#define NES_PAU_COUNTER 10
|
||||
#define NES_CQP_OPCODE_MASK 0x3f
|
||||
|
||||
enum pci_regs {
|
||||
NES_INT_STAT = 0x0000,
|
||||
NES_INT_MASK = 0x0004,
|
||||
@ -73,8 +78,10 @@ enum indexed_regs {
|
||||
NES_IDX_QP_CONTROL = 0x0040,
|
||||
NES_IDX_FLM_CONTROL = 0x0080,
|
||||
NES_IDX_INT_CPU_STATUS = 0x00a0,
|
||||
NES_IDX_GPR_TRIGGER = 0x00bc,
|
||||
NES_IDX_GPIO_CONTROL = 0x00f0,
|
||||
NES_IDX_GPIO_DATA = 0x00f4,
|
||||
NES_IDX_GPR2 = 0x010c,
|
||||
NES_IDX_TCP_CONFIG0 = 0x01e4,
|
||||
NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
|
||||
NES_IDX_TCP_NOW = 0x01f0,
|
||||
@ -202,6 +209,7 @@ enum nes_cqp_opcodes {
|
||||
NES_CQP_REGISTER_SHARED_STAG = 0x0c,
|
||||
NES_CQP_DEALLOCATE_STAG = 0x0d,
|
||||
NES_CQP_MANAGE_ARP_CACHE = 0x0f,
|
||||
NES_CQP_DOWNLOAD_SEGMENT = 0x10,
|
||||
NES_CQP_SUSPEND_QPS = 0x11,
|
||||
NES_CQP_UPLOAD_CONTEXT = 0x13,
|
||||
NES_CQP_CREATE_CEQ = 0x16,
|
||||
@ -210,7 +218,8 @@ enum nes_cqp_opcodes {
|
||||
NES_CQP_DESTROY_AEQ = 0x1b,
|
||||
NES_CQP_LMI_ACCESS = 0x20,
|
||||
NES_CQP_FLUSH_WQES = 0x22,
|
||||
NES_CQP_MANAGE_APBVT = 0x23
|
||||
NES_CQP_MANAGE_APBVT = 0x23,
|
||||
NES_CQP_MANAGE_QUAD_HASH = 0x25
|
||||
};
|
||||
|
||||
enum nes_cqp_wqe_word_idx {
|
||||
@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx {
|
||||
NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
|
||||
};
|
||||
|
||||
enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
|
||||
NES_CQP_WQE_DL_OPCODE_IDX = 0,
|
||||
NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
|
||||
NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
|
||||
NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
|
||||
/* For index values 4-15 use NES_NIC_SQ_WQE_ values */
|
||||
};
|
||||
|
||||
enum nes_cqp_cq_wqeword_idx {
|
||||
NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
|
||||
NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
|
||||
@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx {
|
||||
NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
|
||||
};
|
||||
|
||||
#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
|
||||
#define NES_CQP_OP_IWARP_STATE_SHIFT 28
|
||||
#define NES_CQP_OP_TERMLEN_SHIFT 28
|
||||
|
||||
@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits {
|
||||
|
||||
enum nes_nic_cqe_word_idx {
|
||||
NES_NIC_CQE_ACCQP_ID_IDX = 0,
|
||||
NES_NIC_CQE_HASH_RCVNXT = 1,
|
||||
NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
|
||||
NES_NIC_CQE_MISC_IDX = 3,
|
||||
};
|
||||
@ -1005,6 +1024,11 @@ struct nes_arp_entry {
|
||||
#define NES_NIC_CQ_DOWNWARD_TREND 16
|
||||
#define NES_PFT_SIZE 48
|
||||
|
||||
#define NES_MGT_WQ_COUNT 32
|
||||
#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
|
||||
#define NES_MGT_QP_OFFSET 36
|
||||
#define NES_MGT_QP_COUNT 4
|
||||
|
||||
struct nes_hw_tune_timer {
|
||||
/* u16 cq_count; */
|
||||
u16 threshold_low;
|
||||
@ -1118,6 +1142,7 @@ struct nes_adapter {
|
||||
u32 et_rate_sample_interval;
|
||||
u32 timer_int_limit;
|
||||
u32 wqm_quanta;
|
||||
u8 allow_unaligned_fpdus;
|
||||
|
||||
/* Adapter base MAC address */
|
||||
u32 mac_addr_low;
|
||||
@ -1251,6 +1276,14 @@ struct nes_vnic {
|
||||
enum ib_event_type delayed_event;
|
||||
enum ib_event_type last_dispatched_event;
|
||||
spinlock_t port_ibevent_lock;
|
||||
u32 mgt_mem_size;
|
||||
void *mgt_vbase;
|
||||
dma_addr_t mgt_pbase;
|
||||
struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
|
||||
struct task_struct *mgt_thread;
|
||||
wait_queue_head_t mgt_wait_queue;
|
||||
struct sk_buff_head mgt_skb_list;
|
||||
|
||||
};
|
||||
|
||||
struct nes_ib_device {
|
||||
|
1162
drivers/infiniband/hw/nes/nes_mgt.c
Normal file
1162
drivers/infiniband/hw/nes/nes_mgt.c
Normal file
File diff suppressed because it is too large
Load Diff
97
drivers/infiniband/hw/nes/nes_mgt.h
Normal file
97
drivers/infiniband/hw/nes/nes_mgt.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Intel-NE, Inc. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __NES_MGT_H
|
||||
#define __NES_MGT_H
|
||||
|
||||
#define MPA_FRAMING 6 /* length is 2 bytes, crc is 4 bytes */
|
||||
|
||||
int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic);
|
||||
void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp);
|
||||
void nes_destroy_mgt(struct nes_vnic *nesvnic);
|
||||
void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp);
|
||||
|
||||
struct nes_hw_mgt {
|
||||
struct nes_hw_nic_rq_wqe *rq_vbase; /* virtual address of rq */
|
||||
dma_addr_t rq_pbase; /* PCI memory for host rings */
|
||||
struct sk_buff *rx_skb[NES_NIC_WQ_SIZE];
|
||||
u16 qp_id;
|
||||
u16 sq_head;
|
||||
u16 rq_head;
|
||||
u16 rq_tail;
|
||||
u16 rq_size;
|
||||
u8 replenishing_rq;
|
||||
u8 reserved;
|
||||
spinlock_t rq_lock;
|
||||
};
|
||||
|
||||
struct nes_vnic_mgt {
|
||||
struct nes_vnic *nesvnic;
|
||||
struct nes_hw_mgt mgt;
|
||||
struct nes_hw_nic_cq mgt_cq;
|
||||
atomic_t rx_skbs_needed;
|
||||
struct timer_list rq_wqes_timer;
|
||||
atomic_t rx_skb_timer_running;
|
||||
};
|
||||
|
||||
#define MAX_FPDU_FRAGS 4
|
||||
struct pau_fpdu_frag {
|
||||
struct sk_buff *skb;
|
||||
u64 physaddr;
|
||||
u32 frag_len;
|
||||
bool cmplt;
|
||||
};
|
||||
|
||||
struct pau_fpdu_info {
|
||||
struct nes_qp *nesqp;
|
||||
struct nes_cqp_request *cqp_request;
|
||||
void *hdr_vbase;
|
||||
dma_addr_t hdr_pbase;
|
||||
int hdr_len;
|
||||
u16 data_len;
|
||||
u16 frag_cnt;
|
||||
struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
|
||||
};
|
||||
|
||||
enum pau_qh_state {
|
||||
PAU_DEL_QH,
|
||||
PAU_ADD_LB_QH,
|
||||
PAU_READY
|
||||
};
|
||||
|
||||
struct pau_qh_chg {
|
||||
struct nes_device *nesdev;
|
||||
struct nes_vnic *nesvnic;
|
||||
struct nes_qp *nesqp;
|
||||
};
|
||||
|
||||
#endif /* __NES_MGT_H */
|
@ -1090,6 +1090,8 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
|
||||
"LRO aggregated",
|
||||
"LRO flushed",
|
||||
"LRO no_desc",
|
||||
"PAU CreateQPs",
|
||||
"PAU DestroyQPs",
|
||||
};
|
||||
#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
|
||||
|
||||
@ -1305,6 +1307,8 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
|
||||
target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
|
||||
target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
|
||||
target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
|
||||
target_stat_values[++index] = atomic_read(&pau_qps_created);
|
||||
target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,13 +51,34 @@
|
||||
|
||||
#include "nes.h"
|
||||
|
||||
|
||||
|
||||
static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
|
||||
|
||||
u32 mh_detected;
|
||||
u32 mh_pauses_sent;
|
||||
|
||||
u32 nes_set_pau(struct nes_device *nesdev)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 counter;
|
||||
|
||||
nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
|
||||
nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
|
||||
|
||||
for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
|
||||
udelay(30);
|
||||
if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
|
||||
printk(KERN_INFO PFX "PAU is supported.\n");
|
||||
break;
|
||||
}
|
||||
nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
|
||||
}
|
||||
if (counter == NES_PAU_COUNTER) {
|
||||
printk(KERN_INFO PFX "PAU is not supported.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nes_read_eeprom_values -
|
||||
*/
|
||||
@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada
|
||||
if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
|
||||
nesadapter->send_term_ok = 1;
|
||||
|
||||
if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
|
||||
if (!nes_set_pau(nesdev))
|
||||
nesadapter->allow_unaligned_fpdus = 1;
|
||||
}
|
||||
|
||||
nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) +
|
||||
(u32)((u8)eeprom_data);
|
||||
|
||||
@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_device *nesdev,
|
||||
nes_free_cqp_request(nesdev, cqp_request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nes_post_cqp_request
|
||||
*/
|
||||
@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_device *nesdev,
|
||||
unsigned long flags;
|
||||
u32 cqp_head;
|
||||
u64 u64temp;
|
||||
u32 opcode;
|
||||
int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
|
||||
|
||||
spin_lock_irqsave(&nesdev->cqp.lock, flags);
|
||||
|
||||
@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_device *nesdev,
|
||||
nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
|
||||
cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
|
||||
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
|
||||
opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
|
||||
if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
|
||||
ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
|
||||
barrier();
|
||||
u64temp = (unsigned long)cqp_request;
|
||||
set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
|
||||
u64temp);
|
||||
set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
|
||||
nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
|
||||
" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
|
||||
" waiting = %d, refcount = %d.\n",
|
||||
le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
|
||||
le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
|
||||
nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
|
||||
cqp_request->waiting, atomic_read(&cqp_request->refcount));
|
||||
" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
|
||||
" waiting = %d, refcount = %d.\n",
|
||||
opcode & NES_CQP_OPCODE_MASK,
|
||||
le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
|
||||
nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
|
||||
cqp_request->waiting, atomic_read(&cqp_request->refcount));
|
||||
|
||||
barrier();
|
||||
|
||||
/* Ring doorbell (1 WQEs) */
|
||||
@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_device *nesdev,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nes_arp_table
|
||||
*/
|
||||
|
@ -1458,7 +1458,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
|
||||
struct ib_qp_attr attr;
|
||||
struct iw_cm_id *cm_id;
|
||||
struct iw_cm_event cm_event;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
atomic_inc(&sw_qps_destroyed);
|
||||
nesqp->destroyed = 1;
|
||||
@ -1511,7 +1511,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
|
||||
if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
|
||||
nes_clean_cq(nesqp, nesqp->nesrcq);
|
||||
}
|
||||
|
||||
nes_rem_ref(&nesqp->ibqp);
|
||||
return 0;
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ struct nes_qp {
|
||||
u32 mmap_sq_db_index;
|
||||
u32 mmap_rq_db_index;
|
||||
spinlock_t lock;
|
||||
spinlock_t pau_lock;
|
||||
struct nes_qp_context *nesqp_context;
|
||||
dma_addr_t nesqp_context_pbase;
|
||||
void *pbl_vbase;
|
||||
@ -161,6 +162,8 @@ struct nes_qp {
|
||||
struct page *page;
|
||||
struct timer_list terminate_timer;
|
||||
enum ib_event_type terminate_eventtype;
|
||||
struct sk_buff_head pau_list;
|
||||
u32 pau_rcv_nxt;
|
||||
u16 active_conn:1;
|
||||
u16 skip_lsmm:1;
|
||||
u16 user_mode:1;
|
||||
@ -168,7 +171,8 @@ struct nes_qp {
|
||||
u16 flush_issued:1;
|
||||
u16 destroyed:1;
|
||||
u16 sig_all:1;
|
||||
u16 rsvd:9;
|
||||
u16 pau_mode:1;
|
||||
u16 rsvd:8;
|
||||
u16 private_data_len;
|
||||
u16 term_sq_flush_code;
|
||||
u16 term_rq_flush_code;
|
||||
@ -176,5 +180,8 @@ struct nes_qp {
|
||||
u8 hw_tcp_state;
|
||||
u8 term_flags;
|
||||
u8 sq_kmapped;
|
||||
u8 pau_busy;
|
||||
u8 pau_pending;
|
||||
u8 pau_state;
|
||||
};
|
||||
#endif /* NES_VERBS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user