* [PATCH net-next 1/4] cxgb4vf: Add and initialize some sge params for VF driver
From: Hariprasad Shenai @ 2014-12-03 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1417615374-12961-1-git-send-email-hariprasad@chelsio.com>
Add sge_vf_eq_qpp and sge_vf_iq_qpp to (struct sge_params), initialize
sge_queues_per_page and sge_vf_qpp in t4vf_get_sge_params(), add new
t4vf_prep_adapter() which initializes basic adapter parameters.
Grab both SGE_EGRESS_QUEUES_PER_PAGE_VF and SGE_INGRESS_QUEUES_PER_PAGE_VF
for VF Drivers since we need both to calculate the User Doorbell area
offsets for Egress and Ingress Queues.
Based on original work by Casey Leedom <leedom@chelsio.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 10 ++-
.../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 27 +++++++
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | 11 ++-
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | 77 ++++++++++++++++++++
4 files changed, 120 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index ccdf8a7..1efc862 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -164,8 +164,13 @@
#define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_SHIFT)
#define SGE_EGRESS_QUEUES_PER_PAGE_PF 0x1010
-#define QUEUESPERPAGEPF0_MASK 0x0000000fU
-#define QUEUESPERPAGEPF0_GET(x) ((x) & QUEUESPERPAGEPF0_MASK)
+#define SGE_EGRESS_QUEUES_PER_PAGE_VF_A 0x1014
+
+#define QUEUESPERPAGEPF1_S 4
+
+#define QUEUESPERPAGEPF0_S 0
+#define QUEUESPERPAGEPF0_MASK 0x0000000fU
+#define QUEUESPERPAGEPF0_GET(x) ((x) & QUEUESPERPAGEPF0_MASK)
#define QUEUESPERPAGEPF0 0
#define QUEUESPERPAGEPF1 4
@@ -323,6 +328,7 @@
#define SGE_DEBUG_DATA_LOW_INDEX_3 0x12cc
#define SGE_DEBUG_DATA_HIGH_INDEX_10 0x12a8
#define SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4
+#define SGE_INGRESS_QUEUES_PER_PAGE_VF_A 0x10f8
#define S_HP_INT_THRESH 28
#define M_HP_INT_THRESH 0xfU
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index ad88246..c5425f0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2594,6 +2594,27 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
goto err_free_adapter;
}
+ /* Wait for the device to become ready before proceeding ...
+ */
+ err = t4vf_prep_adapter(adapter);
+ if (err) {
+ dev_err(adapter->pdev_dev, "device didn't become ready:"
+ " err=%d\n", err);
+ goto err_unmap_bar0;
+ }
+
+ /* For T5 and later we want to use the new BAR-based User Doorbells,
+ * so we need to map BAR2 here ...
+ */
+ if (!is_t4(adapter->params.chip)) {
+ adapter->bar2 = ioremap_wc(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ if (!adapter->bar2) {
+ dev_err(adapter->pdev_dev, "cannot map BAR2 doorbells\n");
+ err = -ENOMEM;
+ goto err_unmap_bar0;
+ }
+ }
/*
* Initialize adapter level features.
*/
@@ -2786,6 +2807,10 @@ err_free_dev:
}
err_unmap_bar:
+ if (!is_t4(adapter->params.chip))
+ iounmap(adapter->bar2);
+
+err_unmap_bar0:
iounmap(adapter->regs);
err_free_adapter:
@@ -2856,6 +2881,8 @@ static void cxgb4vf_pci_remove(struct pci_dev *pdev)
free_netdev(netdev);
}
iounmap(adapter->regs);
+ if (!is_t4(adapter->params.chip))
+ iounmap(adapter->bar2);
kfree(adapter);
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
index a608c66..6d6a956 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
@@ -135,9 +135,11 @@ struct dev_params {
struct sge_params {
u32 sge_control; /* padding, boundaries, lengths, etc. */
u32 sge_control2; /* T5: more of the same */
- u32 sge_host_page_size; /* RDMA page sizes */
- u32 sge_queues_per_page; /* RDMA queues/page */
- u32 sge_user_mode_limits; /* limits for BAR2 user mode accesses */
+ u32 sge_host_page_size; /* PF0-7 page sizes */
+ u32 sge_egress_queues_per_page; /* PF0-7 egress queues/page */
+ u32 sge_ingress_queues_per_page;/* PF0-7 ingress queues/page */
+ u32 sge_vf_eq_qpp; /* egress queues/page for our VF */
+ u32 sge_vf_iq_qpp; /* ingress queues/page for our VF */
u32 sge_fl_buffer_size[16]; /* free list buffer sizes */
u32 sge_ingress_rx_threshold; /* RX counter interrupt threshold[4] */
u32 sge_congestion_control; /* congestion thresholds, etc. */
@@ -267,6 +269,8 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false);
}
+#define CHELSIO_PCI_ID_VER(dev_id) ((dev_id) >> 12)
+
static inline int is_t4(enum chip_type chip)
{
return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
@@ -309,5 +313,6 @@ int t4vf_iq_free(struct adapter *, unsigned int, unsigned int, unsigned int,
int t4vf_eth_eq_free(struct adapter *, unsigned int);
int t4vf_handle_fw_rpl(struct adapter *, const __be64 *);
+int t4vf_prep_adapter(struct adapter *);
#endif /* __T4VF_COMMON_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index 624a213..03ab19e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -501,6 +501,48 @@ int t4vf_get_sge_params(struct adapter *adapter)
sge_params->sge_ingress_rx_threshold = vals[0];
sge_params->sge_congestion_control = vals[1];
+ /* For T5 and later we want to use the new BAR2 Doorbells.
+ * Unfortunately, older firmware didn't allow the this register to be
+ * read.
+ */
+ if (!is_t4(adapter->params.chip)) {
+ u32 whoami;
+ unsigned int pf, s_qpp;
+
+ params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) |
+ FW_PARAMS_PARAM_XYZ_V(
+ SGE_EGRESS_QUEUES_PER_PAGE_VF_A));
+ params[1] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) |
+ FW_PARAMS_PARAM_XYZ_V(
+ SGE_INGRESS_QUEUES_PER_PAGE_VF_A));
+ v = t4vf_query_params(adapter, 2, params, vals);
+ if (v != FW_SUCCESS) {
+ dev_warn(adapter->pdev_dev,
+ "Unable to get VF SGE Queues/Page; "
+ "probably old firmware.\n");
+ return v;
+ }
+ sge_params->sge_egress_queues_per_page = vals[0];
+ sge_params->sge_ingress_queues_per_page = vals[1];
+
+ /* We need the Queues/Page for our VF. This is based on the
+ * PF from which we're instantiated and is indexed in the
+ * register we just read. Do it once here so other code in
+ * the driver can just use it.
+ */
+ whoami = t4_read_reg(adapter,
+ T4VF_PL_BASE_ADDR + A_PL_VF_WHOAMI);
+ pf = SOURCEPF_GET(whoami);
+ s_qpp = (QUEUESPERPAGEPF0_S +
+ (QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * pf);
+ sge_params->sge_vf_eq_qpp =
+ ((sge_params->sge_egress_queues_per_page >> s_qpp)
+ & QUEUESPERPAGEPF0_MASK);
+ sge_params->sge_vf_iq_qpp =
+ ((sge_params->sge_ingress_queues_per_page >> s_qpp)
+ & QUEUESPERPAGEPF0_MASK);
+ }
+
return 0;
}
@@ -1420,3 +1462,38 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl)
}
return 0;
}
+
+/**
+ */
+int t4vf_prep_adapter(struct adapter *adapter)
+{
+ int err;
+ unsigned int chipid;
+
+ /* Wait for the device to become ready before proceeding ...
+ */
+ err = t4vf_wait_dev_ready(adapter);
+ if (err)
+ return err;
+
+ /* Default port and clock for debugging in case we can't reach
+ * firmware.
+ */
+ adapter->params.nports = 1;
+ adapter->params.vfres.pmask = 1;
+ adapter->params.vpd.cclk = 50000;
+
+ adapter->params.chip = 0;
+ switch (CHELSIO_PCI_ID_VER(adapter->pdev->device)) {
+ case CHELSIO_T4:
+ adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
+ break;
+
+ case CHELSIO_T5:
+ chipid = G_REV(t4_read_reg(adapter, A_PL_VF_REV));
+ adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, chipid);
+ break;
+ }
+
+ return 0;
+}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 2/4] cxgb4/cxgb4vf: Add code to calculate T5 BAR2 Offsets for SGE Queue Registers
From: Hariprasad Shenai @ 2014-12-03 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1417615374-12961-1-git-send-email-hariprasad@chelsio.com>
Add new Common Code facilities for calculating T5 BAR2 Offsets for SGE Queue
Registers. This new code can handle situations where
Queues Per Page * SGE BAR2 Queue Register Area Size > Page Size
Based on original work by Casey Leedom <leedom@chelsio.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 16 +++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 120 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 12 +-
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | 8 ++
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | 98 ++++++++++++++++-
5 files changed, 247 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index e8b09bb..40905c6 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -222,6 +222,12 @@ struct tp_err_stats {
u32 ofldCongDefer;
};
+struct sge_params {
+ u32 hps; /* host page size for our PF/VF */
+ u32 eq_qpp; /* egress queues/page for our PF/VF */
+ u32 iq_qpp; /* egress queues/page for our PF/VF */
+};
+
struct tp_params {
unsigned int ntxchan; /* # of Tx channels */
unsigned int tre; /* log2 of core clocks per TP tick */
@@ -285,6 +291,7 @@ enum chip_type {
};
struct adapter_params {
+ struct sge_params sge;
struct tp_params tp;
struct vpd_params vpd;
struct pci_params pci;
@@ -995,6 +1002,15 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
const u8 *fw_data, unsigned int fw_size,
struct fw_hdr *card_fw, enum dev_state state, int *reset);
int t4_prep_adapter(struct adapter *adapter);
+
+enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
+int t4_bar2_sge_qregs(struct adapter *adapter,
+ unsigned int qid,
+ enum t4_bar2_qtype qtype,
+ u64 *pbar2_qoffset,
+ unsigned int *pbar2_qid);
+
+int t4_init_sge_params(struct adapter *adapter);
int t4_init_tp_params(struct adapter *adap);
int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 7975d26..3f8876f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -4003,6 +4003,126 @@ int t4_prep_adapter(struct adapter *adapter)
}
/**
+ * t4_bar2_sge_qregs - return BAR2 SGE Queue register information
+ * @adapter: the adapter
+ * @qid: the Queue ID
+ * @qtype: the Ingress or Egress type for @qid
+ * @pbar2_qoffset: BAR2 Queue Offset
+ * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
+ *
+ * Returns the BAR2 SGE Queue Registers information associated with the
+ * indicated Absolute Queue ID. These are passed back in return value
+ * pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
+ * and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
+ *
+ * This may return an error which indicates that BAR2 SGE Queue
+ * registers aren't available. If an error is not returned, then the
+ * following values are returned:
+ *
+ * *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
+ * *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
+ *
+ * If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
+ * require the "Inferred Queue ID" ability may be used. E.g. the
+ * Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
+ * then these "Inferred Queue ID" register may not be used.
+ */
+int t4_bar2_sge_qregs(struct adapter *adapter,
+ unsigned int qid,
+ enum t4_bar2_qtype qtype,
+ u64 *pbar2_qoffset,
+ unsigned int *pbar2_qid)
+{
+ unsigned int page_shift, page_size, qpp_shift, qpp_mask;
+ u64 bar2_page_offset, bar2_qoffset;
+ unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
+
+ /* T4 doesn't support BAR2 SGE Queue registers.
+ */
+ if (is_t4(adapter->params.chip))
+ return -EINVAL;
+
+ /* Get our SGE Page Size parameters.
+ */
+ page_shift = adapter->params.sge.hps + 10;
+ page_size = 1 << page_shift;
+
+ /* Get the right Queues per Page parameters for our Queue.
+ */
+ qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
+ ? adapter->params.sge.eq_qpp
+ : adapter->params.sge.iq_qpp);
+ qpp_mask = (1 << qpp_shift) - 1;
+
+ /* Calculate the basics of the BAR2 SGE Queue register area:
+ * o The BAR2 page the Queue registers will be in.
+ * o The BAR2 Queue ID.
+ * o The BAR2 Queue ID Offset into the BAR2 page.
+ */
+ bar2_page_offset = ((qid >> qpp_shift) << page_shift);
+ bar2_qid = qid & qpp_mask;
+ bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
+
+ /* If the BAR2 Queue ID Offset is less than the Page Size, then the
+ * hardware will infer the Absolute Queue ID simply from the writes to
+ * the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
+ * BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply
+ * write to the first BAR2 SGE Queue Area within the BAR2 Page with
+ * the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
+ * from the BAR2 Page and BAR2 Queue ID.
+ *
+ * One important censequence of this is that some BAR2 SGE registers
+ * have a "Queue ID" field and we can write the BAR2 SGE Queue ID
+ * there. But other registers synthesize the SGE Queue ID purely
+ * from the writes to the registers -- the Write Combined Doorbell
+ * Buffer is a good example. These BAR2 SGE Registers are only
+ * available for those BAR2 SGE Register areas where the SGE Absolute
+ * Queue ID can be inferred from simple writes.
+ */
+ bar2_qoffset = bar2_page_offset;
+ bar2_qinferred = (bar2_qid_offset < page_size);
+ if (bar2_qinferred) {
+ bar2_qoffset += bar2_qid_offset;
+ bar2_qid = 0;
+ }
+
+ *pbar2_qoffset = bar2_qoffset;
+ *pbar2_qid = bar2_qid;
+ return 0;
+}
+
+/**
+ * t4_init_sge_params - initialize adap->params.sge
+ * @adapter: the adapter
+ *
+ * Initialize various fields of the adapter's SGE Parameters structure.
+ */
+int t4_init_sge_params(struct adapter *adapter)
+{
+ struct sge_params *sge_params = &adapter->params.sge;
+ u32 hps, qpp;
+ unsigned int s_hps, s_qpp;
+
+ /* Extract the SGE Page Size for our PF.
+ */
+ hps = t4_read_reg(adapter, SGE_HOST_PAGE_SIZE);
+ s_hps = (HOSTPAGESIZEPF0_S +
+ (HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * adapter->fn);
+ sge_params->hps = ((hps >> s_hps) & HOSTPAGESIZEPF0_M);
+
+ /* Extract the SGE Egress and Ingess Queues Per Page for our PF.
+ */
+ s_qpp = (QUEUESPERPAGEPF0_S +
+ (QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * adapter->fn);
+ qpp = t4_read_reg(adapter, SGE_EGRESS_QUEUES_PER_PAGE_PF);
+ sge_params->eq_qpp = ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
+ qpp = t4_read_reg(adapter, SGE_INGRESS_QUEUES_PER_PAGE_PF);
+ sge_params->iq_qpp = ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
+
+ return 0;
+}
+
+/**
* t4_init_tp_params - initialize adap->params.tp
* @adap: the adapter
*
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 1efc862..d7bd34e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -155,13 +155,13 @@
#define HOSTPAGESIZEPF2_SHIFT 8
#define HOSTPAGESIZEPF2(x) ((x) << HOSTPAGESIZEPF2_SHIFT)
-#define HOSTPAGESIZEPF1_MASK 0x0000000fU
-#define HOSTPAGESIZEPF1_SHIFT 4
-#define HOSTPAGESIZEPF1(x) ((x) << HOSTPAGESIZEPF1_SHIFT)
+#define HOSTPAGESIZEPF1_M 0x0000000fU
+#define HOSTPAGESIZEPF1_S 4
+#define HOSTPAGESIZEPF1(x) ((x) << HOSTPAGESIZEPF1_S)
-#define HOSTPAGESIZEPF0_MASK 0x0000000fU
-#define HOSTPAGESIZEPF0_SHIFT 0
-#define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_SHIFT)
+#define HOSTPAGESIZEPF0_M 0x0000000fU
+#define HOSTPAGESIZEPF0_S 0
+#define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_S)
#define SGE_EGRESS_QUEUES_PER_PAGE_PF 0x1010
#define SGE_EGRESS_QUEUES_PER_PAGE_VF_A 0x1014
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
index 6d6a956..8d3237f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
@@ -138,6 +138,7 @@ struct sge_params {
u32 sge_host_page_size; /* PF0-7 page sizes */
u32 sge_egress_queues_per_page; /* PF0-7 egress queues/page */
u32 sge_ingress_queues_per_page;/* PF0-7 ingress queues/page */
+ u32 sge_vf_hps; /* host page size for our vf */
u32 sge_vf_eq_qpp; /* egress queues/page for our VF */
u32 sge_vf_iq_qpp; /* ingress queues/page for our VF */
u32 sge_fl_buffer_size[16]; /* free list buffer sizes */
@@ -282,6 +283,13 @@ int t4vf_port_init(struct adapter *, int);
int t4vf_fw_reset(struct adapter *);
int t4vf_set_params(struct adapter *, unsigned int, const u32 *, const u32 *);
+enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
+int t4_bar2_sge_qregs(struct adapter *adapter,
+ unsigned int qid,
+ enum t4_bar2_qtype qtype,
+ u64 *pbar2_qoffset,
+ unsigned int *pbar2_qid);
+
int t4vf_get_sge_params(struct adapter *);
int t4vf_get_vpd_params(struct adapter *);
int t4vf_get_dev_params(struct adapter *);
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
index 03ab19e..02e8833 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -430,6 +430,95 @@ int t4vf_set_params(struct adapter *adapter, unsigned int nparams,
}
/**
+ * t4_bar2_sge_qregs - return BAR2 SGE Queue register information
+ * @adapter: the adapter
+ * @qid: the Queue ID
+ * @qtype: the Ingress or Egress type for @qid
+ * @pbar2_qoffset: BAR2 Queue Offset
+ * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
+ *
+ * Returns the BAR2 SGE Queue Registers information associated with the
+ * indicated Absolute Queue ID. These are passed back in return value
+ * pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
+ * and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
+ *
+ * This may return an error which indicates that BAR2 SGE Queue
+ * registers aren't available. If an error is not returned, then the
+ * following values are returned:
+ *
+ * *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
+ * *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
+ *
+ * If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
+ * require the "Inferred Queue ID" ability may be used. E.g. the
+ * Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
+ * then these "Inferred Queue ID" register may not be used.
+ */
+int t4_bar2_sge_qregs(struct adapter *adapter,
+ unsigned int qid,
+ enum t4_bar2_qtype qtype,
+ u64 *pbar2_qoffset,
+ unsigned int *pbar2_qid)
+{
+ unsigned int page_shift, page_size, qpp_shift, qpp_mask;
+ u64 bar2_page_offset, bar2_qoffset;
+ unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
+
+ /* T4 doesn't support BAR2 SGE Queue registers.
+ */
+ if (is_t4(adapter->params.chip))
+ return -EINVAL;
+
+ /* Get our SGE Page Size parameters.
+ */
+ page_shift = adapter->params.sge.sge_vf_hps + 10;
+ page_size = 1 << page_shift;
+
+ /* Get the right Queues per Page parameters for our Queue.
+ */
+ qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
+ ? adapter->params.sge.sge_vf_eq_qpp
+ : adapter->params.sge.sge_vf_iq_qpp);
+ qpp_mask = (1 << qpp_shift) - 1;
+
+ /* Calculate the basics of the BAR2 SGE Queue register area:
+ * o The BAR2 page the Queue registers will be in.
+ * o The BAR2 Queue ID.
+ * o The BAR2 Queue ID Offset into the BAR2 page.
+ */
+ bar2_page_offset = ((qid >> qpp_shift) << page_shift);
+ bar2_qid = qid & qpp_mask;
+ bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
+
+ /* If the BAR2 Queue ID Offset is less than the Page Size, then the
+ * hardware will infer the Absolute Queue ID simply from the writes to
+ * the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
+ * BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply
+ * write to the first BAR2 SGE Queue Area within the BAR2 Page with
+ * the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
+ * from the BAR2 Page and BAR2 Queue ID.
+ *
+ * One important censequence of this is that some BAR2 SGE registers
+ * have a "Queue ID" field and we can write the BAR2 SGE Queue ID
+ * there. But other registers synthesize the SGE Queue ID purely
+ * from the writes to the registers -- the Write Combined Doorbell
+ * Buffer is a good example. These BAR2 SGE Registers are only
+ * available for those BAR2 SGE Register areas where the SGE Absolute
+ * Queue ID can be inferred from simple writes.
+ */
+ bar2_qoffset = bar2_page_offset;
+ bar2_qinferred = (bar2_qid_offset < page_size);
+ if (bar2_qinferred) {
+ bar2_qoffset += bar2_qid_offset;
+ bar2_qid = 0;
+ }
+
+ *pbar2_qoffset = bar2_qoffset;
+ *pbar2_qid = bar2_qid;
+ return 0;
+}
+
+/**
* t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
* @adapter: the adapter
*
@@ -507,7 +596,7 @@ int t4vf_get_sge_params(struct adapter *adapter)
*/
if (!is_t4(adapter->params.chip)) {
u32 whoami;
- unsigned int pf, s_qpp;
+ unsigned int pf, s_hps, s_qpp;
params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) |
FW_PARAMS_PARAM_XYZ_V(
@@ -533,6 +622,13 @@ int t4vf_get_sge_params(struct adapter *adapter)
whoami = t4_read_reg(adapter,
T4VF_PL_BASE_ADDR + A_PL_VF_WHOAMI);
pf = SOURCEPF_GET(whoami);
+
+ s_hps = (HOSTPAGESIZEPF0_S +
+ (HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * pf);
+ sge_params->sge_vf_hps =
+ ((sge_params->sge_host_page_size >> s_hps)
+ & HOSTPAGESIZEPF0_M);
+
s_qpp = (QUEUESPERPAGEPF0_S +
(QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * pf);
sge_params->sge_vf_eq_qpp =
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 3/4] cxgb4/cxgb4vf: Use new interfaces to calculate BAR2 SGE Queue Register addresses
From: Hariprasad Shenai @ 2014-12-03 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1417615374-12961-1-git-send-email-hariprasad@chelsio.com>
Use BAR2 Going To Sleep (GTS) for T5 and later. Use new BAR2 User Doorbells for
T5 for both cxgb4 and cxgb4vf driver.
Based on original work by Casey Leedom <leedom@chelsio.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 9 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 60 +++---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 7 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 148 ++++++++--------
drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | 7 +
.../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 12 --
drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 185 +++++++++++++++++---
7 files changed, 288 insertions(+), 140 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 40905c6..c38a936 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -438,7 +438,8 @@ struct sge_fl { /* SGE free-buffer queue state */
struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
__be64 *desc; /* address of HW Rx descriptor ring */
dma_addr_t addr; /* bus address of HW ring start */
- u64 udb; /* BAR2 offset of User Doorbell area */
+ void __iomem *bar2_addr; /* address of BAR2 Queue registers */
+ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */
};
/* A packet gather list */
@@ -468,7 +469,8 @@ struct sge_rspq { /* state for an SGE response queue */
u16 abs_id; /* absolute SGE id for the response q */
__be64 *desc; /* address of HW response ring */
dma_addr_t phys_addr; /* physical address of the ring */
- u64 udb; /* BAR2 offset of User Doorbell area */
+ void __iomem *bar2_addr; /* address of BAR2 Queue registers */
+ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */
unsigned int iqe_len; /* entry size */
unsigned int size; /* capacity of response queue */
struct adapter *adap;
@@ -526,7 +528,8 @@ struct sge_txq {
int db_disabled;
unsigned short db_pidx;
unsigned short db_pidx_inc;
- u64 udb; /* BAR2 offset of User Doorbell area */
+ void __iomem *bar2_addr; /* address of BAR2 Queue registers */
+ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */
};
struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 3aea82b..c770cbf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3791,6 +3791,22 @@ u64 cxgb4_read_sge_timestamp(struct net_device *dev)
}
EXPORT_SYMBOL(cxgb4_read_sge_timestamp);
+int cxgb4_bar2_sge_qregs(struct net_device *dev,
+ unsigned int qid,
+ enum cxgb4_bar2_qtype qtype,
+ u64 *pbar2_qoffset,
+ unsigned int *pbar2_qid)
+{
+ return t4_bar2_sge_qregs(netdev2adap(dev),
+ qid,
+ (qtype == CXGB4_BAR2_QTYPE_EGRESS
+ ? T4_BAR2_QTYPE_EGRESS
+ : T4_BAR2_QTYPE_INGRESS),
+ pbar2_qoffset,
+ pbar2_qid);
+}
+EXPORT_SYMBOL(cxgb4_bar2_sge_qregs);
+
static struct pci_driver cxgb4_driver;
static void check_neigh_update(struct neighbour *neigh)
@@ -3973,31 +3989,18 @@ static void process_db_drop(struct work_struct *work)
u32 dropped_db = t4_read_reg(adap, 0x010ac);
u16 qid = (dropped_db >> 15) & 0x1ffff;
u16 pidx_inc = dropped_db & 0x1fff;
- unsigned int s_qpp;
- unsigned short udb_density;
- unsigned long qpshift;
- int page;
- u32 udb;
-
- dev_warn(adap->pdev_dev,
- "Dropped DB 0x%x qid %d bar2 %d coalesce %d pidx %d\n",
- dropped_db, qid,
- (dropped_db >> 14) & 1,
- (dropped_db >> 13) & 1,
- pidx_inc);
-
- drain_db_fifo(adap, 1);
+ u64 bar2_qoffset;
+ unsigned int bar2_qid;
+ int ret;
- s_qpp = QUEUESPERPAGEPF1 * adap->fn;
- udb_density = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adap,
- SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
- qpshift = PAGE_SHIFT - ilog2(udb_density);
- udb = qid << qpshift;
- udb &= PAGE_MASK;
- page = udb / PAGE_SIZE;
- udb += (qid - (page * udb_density)) * 128;
-
- writel(PIDX(pidx_inc), adap->bar2 + udb + 8);
+ ret = t4_bar2_sge_qregs(adap, qid, T4_BAR2_QTYPE_EGRESS,
+ &bar2_qoffset, &bar2_qid);
+ if (ret)
+ dev_err(adap->pdev_dev, "doorbell drop recovery: "
+ "qid=%d, pidx_inc=%d\n", qid, pidx_inc);
+ else
+ writel(PIDX_T5(pidx_inc) | QID(bar2_qid),
+ adap->bar2 + bar2_qoffset + SGE_UDB_KDOORBELL);
/* Re-enable BAR2 WC */
t4_set_reg_field(adap, 0x10b0, 1<<15, 1<<15);
@@ -4055,12 +4058,8 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.adapter_type = adap->params.chip;
lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
lli.cclk_ps = 1000000000 / adap->params.vpd.cclk;
- lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
- t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
- (adap->fn * 4));
- lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
- t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
- (adap->fn * 4));
+ lli.udb_density = 1 << adap->params.sge.eq_qpp;
+ lli.ucq_density = 1 << adap->params.sge.iq_qpp;
lli.filt_mode = adap->params.tp.vlan_pri_map;
/* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
for (i = 0; i < NCHAN; i++)
@@ -5912,6 +5911,7 @@ static int adap_init0(struct adapter *adap)
t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
adap->params.b_wnd);
}
+ t4_init_sge_params(adap);
t4_init_tp_params(adap);
adap->flags |= FW_OK;
return 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 4eba7cb..152b4c4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -305,4 +305,11 @@ void cxgb4_enable_db_coalescing(struct net_device *dev);
int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte);
u64 cxgb4_read_sge_timestamp(struct net_device *dev);
+enum cxgb4_bar2_qtype { CXGB4_BAR2_QTYPE_EGRESS, CXGB4_BAR2_QTYPE_INGRESS };
+int cxgb4_bar2_sge_qregs(struct net_device *dev,
+ unsigned int qid,
+ enum cxgb4_bar2_qtype qtype,
+ u64 *pbar2_qoffset,
+ unsigned int *pbar2_qid);
+
#endif /* !__CXGB4_OFLD_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 433560b..f12debd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -527,14 +527,16 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
val |= DBPRIO(1);
wmb();
- /* If we're on T4, use the old doorbell mechanism; otherwise
- * use the new BAR2 mechanism.
+ /* If we don't have access to the new User Doorbell (T5+), use
+ * the old doorbell mechanism; otherwise use the new BAR2
+ * mechanism.
*/
- if (is_t4(adap->params.chip)) {
+ if (unlikely(q->bar2_addr == NULL)) {
t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
val | QID(q->cntxt_id));
} else {
- writel(val, adap->bar2 + q->udb + SGE_UDB_KDOORBELL);
+ writel(val | QID(q->bar2_qid),
+ q->bar2_addr + SGE_UDB_KDOORBELL);
/* This Write memory Barrier will force the write to
* the User Doorbell area to be flushed.
@@ -850,14 +852,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
*end = 0;
}
-/* This function copies a tx_desc struct to memory mapped BAR2 space(user space
- * writes). For coalesced WR SGE, fetches data from the FIFO instead of from
- * Host.
+/* This function copies 64 byte coalesced work request to
+ * memory mapped BAR2 space. For coalesced WR SGE fetches
+ * data from the FIFO instead of from Host.
*/
-static void cxgb_pio_copy(u64 __iomem *dst, struct tx_desc *desc)
+static void cxgb_pio_copy(u64 __iomem *dst, u64 *src)
{
- int count = sizeof(*desc) / sizeof(u64);
- u64 *src = (u64 *)desc;
+ int count = 8;
while (count) {
writeq(*src, dst);
@@ -879,7 +880,10 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
{
wmb(); /* write descriptors before telling HW */
- if (is_t4(adap->params.chip)) {
+ /* If we don't have access to the new User Doorbell (T5+), use the old
+ * doorbell mechanism; otherwise use the new BAR2 mechanism.
+ */
+ if (unlikely(q->bar2_addr == NULL)) {
u32 val = PIDX(n);
unsigned long flags;
@@ -905,21 +909,22 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
*/
WARN_ON(val & DBPRIO(1));
- /* For T5 and later we use the Write-Combine mapped BAR2 User
- * Doorbell mechanism. If we're only writing a single TX
- * Descriptor and TX Write Combining hasn't been disabled, we
- * can use the Write Combining Gather Buffer; otherwise we use
- * the simple doorbell.
+ /* If we're only writing a single TX Descriptor and we can use
+ * Inferred QID registers, we can use the Write Combining
+ * Gather Buffer; otherwise we use the simple doorbell.
*/
- if (n == 1) {
+ if (n == 1 && q->bar2_qid == 0) {
int index = (q->pidx
? (q->pidx - 1)
: (q->size - 1));
+ u64 *wr = (u64 *)&q->desc[index];
- cxgb_pio_copy(adap->bar2 + q->udb + SGE_UDB_WCDOORBELL,
- q->desc + index);
+ cxgb_pio_copy((u64 __iomem *)
+ (q->bar2_addr + SGE_UDB_WCDOORBELL),
+ wr);
} else {
- writel(val, adap->bar2 + q->udb + SGE_UDB_KDOORBELL);
+ writel(val | QID(q->bar2_qid),
+ q->bar2_addr + SGE_UDB_KDOORBELL);
}
/* This Write Memory Barrier will force the write to the User
@@ -1997,11 +2002,16 @@ static int napi_rx_handler(struct napi_struct *napi, int budget)
params = QINTR_TIMER_IDX(7);
val = CIDXINC(work_done) | SEINTARM(params);
- if (is_t4(q->adap->params.chip)) {
+
+ /* If we don't have access to the new User GTS (T5+), use the old
+ * doorbell mechanism; otherwise use the new BAR2 mechanism.
+ */
+ if (unlikely(q->bar2_addr == NULL)) {
t4_write_reg(q->adap, MYPF_REG(SGE_PF_GTS),
val | INGRESSQID((u32)q->cntxt_id));
} else {
- writel(val, q->adap->bar2 + q->udb + SGE_UDB_GTS);
+ writel(val | INGRESSQID(q->bar2_qid),
+ q->bar2_addr + SGE_UDB_GTS);
wmb();
}
return work_done;
@@ -2047,11 +2057,16 @@ static unsigned int process_intrq(struct adapter *adap)
}
val = CIDXINC(credits) | SEINTARM(q->intr_params);
- if (is_t4(adap->params.chip)) {
+
+ /* If we don't have access to the new User GTS (T5+), use the old
+ * doorbell mechanism; otherwise use the new BAR2 mechanism.
+ */
+ if (unlikely(q->bar2_addr == NULL)) {
t4_write_reg(adap, MYPF_REG(SGE_PF_GTS),
val | INGRESSQID(q->cntxt_id));
} else {
- writel(val, adap->bar2 + q->udb + SGE_UDB_GTS);
+ writel(val | INGRESSQID(q->bar2_qid),
+ q->bar2_addr + SGE_UDB_GTS);
wmb();
}
spin_unlock(&adap->sge.intrq_lock);
@@ -2235,48 +2250,32 @@ static void sge_tx_timer_cb(unsigned long data)
}
/**
- * udb_address - return the BAR2 User Doorbell address for a Queue
- * @adap: the adapter
- * @cntxt_id: the Queue Context ID
- * @qpp: Queues Per Page (for all PFs)
+ * bar2_address - return the BAR2 address for an SGE Queue's Registers
+ * @adapter: the adapter
+ * @qid: the SGE Queue ID
+ * @qtype: the SGE Queue Type (Egress or Ingress)
+ * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
*
- * Returns the BAR2 address of the user Doorbell associated with the
- * indicated Queue Context ID. Note that this is only applicable
- * for T5 and later.
- */
-static u64 udb_address(struct adapter *adap, unsigned int cntxt_id,
- unsigned int qpp)
-{
- u64 udb;
- unsigned int s_qpp;
- unsigned short udb_density;
- unsigned long qpshift;
- int page;
-
- BUG_ON(is_t4(adap->params.chip));
-
- s_qpp = (QUEUESPERPAGEPF0 +
- (QUEUESPERPAGEPF1 - QUEUESPERPAGEPF0) * adap->fn);
- udb_density = 1 << ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
- qpshift = PAGE_SHIFT - ilog2(udb_density);
- udb = (u64)cntxt_id << qpshift;
- udb &= PAGE_MASK;
- page = udb / PAGE_SIZE;
- udb += (cntxt_id - (page * udb_density)) * SGE_UDB_SIZE;
-
- return udb;
-}
+ * Returns the BAR2 address for the SGE Queue Registers associated with
+ * @qid. If BAR2 SGE Registers aren't available, returns NULL. Also
+ * returns the BAR2 Queue ID to be used with writes to the BAR2 SGE
+ * Queue Registers. If the BAR2 Queue ID is 0, then "Inferred Queue ID"
+ * Registers are supported (e.g. the Write Combining Doorbell Buffer).
+ */
+static void __iomem *bar2_address(struct adapter *adapter,
+ unsigned int qid,
+ enum t4_bar2_qtype qtype,
+ unsigned int *pbar2_qid)
+{
+ u64 bar2_qoffset;
+ int ret;
-static u64 udb_address_eq(struct adapter *adap, unsigned int cntxt_id)
-{
- return udb_address(adap, cntxt_id,
- t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF));
-}
+ ret = t4_bar2_sge_qregs(adapter, qid, qtype,
+ &bar2_qoffset, pbar2_qid);
+ if (ret)
+ return NULL;
-static u64 udb_address_iq(struct adapter *adap, unsigned int cntxt_id)
-{
- return udb_address(adap, cntxt_id,
- t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF));
+ return adapter->bar2 + bar2_qoffset;
}
int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
@@ -2344,8 +2343,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
iq->next_intr_params = iq->intr_params;
iq->cntxt_id = ntohs(c.iqid);
iq->abs_id = ntohs(c.physiqid);
- if (!is_t4(adap->params.chip))
- iq->udb = udb_address_iq(adap, iq->cntxt_id);
+ iq->bar2_addr = bar2_address(adap,
+ iq->cntxt_id,
+ T4_BAR2_QTYPE_INGRESS,
+ &iq->bar2_qid);
iq->size--; /* subtract status entry */
iq->netdev = dev;
iq->handler = hnd;
@@ -2362,11 +2363,13 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
fl->alloc_failed = fl->large_alloc_failed = fl->starving = 0;
adap->sge.egr_map[fl->cntxt_id - adap->sge.egr_start] = fl;
- /* Note, we must initialize the Free List User Doorbell
- * address before refilling the Free List!
+ /* Note, we must initialize the BAR2 Free List User Doorbell
+ * information before refilling the Free List!
*/
- if (!is_t4(adap->params.chip))
- fl->udb = udb_address_eq(adap, fl->cntxt_id);
+ fl->bar2_addr = bar2_address(adap,
+ fl->cntxt_id,
+ T4_BAR2_QTYPE_EGRESS,
+ &fl->bar2_qid);
refill_fl(adap, fl, fl_cap(fl), GFP_KERNEL);
}
return 0;
@@ -2392,9 +2395,10 @@ err:
static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
{
q->cntxt_id = id;
- if (!is_t4(adap->params.chip))
- q->udb = udb_address_eq(adap, q->cntxt_id);
-
+ q->bar2_addr = bar2_address(adap,
+ q->cntxt_id,
+ T4_BAR2_QTYPE_EGRESS,
+ &q->bar2_qid);
q->in_use = 0;
q->cidx = q->pidx = 0;
q->stops = q->restarts = 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
index 3d06e77..d00a751 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
@@ -138,6 +138,8 @@ struct sge_fl {
struct rx_sw_desc *sdesc; /* address of SW RX descriptor ring */
__be64 *desc; /* address of HW RX descriptor ring */
dma_addr_t addr; /* PCI bus address of hardware ring */
+ void __iomem *bar2_addr; /* address of BAR2 Queue registers */
+ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */
};
/*
@@ -178,6 +180,8 @@ struct sge_rspq {
u16 abs_id; /* SGE abs QID for the response Q */
__be64 *desc; /* address of hardware response ring */
dma_addr_t phys_addr; /* PCI bus address of ring */
+ void __iomem *bar2_addr; /* address of BAR2 Queue registers */
+ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */
unsigned int iqe_len; /* entry size */
unsigned int size; /* capcity of response Q */
struct adapter *adapter; /* our adapter */
@@ -240,6 +244,8 @@ struct sge_txq {
struct tx_sw_desc *sdesc; /* address of SW TX descriptor ring */
struct sge_qstat *stat; /* queue status entry */
dma_addr_t phys_addr; /* PCI bus address of hardware ring */
+ void __iomem *bar2_addr; /* address of BAR2 Queue registers */
+ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */
};
/*
@@ -345,6 +351,7 @@ struct sge {
struct adapter {
/* PCI resources */
void __iomem *regs;
+ void __iomem *bar2;
struct pci_dev *pdev;
struct device *pdev_dev;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index c5425f0..aa74ec3 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2095,7 +2095,6 @@ static int adap_init0(struct adapter *adapter)
unsigned int ethqsets;
int err;
u32 param, val = 0;
- unsigned int chipid;
/*
* Wait for the device to become ready before proceeding ...
@@ -2123,17 +2122,6 @@ static int adap_init0(struct adapter *adapter)
return err;
}
- adapter->params.chip = 0;
- switch (adapter->pdev->device >> 12) {
- case CHELSIO_T4:
- adapter->params.chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
- break;
- case CHELSIO_T5:
- chipid = G_REV(t4_read_reg(adapter, A_PL_VF_REV));
- adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, chipid);
- break;
- }
-
/*
* Grab basic operational parameters. These will predominantly have
* been set up by the Physical Function Driver or will be hard coded
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index 045301d..f7fd131 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -525,19 +525,40 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
{
u32 val;
- /*
- * The SGE keeps track of its Producer and Consumer Indices in terms
+ /* The SGE keeps track of its Producer and Consumer Indices in terms
* of Egress Queue Units so we can only tell it about integral numbers
* of multiples of Free List Entries per Egress Queue Units ...
*/
if (fl->pend_cred >= FL_PER_EQ_UNIT) {
- val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT);
- if (!is_t4(adapter->params.chip))
- val |= DBTYPE(1);
+ if (is_t4(adapter->params.chip))
+ val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT);
+ else
+ val = PIDX_T5(fl->pend_cred / FL_PER_EQ_UNIT) |
+ DBTYPE(1);
+ val |= DBPRIO(1);
+
+ /* Make sure all memory writes to the Free List queue are
+ * committed before we tell the hardware about them.
+ */
wmb();
- t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
- DBPRIO(1) |
- QID(fl->cntxt_id) | val);
+
+ /* If we don't have access to the new User Doorbell (T5+), use
+ * the old doorbell mechanism; otherwise use the new BAR2
+ * mechanism.
+ */
+ if (unlikely(fl->bar2_addr == NULL)) {
+ t4_write_reg(adapter,
+ T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
+ QID(fl->cntxt_id) | val);
+ } else {
+ writel(val | QID(fl->bar2_qid),
+ fl->bar2_addr + SGE_UDB_KDOORBELL);
+
+ /* This Write memory Barrier will force the write to
+ * the User Doorbell area to be flushed.
+ */
+ wmb();
+ }
fl->pend_cred %= FL_PER_EQ_UNIT;
}
}
@@ -949,14 +970,74 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *tq,
static inline void ring_tx_db(struct adapter *adapter, struct sge_txq *tq,
int n)
{
- /*
- * Warn if we write doorbells with the wrong priority and write
- * descriptors before telling HW.
+ /* Make sure that all writes to the TX Descriptors are committed
+ * before we tell the hardware about them.
*/
- WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO(1));
wmb();
- t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
- QID(tq->cntxt_id) | PIDX(n));
+
+ /* If we don't have access to the new User Doorbell (T5+), use the old
+ * doorbell mechanism; otherwise use the new BAR2 mechanism.
+ */
+ if (unlikely(tq->bar2_addr == NULL)) {
+ u32 val = PIDX(n);
+
+ t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
+ QID(tq->cntxt_id) | val);
+ } else {
+ u32 val = PIDX_T5(n);
+
+ /* T4 and later chips share the same PIDX field offset within
+ * the doorbell, but T5 and later shrank the field in order to
+ * gain a bit for Doorbell Priority. The field was absurdly
+ * large in the first place (14 bits) so we just use the T5
+ * and later limits and warn if a Queue ID is too large.
+ */
+ WARN_ON(val & DBPRIO(1));
+
+ /* If we're only writing a single Egress Unit and the BAR2
+ * Queue ID is 0, we can use the Write Combining Doorbell
+ * Gather Buffer; otherwise we use the simple doorbell.
+ */
+ if (n == 1 && tq->bar2_qid == 0) {
+ unsigned int index = (tq->pidx
+ ? (tq->pidx - 1)
+ : (tq->size - 1));
+ __be64 *src = (__be64 *)&tq->desc[index];
+ __be64 __iomem *dst = (__be64 *)(tq->bar2_addr +
+ SGE_UDB_WCDOORBELL);
+ unsigned int count = EQ_UNIT / sizeof(__be64);
+
+ /* Copy the TX Descriptor in a tight loop in order to
+ * try to get it to the adapter in a single Write
+ * Combined transfer on the PCI-E Bus. If the Write
+ * Combine fails (say because of an interrupt, etc.)
+ * the hardware will simply take the last write as a
+ * simple doorbell write with a PIDX Increment of 1
+ * and will fetch the TX Descriptor from memory via
+ * DMA.
+ */
+ while (count) {
+ writeq(*src, dst);
+ src++;
+ dst++;
+ count--;
+ }
+ } else
+ writel(val | QID(tq->bar2_qid),
+ tq->bar2_addr + SGE_UDB_KDOORBELL);
+
+ /* This Write Memory Barrier will force the write to the User
+ * Doorbell area to be flushed. This is needed to prevent
+ * writes on different CPUs for the same queue from hitting
+ * the adapter out of order. This is required when some Work
+ * Requests take the Write Combine Gather Buffer path (user
+ * doorbell area offset [SGE_UDB_WCDOORBELL..+63]) and some
+ * take the traditional path where we simply increment the
+ * PIDX (User Doorbell area SGE_UDB_KDOORBELL) and have the
+ * hardware DMA read the actual Work Request.
+ */
+ wmb();
+ }
}
/**
@@ -1782,6 +1863,7 @@ static int napi_rx_handler(struct napi_struct *napi, int budget)
unsigned int intr_params;
struct sge_rspq *rspq = container_of(napi, struct sge_rspq, napi);
int work_done = process_responses(rspq, budget);
+ u32 val;
if (likely(work_done < budget)) {
napi_complete(napi);
@@ -1793,11 +1875,16 @@ static int napi_rx_handler(struct napi_struct *napi, int budget)
if (unlikely(work_done == 0))
rspq->unhandled_irqs++;
- t4_write_reg(rspq->adapter,
- T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
- CIDXINC(work_done) |
- INGRESSQID((u32)rspq->cntxt_id) |
- SEINTARM(intr_params));
+ val = CIDXINC(work_done) | SEINTARM(intr_params);
+ if (is_t4(rspq->adapter->params.chip)) {
+ t4_write_reg(rspq->adapter,
+ T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
+ val | INGRESSQID((u32)rspq->cntxt_id));
+ } else {
+ writel(val | INGRESSQID(rspq->bar2_qid),
+ rspq->bar2_addr + SGE_UDB_GTS);
+ wmb();
+ }
return work_done;
}
@@ -1822,6 +1909,7 @@ static unsigned int process_intrq(struct adapter *adapter)
struct sge *s = &adapter->sge;
struct sge_rspq *intrq = &s->intrq;
unsigned int work_done;
+ u32 val;
spin_lock(&adapter->sge.intrq_lock);
for (work_done = 0; ; work_done++) {
@@ -1887,10 +1975,15 @@ static unsigned int process_intrq(struct adapter *adapter)
rspq_next(intrq);
}
- t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
- CIDXINC(work_done) |
- INGRESSQID(intrq->cntxt_id) |
- SEINTARM(intrq->intr_params));
+ val = CIDXINC(work_done) | SEINTARM(intrq->intr_params);
+ if (is_t4(adapter->params.chip))
+ t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS,
+ val | INGRESSQID(intrq->cntxt_id));
+ else {
+ writel(val | INGRESSQID(intrq->bar2_qid),
+ intrq->bar2_addr + SGE_UDB_GTS);
+ wmb();
+ }
spin_unlock(&adapter->sge.intrq_lock);
@@ -2036,6 +2129,35 @@ static void sge_tx_timer_cb(unsigned long data)
}
/**
+ * bar2_address - return the BAR2 address for an SGE Queue's Registers
+ * @adapter: the adapter
+ * @qid: the SGE Queue ID
+ * @qtype: the SGE Queue Type (Egress or Ingress)
+ * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
+ *
+ * Returns the BAR2 address for the SGE Queue Registers associated with
+ * @qid. If BAR2 SGE Registers aren't available, returns NULL. Also
+ * returns the BAR2 Queue ID to be used with writes to the BAR2 SGE
+ * Queue Registers. If the BAR2 Queue ID is 0, then "Inferred Queue ID"
+ * Registers are supported (e.g. the Write Combining Doorbell Buffer).
+ */
+static void __iomem *bar2_address(struct adapter *adapter,
+ unsigned int qid,
+ enum t4_bar2_qtype qtype,
+ unsigned int *pbar2_qid)
+{
+ u64 bar2_qoffset;
+ int ret;
+
+ ret = t4_bar2_sge_qregs(adapter, qid, qtype,
+ &bar2_qoffset, pbar2_qid);
+ if (ret)
+ return NULL;
+
+ return adapter->bar2 + bar2_qoffset;
+}
+
+/**
* t4vf_sge_alloc_rxq - allocate an SGE RX Queue
* @adapter: the adapter
* @rspq: pointer to to the new rxq's Response Queue to be filled in
@@ -2166,6 +2288,10 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
rspq->gen = 1;
rspq->next_intr_params = rspq->intr_params;
rspq->cntxt_id = be16_to_cpu(rpl.iqid);
+ rspq->bar2_addr = bar2_address(adapter,
+ rspq->cntxt_id,
+ T4_BAR2_QTYPE_INGRESS,
+ &rspq->bar2_qid);
rspq->abs_id = be16_to_cpu(rpl.physiqid);
rspq->size--; /* subtract status entry */
rspq->adapter = adapter;
@@ -2184,6 +2310,15 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
fl->alloc_failed = 0;
fl->large_alloc_failed = 0;
fl->starving = 0;
+
+ /* Note, we must initialize the BAR2 Free List User Doorbell
+ * information before refilling the Free List!
+ */
+ fl->bar2_addr = bar2_address(adapter,
+ fl->cntxt_id,
+ T4_BAR2_QTYPE_EGRESS,
+ &fl->bar2_qid);
+
refill_fl(adapter, fl, fl_cap(fl), GFP_KERNEL);
}
@@ -2296,6 +2431,10 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
txq->q.pidx = 0;
txq->q.stat = (void *)&txq->q.desc[txq->q.size];
txq->q.cntxt_id = FW_EQ_ETH_CMD_EQID_G(be32_to_cpu(rpl.eqid_pkd));
+ txq->q.bar2_addr = bar2_address(adapter,
+ txq->q.cntxt_id,
+ T4_BAR2_QTYPE_EGRESS,
+ &txq->q.bar2_qid);
txq->q.abs_id =
FW_EQ_ETH_CMD_PHYSEQID_G(be32_to_cpu(rpl.physeqid_pkd));
txq->txq = devq;
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 4/4] cxgb4: Update firmware version after flashing it via ethtool
From: Hariprasad Shenai @ 2014-12-03 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1417615374-12961-1-git-send-email-hariprasad@chelsio.com>
After successfully loading new firmware, reload the new firmware's version
number information so "ethtool -i", etc. will report the right value
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 3f8876f..a9323bd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -1213,6 +1213,8 @@ out:
if (ret)
dev_err(adap->pdev_dev, "firmware download failed, error %d\n",
ret);
+ else
+ ret = t4_get_fw_version(adap, &adap->params.fw_vers);
return ret;
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH v2 02/19] kbuild: kselftest_install - add a new make target to install selftests
From: Shuah Khan @ 2014-12-03 14:14 UTC (permalink / raw)
To: Michal Marek, gregkh, akpm, davem, keescook, tranmanphong,
dh.herrmann, hughd, bobby.prani, ebiederm, serge.hallyn
Cc: linux-kbuild, linux-kernel, linux-api, netdev,
masami.hiramatsu.pt, Shuah Khan
In-Reply-To: <547EFD6F.2010204@suse.cz>
On 12/03/2014 05:09 AM, Michal Marek wrote:
> On 2014-12-01 17:39, Shuah Khan wrote:
>> On 12/01/2014 08:47 AM, Michal Marek wrote:
>>> On 2014-11-11 21:27, Shuah Khan wrote:
>>>> diff --git a/Makefile b/Makefile
>>>> index 05d67af..ccbd2e1 100644
>>>> --- a/Makefile
>>>> +++ b/Makefile
>>>> @@ -1071,12 +1071,26 @@ headers_check: headers_install
>>>> $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
>>>>
>>>> # ---------------------------------------------------------------------------
>>>> -# Kernel selftest
>>>> +# Kernel selftest targets
>>>> +
>>>> +PHONY += __kselftest_configure
>>>> +INSTALL_KSFT_PATH=$(INSTALL_MOD_PATH)/lib/kselftest/$(KERNELRELEASE)
>>>> +export INSTALL_KSFT_PATH
>>>> +KSELFTEST=$(INSTALL_KSFT_PATH)/kselftest.sh
>>>> +export KSELFTEST
>>>
>>> Can this be moved to tools/testing/selftests/Makefile? It's only used in
>>> this part of the tree.
>>
>> I looked into doing that. KERNELRELEASE will have to be exported for
>> tools/testing/selftests/Makefile to use it? Does that sound okay?
>
> In fact, KERNELRELEASE is already exported. So go ahead.
Good.
>
>
>> Also, it might be easier to get this series in, if you can Ack the main
>> Makefile patch (when we are ready i.e), so I can take it through
>> kselftest tree.
>
> Sure. The Makefile change will only consist of redirecting the
> kselftest_install target to tools/testing/selftests, right?
>
Correct. I plan to keep the selftests specific work under the
selftests related Makefiles.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
^ permalink raw reply
* Re: [PATCH v2 4/7] fs/proc/task_mmu.c: shift mm_access() from m_start() to proc_maps_open()
From: Kirill A. Shutemov @ 2014-12-03 14:14 UTC (permalink / raw)
To: Oleg Nesterov, David S. Miller, Linus Torvalds
Cc: Andrew Morton, Alexander Viro, Cyrill Gorcunov, David Howells,
Eric W. Biederman, Kirill A. Shutemov, Peter Zijlstra,
Sasha Levin, linux-fsdevel, linux-kernel, Alexey Dobriyan, netdev
In-Reply-To: <20140805194655.GA30728@redhat.com>
On Tue, Aug 05, 2014 at 09:46:55PM +0200, Oleg Nesterov wrote:
> A simple test-case from Kirill Shutemov
>
> cat /proc/self/maps >/dev/null
> chmod +x /proc/self/net/packet
> exec /proc/self/net/packet
>
> makes lockdep unhappy, cat/exec take seq_file->lock + cred_guard_mutex in
> the opposite order.
Oleg, I see it again with almost the same test-case:
cat /proc/self/stack >/dev/null
chmod +x /proc/self/net/packet
exec /proc/self/net/packet
Looks like bunch of proc files were converted to use seq_file by Alexey
Dobriyan around the same time you've fixed the issue for /proc/pid/maps.
More generic test-case:
find /proc/self/ -type f -exec dd if='{}' of=/dev/null bs=1 count=1 ';' 2>/dev/null
chmod +x /proc/self/net/packet
exec /proc/self/net/packet
David, any justification for allowing chmod +x for files under
/proc/pid/net?
[ 2.042212] ======================================================
[ 2.042930] [ INFO: possible circular locking dependency detected ]
[ 2.043648] 3.18.0-rc7-00003-g3a18ca061311-dirty #237 Not tainted
[ 2.044350] -------------------------------------------------------
[ 2.045054] sh/94 is trying to acquire lock:
[ 2.045546] (&p->lock){+.+.+.}, at: [<ffffffff811e12fd>] seq_read+0x3d/0x3e0
[ 2.045781]
[ 2.045781] but task is already holding lock:
[ 2.045781] (&sig->cred_guard_mutex){+.+.+.}, at: [<ffffffff811c0e3d>] prepare_bprm_creds+0x2d/0x90
[ 2.045781]
[ 2.045781] which lock already depends on the new lock.
[ 2.045781]
[ 2.045781]
[ 2.045781] the existing dependency chain (in reverse order) is:
[ 2.045781]
-> #1 (&sig->cred_guard_mutex){+.+.+.}:
[ 2.045781] [<ffffffff810a6e99>] __lock_acquire+0x4d9/0xd40
[ 2.045781] [<ffffffff810a7ff2>] lock_acquire+0xd2/0x2a0
[ 2.045781] [<ffffffff81849da6>] mutex_lock_killable_nested+0x66/0x460
[ 2.045781] [<ffffffff81229de4>] lock_trace+0x24/0x70
[ 2.045781] [<ffffffff81229e8f>] proc_pid_stack+0x5f/0xe0
[ 2.045781] [<ffffffff81227244>] proc_single_show+0x54/0xa0
[ 2.045781] [<ffffffff811e13a0>] seq_read+0xe0/0x3e0
[ 2.045781] [<ffffffff811b9377>] vfs_read+0x97/0x180
[ 2.045781] [<ffffffff811b9f5d>] SyS_read+0x4d/0xc0
[ 2.045781] [<ffffffff8184e492>] system_call_fastpath+0x12/0x17
[ 2.045781]
-> #0 (&p->lock){+.+.+.}:
[ 2.045781] [<ffffffff810a389f>] validate_chain.isra.36+0xfff/0x1400
[ 2.045781] [<ffffffff810a6e99>] __lock_acquire+0x4d9/0xd40
[ 2.045781] [<ffffffff810a7ff2>] lock_acquire+0xd2/0x2a0
[ 2.045781] [<ffffffff81849629>] mutex_lock_nested+0x69/0x3c0
[ 2.045781] [<ffffffff811e12fd>] seq_read+0x3d/0x3e0
[ 2.045781] [<ffffffff81226428>] proc_reg_read+0x48/0x70
[ 2.045781] [<ffffffff811b9377>] vfs_read+0x97/0x180
[ 2.045781] [<ffffffff811bf1a8>] kernel_read+0x48/0x60
[ 2.045781] [<ffffffff811bfb2c>] prepare_binprm+0xdc/0x180
[ 2.045781] [<ffffffff811c139a>] do_execve_common.isra.29+0x4fa/0x960
[ 2.045781] [<ffffffff811c1818>] do_execve+0x18/0x20
[ 2.045781] [<ffffffff811c1b05>] SyS_execve+0x25/0x30
[ 2.045781] [<ffffffff8184ea49>] stub_execve+0x69/0xa0
[ 2.045781]
[ 2.045781] other info that might help us debug this:
[ 2.045781]
[ 2.045781] Possible unsafe locking scenario:
[ 2.045781]
[ 2.045781] CPU0 CPU1
[ 2.045781] ---- ----
[ 2.045781] lock(&sig->cred_guard_mutex);
[ 2.045781] lock(&p->lock);
[ 2.045781] lock(&sig->cred_guard_mutex);
[ 2.045781] lock(&p->lock);
[ 2.045781]
[ 2.045781] *** DEADLOCK ***
[ 2.045781]
[ 2.045781] 1 lock held by sh/94:
[ 2.045781] #0: (&sig->cred_guard_mutex){+.+.+.}, at: [<ffffffff811c0e3d>] prepare_bprm_creds+0x2d/0x90
[ 2.045781]
[ 2.045781] stack backtrace:
[ 2.045781] CPU: 0 PID: 94 Comm: sh Not tainted 3.18.0-rc7-00003-g3a18ca061311-dirty #237
[ 2.045781] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2.045781] ffffffff82a48d50 ffff88085427bad8 ffffffff81844a85 0000000000000cac
[ 2.045781] ffffffff82a654a0 ffff88085427bb28 ffffffff810a1b03 0000000000000000
[ 2.045781] ffff88085427bb68 ffff88085427bb28 ffff8808547f1500 ffff8808547f1c40
[ 2.045781] Call Trace:
[ 2.045781] [<ffffffff81844a85>] dump_stack+0x4e/0x68
[ 2.045781] [<ffffffff810a1b03>] print_circular_bug+0x203/0x310
[ 2.045781] [<ffffffff810a389f>] validate_chain.isra.36+0xfff/0x1400
[ 2.045781] [<ffffffff8108fa76>] ? local_clock+0x16/0x30
[ 2.045781] [<ffffffff810a6e99>] __lock_acquire+0x4d9/0xd40
[ 2.045781] [<ffffffff810a7ff2>] lock_acquire+0xd2/0x2a0
[ 2.045781] [<ffffffff811e12fd>] ? seq_read+0x3d/0x3e0
[ 2.045781] [<ffffffff81849629>] mutex_lock_nested+0x69/0x3c0
[ 2.045781] [<ffffffff811e12fd>] ? seq_read+0x3d/0x3e0
[ 2.045781] [<ffffffff8108f9f8>] ? sched_clock_cpu+0x98/0xc0
[ 2.045781] [<ffffffff811e12fd>] ? seq_read+0x3d/0x3e0
[ 2.045781] [<ffffffff814050b9>] ? lockref_put_or_lock+0x29/0x40
[ 2.045781] [<ffffffff811e12fd>] seq_read+0x3d/0x3e0
[ 2.045781] [<ffffffff814050b9>] ? lockref_put_or_lock+0x29/0x40
[ 2.045781] [<ffffffff81226428>] proc_reg_read+0x48/0x70
[ 2.045781] [<ffffffff811b9377>] vfs_read+0x97/0x180
[ 2.045781] [<ffffffff811bf1a8>] kernel_read+0x48/0x60
[ 2.045781] [<ffffffff811bfb2c>] prepare_binprm+0xdc/0x180
[ 2.045781] [<ffffffff811c139a>] do_execve_common.isra.29+0x4fa/0x960
[ 2.092142] tsc: Refined TSC clocksource calibration: 2693.484 MHz
[ 2.045781] [<ffffffff811c0fd3>] ? do_execve_common.isra.29+0x133/0x960
[ 2.045781] [<ffffffff8184f04d>] ? retint_swapgs+0xe/0x13
[ 2.045781] [<ffffffff811c1818>] do_execve+0x18/0x20
[ 2.045781] [<ffffffff811c1b05>] SyS_execve+0x25/0x30
[ 2.045781] [<ffffffff8184ea49>] stub_execve+0x69/0xa0
--
Kirill A. Shutemov
^ permalink raw reply
* Re: [PATCH net v1 1/2] amd-xgbe: Do not clear interrupt indicator
From: Tom Lendacky @ 2014-12-03 14:27 UTC (permalink / raw)
To: Sergei Shtylyov, netdev; +Cc: David Miller
In-Reply-To: <547EF54B.1050308@cogentembedded.com>
On 12/03/2014 05:34 AM, Sergei Shtylyov wrote:
> Hello.
>
> On 12/3/2014 3:16 AM, Tom Lendacky wrote:
>
>> The interrupt value within the xgbe_ring_data structure is used as an
>> indicator of which Rx descriptor should have the INTE bit set to
>> generate an interrupt when that Rx descriptor is used. This bit was
>> mistakenly cleared in the xgbe_unmap_rdata function, effectively
>
> Not xgbe_unmap_skb() (as seems to follow from the patch)?
Yup, I'm mixing up my versions between net-next and net. I'll send
an updated version with a more appropriate comment.
Thanks,
Tom
>
>> nullifying the ethtool rx-frames support.
>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>> drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 1 -
>> 1 file changed, 1 deletion(-)
>
>> diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
>> b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
>> index 6fc5da0..43b7d2e 100644
>> --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
>> +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
>> @@ -356,7 +356,6 @@ static void xgbe_unmap_skb(struct xgbe_prv_data
>> *pdata,
>>
>> rdata->tso_header = 0;
>> rdata->len = 0;
>> - rdata->interrupt = 0;
>> rdata->mapped_as_page = 0;
>>
>> if (rdata->state_saved) {
>
> WBR, Sergei
>
^ permalink raw reply
* Re: [patch net-next 6/6] net_sched: cls_cgroup: remove unnecessary if
From: Jamal Hadi Salim @ 2014-12-03 14:30 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem
In-Reply-To: <20141203131815.GF1860@nanopsycho.orion>
On 12/03/14 08:18, Jiri Pirko wrote:
>>
>> Hrm. head could be NULL, no?
>
> Sure it can. But that is not a problem. Not sure what you are trying to
> point at...
>
I suppose head->handle MUST always be equal to handle for the change to
work. So doesnt matter if handle is null or not. Too clever for me.
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
cheers,
jamal
^ permalink raw reply
* Re: [PATCH net-next 2/4] vlan: Fix mac_len adjustment.
From: Jiri Benc @ 2014-12-03 14:32 UTC (permalink / raw)
To: Pravin B Shelar; +Cc: davem, netdev
In-Reply-To: <1417473038-2165-1-git-send-email-pshelar@nicira.com>
On Mon, 1 Dec 2014 14:30:38 -0800, Pravin B Shelar wrote:
> skb_reset_mac_len() sets length according to ethernet and network
> offsets, but mpls expects mac-length to be offset to mpls header (ref.
> skb_mpls_header()). Therefore rather than reset we need to subtract
> VLAN_HLEN from mac_len.
>
> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
> ---
> net/core/skbuff.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 92116df..c45888f 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -4178,7 +4178,7 @@ static int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci)
> if (skb_network_offset(skb) < ETH_HLEN)
> skb_set_network_header(skb, ETH_HLEN);
>
> - skb_reset_mac_len(skb);
> + skb->mac_len -= VLAN_HLEN;
> pull:
> __skb_pull(skb, offset);
>
See my previous explanation why this patch is wrong with the current
code: http://article.gmane.org/gmane.linux.network/339457
Jiri
--
Jiri Benc
^ permalink raw reply
* [PATCH net v2 0/2] amd-xgbe: AMD XGBE driver fixes 2014-12-02
From: Tom Lendacky @ 2014-12-03 14:36 UTC (permalink / raw)
To: netdev; +Cc: David Miller
The following series of patches includes two bug fixes. Unfortunately,
the first patch will create a conflict when eventually merged into
net-next but should be very easy to resolve.
- Do not clear the interrupt bit in the xgbe_ring_data structure
- Associate a Tx SKB with the proper xgbe_ring_data structure
This patch series is based on net.
Changes from v1:
- Update the commit message associated with the first patch
---
Tom Lendacky (2):
amd-xgbe: Do not clear interrupt indicator
amd-xgbe: Associate Tx SKB with proper ring descriptor
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--
Tom Lendacky
^ permalink raw reply
* [PATCH net v2 1/2] amd-xgbe: Do not clear interrupt indicator
From: Tom Lendacky @ 2014-12-03 14:36 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141203143630.25084.91079.stgit@tlendack-t1.amdoffice.net>
The interrupt value within the xgbe_ring_data structure is used as an
indicator of which Rx descriptor should have the INTE bit set to
generate an interrupt when that Rx descriptor is used. This bit was
mistakenly cleared when unmapping the associated ring data, effectively
nullifying the ethtool rx-frames support.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 6fc5da0..43b7d2e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -356,7 +356,6 @@ static void xgbe_unmap_skb(struct xgbe_prv_data *pdata,
rdata->tso_header = 0;
rdata->len = 0;
- rdata->interrupt = 0;
rdata->mapped_as_page = 0;
if (rdata->state_saved) {
^ permalink raw reply related
* [PATCH net v2 2/2] amd-xgbe: Associate Tx SKB with proper ring descriptor
From: Tom Lendacky @ 2014-12-03 14:36 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141203143630.25084.91079.stgit@tlendack-t1.amdoffice.net>
The SKB for a Tx packet is associated with an xgbe_ring_data structure
in the xgbe_map_tx_skb function. However, it is being saved in the
structure after the last structure used when the SKB is mapped. Use
the last used structure to save the SKB value.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 43b7d2e..b15551b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -480,7 +480,11 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
}
}
- /* Save the skb address in the last entry */
+ /* Save the skb address in the last entry. We always have some data
+ * that has been mapped so rdata is always advanced past the last
+ * piece of mapped data - use the entry pointed to by cur_index - 1.
+ */
+ rdata = XGBE_GET_DESC_DATA(ring, cur_index - 1);
rdata->skb = skb;
/* Save the number of descriptor entries used */
^ permalink raw reply related
* Re: [patch net-next 3/6] net_sched: cls_bpf: remove faulty use of list_for_each_entry_rcu
From: Jamal Hadi Salim @ 2014-12-03 14:37 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem
In-Reply-To: <20141203132635.GH1860@nanopsycho.orion>
On 12/03/14 08:26, Jiri Pirko wrote:
> Wed, Dec 03, 2014 at 01:51:15PM CET, jhs@mojatatu.com wrote:
>> I think this may be problematic. Doesnt a flush operation also use the
>> walker?
>
> I don't believe so. Just look at tc_dump_tfilter.
>
Actually we cant flush filters (we could actions).
> But even if that would the the case, _rcu variant is wrong (yep, it
> would have to be replaced by _safe variant then).
>
Sorry, still humping on the get part:
that gets invoked for del for a filter that may be in use in the
datapath. del uses rcu - should get not use rcu in such a case?
cheers,
jamal
^ permalink raw reply
* Re: [patch net-next 6/6] net_sched: cls_cgroup: remove unnecessary if
From: Jiri Pirko @ 2014-12-03 14:39 UTC (permalink / raw)
To: Jamal Hadi Salim; +Cc: netdev, davem
In-Reply-To: <547F1E98.1050704@mojatatu.com>
Wed, Dec 03, 2014 at 03:30:48PM CET, jhs@mojatatu.com wrote:
>On 12/03/14 08:18, Jiri Pirko wrote:
>
>>>
>>>Hrm. head could be NULL, no?
>>
>>Sure it can. But that is not a problem. Not sure what you are trying to
>>point at...
>>
>
>I suppose head->handle MUST always be equal to handle for the change to
>work. So doesnt matter if handle is null or not. Too clever for me.
Exactly. That is what I tried to say in patch desc :)
>
>Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
>
>cheers,
>jamal
^ permalink raw reply
* Re: [PATCH iproute2] ip link: Show devices by link type
From: Roopa Prabhu @ 2014-12-03 14:40 UTC (permalink / raw)
To: vadim4j; +Cc: netdev
In-Reply-To: <20141203011305.GA5945@angus-think.lan>
On 12/2/14, 5:13 PM, vadim4j@gmail.com wrote:
> On Tue, Dec 02, 2014 at 04:55:44PM -0800, Roopa Prabhu wrote:
>>> int master;
>>> + char *link_kind;
>> The name can be just "kind", given all the others dont use the link prefix
>>> } filter;
> OK
>
>>> + if (filter.link_kind && tb[IFLA_LINKINFO]) {
>>> + char *link_kind = parse_link_kind(tb[IFLA_LINKINFO]);
>>> + if (strcmp(link_kind, filter.link_kind)) {
>>> + return -1;
>>> + }
>> you can skip the braces
>>> + } else if (filter.link_kind)
>> you have if (filter.link_kind) twice, you can use a single if without the
>> else.
>>> + return -1;
>>> +
> I need to skip interfaces which has not IFLA_LINKINFO attribute,
> w/o "else if(...)" I get bridges with normal ether devices:
>
> bash# ip link show type bridge
>
> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
> 2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
> link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
> 5: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default
> link/ether 6e:02:f9:17:7f:10 brd ff:ff:ff:ff:ff:ff
>
> but expected result should be only bridges.
I was just saying, it could be:
if (filter.link_kind) {
if (tb[IFLA_LINKINFO]) {
char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
if (strcmp(kind, filter.kind))
return -1;
} else {
return -1;
}
}
^ permalink raw reply
* Re: [PATCH iproute2] ip link: Show devices by link type
From: Vadim Kochan @ 2014-12-03 14:47 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: netdev@vger.kernel.org
In-Reply-To: <547F20CA.4060501@cumulusnetworks.com>
OK, I can use it)
Thanks,
On Wed, Dec 3, 2014 at 4:40 PM, Roopa Prabhu <roopa@cumulusnetworks.com> wrote:
> On 12/2/14, 5:13 PM, vadim4j@gmail.com wrote:
>>
>> On Tue, Dec 02, 2014 at 04:55:44PM -0800, Roopa Prabhu wrote:
>>>>
>>>> int master;
>>>> + char *link_kind;
>>>
>>> The name can be just "kind", given all the others dont use the link
>>> prefix
>>>>
>>>> } filter;
>>
>> OK
>>
>>>> + if (filter.link_kind && tb[IFLA_LINKINFO]) {
>>>> + char *link_kind = parse_link_kind(tb[IFLA_LINKINFO]);
>>>> + if (strcmp(link_kind, filter.link_kind)) {
>>>> + return -1;
>>>> + }
>>>
>>> you can skip the braces
>>>>
>>>> + } else if (filter.link_kind)
>>>
>>> you have if (filter.link_kind) twice, you can use a single if without the
>>> else.
>>>>
>>>> + return -1;
>>>> +
>>
>> I need to skip interfaces which has not IFLA_LINKINFO attribute,
>> w/o "else if(...)" I get bridges with normal ether devices:
>> bash# ip link show type bridge
>>
>> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
>> mode DEFAULT group default
>> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
>> 2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc
>> pfifo_fast state DOWN mode DEFAULT group default qlen 1000
>> link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
>> 5: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
>> DEFAULT group default
>> link/ether 6e:02:f9:17:7f:10 brd ff:ff:ff:ff:ff:ff
>>
>> but expected result should be only bridges.
>
>
> I was just saying, it could be:
>
> if (filter.link_kind) {
> if (tb[IFLA_LINKINFO]) {
> char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
> if (strcmp(kind, filter.kind))
> return -1;
> } else {
> return -1;
> }
> }
^ permalink raw reply
* Re: linux-next Problems with VPN tunnel - no packets sent
From: Valdis.Kletnieks @ 2014-12-03 14:51 UTC (permalink / raw)
To: Jason Wang; +Cc: Herbert Xu, davem, netdev, linux-kernel
In-Reply-To: <1417576339.19959.0@smtp.corp.redhat.com>
[-- Attachment #1: Type: text/plain, Size: 571 bytes --]
On Wed, 03 Dec 2014 03:20:19 +0008, Jason Wang said:
> > Still broken in next-20141201, and bisection fingers this commit:
> >
> > commit e0b46d0ee9c240c7430a47e9b0365674d4a04522
> > Author: Herbert Xu <herbert@gondor.apana.org.au>
> > Date: Fri Nov 7 21:22:23 2014 +0800
> >
> > tun: Use iovec iterators
> > What's the best way to proceed?
>
> See another fixes from Herbert, it probably fixes your issue:
>
> http://marc.info/?l=linux-netdev&m=141734182302021&w=2
Unfortunately, I'm still seeing the same behavior with that patch
applied to next-20141201....
[-- Attachment #2: Type: application/pgp-signature, Size: 848 bytes --]
^ permalink raw reply
* 3.12.33 - BUG xfrm_selector_match+0x25/0x2f6
From: Smart Weblications GmbH - Florian Wiessner @ 2014-12-03 14:55 UTC (permalink / raw)
To: netdev, LKML, stable
Hi list,
[16623.095403] BUG: unable to handle kernel paging request at 00000000010600d0
[16623.095445] IP: [<ffffffff81547767>] xfrm_selector_match+0x25/0x2f6
[16623.095480] PGD aeaea067 PUD 85d95067 PMD 0
[16623.095513] Oops: 0000 [#1] SMP
[16623.095543] Modules linked in: netconsole xt_nat xt_multiport veth ip_vs_rr
nfsd lockd nfs_acl auth_rpcgss sunrpc oid_registry iptable_mangle xt_mark
nf_conntrack_netlink nfnetlink ipt_MASQUERADE iptable_nat nf_nat_ipv4
nf_conntrack_ipv4 nf_defrag_ipv4 ipt_REJECT xt_tcpudp iptable_filter ip_tables
cpufreq_ondemand cpufreq_powersave cpufreq_conservative cpufreq_userspace
ocfs2_stack_o2cb ocfs2_dlm bridge stp llc bonding fuse nf_conntrack_ftp 8021q
openvswitch gre vxlan xt_conntrack x_tables ocfs2_dlmfs dlm sctp ocfs2
ocfs2_nodemanager ocfs2_stackglue configfs rbd kvm_intel kvm coretemp ip_vs_ftp
ip_vs nf_nat nf_conntrack ctr twofish_generic twofish_x86_64 twofish_common
camellia_generic serpent_generic blowfish_generic blowfish_common cast5_generic
cast_common xcbc sha512_generic crypto_null af_key xfrm_algo psmouse serio_raw
i2c_i801 lpc_ich mfd_core evdev btrfs lzo_decompress lzo_compress
[16623.096062] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.12.33 #1
[16623.096091] Hardware name: Supermicro X9SCI/X9SCA/X9SCI/X9SCA, BIOS 1.1a
09/28/2011
[16623.096137] task: ffffffff81804450 ti: ffffffff817f4000 task.ti: ffffffff817f4000
[16623.096182] RIP: 0010:[<ffffffff81547767>] [<ffffffff81547767>]
xfrm_selector_match+0x25/0x2f6
[16623.096233] RSP: 0018:ffff88083fc03900 EFLAGS: 00010246
[16623.096261] RAX: 0000000000000001 RBX: ffff88083fc03a20 RCX: ffff880787fb1200
[16623.096292] RDX: 0000000000000002 RSI: ffff88083fc03a20 RDI: 00000000010600a6
[16623.096323] RBP: 00000000010600a6 R08: 0000000000000000 R09: ffff88083fc039a0
[16623.096353] R10: 0000000000000000 R11: 0000000000000001 R12: ffff88083fc03a20
[16623.096383] R13: 0000000000000001 R14: ffffffff818a9700 R15: ffffffffa01c73e0
[16623.096414] FS: 0000000000000000(0000) GS:ffff88083fc00000(0000)
knlGS:0000000000000000
[16623.096469] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[16623.096498] CR2: 00000000010600d0 CR3: 0000000085f0b000 CR4: 00000000000407f0
[16623.096528] Stack:
[16623.096550] 0000000000000000 0000000001060002 ffff880787fb1200 ffff88083fc03a20
[16623.096602] 0000000000000001 ffffffff81547a7c 0000000000000000 ffff8800baad5480
[16623.096655] ffffffff81804450 ffffffff818a9700 000000003c9041bc ffffffff81547ef7
[16623.096721] Call Trace:
[16623.096744] <IRQ>
[16623.096749] [<ffffffff81547a7c>] ? xfrm_sk_policy_lookup+0x44/0x9b
[16623.096802] [<ffffffff81547ef7>] ? xfrm_lookup+0x91/0x446
[16623.096832] [<ffffffff81541316>] ? ip_route_me_harder+0x150/0x1b0
[16623.096865] [<ffffffffa01b6457>] ? ip_vs_route_me_harder+0x86/0x91 [ip_vs]
[16623.096899] [<ffffffffa01b797a>] ? ip_vs_out+0x2d3/0x5bc [ip_vs]
[16623.096930] [<ffffffff81501420>] ? ip_rcv_finish+0x2b8/0x2b8
[16623.096959] [<ffffffff814fc2d3>] ? nf_iterate+0x42/0x80
[16623.096989] [<ffffffff814fc37a>] ? nf_hook_slow+0x69/0xff
[16623.097017] [<ffffffff81501420>] ? ip_rcv_finish+0x2b8/0x2b8
[16623.097047] [<ffffffff81501744>] ? ip_local_deliver+0x6f/0x7e
[16623.097078] [<ffffffff814d82a6>] ? __netif_receive_skb_core+0x5f0/0x66c
[16623.097108] [<ffffffff814d84b7>] ? process_backlog+0x13e/0x13e
[16623.097140] [<ffffffffa04b4e09>] ? br_handle_frame_finish+0x382/0x382 [bridge]
[16623.097187] [<ffffffff814d8503>] ? netif_receive_skb+0x4c/0x7d
[16623.097218] [<ffffffffa04b4d95>] ? br_handle_frame_finish+0x30e/0x382 [bridge]
[16623.097265] [<ffffffffa04b4fda>] ? br_handle_frame+0x1d1/0x217 [bridge]
[16623.097297] [<ffffffffa048e4aa>] ? bond_handle_frame+0x86/0x1bd [bonding]
[16623.097328] [<ffffffff814d8155>] ? __netif_receive_skb_core+0x49f/0x66c
[16623.097358] [<ffffffff814d8503>] ? netif_receive_skb+0x4c/0x7d
[16623.097388] [<ffffffff814d9091>] ? napi_gro_receive+0x35/0x76
[16623.097418] [<ffffffff813eae17>] ? e1000_clean_rx_irq+0x26d/0x2f5
[16623.097448] [<ffffffff813ef48e>] ? e1000e_poll+0x65/0x23d
[16623.097477] [<ffffffff814d8709>] ? net_rx_action+0xa2/0x1c0
[16623.097507] [<ffffffff8136895c>] ? credit_entropy_bits.part.7+0x127/0x168
[16623.097540] [<ffffffff8103cd9c>] ? __do_softirq+0xe8/0x201
[16623.097569] [<ffffffff815ae61c>] ? call_softirq+0x1c/0x30
[16623.097599] [<ffffffff810042ad>] ? do_softirq+0x2c/0x5f
[16623.097627] [<ffffffff8103cf7a>] ? irq_exit+0x3b/0x7f
[16623.097655] [<ffffffff81003d90>] ? do_IRQ+0x91/0xa8
[16623.097684] [<ffffffff815ac7ea>] ? common_interrupt+0x6a/0x6a
[16623.097713] <EOI>
[16623.097718] [<ffffffff8105549a>] ? enqueue_hrtimer+0x36/0x6d
[16623.097771] [<ffffffff814a904d>] ? cpuidle_enter_state+0x43/0xa6
[16623.097801] [<ffffffff814a9046>] ? cpuidle_enter_state+0x3c/0xa6
[16623.097831] [<ffffffff814a91a2>] ? cpuidle_idle_call+0xf2/0x19e
[16623.097862] [<ffffffff8100a2b8>] ? arch_cpu_idle+0x6/0x17
[16623.097892] [<ffffffff81071715>] ? cpu_startup_entry+0x119/0x1a8
[16623.097921] [<ffffffff818f6cf3>] ? start_kernel+0x3ca/0x3d5
[16623.097951] [<ffffffff818f673f>] ? repair_env_string+0x57/0x57
[16623.097979] Code: 5d 41 5e 41 5f c3 41 55 66 83 fa 02 41 54 55 48 89 fd 53 48
89 f3 41 50 74 11 31 c0 66 83 fa 0a 0f 85 ce 02 00 00 e9 fd 00 00 00 <0f> b6 47
2a 8b 17 8b 76 18 84 c0 74 1a b9 20 00 00 00 31 f2 29
[16623.098244] RIP [<ffffffff81547767>] xfrm_selector_match+0x25/0x2f6
[16623.098459] RSP <ffff88083fc03900>
[16623.098484] CR2: 00000000010600d0
[16623.098903] ---[ end trace 36545dfc8f7672ee ]---
[16623.098996] Kernel panic - not syncing: Fatal exception in interrupt
[16623.099085] Rebooting in 10 seconds..
[16633.158496] ACPI MEMORY or I/O RESET_REG.
This happens again and again with 3.12.33
see also: http://www.spinics.net/lists/netdev/msg306283.html
is this already fixed somehow?
--
Mit freundlichen Grüßen,
Florian Wiessner
Smart Weblications GmbH
Martinsberger Str. 1
D-95119 Naila
fon.: +49 9282 9638 200
fax.: +49 9282 9638 205
24/7: +49 900 144 000 00 - 0,99 EUR/Min*
http://www.smart-weblications.de
--
Sitz der Gesellschaft: Naila
Geschäftsführer: Florian Wiessner
HRB-Nr.: HRB 3840 Amtsgericht Hof
*aus dem dt. Festnetz, ggf. abweichende Preise aus dem Mobilfunknetz
^ permalink raw reply
* [PATCH iproute2 v2] ip link: Show devices by type
From: Vadim Kochan @ 2014-12-03 14:56 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
Added new option 'type' to 'ip link show'
command which allows to filter devices by type:
ip link show type bridge
ip link show type vlan
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
ip/ipaddress.c | 26 ++++++++++++++++++++++++++
ip/iplink.c | 2 +-
man/man8/ip-link.8.in | 20 +++++++++++++++++++-
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 4d99324..4ffac81 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -57,6 +57,7 @@ static struct
int flushe;
int group;
int master;
+ char *kind;
} filter;
static int do_link;
@@ -189,6 +190,18 @@ static void print_linkmode(FILE *f, struct rtattr *tb)
fprintf(f, "mode %s ", link_modes[mode]);
}
+static char *parse_link_kind(struct rtattr *tb)
+{
+ struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+
+ parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
+
+ if (linkinfo[IFLA_INFO_KIND])
+ return RTA_DATA(linkinfo[IFLA_INFO_KIND]);
+
+ return "";
+}
+
static void print_linktype(FILE *fp, struct rtattr *tb)
{
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
@@ -551,6 +564,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
else if (filter.master > 0)
return -1;
+ if (filter.kind) {
+ if (tb[IFLA_LINKINFO]) {
+ char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
+ if (strcmp(kind, filter.kind))
+ return -1;
+ } else {
+ return -1;
+ }
+ }
+
if (n->nlmsg_type == RTM_DELLINK)
fprintf(fp, "Deleted ");
@@ -1293,6 +1316,9 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (!ifindex)
invarg("Device does not exist\n", *argv);
filter.master = ifindex;
+ } else if (do_link && strcmp(*argv, "type") == 0) {
+ NEXT_ARG();
+ filter.kind = *argv;
} else {
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
diff --git a/ip/iplink.c b/ip/iplink.c
index ce6eb3e..f9a75d5 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -82,7 +82,7 @@ void iplink_usage(void)
fprintf(stderr, " [ master DEVICE ]\n");
fprintf(stderr, " [ nomaster ]\n");
fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n");
- fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV]\n");
+ fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
if (iplink_have_newlink()) {
fprintf(stderr, " ip link help [ TYPE ]\n");
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 9d4e3da..7678065 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -148,7 +148,9 @@ ip-link \- network device configuration
.IR GROUP " | "
.BR up " | "
.B master
-.IR DEVICE " ]"
+.IR DEVICE " | "
+.B type
+.IR TYPE " ]"
.ti -8
.B ip link help
@@ -688,6 +690,12 @@ only display running interfaces.
.I DEVICE
specifies the master device which enslaves devices to show.
+.TP
+.BI type " TYPE "
+.I TYPE
+specifies the type of devices to show.
+
+.TP
The show command has additional formatting options:
.TP
@@ -719,6 +727,16 @@ ip link show
Shows the state of all network interfaces on the system.
.RE
.PP
+ip link show type bridge
+.RS 4
+Shows the bridge devices.
+.RE
+.PP
+ip link show type vlan
+.RS 4
+Shows the vlan devices.
+.RE
+.PP
ip link set dev ppp0 mtu 1400
.RS 4
Change the MTU the ppp0 device.
--
2.1.3
^ permalink raw reply related
* Re: [PATCH iproute2] ip link: Show devices by link type
From: Vadim Kochan @ 2014-12-03 15:08 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: netdev@vger.kernel.org
In-Reply-To: <CAMw6YJKxPK_MKbCdxVwGSBXbZ7MqtXBA3FJ_ovw4-8heB6ci9w@mail.gmail.com>
I have sent v2 with subject "ip link: Show devices by type"
Regards,
Vadim
On Wed, Dec 3, 2014 at 4:47 PM, Vadim Kochan <vadim4j@gmail.com> wrote:
> OK, I can use it)
>
> Thanks,
>
> On Wed, Dec 3, 2014 at 4:40 PM, Roopa Prabhu <roopa@cumulusnetworks.com> wrote:
>> On 12/2/14, 5:13 PM, vadim4j@gmail.com wrote:
>>>
>>> On Tue, Dec 02, 2014 at 04:55:44PM -0800, Roopa Prabhu wrote:
>>>>>
>>>>> int master;
>>>>> + char *link_kind;
>>>>
>>>> The name can be just "kind", given all the others dont use the link
>>>> prefix
>>>>>
>>>>> } filter;
>>>
>>> OK
>>>
>>>>> + if (filter.link_kind && tb[IFLA_LINKINFO]) {
>>>>> + char *link_kind = parse_link_kind(tb[IFLA_LINKINFO]);
>>>>> + if (strcmp(link_kind, filter.link_kind)) {
>>>>> + return -1;
>>>>> + }
>>>>
>>>> you can skip the braces
>>>>>
>>>>> + } else if (filter.link_kind)
>>>>
>>>> you have if (filter.link_kind) twice, you can use a single if without the
>>>> else.
>>>>>
>>>>> + return -1;
>>>>> +
>>>
>>> I need to skip interfaces which has not IFLA_LINKINFO attribute,
>>> w/o "else if(...)" I get bridges with normal ether devices:
>>> bash# ip link show type bridge
>>>
>>> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
>>> mode DEFAULT group default
>>> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
>>> 2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc
>>> pfifo_fast state DOWN mode DEFAULT group default qlen 1000
>>> link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
>>> 5: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
>>> DEFAULT group default
>>> link/ether 6e:02:f9:17:7f:10 brd ff:ff:ff:ff:ff:ff
>>>
>>> but expected result should be only bridges.
>>
>>
>> I was just saying, it could be:
>>
>> if (filter.link_kind) {
>> if (tb[IFLA_LINKINFO]) {
>> char *kind = parse_link_kind(tb[IFLA_LINKINFO]);
>> if (strcmp(kind, filter.kind))
>> return -1;
>> } else {
>> return -1;
>> }
>> }
^ permalink raw reply
* Re: [PATCH] SSB / B44: fix WOL for BCM4401
From: Michael Büsch @ 2014-12-03 15:18 UTC (permalink / raw)
To: Larry Finger, John W. Linville
Cc: Andrey Skvortsov, Rafael J. Wysocki, Gary.Zambrano, netdev,
linux-kernel, b43-dev, Rafał Miłecki
In-Reply-To: <547E3BF5.5060201@lwfinger.net>
[-- Attachment #1.1: Type: text/plain, Size: 2302 bytes --]
On Tue, 02 Dec 2014 16:23:49 -0600
Larry Finger <Larry.Finger@lwfinger.net> wrote:
> On 12/02/2014 02:12 PM, Michael Büsch wrote:
> > On Tue, 2 Dec 2014 23:01:29 +0300
> > Andrey Skvortsov <andrej.skvortzov@gmail.com> wrote:
> >
> >> On Mon, Dec 01, 2014 at 10:10:23PM +0100, Michael Büsch wrote:
> >>> On Mon, 1 Dec 2014 23:46:38 +0300
> >>> Andrey Skvortsov <andrej.skvortzov@gmail.com> wrote:
> >>>
> >>>> Wake On Lan was not working on laptop DELL Vostro 1500.
> >>>> If WOL was turned on, BCM4401 was powered up in suspend mode. LEDs blinked.
> >>>> But the laptop could not be woken up with the Magic Packet. The reason for
> >>>> that was that PCIE was not enabled as a system wakeup source and
> >>>> therefore the host PCI bridge was not powered up in suspend mode.
> >>>> PCIE was not enabled in suspend by PM because no child devices were
> >>>> registered as wakeup source during suspend process.
> >>>> On laptop BCM4401 is connected through the SSB bus, that is connected to the
> >>>> PCI-Express bus. SSB and B44 did not use standard PM wakeup functions
> >>>> and did not forward wakeup settings to their parents.
> >>>> To fix that B44 driver enables PM wakeup and registers new wakeup source
> >>>> using device_set_wakeup_enable(). Wakeup is automatically reported to the parent SSB
> >>>> bus via power.wakeup_path. SSB bus enables wakeup for the parent PCI bridge, if there is any
> >>>> child devices with enabled wakeup functionality. All other steps are
> >>>> done by PM core code.
> >>>
> >>> Thanks, this looks good.
> >>> I assume you tested this (I currently don't have a device to test this).
> >>
> >> Sure, I've tested it. WOL from suspend is working and after resume from hibernate Ethernet is working too.
> >
> > That sounds good, indeed.
> > I'd still prefer, if someone with b43 (wireless) would test it, too.
>
> I did a partial test with my PowerBook G4. With the patch installed, it would
> both suspend and hibernate, but WOL would be impossible. This computer uses a
> PCMCIA version of the BCM4318, and power is turned off to the PCMCIA card when
> suspended or hibernating.
Thanks for testing.
John, can you take this one? Or do we need to split the b44 part out?
I added my Signed-off.
--
Michael
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: b44_wol.patch --]
[-- Type: text/x-patch, Size: 4400 bytes --]
From: Andrey Skvortsov <andrej.skvortzov@gmail.com>
Subject: [PATCH] SSB / B44: fix WOL for BCM4401
Wake On Lan was not working on laptop DELL Vostro 1500.
If WOL was turned on, BCM4401 was powered up in suspend mode. LEDs blinked.
But the laptop could not be woken up with the Magic Packet. The reason for
that was that PCIE was not enabled as a system wakeup source and
therefore the host PCI bridge was not powered up in suspend mode.
PCIE was not enabled in suspend by PM because no child devices were
registered as wakeup source during suspend process.
On laptop BCM4401 is connected through the SSB bus, that is connected to the
PCI-Express bus. SSB and B44 did not use standard PM wakeup functions
and did not forward wakeup settings to their parents.
To fix that B44 driver enables PM wakeup and registers new wakeup source
using device_set_wakeup_enable(). Wakeup is automatically reported to the parent SSB
bus via power.wakeup_path. SSB bus enables wakeup for the parent PCI bridge, if there is any
child devices with enabled wakeup functionality. All other steps are
done by PM core code.
Signed-off-by: Andrey Skvortsov <Andrej.Skvortzov@gmail.com>
Signed-off-by: Michael Buesch <m@bues.ch>
---
drivers/net/ethernet/broadcom/b44.c | 2 ++
drivers/ssb/pcihost_wrapper.c | 33 ++++++++++++++++++++++-----------
2 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 416620f..ffeaf47 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2104,6 +2104,7 @@ static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
bp->flags &= ~B44_FLAG_WOL_ENABLE;
spin_unlock_irq(&bp->lock);
+ device_set_wakeup_enable(bp->sdev->dev, wol->wolopts & WAKE_MAGIC);
return 0;
}
@@ -2452,6 +2453,7 @@ static int b44_init_one(struct ssb_device *sdev,
}
}
+ device_set_wakeup_capable(sdev->dev, true);
netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
return 0;
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index 69161bb..410215c 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -11,15 +11,17 @@
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/ssb/ssb.h>
-#ifdef CONFIG_PM
-static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int ssb_pcihost_suspend(struct device *d)
{
+ struct pci_dev *dev = to_pci_dev(d);
struct ssb_bus *ssb = pci_get_drvdata(dev);
int err;
@@ -28,17 +30,23 @@ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
return err;
pci_save_state(dev);
pci_disable_device(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ /* if there is a wakeup enabled child device on ssb bus,
+ enable pci wakeup posibility. */
+ device_set_wakeup_enable(d, d->power.wakeup_path);
+
+ pci_prepare_to_sleep(dev);
return 0;
}
-static int ssb_pcihost_resume(struct pci_dev *dev)
+static int ssb_pcihost_resume(struct device *d)
{
+ struct pci_dev *dev = to_pci_dev(d);
struct ssb_bus *ssb = pci_get_drvdata(dev);
int err;
- pci_set_power_state(dev, PCI_D0);
+ pci_back_from_sleep(dev);
err = pci_enable_device(dev);
if (err)
return err;
@@ -49,10 +57,12 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
return 0;
}
-#else /* CONFIG_PM */
-# define ssb_pcihost_suspend NULL
-# define ssb_pcihost_resume NULL
-#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops ssb_pcihost_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
+};
+
+#endif /* CONFIG_PM_SLEEP */
static int ssb_pcihost_probe(struct pci_dev *dev,
const struct pci_device_id *id)
@@ -115,8 +125,9 @@ int ssb_pcihost_register(struct pci_driver *driver)
{
driver->probe = ssb_pcihost_probe;
driver->remove = ssb_pcihost_remove;
- driver->suspend = ssb_pcihost_suspend;
- driver->resume = ssb_pcihost_resume;
+#ifdef CONFIG_PM_SLEEP
+ driver->driver.pm = &ssb_pcihost_pm_ops;
+#endif
return pci_register_driver(driver);
}
--
1.7.2.5
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply related
* Re: [patch net-next 3/6] net_sched: cls_bpf: remove faulty use of list_for_each_entry_rcu
From: Jiri Pirko @ 2014-12-03 15:20 UTC (permalink / raw)
To: Jamal Hadi Salim; +Cc: netdev, davem
In-Reply-To: <547F203A.3080208@mojatatu.com>
Wed, Dec 03, 2014 at 03:37:46PM CET, jhs@mojatatu.com wrote:
>On 12/03/14 08:26, Jiri Pirko wrote:
>>Wed, Dec 03, 2014 at 01:51:15PM CET, jhs@mojatatu.com wrote:
>
>>>I think this may be problematic. Doesnt a flush operation also use the
>>>walker?
>>
>>I don't believe so. Just look at tc_dump_tfilter.
>>
>
>Actually we cant flush filters (we could actions).
>
>>But even if that would the the case, _rcu variant is wrong (yep, it
>>would have to be replaced by _safe variant then).
>>
>
>Sorry, still humping on the get part:
>that gets invoked for del for a filter that may be in use in the
>datapath. del uses rcu - should get not use rcu in such a case?
Yep, but this is updater, protected by rtnl. _rcu list travelsal variant
should be used by reader only (classify callback in cls case).
get op is only called from tc_ctl_tfilter which is always called with
rtnl held.
>
>cheers,
>jamal
^ permalink raw reply
* Re: [PATCH net] net: sctp: use MAX_HEADER for headroom reserve in output path
From: Vlad Yasevich @ 2014-12-03 15:32 UTC (permalink / raw)
To: Daniel Borkmann, davem; +Cc: linux-sctp, netdev, robert
In-Reply-To: <1417605238-9936-1-git-send-email-dborkman@redhat.com>
On 12/03/2014 06:13 AM, Daniel Borkmann wrote:
> To accomodate for enough headroom for tunnels, use MAX_HEADER instead
> of LL_MAX_HEADER. Robert reported that he has hit after roughly 40hrs
> of trinity an skb_under_panic() via SCTP output path (see reference).
> I couldn't reproduce it from here, but not using MAX_HEADER as elsewhere
> in other protocols might be one possible cause for this.
>
> In any case, it looks like accounting on chunks themself seems to look
> good as the skb already passed the SCTP output path and did not hit
> any skb_over_panic(). Given tunneling was enabled in his .config, the
> headroom would have been expanded by MAX_HEADER in this case.
>
> Reported-by: Robert Święcki <robert@swiecki.net>
> Reference: https://lkml.org/lkml/2014/12/1/507
> Fixes: 594ccc14dfe4d ("[SCTP] Replace incorrect use of dev_alloc_skb with alloc_skb in sctp_packet_transmit().")
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Looks right. If sctp path is over any kind of L3 tunnel, we'll see this.
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
-vlad
> ---
> net/sctp/output.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 42dffd4..fc5e45b 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -401,12 +401,12 @@ int sctp_packet_transmit(struct sctp_packet *packet)
> sk = chunk->skb->sk;
>
> /* Allocate the new skb. */
> - nskb = alloc_skb(packet->size + LL_MAX_HEADER, GFP_ATOMIC);
> + nskb = alloc_skb(packet->size + MAX_HEADER, GFP_ATOMIC);
> if (!nskb)
> goto nomem;
>
> /* Make sure the outbound skb has enough header room reserved. */
> - skb_reserve(nskb, packet->overhead + LL_MAX_HEADER);
> + skb_reserve(nskb, packet->overhead + MAX_HEADER);
>
> /* Set the owning socket so that we know where to get the
> * destination IP address.
>
^ permalink raw reply
* Re: [PATCH v2 net] bpf: x86: fix epilogue generation for eBPF programs
From: Alexei Starovoitov @ 2014-12-03 15:51 UTC (permalink / raw)
To: Z Lim
Cc: David S. Miller, Eric Dumazet, Daniel Borkmann, H. Peter Anvin,
Thomas Gleixner, Ingo Molnar, Network Development, LKML
In-Reply-To: <CABg9mcso+YeS-sgAQmAu6MvsfNnzrKYuUG8m+WYJmxdaxbGmPA@mail.gmail.com>
On Tue, Dec 2, 2014 at 10:38 PM, Z Lim <zlim.lnx@gmail.com> wrote:
> Hi Alexei,
>
> On Sat, Nov 29, 2014 at 2:46 PM, Alexei Starovoitov <ast@plumgrid.com> wrote:
>> classic BPF has a restriction that last insn is always BPF_RET.
>> eBPF doesn't have BPF_RET instruction and this restriction.
>> It has BPF_EXIT insn which can appear anywhere in the program
>> one or more times and it doesn't have to be last insn.
>
> Just to confirm, in valid eBPF, BPF_EXIT *must* be present at least
> once, correct?
> Does an eBPF JIT implementation need to check for it?
yes. of course. At least one bpf_exit is always there
and there are no loops. verifier is checking for it.
So no need for jit to check it again.
> I'll cook up a patch for arm64 if you haven't already done so.
> Any related test case I should run through?
Pending socket samples are generating such code by llvm.
I was planning to add an explicit test to test_bpf, but feel free
to beat me to it.
^ permalink raw reply
* Re: [PATCH] bpf: arm64: lift restriction on last instruction
From: Alexei Starovoitov @ 2014-12-03 15:54 UTC (permalink / raw)
To: Zi Shen Lim
Cc: David S. Miller, Catalin Marinas, Will Deacon, Daniel Borkmann,
Network Development, linux-arm-kernel@lists.infradead.org, LKML
In-Reply-To: <1417595881-32218-1-git-send-email-zlim.lnx@gmail.com>
On Wed, Dec 3, 2014 at 12:38 AM, Zi Shen Lim <zlim.lnx@gmail.com> wrote:
> Earlier implementation assumed last instruction is BPF_EXIT.
> Since this is no longer a restriction in eBPF, we remove this
> limitation.
>
> Per Alexei Starovoitov [1]:
>> classic BPF has a restriction that last insn is always BPF_RET.
>> eBPF doesn't have BPF_RET instruction and this restriction.
>> It has BPF_EXIT insn which can appear anywhere in the program
>> one or more times and it doesn't have to be last insn.
>
> [1] https://lkml.org/lkml/2014/11/27/2
>
> Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
> Signed-off-by: Zi Shen Lim <zlim.lnx@gmail.com>
yours is cleaner than my own attempt to fix it.
Thanks!
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox