staging/rdma/hfi1: Method to toggle "fast ECN" detection

Add a per port sysfs paramter to toggle cc_prescan/Fast ECN Detection and
remove the Kconfig option which was previously used to control this.

While am updating the sysfs documentation, fix the name of CCMgtA.

Reviewed-by: Arthur Kepner <arthur.kepner@intel.com>
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Vennila Megavannan <vennila.megavannan@intel.com>
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Vennila Megavannan 2016-02-03 14:32:57 -08:00 committed by Doug Ledford
parent 566c157cbd
commit 6c9e50f894
5 changed files with 77 additions and 28 deletions

View File

@ -78,9 +78,10 @@ HFI1
chip_reset - diagnostic (root only) chip_reset - diagnostic (root only)
boardversion - board version boardversion - board version
ports/1/ ports/1/
CMgtA/ CCMgtA/
cc_settings_bin - CCA tables used by PSM2 cc_settings_bin - CCA tables used by PSM2
cc_table_bin cc_table_bin
cc_prescan - enable prescaning for faster BECN response
sc2v/ - 32 files (0 - 31) used to translate sl->vl sc2v/ - 32 files (0 - 31) used to translate sl->vl
sl2sc/ - 32 files (0 - 31) used to translate sl->sc sl2sc/ - 32 files (0 - 31) used to translate sl->sc
vl2mtu/ - 16 (0 - 15) files used to determine MTU for vl vl2mtu/ - 16 (0 - 15) files used to determine MTU for vl

View File

@ -26,13 +26,3 @@ config SDMA_VERBOSITY
---help--- ---help---
This is a configuration flag to enable verbose This is a configuration flag to enable verbose
SDMA debug SDMA debug
config PRESCAN_RXQ
bool "Enable prescanning of the RX queue for ECNs"
depends on INFINIBAND_HFI1
default n
---help---
This option toggles the prescanning of the receive queue for
Explicit Congestion Notifications. If an ECN is detected, it
is processed as quickly as possible, the ECN is toggled off.
After the prescanning step, the receive queue is processed as
usual.

View File

