* They are all read only after driver load
*/
-#define add_qsz_parameter(type, hwtype, initsize) \
+#define add_qsz_parameter(type, initsize) \
+static const uint sif_##type##_default_size = initsize;\
uint sif_##type##_size = initsize;\
module_param_named(type##_size, sif_##type##_size, uint, S_IRUGO);\
MODULE_PARM_DESC(type##_size, "Size of the " #type " descriptor table")
* e.g. for instance qp_size=2048 or ah_size=100
* (all sizes will be rounded up to a power of two value)
*/
-add_qsz_parameter(mr, key, 4194304);
-add_qsz_parameter(epsc, epsc_csr_req, 2048);
-add_qsz_parameter(qp, qp, 1048576);
-add_qsz_parameter(rq, rq_hw, 1048576);
-add_qsz_parameter(cq, cq_hw, 524288);
-add_qsz_parameter(ah, ah, 262144);
-add_qsz_parameter(sq_ring, sq_ring, 262144);
-add_qsz_parameter(sq_tvl, sq_tvl, 128);
+add_qsz_parameter(mr, 4194304);
+add_qsz_parameter(epsc, 2048);
+add_qsz_parameter(qp, 1048576);
+add_qsz_parameter(rq, 1048576);
+add_qsz_parameter(cq, 524288);
+add_qsz_parameter(ah, 262144);
+add_qsz_parameter(sq_ring, 262144);
+add_qsz_parameter(sq_tvl, 128);
/* These sizes must be equal to QP size */
#define sif_sq_rspq_size sif_qp_size
+#define sif_sq_rspq_default_size sif_qp_default_size
#define sif_rqsp_size sif_qp_size
+#define sif_rqsp_default_size sif_qp_default_size
#define sif_atsp_size sif_qp_size
+#define sif_atsp_default_size sif_qp_default_size
/* These can be set from the command line - no parameter needed */
static uint sif_epsa0_size = 64;
+static const uint sif_epsa0_default_size = 64;
static uint sif_epsa1_size = 64;
+static const uint sif_epsa1_default_size = 64;
static uint sif_epsa2_size = 64;
+static const uint sif_epsa2_default_size = 64;
static uint sif_epsa3_size = 64;
+static const uint sif_epsa3_default_size = 64;
/* This defines how small the smallest (sw) pointers can get.
* If set to <= 8, 512 sw descriptors will fit in one page.
const char *name; /* Corresponding to enum name */
const char *desc; /* Textual table desc (for logging) */
uint *e_cnt_ref; /* Driver parameter ref for no.of entries to allocate */
+ const uint *e_def_cnt; /* Driver parameter ref for default no.of entries to allocate */
u32 entry_sz; /* Real size of entries in this table */
u32 ext; /* Actual extent of (stride between) entries in this table */
sif_dfs_printer dfs_printer; /* entry printing in debugfs */
.name = #type,\
.desc = _desc,\
.e_cnt_ref = &sif_##ec##_size,\
+ .e_def_cnt = &sif_##ec##_default_size, \
.entry_sz = sizeof(struct _e_type),\
.ext = roundup_pow_of_two(sizeof(struct _e_type)),\
.dfs_printer = _dfs_printer,\
.name = #type "_csr_req", \
.desc = "EPS" #_suff " Request queue", \
.e_cnt_ref = &sif_##type##_size, \
+ .e_def_cnt = &sif_##type##_default_size, \
.entry_sz = sizeof(struct psif_epsc_csr_req),\
.ext = roundup_pow_of_two(sizeof(struct psif_epsc_csr_req)), \
.dfs_printer = sif_dfs_print_##type, \
.name = #type "_csr_rsp", \
.desc = "EPS" #_suff " Response queue", \
.e_cnt_ref = &sif_##type##_size, \
+ .e_def_cnt = &sif_##type##_default_size, \
.entry_sz = sizeof(struct psif_epsc_csr_rsp),\
.ext = roundup_pow_of_two(sizeof(struct psif_epsc_csr_rsp)), \
.dfs_printer = NULL, \
.name = "sq_cmpl",
.desc = "cq: SQ addr.map",
.e_cnt_ref = &sif_qp_size,
+ .e_def_cnt = &sif_qp_default_size, \
.entry_sz = 0, /* Calculated later */
.ext = 0, /* Calculated later */
.dfs_printer = sif_dfs_print_sq_cmpl,
.name = "bw_cb",
.desc = "High bandwith collect buffer",
.e_cnt_ref = &dummy_bw_cb_size,
+ .e_def_cnt = &dummy_bw_cb_size,
.entry_sz = sizeof(struct psif_cb),
.ext = 4096,
.dfs_printer = NULL,
.name = "lat_cb",
.desc = "Low latency collect buffer",
.e_cnt_ref = &dummy_lat_cb_size,
+ .e_def_cnt = &dummy_lat_cb_size,
.entry_sz = sizeof(struct psif_cb),
.ext = 4096,
.dfs_printer = NULL,
tp->type = type;
tp->sdev = sdev;
cfg_sz = (u32)(*base_layout[type].e_cnt_ref);
+ if (type < bw_cb && sdev->res_frac > 1 && cfg_sz == (u32)(*base_layout[type].e_def_cnt))
+ cfg_sz = cfg_sz / sdev->res_frac;
+
if (cfg_sz & 0x80000000 || cfg_sz == 0) {
sif_log(sdev, SIF_INFO, "%s(%u): table size %#x out of bounds",
base_layout[type].desc, type, cfg_sz);
/* Obtain information about lat_cb and bw_cb resources
* We cannot use the ba structs yet as they are not initialized at this point:
*/
-static void sif_cb_init(struct sif_dev *sdev)
+void sif_cb_init(struct sif_dev *sdev)
{
struct psif_epsc_csr_req req;
struct psif_epsc_csr_rsp rsp;
struct sif_eps *es = &sdev->es[sdev->mbox_epsc];
+ /* To work with very old fw assume at least 4 lat_cb and some bw_cbs */
+ sdev->lat_cb_cnt = 4;
+ sdev->bw_cb_cnt = 128;
+
/* EPSC supports the new requests starting from v.0.36 */
if (eps_version_ge(es, 0, 37)) {
int ret = 0;
req.opcode = EPSC_QUERY;
req.u.query.data.op = EPSC_QUERY_CAP_VCB_LO;
req.u.query.info.op = EPSC_QUERY_CAP_VCB_HI;
- ret = sif_epsc_wr(sdev, &req, &rsp);
- if (ret)
+ ret = sif_epsc_wr_poll(sdev, &req, &rsp);
+ if (ret) {
sif_log(sdev, SIF_INFO, "Request for VCB info failed with %d", ret);
- else {
+ } else {
sdev->bw_cb_cnt = rsp.data;
sdev->lat_cb_cnt = rsp.info;
sif_log(sdev, SIF_INIT, "Got %ld bw_cbs and %ld lat_cbs",
sdev->bw_cb_cnt, sdev->lat_cb_cnt);
}
}
+
+ /* estimate what fraction of the hardware resources we got based on the
+ * number of collect buffers reserved and use this to scale down
+ * configured base address ranges:
+ */
+ sdev->res_frac = max(1UL, CBU_NUM_VCB / (sdev->bw_cb_cnt + sdev->lat_cb_cnt));
+ if (sdev->res_frac > 1)
+ sif_log(sdev, SIF_INFO, "Scaling down default queue sizes by a factor %ld",
+ sdev->res_frac);
}
/* Update table values with EPSC data: */
if (type == bw_cb) {
- sif_cb_init(sdev);
- if (sdev->bw_cb_cnt) {
- tp->entry_cnt = sdev->bw_cb_cnt;
- tp->table_sz = tp->ext_sz * tp->entry_cnt;
- }
+ tp->entry_cnt = sdev->bw_cb_cnt;
+ tp->table_sz = tp->ext_sz * tp->entry_cnt;
tp->sif_off = sdev->cb_base;
} else {
- /* lat_cb */
- if (sdev->lat_cb_cnt) {
- tp->entry_cnt = sdev->lat_cb_cnt;
- tp->table_sz = tp->ext_sz * tp->entry_cnt;
- tp->sif_off = sdev->cb_base + sdev->ba[bw_cb].table_sz;
- } else
- tp->entry_cnt = 0;
+ tp->entry_cnt = sdev->lat_cb_cnt;
+ tp->table_sz = tp->ext_sz * tp->entry_cnt;
+ tp->sif_off = sdev->cb_base + sdev->ba[bw_cb].table_sz;
}
tp->mem = sif_mem_create_ref(sdev, SIFMT_NOMEM, tp->sif_base,