Skip to content

Commit

Permalink
IB/qib: Add congestion control agent implementation
Browse files Browse the repository at this point in the history
Add a congestion control agent in the driver that handles gets and
sets from the congestion control manager in the fabric for the
Performance Scale Messaging (PSM) library.

Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Mike Marciniszyn authored and Roland Dreier committed Jul 19, 2012
1 parent 551ace1 commit 36a8f01
Show file tree
Hide file tree
Showing 5 changed files with 790 additions and 12 deletions.
35 changes: 35 additions & 0 deletions drivers/infiniband/hw/qib/qib.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ struct qib_pportdata {
struct qib_devdata *dd;
struct qib_chippport_specific *cpspec; /* chip-specific per-port */
struct kobject pport_kobj;
struct kobject pport_cc_kobj;
struct kobject sl2vl_kobj;
struct kobject diagc_kobj;

Expand Down Expand Up @@ -638,6 +639,39 @@ struct qib_pportdata {
struct timer_list led_override_timer;
struct xmit_wait cong_stats;
struct timer_list symerr_clear_timer;

/* Synchronize access between driver writes and sysfs reads */
spinlock_t cc_shadow_lock
____cacheline_aligned_in_smp;

/* Shadow copy of the congestion control table */
struct cc_table_shadow *ccti_entries_shadow;

/* Shadow copy of the congestion control entries */
struct ib_cc_congestion_setting_attr_shadow *congestion_entries_shadow;

/* List of congestion control table entries */
struct ib_cc_table_entry_shadow *ccti_entries;

/* 16 congestion entries with each entry corresponding to a SL */
struct ib_cc_congestion_entry_shadow *congestion_entries;

/* Total number of congestion control table entries */
u16 total_cct_entry;

/* Bit map identifying service level */
u16 cc_sl_control_map;

/* maximum congestion control table index */
u16 ccti_limit;

/* CA's max number of 64 entry units in the congestion control table */
u8 cc_max_table_entries;

/* Maximum number of congestion control entries that the agent expects
* the manager to send.
*/
u8 cc_supported_table_entries;
};

/* Observers. Not to be taken lightly, possibly not to ship. */
Expand Down Expand Up @@ -1078,6 +1112,7 @@ extern u32 qib_cpulist_count;
extern unsigned long *qib_cpulist;

extern unsigned qib_wc_pat;
extern unsigned qib_cc_table_size;
int qib_init(struct qib_devdata *, int);
int init_chip_wc_pat(struct qib_devdata *dd, u32);
int qib_enable_wc(struct qib_devdata *dd);
Expand Down
96 changes: 95 additions & 1 deletion drivers/infiniband/hw/qib/qib_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#include "qib.h"
#include "qib_common.h"
#include "qib_mad.h"

/*
* min buffers we want to have per context, after driver
Expand Down Expand Up @@ -71,6 +72,9 @@ unsigned qib_n_krcv_queues;
module_param_named(krcvqs, qib_n_krcv_queues, uint, S_IRUGO);
MODULE_PARM_DESC(krcvqs, "number of kernel receive queues per IB port");

unsigned qib_cc_table_size;
module_param_named(cc_table_size, qib_cc_table_size, uint, S_IRUGO);
MODULE_PARM_DESC(cc_table_size, "Congestion control table entries 0 (CCA disabled - default), min = 128, max = 1984");
/*
* qib_wc_pat parameter:
* 0 is WC via MTRR
Expand Down Expand Up @@ -199,6 +203,7 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt)
void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,
u8 hw_pidx, u8 port)
{
int size;
ppd->dd = dd;
ppd->hw_pidx = hw_pidx;
ppd->port = port; /* IB port number, not index */
Expand All @@ -212,6 +217,81 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,
ppd->symerr_clear_timer.data = (unsigned long)ppd;

ppd->qib_wq = NULL;

spin_lock_init(&ppd->cc_shadow_lock);

if (qib_cc_table_size < IB_CCT_MIN_ENTRIES)
goto bail;

ppd->cc_supported_table_entries = min(max_t(int, qib_cc_table_size,
IB_CCT_MIN_ENTRIES), IB_CCT_ENTRIES*IB_CC_TABLE_CAP_DEFAULT);

ppd->cc_max_table_entries =
ppd->cc_supported_table_entries/IB_CCT_ENTRIES;

size = IB_CC_TABLE_CAP_DEFAULT * sizeof(struct ib_cc_table_entry)
* IB_CCT_ENTRIES;
ppd->ccti_entries = kzalloc(size, GFP_KERNEL);
if (!ppd->ccti_entries) {
qib_dev_err(dd,
"failed to allocate congestion control table for port %d!\n",
port);
goto bail;
}

size = IB_CC_CCS_ENTRIES * sizeof(struct ib_cc_congestion_entry);
ppd->congestion_entries = kzalloc(size, GFP_KERNEL);
if (!ppd->congestion_entries) {
qib_dev_err(dd,
"failed to allocate congestion setting list for port %d!\n",
port);
goto bail_1;
}

size = sizeof(struct cc_table_shadow);
ppd->ccti_entries_shadow = kzalloc(size, GFP_KERNEL);
if (!ppd->ccti_entries_shadow) {
qib_dev_err(dd,
"failed to allocate shadow ccti list for port %d!\n",
port);
goto bail_2;
}

size = sizeof(struct ib_cc_congestion_setting_attr);
ppd->congestion_entries_shadow = kzalloc(size, GFP_KERNEL);
if (!ppd->congestion_entries_shadow) {
qib_dev_err(dd,
"failed to allocate shadow congestion setting list for port %d!\n",
port);
goto bail_3;
}

return;

bail_3:
kfree(ppd->ccti_entries_shadow);
ppd->ccti_entries_shadow = NULL;
bail_2:
kfree(ppd->congestion_entries);
ppd->congestion_entries = NULL;
bail_1:
kfree(ppd->ccti_entries);
ppd->ccti_entries = NULL;
bail:
/* User is intentionally disabling the congestion control agent */
if (!qib_cc_table_size)
return;

if (qib_cc_table_size < IB_CCT_MIN_ENTRIES) {
qib_cc_table_size = 0;
qib_dev_err(dd,
"Congestion Control table size %d less than minimum %d for port %d\n",
qib_cc_table_size, IB_CCT_MIN_ENTRIES, port);
}

qib_dev_err(dd, "Congestion Control Agent disabled for port %d\n",
port);
return;
}

static int init_pioavailregs(struct qib_devdata *dd)
Expand Down Expand Up @@ -1164,10 +1244,24 @@ static void cleanup_device_data(struct qib_devdata *dd)
unsigned long flags;

/* users can't do anything more with chip */
for (pidx = 0; pidx < dd->num_pports; ++pidx)
for (pidx = 0; pidx < dd->num_pports; ++pidx) {
if (dd->pport[pidx].statusp)
*dd->pport[pidx].statusp &= ~QIB_STATUS_CHIP_PRESENT;

spin_lock(&dd->pport[pidx].cc_shadow_lock);

kfree(dd->pport[pidx].congestion_entries);
dd->pport[pidx].congestion_entries = NULL;
kfree(dd->pport[pidx].ccti_entries);
dd->pport[pidx].ccti_entries = NULL;
kfree(dd->pport[pidx].ccti_entries_shadow);
dd->pport[pidx].ccti_entries_shadow = NULL;
kfree(dd->pport[pidx].congestion_entries_shadow);
dd->pport[pidx].congestion_entries_shadow = NULL;

spin_unlock(&dd->pport[pidx].cc_shadow_lock);
}

if (!qib_wc_pat)
qib_disable_wc(dd);

Expand Down
Loading

0 comments on commit 36a8f01

Please sign in to comment.