@ -453,11 +453,6 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
packet->rcv_flags = 0; packet->rcv_flags = 0;
} }
#ifndef CONFIG_PRESCAN_RXQ
static void prescan_rxq(struct hfi1_packet *packet) {}
#else /* !CONFIG_PRESCAN_RXQ */
static int prescan_receive_queue;
static void process_ecn(struct rvt_qp *qp, struct hfi1_ib_header *hdr, static void process_ecn(struct rvt_qp *qp, struct hfi1_ib_header *hdr,
struct hfi1_other_headers *ohdr, struct hfi1_other_headers *ohdr,
u64 rhf, u32 bth1, struct ib_grh *grh) u64 rhf, u32 bth1, struct ib_grh *grh)
@ -581,15 +576,19 @@ static inline void update_ps_mdata(struct ps_mdata *mdata,
* containing Excplicit Congestion Notifications (FECNs, or BECNs). * containing Excplicit Congestion Notifications (FECNs, or BECNs).
* When an ECN is found, process the Congestion Notification, and toggle * When an ECN is found, process the Congestion Notification, and toggle
* it off. * it off.
* This is declared as a macro to allow quick checking of the port to avoid
* the overhead of a function call if not enabled.
*/ */
static void prescan_rxq(struct hfi1_packet *packet) #define prescan_rxq(rcd, packet) \
do { \
if (rcd->ppd->cc_prescan) \
__prescan_rxq(packet); \
} while (0)
static void __prescan_rxq(struct hfi1_packet *packet)
{ {
struct hfi1_ctxtdata *rcd = packet->rcd; struct hfi1_ctxtdata *rcd = packet->rcd;
struct ps_mdata mdata; struct ps_mdata mdata;
if (!prescan_receive_queue)
return;
init_ps_mdata(&mdata, packet); init_ps_mdata(&mdata, packet);
while (1) { while (1) {
@ -653,7 +652,6 @@ next:
update_ps_mdata(&mdata, rcd); update_ps_mdata(&mdata, rcd);
} }
} }
#endif /* CONFIG_PRESCAN_RXQ */
static inline int skip_rcv_packet(struct hfi1_packet *packet, int thread) static inline int skip_rcv_packet(struct hfi1_packet *packet, int thread)
{ {
@ -819,7 +817,7 @@ int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd, int thread)
goto bail; goto bail;
} }
prescan_rxq(&packet); prescan_rxq(rcd, &packet);
while (last == RCV_PKT_OK) { while (last == RCV_PKT_OK) {
last = process_rcv_packet(&packet, thread); last = process_rcv_packet(&packet, thread);
@ -850,7 +848,7 @@ int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd, int thread)
} }
smp_rmb(); /* prevent speculative reads of dma'ed hdrq */ smp_rmb(); /* prevent speculative reads of dma'ed hdrq */
prescan_rxq(&packet); prescan_rxq(rcd, &packet);
while (last == RCV_PKT_OK) { while (last == RCV_PKT_OK) {
last = process_rcv_packet(&packet, thread); last = process_rcv_packet(&packet, thread);
@ -961,7 +959,7 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread)
} }
} }
prescan_rxq(&packet); prescan_rxq(rcd, &packet);
while (last == RCV_PKT_OK) { while (last == RCV_PKT_OK) {

View File

@ -734,6 +734,8 @@ struct hfi1_pportdata {
/* Error events that will cause a port bounce. */ /* Error events that will cause a port bounce. */
u32 port_error_action; u32 port_error_action;
struct work_struct linkstate_active_work; struct work_struct linkstate_active_work;
/* Does this port need to prescan for FECNs */
bool cc_prescan;
}; };
typedef int (*rhf_rcv_function_ptr)(struct hfi1_packet *packet); typedef int (*rhf_rcv_function_ptr)(struct hfi1_packet *packet);

View File

@ -99,10 +99,6 @@ static void port_release(struct kobject *kobj)
/* nothing to do since memory is freed by hfi1_free_devdata() */ /* nothing to do since memory is freed by hfi1_free_devdata() */
} }
static struct kobj_type port_cc_ktype = {
.release = port_release,
};
static struct bin_attribute cc_table_bin_attr = { static struct bin_attribute cc_table_bin_attr = {
.attr = {.name = "cc_table_bin", .mode = 0444}, .attr = {.name = "cc_table_bin", .mode = 0444},
.read = read_cc_table_bin, .read = read_cc_table_bin,
@ -151,6 +147,68 @@ static struct bin_attribute cc_setting_bin_attr = {
.size = PAGE_SIZE, .size = PAGE_SIZE,
}; };
struct hfi1_port_attr {
struct attribute attr;
ssize_t (*show)(struct hfi1_pportdata *, char *);
ssize_t (*store)(struct hfi1_pportdata *, const char *, size_t);
};
static ssize_t cc_prescan_show(struct hfi1_pportdata *ppd, char *buf)
{
return sprintf(buf, "%s\n", ppd->cc_prescan ? "on" : "off");
}
static ssize_t cc_prescan_store(struct hfi1_pportdata *ppd, const char *buf,
size_t count)
{
if (!memcmp(buf, "on", 2))
ppd->cc_prescan = true;
else if (!memcmp(buf, "off", 3))
ppd->cc_prescan = false;
return count;
}
static struct hfi1_port_attr cc_prescan_attr =
__ATTR(cc_prescan, 0600, cc_prescan_show, cc_prescan_store);
static ssize_t cc_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct hfi1_port_attr *port_attr =
container_of(attr, struct hfi1_port_attr, attr);
struct hfi1_pportdata *ppd =
container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
return port_attr->show(ppd, buf);
}
static ssize_t cc_attr_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
struct hfi1_port_attr *port_attr =
container_of(attr, struct hfi1_port_attr, attr);
struct hfi1_pportdata *ppd =
container_of(kobj, struct hfi1_pportdata, pport_cc_kobj);
return port_attr->store(ppd, buf, count);
}
static const struct sysfs_ops port_cc_sysfs_ops = {
.show = cc_attr_show,
.store = cc_attr_store
};
static struct attribute *port_cc_default_attributes[] = {
&cc_prescan_attr.attr
};
static struct kobj_type port_cc_ktype = {
.release = port_release,
.sysfs_ops = &port_cc_sysfs_ops,
.default_attrs = port_cc_default_attributes
};
/* Start sc2vl */ /* Start sc2vl */
#define HFI1_SC2VL_ATTR(N) \ #define HFI1_SC2VL_ATTR(N) \
static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \ static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \