aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHariprasad Shenai <hariprasad@chelsio.com>2015-03-26 00:34:25 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-29 15:24:42 -0400
commit4b8e27a86d209063d8aacfb918668bbb75e56019 (patch)
tree36b896c22a4259766c37f7e64a452c58e64dcffb
parentf243e5a7859a24d10975afb9a1708cac624ba6f1 (diff)
cxgb4: Allocate dynamic mem. for egress and ingress queue maps
QIDs (egress/ingress) from firmware in FW_*_CMD.alloc command can be anywhere in the range from EQ(IQFLINT)_START to EQ(IQFLINT)_END. For eg, in the first load eqid can be from 100 to 300. In the next load it can be from 301 to 500 (assume eq_start is 100 and eq_end is 1000). The driver was assuming them to always start from EQ(IQFLINT)_START till MAX_EGRQ(INGQ). This was causing stack overflow and subsequent crash. Fixed it by dynamically allocating memory (of qsize (x_END - x_START + 1)) for these structures. Based on original work by Santosh Rastapur <santosh@chelsio.com> Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c79
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c7
3 files changed, 83 insertions, 15 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 97842d03675b..8816c645de7d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -376,8 +376,6 @@ enum {
376enum { 376enum {
377 INGQ_EXTRAS = 2, /* firmware event queue and */ 377 INGQ_EXTRAS = 2, /* firmware event queue and */
378 /* forwarded interrupts */ 378 /* forwarded interrupts */
379 MAX_EGRQ = MAX_ETH_QSETS*2 + MAX_OFLD_QSETS*2
380 + MAX_CTRL_QUEUES + MAX_RDMA_QUEUES + MAX_ISCSI_QUEUES,
381 MAX_INGQ = MAX_ETH_QSETS + MAX_OFLD_QSETS + MAX_RDMA_QUEUES 379 MAX_INGQ = MAX_ETH_QSETS + MAX_OFLD_QSETS + MAX_RDMA_QUEUES
382 + MAX_RDMA_CIQS + MAX_ISCSI_QUEUES + INGQ_EXTRAS, 380 + MAX_RDMA_CIQS + MAX_ISCSI_QUEUES + INGQ_EXTRAS,
383}; 381};
@@ -616,11 +614,13 @@ struct sge {
616 unsigned int idma_qid[2]; /* SGE IDMA Hung Ingress Queue ID */ 614 unsigned int idma_qid[2]; /* SGE IDMA Hung Ingress Queue ID */
617 615
618 unsigned int egr_start; 616 unsigned int egr_start;
617 unsigned int egr_sz;
619 unsigned int ingr_start; 618 unsigned int ingr_start;
620 void *egr_map[MAX_EGRQ]; /* qid->queue egress queue map */ 619 unsigned int ingr_sz;
621 struct sge_rspq *ingr_map[MAX_INGQ]; /* qid->queue ingress queue map */ 620 void **egr_map; /* qid->queue egress queue map */
622 DECLARE_BITMAP(starving_fl, MAX_EGRQ); 621 struct sge_rspq **ingr_map; /* qid->queue ingress queue map */
623 DECLARE_BITMAP(txq_maperr, MAX_EGRQ); 622 unsigned long *starving_fl;
623 unsigned long *txq_maperr;
624 struct timer_list rx_timer; /* refills starving FLs */ 624 struct timer_list rx_timer; /* refills starving FLs */
625 struct timer_list tx_timer; /* checks Tx queues */ 625 struct timer_list tx_timer; /* checks Tx queues */
626}; 626};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index a22cf932ca35..b9b5a7b1a116 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -920,7 +920,7 @@ static void quiesce_rx(struct adapter *adap)
920{ 920{
921 int i; 921 int i;
922 922
923 for (i = 0; i < ARRAY_SIZE(adap->sge.ingr_map); i++) { 923 for (i = 0; i < adap->sge.ingr_sz; i++) {
924 struct sge_rspq *q = adap->sge.ingr_map[i]; 924 struct sge_rspq *q = adap->sge.ingr_map[i];
925 925
926 if (q && q->handler) { 926 if (q && q->handler) {
@@ -941,7 +941,7 @@ static void enable_rx(struct adapter *adap)
941{ 941{
942 int i; 942 int i;
943 943
944 for (i = 0; i < ARRAY_SIZE(adap->sge.ingr_map); i++) { 944 for (i = 0; i < adap->sge.ingr_sz; i++) {
945 struct sge_rspq *q = adap->sge.ingr_map[i]; 945 struct sge_rspq *q = adap->sge.ingr_map[i];
946 946
947 if (!q) 947 if (!q)
@@ -970,8 +970,8 @@ static int setup_sge_queues(struct adapter *adap)
970 int err, msi_idx, i, j; 970 int err, msi_idx, i, j;
971 struct sge *s = &adap->sge; 971 struct sge *s = &adap->sge;
972 972
973 bitmap_zero(s->starving_fl, MAX_EGRQ); 973 bitmap_zero(s->starving_fl, s->egr_sz);
974 bitmap_zero(s->txq_maperr, MAX_EGRQ); 974 bitmap_zero(s->txq_maperr, s->egr_sz);
975 975
976 if (adap->flags & USING_MSIX) 976 if (adap->flags & USING_MSIX)
977 msi_idx = 1; /* vector 0 is for non-queue interrupts */ 977 msi_idx = 1; /* vector 0 is for non-queue interrupts */
@@ -983,6 +983,19 @@ static int setup_sge_queues(struct adapter *adap)
983 msi_idx = -((int)s->intrq.abs_id + 1); 983 msi_idx = -((int)s->intrq.abs_id + 1);
984 } 984 }
985 985
986 /* NOTE: If you add/delete any Ingress/Egress Queue allocations in here,
987 * don't forget to update the following which need to be
988 * synchronized to and changes here.
989 *
990 * 1. The calculations of MAX_INGQ in cxgb4.h.
991 *
992 * 2. Update enable_msix/name_msix_vecs/request_msix_queue_irqs
993 * to accommodate any new/deleted Ingress Queues
994 * which need MSI-X Vectors.
995 *
996 * 3. Update sge_qinfo_show() to include information on the
997 * new/deleted queues.
998 */
986 err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0], 999 err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0],
987 msi_idx, NULL, fwevtq_handler); 1000 msi_idx, NULL, fwevtq_handler);
988 if (err) { 1001 if (err) {
@@ -4733,8 +4746,9 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
4733 if (ret < 0) 4746 if (ret < 0)
4734 return ret; 4747 return ret;
4735 4748
4736 ret = t4_cfg_pfvf(adap, adap->fn, adap->fn, 0, MAX_EGRQ, 64, MAX_INGQ, 4749 ret = t4_cfg_pfvf(adap, adap->fn, adap->fn, 0, adap->sge.egr_sz, 64,
4737 0, 0, 4, 0xf, 0xf, 16, FW_CMD_CAP_PF, FW_CMD_CAP_PF); 4750 MAX_INGQ, 0, 0, 4, 0xf, 0xf, 16, FW_CMD_CAP_PF,
4751 FW_CMD_CAP_PF);
4738 if (ret < 0) 4752 if (ret < 0)
4739 return ret; 4753 return ret;
4740 4754
@@ -5293,6 +5307,51 @@ static int adap_init0(struct adapter *adap)
5293 adap->tids.nftids = val[4] - val[3] + 1; 5307 adap->tids.nftids = val[4] - val[3] + 1;
5294 adap->sge.ingr_start = val[5]; 5308 adap->sge.ingr_start = val[5];
5295 5309
5310 /* qids (ingress/egress) returned from firmware can be anywhere
5311 * in the range from EQ(IQFLINT)_START to EQ(IQFLINT)_END.
5312 * Hence driver needs to allocate memory for this range to
5313 * store the queue info. Get the highest IQFLINT/EQ index returned
5314 * in FW_EQ_*_CMD.alloc command.
5315 */
5316 params[0] = FW_PARAM_PFVF(EQ_END);
5317 params[1] = FW_PARAM_PFVF(IQFLINT_END);
5318 ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params, val);
5319 if (ret < 0)
5320 goto bye;
5321 adap->sge.egr_sz = val[0] - adap->sge.egr_start + 1;
5322 adap->sge.ingr_sz = val[1] - adap->sge.ingr_start + 1;
5323
5324 adap->sge.egr_map = kcalloc(adap->sge.egr_sz,
5325 sizeof(*adap->sge.egr_map), GFP_KERNEL);
5326 if (!adap->sge.egr_map) {
5327 ret = -ENOMEM;
5328 goto bye;
5329 }
5330
5331 adap->sge.ingr_map = kcalloc(adap->sge.ingr_sz,
5332 sizeof(*adap->sge.ingr_map), GFP_KERNEL);
5333 if (!adap->sge.ingr_map) {
5334 ret = -ENOMEM;
5335 goto bye;
5336 }
5337
5338 /* Allocate the memory for the vaious egress queue bitmaps
5339 * ie starving_fl and txq_maperr.
5340 */
5341 adap->sge.starving_fl = kcalloc(BITS_TO_LONGS(adap->sge.egr_sz),
5342 sizeof(long), GFP_KERNEL);
5343 if (!adap->sge.starving_fl) {
5344 ret = -ENOMEM;
5345 goto bye;
5346 }
5347
5348 adap->sge.txq_maperr = kcalloc(BITS_TO_LONGS(adap->sge.egr_sz),
5349 sizeof(long), GFP_KERNEL);
5350 if (!adap->sge.txq_maperr) {
5351 ret = -ENOMEM;
5352 goto bye;
5353 }
5354
5296 params[0] = FW_PARAM_PFVF(CLIP_START); 5355 params[0] = FW_PARAM_PFVF(CLIP_START);
5297 params[1] = FW_PARAM_PFVF(CLIP_END); 5356 params[1] = FW_PARAM_PFVF(CLIP_END);
5298 ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params, val); 5357 ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params, val);
@@ -5501,6 +5560,10 @@ static int adap_init0(struct adapter *adap)
5501 * happened to HW/FW, stop issuing commands. 5560 * happened to HW/FW, stop issuing commands.
5502 */ 5561 */
5503bye: 5562bye:
5563 kfree(adap->sge.egr_map);
5564 kfree(adap->sge.ingr_map);
5565 kfree(adap->sge.starving_fl);
5566 kfree(adap->sge.txq_maperr);
5504 if (ret != -ETIMEDOUT && ret != -EIO) 5567 if (ret != -ETIMEDOUT && ret != -EIO)
5505 t4_fw_bye(adap, adap->mbox); 5568 t4_fw_bye(adap, adap->mbox);
5506 return ret; 5569 return ret;
@@ -5912,6 +5975,10 @@ static void free_some_resources(struct adapter *adapter)
5912 5975
5913 t4_free_mem(adapter->l2t); 5976 t4_free_mem(adapter->l2t);
5914 t4_free_mem(adapter->tids.tid_tab); 5977 t4_free_mem(adapter->tids.tid_tab);
5978 kfree(adapter->sge.egr_map);
5979 kfree(adapter->sge.ingr_map);
5980 kfree(adapter->sge.starving_fl);
5981 kfree(adapter->sge.txq_maperr);
5915 disable_msi(adapter); 5982 disable_msi(adapter);
5916 5983
5917 for_each_port(adapter, i) 5984 for_each_port(adapter, i)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index b4b9f6048fe7..b688b32c21fe 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -2171,7 +2171,7 @@ static void sge_rx_timer_cb(unsigned long data)
2171 struct adapter *adap = (struct adapter *)data; 2171 struct adapter *adap = (struct adapter *)data;
2172 struct sge *s = &adap->sge; 2172 struct sge *s = &adap->sge;
2173 2173
2174 for (i = 0; i < ARRAY_SIZE(s->starving_fl); i++) 2174 for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
2175 for (m = s->starving_fl[i]; m; m &= m - 1) { 2175 for (m = s->starving_fl[i]; m; m &= m - 1) {
2176 struct sge_eth_rxq *rxq; 2176 struct sge_eth_rxq *rxq;
2177 unsigned int id = __ffs(m) + i * BITS_PER_LONG; 2177 unsigned int id = __ffs(m) + i * BITS_PER_LONG;
@@ -2259,7 +2259,7 @@ static void sge_tx_timer_cb(unsigned long data)
2259 struct adapter *adap = (struct adapter *)data; 2259 struct adapter *adap = (struct adapter *)data;
2260 struct sge *s = &adap->sge; 2260 struct sge *s = &adap->sge;
2261 2261
2262 for (i = 0; i < ARRAY_SIZE(s->txq_maperr); i++) 2262 for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
2263 for (m = s->txq_maperr[i]; m; m &= m - 1) { 2263 for (m = s->txq_maperr[i]; m; m &= m - 1) {
2264 unsigned long id = __ffs(m) + i * BITS_PER_LONG; 2264 unsigned long id = __ffs(m) + i * BITS_PER_LONG;
2265 struct sge_ofld_txq *txq = s->egr_map[id]; 2265 struct sge_ofld_txq *txq = s->egr_map[id];
@@ -2741,7 +2741,8 @@ void t4_free_sge_resources(struct adapter *adap)
2741 free_rspq_fl(adap, &adap->sge.intrq, NULL); 2741 free_rspq_fl(adap, &adap->sge.intrq, NULL);
2742 2742
2743 /* clear the reverse egress queue map */ 2743 /* clear the reverse egress queue map */
2744 memset(adap->sge.egr_map, 0, sizeof(adap->sge.egr_map)); 2744 memset(adap->sge.egr_map, 0,
2745 adap->sge.egr_sz * sizeof(*adap->sge.egr_map));
2745} 2746}
2746 2747
2747void t4_sge_start(struct adapter *adap) 2748void t4_sge_start(struct adapter *adap)