* [PATCH v2 1/3] drivers/net: enic: Adding support for Cisco Low Latency NIC
From: Neel Patel @ 2013-08-13 22:19 UTC (permalink / raw)
To: netdev; +Cc: Neel Patel
In-Reply-To: <1376432381-5546-1-git-send-email-neepatel@cisco.com>
This patch,
- Adds new firmware commands for the new Cisco Low Latency NIC
(aka. USNIC).
- Enables descriptor prefetch on the hardware. This feature
reduces latency for small packet transmit.
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
drivers/net/ethernet/cisco/enic/enic.h | 2 +-
drivers/net/ethernet/cisco/enic/enic_res.h | 9 +-
drivers/net/ethernet/cisco/enic/vnic_dev.c | 5 +
drivers/net/ethernet/cisco/enic/vnic_dev.h | 1 +
drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 176 +++++++++++++++++++++++++-
drivers/net/ethernet/cisco/enic/vnic_rq.c | 5 +-
drivers/net/ethernet/cisco/enic/vnic_rq.h | 5 +-
drivers/net/ethernet/cisco/enic/vnic_wq.c | 3 -
drivers/net/ethernet/cisco/enic/vnic_wq.h | 86 ++++++++++++-
9 files changed, 275 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 2e37c63..75e842d 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -33,7 +33,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
#define DRV_VERSION "2.1.1.39"
-#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
+#define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
diff --git a/drivers/net/ethernet/cisco/enic/enic_res.h b/drivers/net/ethernet/cisco/enic/enic_res.h
index 25be273..69f60af 100644
--- a/drivers/net/ethernet/cisco/enic/enic_res.h
+++ b/drivers/net/ethernet/cisco/enic/enic_res.h
@@ -47,6 +47,9 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
int offload_mode, int cq_entry, int sop, int eop, int loopback)
{
struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
+ u8 desc_skip_cnt = 1;
+ u8 compressed_send = 0;
+ u64 wrid = 0;
wq_enet_desc_enc(desc,
(u64)dma_addr | VNIC_PADDR_TARGET,
@@ -59,7 +62,8 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
(u16)vlan_tag,
(u8)loopback);
- vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
+ vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop, desc_skip_cnt,
+ (u8)cq_entry, compressed_send, wrid);
}
static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq,
@@ -120,6 +124,7 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
dma_addr_t dma_addr, unsigned int len)
{
struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
+ u64 wrid = 0;
u8 type = os_buf_index ?
RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP;
@@ -127,7 +132,7 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
(u64)dma_addr | VNIC_PADDR_TARGET,
type, (u16)len);
- vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len);
+ vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len, wrid);
}
struct enic;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index 97455c5..1b436b3 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -970,6 +970,11 @@ err_out:
return NULL;
}
+struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev)
+{
+ return vdev->pdev;
+}
+
int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len)
{
u64 a0, a1 = len;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index f3d9b79..e670029 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -127,6 +127,7 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
unsigned int num_bars);
+struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev);
int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len);
int vnic_dev_enable2(struct vnic_dev *vdev, int active);
int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
index 23d5552..b9a0d78 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
@@ -281,11 +281,25 @@ enum vnic_devcmd_cmd {
* 0 if no VIF-CONFIG-INFO TLV was ever received. */
CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
+ /* INT13 API: (u64)a0=paddr to vnic_int13_params struct
+ * (u32)a1=INT13_CMD_xxx
+ */
+ CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45),
+
+ /* Set default vlan:
+ * in: (u16)a0=new default vlan
+ * (u16)a1=zero for overriding vlan with param a0,
+ * non-zero for resetting vlan to the default
+ * out: (u16)a0=old default vlan
+ */
+ CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46),
+
/* init_prov_info2:
* Variant of CMD_INIT_PROV_INFO, where it will not try to enable
* the vnic until CMD_ENABLE2 is issued.
* (u64)a0=paddr of vnic_devcmd_provinfo
- * (u32)a1=sizeof provision info */
+ * (u32)a1=sizeof provision info
+ */
CMD_INIT_PROV_INFO2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47),
/* enable2:
@@ -339,16 +353,57 @@ enum vnic_devcmd_cmd {
CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
/*
- * cmd_set_mac_addr
- * set mac address
+ * Set the predefined mac address as default
* in:
* (u48)a0 = mac addr
- *
*/
CMD_SET_MAC_ADDR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 55),
+
+ /* Update the provisioning info of the given VIF
+ * (u64)a0=paddr of vnic_devcmd_provinfo
+ * (u32)a1=sizeof provision info
+ */
+ CMD_PROV_INFO_UPDATE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 56),
+
+ /* Add a filter.
+ * in: (u64) a0= filter address
+ * (u32) a1= size of filter
+ * out: (u32) a0=filter identifier
+ */
+ CMD_ADD_FILTER = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 58),
+
+ /* Delete a filter.
+ * in: (u32) a0=filter identifier
+ */
+ CMD_DEL_FILTER = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 59),
+
+ /* Enable a Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ * (u32) a1= command
+ */
+ CMD_QP_ENABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 60),
+
+ /* Disable a Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ * (u32) a1= command
+ */
+ CMD_QP_DISABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 61),
+
+ /* Stats dump Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ * (u64) a1=host buffer addr for status dump
+ * (u32) a2=length of the buffer
+ */
+ CMD_QP_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 62),
+
+ /* Clear stats for Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ */
+ CMD_QP_STATS_CLEAR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 63),
};
/* CMD_ENABLE2 flags */
+#define CMD_ENABLE2_STANDBY 0x0
#define CMD_ENABLE2_ACTIVE 0x1
/* flags for CMD_OPEN */
@@ -364,6 +419,9 @@ enum vnic_devcmd_cmd {
#define CMD_PFILTER_PROMISCUOUS 0x08
#define CMD_PFILTER_ALL_MULTICAST 0x10
+/* Commands for CMD_QP_ENABLE/CM_QP_DISABLE */
+#define CMD_QP_RQWQ 0x0
+
/* rewrite modes for CMD_IG_VLAN_REWRITE_MODE */
#define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK 0
#define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN 1
@@ -390,6 +448,7 @@ enum vnic_devcmd_error {
ERR_EMAXRES = 10,
ERR_ENOTSUPPORTED = 11,
ERR_EINPROGRESS = 12,
+ ERR_MAX
};
/*
@@ -435,6 +494,115 @@ struct vnic_devcmd_provinfo {
u8 data[0];
};
+/* These are used in flags field of different filters to denote
+ * valid fields used.
+ */
+#define FILTER_FIELD_VALID(fld) (1 << (fld - 1))
+
+#define FILTER_FIELDS_USNIC ( \
+ FILTER_FIELD_VALID(1) | \
+ FILTER_FIELD_VALID(2) | \
+ FILTER_FIELD_VALID(3) | \
+ FILTER_FIELD_VALID(4))
+
+#define FILTER_FIELDS_IPV4_5TUPLE ( \
+ FILTER_FIELD_VALID(1) | \
+ FILTER_FIELD_VALID(2) | \
+ FILTER_FIELD_VALID(3) | \
+ FILTER_FIELD_VALID(4) | \
+ FILTER_FIELD_VALID(5))
+
+#define FILTER_FIELDS_MAC_VLAN ( \
+ FILTER_FIELD_VALID(1) | \
+ FILTER_FIELD_VALID(2))
+
+#define FILTER_FIELD_USNIC_VLAN FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_USNIC_ETHTYPE FILTER_FIELD_VALID(2)
+#define FILTER_FIELD_USNIC_PROTO FILTER_FIELD_VALID(3)
+#define FILTER_FIELD_USNIC_ID FILTER_FIELD_VALID(4)
+
+struct filter_usnic_id {
+ u32 flags;
+ u16 vlan;
+ u16 ethtype;
+ u8 proto_version;
+ u32 usnic_id;
+} __packed;
+
+#define FILTER_FIELD_5TUP_PROTO FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_5TUP_SRC_AD FILTER_FIELD_VALID(2)
+#define FILTER_FIELD_5TUP_DST_AD FILTER_FIELD_VALID(3)
+#define FILTER_FIELD_5TUP_SRC_PT FILTER_FIELD_VALID(4)
+#define FILTER_FIELD_5TUP_DST_PT FILTER_FIELD_VALID(5)
+
+/* Enums for the protocol field. */
+enum protocol_e {
+ PROTO_UDP = 0,
+ PROTO_TCP = 1,
+};
+
+struct filter_ipv4_5tuple {
+ u32 flags;
+ u32 protocol;
+ u32 src_addr;
+ u32 dst_addr;
+ u16 src_port;
+ u16 dst_port;
+} __packed;
+
+#define FILTER_FIELD_VMQ_VLAN FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_VMQ_MAC FILTER_FIELD_VALID(2)
+
+struct filter_mac_vlan {
+ u32 flags;
+ u16 vlan;
+ u8 mac_addr[6];
+} __packed;
+
+/* Specifies the filter_action type. */
+enum {
+ FILTER_ACTION_RQ_STEERING = 0,
+ FILTER_ACTION_MAX
+};
+
+struct filter_action {
+ u32 type;
+ union {
+ u32 rq_idx;
+ } u;
+} __packed;
+
+/* Specifies the filter type. */
+enum filter_type {
+ FILTER_USNIC_ID = 0,
+ FILTER_IPV4_5TUPLE = 1,
+ FILTER_MAC_VLAN = 2,
+ FILTER_MAX
+};
+
+struct filter {
+ u32 type;
+ union {
+ struct filter_usnic_id usnic;
+ struct filter_ipv4_5tuple ipv4;
+ struct filter_mac_vlan mac_vlan;
+ } u;
+} __packed;
+
+enum {
+ CLSF_TLV_FILTER = 0,
+ CLSF_TLV_ACTION = 1,
+};
+
+/* Maximum size of buffer to CMD_ADD_FILTER */
+#define FILTER_MAX_BUF_SIZE 100
+
+struct filter_tlv {
+ u_int32_t type;
+ u_int32_t length;
+ u_int32_t val[0];
+};
+
/*
* Writing cmd register causes STAT_BUSY to get set in status register.
* When cmd completes, STAT_BUSY will be cleared.
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.c b/drivers/net/ethernet/cisco/enic/vnic_rq.c
index 7e1488f..36a2ed6 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_rq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.c
@@ -30,12 +30,9 @@
static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
{
struct vnic_rq_buf *buf;
- struct vnic_dev *vdev;
unsigned int i, j, count = rq->ring.desc_count;
unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
- vdev = rq->vdev;
-
for (i = 0; i < blks; i++) {
rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
if (!rq->bufs[i])
@@ -141,7 +138,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset)
{
- u32 fetch_index;
+ u32 fetch_index = 0;
/* Use current fetch_index as the ring starting point */
fetch_index = ioread32(&rq->ctrl->fetch_index);
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.h b/drivers/net/ethernet/cisco/enic/vnic_rq.h
index 2056586..ee7bc95 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_rq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.h
@@ -72,6 +72,7 @@ struct vnic_rq_buf {
unsigned int len;
unsigned int index;
void *desc;
+ uint64_t wr_id;
};
struct vnic_rq {
@@ -110,7 +111,8 @@ static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
static inline void vnic_rq_post(struct vnic_rq *rq,
void *os_buf, unsigned int os_buf_index,
- dma_addr_t dma_addr, unsigned int len)
+ dma_addr_t dma_addr, unsigned int len,
+ uint64_t wrid)
{
struct vnic_rq_buf *buf = rq->to_use;
@@ -118,6 +120,7 @@ static inline void vnic_rq_post(struct vnic_rq *rq,
buf->os_buf_index = os_buf_index;
buf->dma_addr = dma_addr;
buf->len = len;
+ buf->wr_id = wrid;
buf = buf->next;
rq->to_use = buf;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.c b/drivers/net/ethernet/cisco/enic/vnic_wq.c
index 5e0d7a2..3e6b8d5 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_wq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.c
@@ -30,12 +30,9 @@
static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
{
struct vnic_wq_buf *buf;
- struct vnic_dev *vdev;
unsigned int i, j, count = wq->ring.desc_count;
unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
- vdev = wq->vdev;
-
for (i = 0; i < blks; i++) {
wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC);
if (!wq->bufs[i])
diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.h b/drivers/net/ethernet/cisco/enic/vnic_wq.h
index 7dd937a..b655667 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_wq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.h
@@ -58,6 +58,10 @@ struct vnic_wq_buf {
unsigned int index;
int sop;
void *desc;
+ uint64_t wr_id; /* Cookie */
+ uint8_t cq_entry; /* Gets completion event from hw */
+ uint8_t desc_skip_cnt; /* Num descs to occupy */
+ uint8_t compressed_send; /* Both hdr and payload in one desc */
};
/* Break the vnic_wq_buf allocations into blocks of 32/64 entries */
@@ -100,16 +104,94 @@ static inline void *vnic_wq_next_desc(struct vnic_wq *wq)
return wq->to_use->desc;
}
+#define PI_LOG2_CACHE_LINE_SIZE 5
+#define PI_INDEX_BITS 12
+#define PI_INDEX_MASK ((1U << PI_INDEX_BITS) - 1)
+#define PI_PREFETCH_LEN_MASK ((1U << PI_LOG2_CACHE_LINE_SIZE) - 1)
+#define PI_PREFETCH_LEN_OFF 16
+#define PI_PREFETCH_ADDR_BITS 43
+#define PI_PREFETCH_ADDR_MASK ((1ULL << PI_PREFETCH_ADDR_BITS) - 1)
+#define PI_PREFETCH_ADDR_OFF 21
+
+/* How many cache lines are touched by buffer (addr, len). */
+static inline unsigned int num_cache_lines_touched(dma_addr_t addr,
+ unsigned int len)
+{
+ const unsigned long mask = PI_PREFETCH_LEN_MASK;
+ const unsigned long laddr = (unsigned long)addr;
+ unsigned long lines, equiv_len;
+ /* A. If addr is aligned, our solution is just to round up len to the
+ * next boundary.
+ *
+ * e.g. addr = 0, len = 48
+ * +--------------------+
+ * |XXXXXXXXXXXXXXXXXXXX| 32-byte cacheline a
+ * +--------------------+
+ * |XXXXXXXXXX | cacheline b
+ * +--------------------+
+ *
+ * B. If addr is not aligned, however, we may use an extra
+ * cacheline. e.g. addr = 12, len = 22
+ *
+ * +--------------------+
+ * | XXXXXXXXXXXXX|
+ * +--------------------+
+ * |XX |
+ * +--------------------+
+ *
+ * Our solution is to make the problem equivalent to case A
+ * above by adding the empty space in the first cacheline to the length:
+ * unsigned long len;
+ *
+ * +--------------------+
+ * |eeeeeeeXXXXXXXXXXXXX| "e" is empty space, which we add to len
+ * +--------------------+
+ * |XX |
+ * +--------------------+
+ */
+ equiv_len = len + (laddr & mask);
+
+ /* Now we can just round up this len to the next 32-byte boundary. */
+ lines = (equiv_len + mask) & (~mask);
+
+ /* Scale bytes -> cachelines. */
+ return lines >> PI_LOG2_CACHE_LINE_SIZE;
+}
+
+static inline u64 vnic_cached_posted_index(dma_addr_t addr,
+ unsigned int len, unsigned int index)
+{
+ unsigned int num_cache_lines = num_cache_lines_touched(addr, len);
+ /* Wish we could avoid a branch here. We could have separate
+ * vnic_wq_post() and vinc_wq_post_inline(), the latter
+ * only supporting < 1k (2^5 * 2^5) sends, I suppose. This would
+ * eliminate the if (eop) branch as well.
+ */
+ if (num_cache_lines > PI_PREFETCH_LEN_MASK)
+ num_cache_lines = 0;
+ return (index & PI_INDEX_MASK) |
+ ((num_cache_lines & PI_PREFETCH_LEN_MASK)
+ << PI_PREFETCH_LEN_OFF) |
+ (((addr >> PI_LOG2_CACHE_LINE_SIZE) &
+ PI_PREFETCH_ADDR_MASK) << PI_PREFETCH_ADDR_OFF);
+}
+
static inline void vnic_wq_post(struct vnic_wq *wq,
void *os_buf, dma_addr_t dma_addr,
- unsigned int len, int sop, int eop)
+ unsigned int len, int sop, int eop,
+ uint8_t desc_skip_cnt, uint8_t cq_entry,
+ uint8_t compressed_send, uint64_t wrid)
{
struct vnic_wq_buf *buf = wq->to_use;
buf->sop = sop;
+ buf->cq_entry = cq_entry;
+ buf->compressed_send = compressed_send;
+ buf->desc_skip_cnt = desc_skip_cnt;
buf->os_buf = eop ? os_buf : NULL;
buf->dma_addr = dma_addr;
buf->len = len;
+ buf->wr_id = wrid;
buf = buf->next;
if (eop) {
@@ -123,7 +205,7 @@ static inline void vnic_wq_post(struct vnic_wq *wq,
}
wq->to_use = buf;
- wq->ring.desc_avail--;
+ wq->ring.desc_avail -= desc_skip_cnt;
}
static inline void vnic_wq_service(struct vnic_wq *wq,
--
1.8.4-rc0
^ permalink raw reply related
* [PATCH v2 2/3] drivers/net: enic: Add an interface for USNIC to interact with firmware
From: Neel Patel @ 2013-08-13 22:19 UTC (permalink / raw)
To: netdev; +Cc: Neel Patel
In-Reply-To: <1376432381-5546-1-git-send-email-neepatel@cisco.com>
This patch adds an interface for USNIC to proxy firmware commands
through ENIC.
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
drivers/net/ethernet/cisco/enic/Makefile | 2 +-
drivers/net/ethernet/cisco/enic/enic.h | 1 +
drivers/net/ethernet/cisco/enic/enic_api.c | 48 +++++++++++++++++++++++++++++
drivers/net/ethernet/cisco/enic/enic_api.h | 30 ++++++++++++++++++
drivers/net/ethernet/cisco/enic/enic_main.c | 3 ++
5 files changed, 83 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.c
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.h
diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/ethernet/cisco/enic/Makefile
index e52296d..239e1e4 100644
--- a/drivers/net/ethernet/cisco/enic/Makefile
+++ b/drivers/net/ethernet/cisco/enic/Makefile
@@ -2,5 +2,5 @@ obj-$(CONFIG_ENIC) := enic.o
enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \
- enic_ethtool.o
+ enic_ethtool.o enic_api.o
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 75e842d..cacca29 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -96,6 +96,7 @@ struct enic {
#ifdef CONFIG_PCI_IOV
u16 num_vfs;
#endif
+ spinlock_t enic_api_lock;
struct enic_port_profile *pp;
/* work queue cache line section */
diff --git a/drivers/net/ethernet/cisco/enic/enic_api.c b/drivers/net/ethernet/cisco/enic/enic_api.c
new file mode 100644
index 0000000..e13efbd
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_api.c
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2013 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+
+#include "vnic_dev.h"
+#include "vnic_devcmd.h"
+
+#include "enic_res.h"
+#include "enic.h"
+#include "enic_api.h"
+
+int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf,
+ enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
+{
+ int err;
+ struct enic *enic = netdev_priv(netdev);
+ struct vnic_dev *vdev = enic->vdev;
+
+ spin_lock(&enic->enic_api_lock);
+ spin_lock(&enic->devcmd_lock);
+
+ vnic_dev_cmd_proxy_by_index_start(vdev, vf);
+ err = vnic_dev_cmd(vdev, cmd, a0, a1, wait);
+ vnic_dev_cmd_proxy_end(vdev);
+
+ spin_unlock(&enic->devcmd_lock);
+ spin_unlock(&enic->enic_api_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(enic_api_devcmd_proxy_by_index);
diff --git a/drivers/net/ethernet/cisco/enic/enic_api.h b/drivers/net/ethernet/cisco/enic/enic_api.h
new file mode 100644
index 0000000..6b9f925
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_api.h
@@ -0,0 +1,30 @@
+/**
+ * Copyright 2013 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __ENIC_API_H__
+#define __ENIC_API_H__
+
+#include <linux/netdevice.h>
+
+#include "vnic_dev.h"
+#include "vnic_devcmd.h"
+
+int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf,
+ enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait);
+
+#endif
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b12b32b..7f8891b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1733,6 +1733,7 @@ static void enic_reset(struct work_struct *work)
rtnl_lock();
+ spin_lock(&enic->enic_api_lock);
enic_dev_hang_notify(enic);
enic_stop(enic->netdev);
enic_dev_hang_reset(enic);
@@ -1741,6 +1742,7 @@ static void enic_reset(struct work_struct *work)
enic_set_rss_nic_cfg(enic);
enic_dev_set_ig_vlan_rewrite_mode(enic);
enic_open(enic->netdev);
+ spin_unlock(&enic->enic_api_lock);
rtnl_unlock();
}
@@ -2153,6 +2155,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
spin_lock_init(&enic->devcmd_lock);
+ spin_lock_init(&enic->enic_api_lock);
/*
* Set ingress vlan rewrite mode before vnic initialization
--
1.8.4-rc0
^ permalink raw reply related
* [PATCH v2 0/3] enic: This patchset adds support for Cisco Low Latency NIC
From: Neel Patel @ 2013-08-13 22:19 UTC (permalink / raw)
To: netdev; +Cc: Neel Patel
v1 -> v2:
- Removed OOM messages
- Removed ethtool patch where, enic was storing ASIC info in a reserved
field of ethtool_drvinfo structure
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Neel Patel (3):
drivers/net: enic: Adding support for Cisco Low Latency NIC
drivers/net: enic: Add an interface for USNIC to interact with
firmware
drivers/net: enic: Generate notification of hardware crash
drivers/net/ethernet/cisco/enic/Makefile | 2 +-
drivers/net/ethernet/cisco/enic/enic.h | 5 +-
drivers/net/ethernet/cisco/enic/enic_api.c | 48 +++++++
drivers/net/ethernet/cisco/enic/enic_api.h | 30 +++++
drivers/net/ethernet/cisco/enic/enic_main.c | 4 +
drivers/net/ethernet/cisco/enic/enic_res.h | 9 +-
drivers/net/ethernet/cisco/enic/vnic_dev.c | 5 +
drivers/net/ethernet/cisco/enic/vnic_dev.h | 1 +
drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 176 +++++++++++++++++++++++++-
drivers/net/ethernet/cisco/enic/vnic_rq.c | 5 +-
drivers/net/ethernet/cisco/enic/vnic_rq.h | 5 +-
drivers/net/ethernet/cisco/enic/vnic_wq.c | 3 -
drivers/net/ethernet/cisco/enic/vnic_wq.h | 86 ++++++++++++-
13 files changed, 360 insertions(+), 19 deletions(-)
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.c
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.h
--
1.8.4-rc0
^ permalink raw reply
* [PATCH v2 2/3] drivers/net: enic: Add an interface for USNIC to interact with firmware
From: Neel Patel @ 2013-08-13 22:17 UTC (permalink / raw)
To: netdev; +Cc: umalhi, Neel Patel, Nishank Trivedi, Christian Benvenuti
In-Reply-To: <1376432265-5497-1-git-send-email-neepatel@cisco.com>
This patch adds an interface for USNIC to proxy firmware commands
through ENIC.
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
drivers/net/ethernet/cisco/enic/Makefile | 2 +-
drivers/net/ethernet/cisco/enic/enic.h | 1 +
drivers/net/ethernet/cisco/enic/enic_api.c | 48 +++++++++++++++++++++++++++++
drivers/net/ethernet/cisco/enic/enic_api.h | 30 ++++++++++++++++++
drivers/net/ethernet/cisco/enic/enic_main.c | 3 ++
5 files changed, 83 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.c
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.h
diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/ethernet/cisco/enic/Makefile
index e52296d..239e1e4 100644
--- a/drivers/net/ethernet/cisco/enic/Makefile
+++ b/drivers/net/ethernet/cisco/enic/Makefile
@@ -2,5 +2,5 @@ obj-$(CONFIG_ENIC) := enic.o
enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \
- enic_ethtool.o
+ enic_ethtool.o enic_api.o
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 75e842d..cacca29 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -96,6 +96,7 @@ struct enic {
#ifdef CONFIG_PCI_IOV
u16 num_vfs;
#endif
+ spinlock_t enic_api_lock;
struct enic_port_profile *pp;
/* work queue cache line section */
diff --git a/drivers/net/ethernet/cisco/enic/enic_api.c b/drivers/net/ethernet/cisco/enic/enic_api.c
new file mode 100644
index 0000000..e13efbd
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_api.c
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2013 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+
+#include "vnic_dev.h"
+#include "vnic_devcmd.h"
+
+#include "enic_res.h"
+#include "enic.h"
+#include "enic_api.h"
+
+int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf,
+ enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
+{
+ int err;
+ struct enic *enic = netdev_priv(netdev);
+ struct vnic_dev *vdev = enic->vdev;
+
+ spin_lock(&enic->enic_api_lock);
+ spin_lock(&enic->devcmd_lock);
+
+ vnic_dev_cmd_proxy_by_index_start(vdev, vf);
+ err = vnic_dev_cmd(vdev, cmd, a0, a1, wait);
+ vnic_dev_cmd_proxy_end(vdev);
+
+ spin_unlock(&enic->devcmd_lock);
+ spin_unlock(&enic->enic_api_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(enic_api_devcmd_proxy_by_index);
diff --git a/drivers/net/ethernet/cisco/enic/enic_api.h b/drivers/net/ethernet/cisco/enic/enic_api.h
new file mode 100644
index 0000000..6b9f925
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_api.h
@@ -0,0 +1,30 @@
+/**
+ * Copyright 2013 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __ENIC_API_H__
+#define __ENIC_API_H__
+
+#include <linux/netdevice.h>
+
+#include "vnic_dev.h"
+#include "vnic_devcmd.h"
+
+int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf,
+ enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait);
+
+#endif
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b12b32b..7f8891b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1733,6 +1733,7 @@ static void enic_reset(struct work_struct *work)
rtnl_lock();
+ spin_lock(&enic->enic_api_lock);
enic_dev_hang_notify(enic);
enic_stop(enic->netdev);
enic_dev_hang_reset(enic);
@@ -1741,6 +1742,7 @@ static void enic_reset(struct work_struct *work)
enic_set_rss_nic_cfg(enic);
enic_dev_set_ig_vlan_rewrite_mode(enic);
enic_open(enic->netdev);
+ spin_unlock(&enic->enic_api_lock);
rtnl_unlock();
}
@@ -2153,6 +2155,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
spin_lock_init(&enic->devcmd_lock);
+ spin_lock_init(&enic->enic_api_lock);
/*
* Set ingress vlan rewrite mode before vnic initialization
--
1.8.4-rc0
^ permalink raw reply related
* [PATCH v2 3/3] drivers/net: enic: Generate notification of hardware crash
From: Neel Patel @ 2013-08-13 22:17 UTC (permalink / raw)
To: netdev; +Cc: umalhi, Neel Patel, Nishank Trivedi, Christian Benvenuti
In-Reply-To: <1376432265-5497-1-git-send-email-neepatel@cisco.com>
This patch generates a hardware crash notification (NETDEV_REBOOT)
during reset. After a hardware crash, ENIC resets all its resources
including queue pair filters programmed by USNIC. USNIC registers for
this notification, and on receiving it, reprograms the queue pair
filters.
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
drivers/net/ethernet/cisco/enic/enic.h | 2 +-
drivers/net/ethernet/cisco/enic/enic_main.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index cacca29..be16731 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -32,7 +32,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.39"
+#define DRV_VERSION "2.1.1.43"
#define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 7f8891b..bcf15b1 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1743,6 +1743,7 @@ static void enic_reset(struct work_struct *work)
enic_dev_set_ig_vlan_rewrite_mode(enic);
enic_open(enic->netdev);
spin_unlock(&enic->enic_api_lock);
+ call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
rtnl_unlock();
}
--
1.8.4-rc0
^ permalink raw reply related
* [PATCH v2 1/3] drivers/net: enic: Adding support for Cisco Low Latency NIC
From: Neel Patel @ 2013-08-13 22:17 UTC (permalink / raw)
To: netdev; +Cc: umalhi, Neel Patel, Nishank Trivedi, Christian Benvenuti
In-Reply-To: <1376432265-5497-1-git-send-email-neepatel@cisco.com>
This patch,
- Adds new firmware commands for the new Cisco Low Latency NIC
(aka. USNIC).
- Enables descriptor prefetch on the hardware. This feature
reduces latency for small packet transmit.
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
drivers/net/ethernet/cisco/enic/enic.h | 2 +-
drivers/net/ethernet/cisco/enic/enic_res.h | 9 +-
drivers/net/ethernet/cisco/enic/vnic_dev.c | 5 +
drivers/net/ethernet/cisco/enic/vnic_dev.h | 1 +
drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 176 +++++++++++++++++++++++++-
drivers/net/ethernet/cisco/enic/vnic_rq.c | 5 +-
drivers/net/ethernet/cisco/enic/vnic_rq.h | 5 +-
drivers/net/ethernet/cisco/enic/vnic_wq.c | 3 -
drivers/net/ethernet/cisco/enic/vnic_wq.h | 86 ++++++++++++-
9 files changed, 275 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 2e37c63..75e842d 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -33,7 +33,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
#define DRV_VERSION "2.1.1.39"
-#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
+#define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
diff --git a/drivers/net/ethernet/cisco/enic/enic_res.h b/drivers/net/ethernet/cisco/enic/enic_res.h
index 25be273..69f60af 100644
--- a/drivers/net/ethernet/cisco/enic/enic_res.h
+++ b/drivers/net/ethernet/cisco/enic/enic_res.h
@@ -47,6 +47,9 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
int offload_mode, int cq_entry, int sop, int eop, int loopback)
{
struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
+ u8 desc_skip_cnt = 1;
+ u8 compressed_send = 0;
+ u64 wrid = 0;
wq_enet_desc_enc(desc,
(u64)dma_addr | VNIC_PADDR_TARGET,
@@ -59,7 +62,8 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
(u16)vlan_tag,
(u8)loopback);
- vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
+ vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop, desc_skip_cnt,
+ (u8)cq_entry, compressed_send, wrid);
}
static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq,
@@ -120,6 +124,7 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
dma_addr_t dma_addr, unsigned int len)
{
struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
+ u64 wrid = 0;
u8 type = os_buf_index ?
RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP;
@@ -127,7 +132,7 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
(u64)dma_addr | VNIC_PADDR_TARGET,
type, (u16)len);
- vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len);
+ vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len, wrid);
}
struct enic;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index 97455c5..1b436b3 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -970,6 +970,11 @@ err_out:
return NULL;
}
+struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev)
+{
+ return vdev->pdev;
+}
+
int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len)
{
u64 a0, a1 = len;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index f3d9b79..e670029 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -127,6 +127,7 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
unsigned int num_bars);
+struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev);
int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len);
int vnic_dev_enable2(struct vnic_dev *vdev, int active);
int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
index 23d5552..b9a0d78 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
@@ -281,11 +281,25 @@ enum vnic_devcmd_cmd {
* 0 if no VIF-CONFIG-INFO TLV was ever received. */
CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
+ /* INT13 API: (u64)a0=paddr to vnic_int13_params struct
+ * (u32)a1=INT13_CMD_xxx
+ */
+ CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45),
+
+ /* Set default vlan:
+ * in: (u16)a0=new default vlan
+ * (u16)a1=zero for overriding vlan with param a0,
+ * non-zero for resetting vlan to the default
+ * out: (u16)a0=old default vlan
+ */
+ CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46),
+
/* init_prov_info2:
* Variant of CMD_INIT_PROV_INFO, where it will not try to enable
* the vnic until CMD_ENABLE2 is issued.
* (u64)a0=paddr of vnic_devcmd_provinfo
- * (u32)a1=sizeof provision info */
+ * (u32)a1=sizeof provision info
+ */
CMD_INIT_PROV_INFO2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47),
/* enable2:
@@ -339,16 +353,57 @@ enum vnic_devcmd_cmd {
CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
/*
- * cmd_set_mac_addr
- * set mac address
+ * Set the predefined mac address as default
* in:
* (u48)a0 = mac addr
- *
*/
CMD_SET_MAC_ADDR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 55),
+
+ /* Update the provisioning info of the given VIF
+ * (u64)a0=paddr of vnic_devcmd_provinfo
+ * (u32)a1=sizeof provision info
+ */
+ CMD_PROV_INFO_UPDATE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 56),
+
+ /* Add a filter.
+ * in: (u64) a0= filter address
+ * (u32) a1= size of filter
+ * out: (u32) a0=filter identifier
+ */
+ CMD_ADD_FILTER = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 58),
+
+ /* Delete a filter.
+ * in: (u32) a0=filter identifier
+ */
+ CMD_DEL_FILTER = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 59),
+
+ /* Enable a Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ * (u32) a1= command
+ */
+ CMD_QP_ENABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 60),
+
+ /* Disable a Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ * (u32) a1= command
+ */
+ CMD_QP_DISABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 61),
+
+ /* Stats dump Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ * (u64) a1=host buffer addr for status dump
+ * (u32) a2=length of the buffer
+ */
+ CMD_QP_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 62),
+
+ /* Clear stats for Queue Pair in User space NIC
+ * in: (u32) a0=Queue Pair number
+ */
+ CMD_QP_STATS_CLEAR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 63),
};
/* CMD_ENABLE2 flags */
+#define CMD_ENABLE2_STANDBY 0x0
#define CMD_ENABLE2_ACTIVE 0x1
/* flags for CMD_OPEN */
@@ -364,6 +419,9 @@ enum vnic_devcmd_cmd {
#define CMD_PFILTER_PROMISCUOUS 0x08
#define CMD_PFILTER_ALL_MULTICAST 0x10
+/* Commands for CMD_QP_ENABLE/CM_QP_DISABLE */
+#define CMD_QP_RQWQ 0x0
+
/* rewrite modes for CMD_IG_VLAN_REWRITE_MODE */
#define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK 0
#define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN 1
@@ -390,6 +448,7 @@ enum vnic_devcmd_error {
ERR_EMAXRES = 10,
ERR_ENOTSUPPORTED = 11,
ERR_EINPROGRESS = 12,
+ ERR_MAX
};
/*
@@ -435,6 +494,115 @@ struct vnic_devcmd_provinfo {
u8 data[0];
};
+/* These are used in flags field of different filters to denote
+ * valid fields used.
+ */
+#define FILTER_FIELD_VALID(fld) (1 << (fld - 1))
+
+#define FILTER_FIELDS_USNIC ( \
+ FILTER_FIELD_VALID(1) | \
+ FILTER_FIELD_VALID(2) | \
+ FILTER_FIELD_VALID(3) | \
+ FILTER_FIELD_VALID(4))
+
+#define FILTER_FIELDS_IPV4_5TUPLE ( \
+ FILTER_FIELD_VALID(1) | \
+ FILTER_FIELD_VALID(2) | \
+ FILTER_FIELD_VALID(3) | \
+ FILTER_FIELD_VALID(4) | \
+ FILTER_FIELD_VALID(5))
+
+#define FILTER_FIELDS_MAC_VLAN ( \
+ FILTER_FIELD_VALID(1) | \
+ FILTER_FIELD_VALID(2))
+
+#define FILTER_FIELD_USNIC_VLAN FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_USNIC_ETHTYPE FILTER_FIELD_VALID(2)
+#define FILTER_FIELD_USNIC_PROTO FILTER_FIELD_VALID(3)
+#define FILTER_FIELD_USNIC_ID FILTER_FIELD_VALID(4)
+
+struct filter_usnic_id {
+ u32 flags;
+ u16 vlan;
+ u16 ethtype;
+ u8 proto_version;
+ u32 usnic_id;
+} __packed;
+
+#define FILTER_FIELD_5TUP_PROTO FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_5TUP_SRC_AD FILTER_FIELD_VALID(2)
+#define FILTER_FIELD_5TUP_DST_AD FILTER_FIELD_VALID(3)
+#define FILTER_FIELD_5TUP_SRC_PT FILTER_FIELD_VALID(4)
+#define FILTER_FIELD_5TUP_DST_PT FILTER_FIELD_VALID(5)
+
+/* Enums for the protocol field. */
+enum protocol_e {
+ PROTO_UDP = 0,
+ PROTO_TCP = 1,
+};
+
+struct filter_ipv4_5tuple {
+ u32 flags;
+ u32 protocol;
+ u32 src_addr;
+ u32 dst_addr;
+ u16 src_port;
+ u16 dst_port;
+} __packed;
+
+#define FILTER_FIELD_VMQ_VLAN FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_VMQ_MAC FILTER_FIELD_VALID(2)
+
+struct filter_mac_vlan {
+ u32 flags;
+ u16 vlan;
+ u8 mac_addr[6];
+} __packed;
+
+/* Specifies the filter_action type. */
+enum {
+ FILTER_ACTION_RQ_STEERING = 0,
+ FILTER_ACTION_MAX
+};
+
+struct filter_action {
+ u32 type;
+ union {
+ u32 rq_idx;
+ } u;
+} __packed;
+
+/* Specifies the filter type. */
+enum filter_type {
+ FILTER_USNIC_ID = 0,
+ FILTER_IPV4_5TUPLE = 1,
+ FILTER_MAC_VLAN = 2,
+ FILTER_MAX
+};
+
+struct filter {
+ u32 type;
+ union {
+ struct filter_usnic_id usnic;
+ struct filter_ipv4_5tuple ipv4;
+ struct filter_mac_vlan mac_vlan;
+ } u;
+} __packed;
+
+enum {
+ CLSF_TLV_FILTER = 0,
+ CLSF_TLV_ACTION = 1,
+};
+
+/* Maximum size of buffer to CMD_ADD_FILTER */
+#define FILTER_MAX_BUF_SIZE 100
+
+struct filter_tlv {
+ u_int32_t type;
+ u_int32_t length;
+ u_int32_t val[0];
+};
+
/*
* Writing cmd register causes STAT_BUSY to get set in status register.
* When cmd completes, STAT_BUSY will be cleared.
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.c b/drivers/net/ethernet/cisco/enic/vnic_rq.c
index 7e1488f..36a2ed6 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_rq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.c
@@ -30,12 +30,9 @@
static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
{
struct vnic_rq_buf *buf;
- struct vnic_dev *vdev;
unsigned int i, j, count = rq->ring.desc_count;
unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
- vdev = rq->vdev;
-
for (i = 0; i < blks; i++) {
rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
if (!rq->bufs[i])
@@ -141,7 +138,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset)
{
- u32 fetch_index;
+ u32 fetch_index = 0;
/* Use current fetch_index as the ring starting point */
fetch_index = ioread32(&rq->ctrl->fetch_index);
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.h b/drivers/net/ethernet/cisco/enic/vnic_rq.h
index 2056586..ee7bc95 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_rq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.h
@@ -72,6 +72,7 @@ struct vnic_rq_buf {
unsigned int len;
unsigned int index;
void *desc;
+ uint64_t wr_id;
};
struct vnic_rq {
@@ -110,7 +111,8 @@ static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
static inline void vnic_rq_post(struct vnic_rq *rq,
void *os_buf, unsigned int os_buf_index,
- dma_addr_t dma_addr, unsigned int len)
+ dma_addr_t dma_addr, unsigned int len,
+ uint64_t wrid)
{
struct vnic_rq_buf *buf = rq->to_use;
@@ -118,6 +120,7 @@ static inline void vnic_rq_post(struct vnic_rq *rq,
buf->os_buf_index = os_buf_index;
buf->dma_addr = dma_addr;
buf->len = len;
+ buf->wr_id = wrid;
buf = buf->next;
rq->to_use = buf;
diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.c b/drivers/net/ethernet/cisco/enic/vnic_wq.c
index 5e0d7a2..3e6b8d5 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_wq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.c
@@ -30,12 +30,9 @@
static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
{
struct vnic_wq_buf *buf;
- struct vnic_dev *vdev;
unsigned int i, j, count = wq->ring.desc_count;
unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
- vdev = wq->vdev;
-
for (i = 0; i < blks; i++) {
wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC);
if (!wq->bufs[i])
diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.h b/drivers/net/ethernet/cisco/enic/vnic_wq.h
index 7dd937a..b655667 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_wq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.h
@@ -58,6 +58,10 @@ struct vnic_wq_buf {
unsigned int index;
int sop;
void *desc;
+ uint64_t wr_id; /* Cookie */
+ uint8_t cq_entry; /* Gets completion event from hw */
+ uint8_t desc_skip_cnt; /* Num descs to occupy */
+ uint8_t compressed_send; /* Both hdr and payload in one desc */
};
/* Break the vnic_wq_buf allocations into blocks of 32/64 entries */
@@ -100,16 +104,94 @@ static inline void *vnic_wq_next_desc(struct vnic_wq *wq)
return wq->to_use->desc;
}
+#define PI_LOG2_CACHE_LINE_SIZE 5
+#define PI_INDEX_BITS 12
+#define PI_INDEX_MASK ((1U << PI_INDEX_BITS) - 1)
+#define PI_PREFETCH_LEN_MASK ((1U << PI_LOG2_CACHE_LINE_SIZE) - 1)
+#define PI_PREFETCH_LEN_OFF 16
+#define PI_PREFETCH_ADDR_BITS 43
+#define PI_PREFETCH_ADDR_MASK ((1ULL << PI_PREFETCH_ADDR_BITS) - 1)
+#define PI_PREFETCH_ADDR_OFF 21
+
+/* How many cache lines are touched by buffer (addr, len). */
+static inline unsigned int num_cache_lines_touched(dma_addr_t addr,
+ unsigned int len)
+{
+ const unsigned long mask = PI_PREFETCH_LEN_MASK;
+ const unsigned long laddr = (unsigned long)addr;
+ unsigned long lines, equiv_len;
+ /* A. If addr is aligned, our solution is just to round up len to the
+ * next boundary.
+ *
+ * e.g. addr = 0, len = 48
+ * +--------------------+
+ * |XXXXXXXXXXXXXXXXXXXX| 32-byte cacheline a
+ * +--------------------+
+ * |XXXXXXXXXX | cacheline b
+ * +--------------------+
+ *
+ * B. If addr is not aligned, however, we may use an extra
+ * cacheline. e.g. addr = 12, len = 22
+ *
+ * +--------------------+
+ * | XXXXXXXXXXXXX|
+ * +--------------------+
+ * |XX |
+ * +--------------------+
+ *
+ * Our solution is to make the problem equivalent to case A
+ * above by adding the empty space in the first cacheline to the length:
+ * unsigned long len;
+ *
+ * +--------------------+
+ * |eeeeeeeXXXXXXXXXXXXX| "e" is empty space, which we add to len
+ * +--------------------+
+ * |XX |
+ * +--------------------+
+ */
+ equiv_len = len + (laddr & mask);
+
+ /* Now we can just round up this len to the next 32-byte boundary. */
+ lines = (equiv_len + mask) & (~mask);
+
+ /* Scale bytes -> cachelines. */
+ return lines >> PI_LOG2_CACHE_LINE_SIZE;
+}
+
+static inline u64 vnic_cached_posted_index(dma_addr_t addr,
+ unsigned int len, unsigned int index)
+{
+ unsigned int num_cache_lines = num_cache_lines_touched(addr, len);
+ /* Wish we could avoid a branch here. We could have separate
+ * vnic_wq_post() and vinc_wq_post_inline(), the latter
+ * only supporting < 1k (2^5 * 2^5) sends, I suppose. This would
+ * eliminate the if (eop) branch as well.
+ */
+ if (num_cache_lines > PI_PREFETCH_LEN_MASK)
+ num_cache_lines = 0;
+ return (index & PI_INDEX_MASK) |
+ ((num_cache_lines & PI_PREFETCH_LEN_MASK)
+ << PI_PREFETCH_LEN_OFF) |
+ (((addr >> PI_LOG2_CACHE_LINE_SIZE) &
+ PI_PREFETCH_ADDR_MASK) << PI_PREFETCH_ADDR_OFF);
+}
+
static inline void vnic_wq_post(struct vnic_wq *wq,
void *os_buf, dma_addr_t dma_addr,
- unsigned int len, int sop, int eop)
+ unsigned int len, int sop, int eop,
+ uint8_t desc_skip_cnt, uint8_t cq_entry,
+ uint8_t compressed_send, uint64_t wrid)
{
struct vnic_wq_buf *buf = wq->to_use;
buf->sop = sop;
+ buf->cq_entry = cq_entry;
+ buf->compressed_send = compressed_send;
+ buf->desc_skip_cnt = desc_skip_cnt;
buf->os_buf = eop ? os_buf : NULL;
buf->dma_addr = dma_addr;
buf->len = len;
+ buf->wr_id = wrid;
buf = buf->next;
if (eop) {
@@ -123,7 +205,7 @@ static inline void vnic_wq_post(struct vnic_wq *wq,
}
wq->to_use = buf;
- wq->ring.desc_avail--;
+ wq->ring.desc_avail -= desc_skip_cnt;
}
static inline void vnic_wq_service(struct vnic_wq *wq,
--
1.8.4-rc0
^ permalink raw reply related
* [PATCH v2 0/3] enic: This patchset adds support for Cisco Low Latency NIC
From: Neel Patel @ 2013-08-13 22:17 UTC (permalink / raw)
To: netdev; +Cc: umalhi, Neel Patel, Nishank Trivedi, Christian Benvenuti
v1 -> v2:
- Removed OOM messages
- Removed ethtool patch where, enic was storing ASIC info in a reserved
field of ethtool_drvinfo structure
Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Neel Patel (3):
drivers/net: enic: Adding support for Cisco Low Latency NIC
drivers/net: enic: Add an interface for USNIC to interact with
firmware
drivers/net: enic: Generate notification of hardware crash
drivers/net/ethernet/cisco/enic/Makefile | 2 +-
drivers/net/ethernet/cisco/enic/enic.h | 5 +-
drivers/net/ethernet/cisco/enic/enic_api.c | 48 +++++++
drivers/net/ethernet/cisco/enic/enic_api.h | 30 +++++
drivers/net/ethernet/cisco/enic/enic_main.c | 4 +
drivers/net/ethernet/cisco/enic/enic_res.h | 9 +-
drivers/net/ethernet/cisco/enic/vnic_dev.c | 5 +
drivers/net/ethernet/cisco/enic/vnic_dev.h | 1 +
drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 176 +++++++++++++++++++++++++-
drivers/net/ethernet/cisco/enic/vnic_rq.c | 5 +-
drivers/net/ethernet/cisco/enic/vnic_rq.h | 5 +-
drivers/net/ethernet/cisco/enic/vnic_wq.c | 3 -
drivers/net/ethernet/cisco/enic/vnic_wq.h | 86 ++++++++++++-
13 files changed, 360 insertions(+), 19 deletions(-)
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.c
create mode 100644 drivers/net/ethernet/cisco/enic/enic_api.h
--
1.8.4-rc0
^ permalink raw reply
* Re: [PATCH] 6lowpan: handle only real link-local addresses
From: David Miller @ 2013-08-13 22:12 UTC (permalink / raw)
To: alex.aring; +Cc: alex.bluesman.smirnov, dbaryshkov, linux-zigbee-devel, netdev
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring@gmail.com>
You're submitting 7 patches, one set is numbered 1-6 and this
one has no number.
What in the world do you want me to do with these patches?
What tree are they targetted at?
Are there dependencies?
What order should I apply them in?
You've given me none of this information, therefore I am tossing
all of these patches and you will need to submit them properly
all over again.
Thanks.
^ permalink raw reply
* Re: [PATCH net-next] pptp: fix byte order warnings
From: David Miller @ 2013-08-13 22:11 UTC (permalink / raw)
To: stephen; +Cc: xeb, netdev
In-Reply-To: <20130810152258.1cef6d89@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Sat, 10 Aug 2013 15:22:58 -0700
> Pptp driver has lots of byte order warnings from sparse.
> This was because the on-the-wire header is in network byte order (obviously)
> but the definition did not reflect that.
>
> Also, the address structure to user space actually put the call id
> in host order. Rather than break ABI compatibility, just acknowledge
> the existing design.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net] skge: dma_sync the whole receive buffer
From: David Miller @ 2013-08-13 22:09 UTC (permalink / raw)
To: stephen; +Cc: pomidorabelisima, netdev
In-Reply-To: <20130810150207.37432299@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Sat, 10 Aug 2013 15:02:07 -0700
> The DMA sync should sync the whole receive buffer, not just
> part of it. Fixes log messages dma_sync_check.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Applied, but I really suspect that your "check DMA mapping errors"
patch has added a serious regression. A regression much worse than
the bug you were trying to fix with that change.
^ permalink raw reply
* Re: [PATCH net-next] net: sctp: Add rudimentary infrastructure to account for control chunks
From: David Miller @ 2013-08-13 22:04 UTC (permalink / raw)
To: vyasevich; +Cc: netdev, linux-sctp, dborkman, eric.dumazet
In-Reply-To: <1376100336-21481-1-git-send-email-vyasevich@gmail.com>
From: Vlad Yasevich <vyasevich@gmail.com>
Date: Fri, 9 Aug 2013 22:05:36 -0400
> This patch adds a base infrastructure that allows SCTP to do
> memory accounting for control chunks. Real accounting code will
> follow.
>
> This patch alos fixes the following triggered bug ...
...
> The approach taken here is to split data and control chunks
> creation a bit. Data chunks already have memory accounting
> so noting needs to happen. For control chunks, add stubs handlers.
>
> Signed-off-by: Vlad Yasevich <vyasevich@gmail.com>
Applied, but:
> + /* TODO: properly account for control chunks.
I had to delete the trailing whitespace on that line.
^ permalink raw reply
* Re: [PATCH V2 0/4] Enable bus master till the FLR completes for Chelsio T4
From: Casey Leedom @ 2013-08-13 21:53 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Vipul Pandya, linux-pci@vger.kernel.org, tomreu, divy, dm,
nirranjan, eilong, netdev
In-Reply-To: <CAErSpo7=oBG3tJBpwscnL-4D-9kLhHUrQSZFrRRC4sBsT2_U2Q@mail.gmail.com>
On 08/12/13 14:17, Bjorn Helgaas wrote:
> On Tue, Aug 6, 2013 at 4:18 AM, Vipul Pandya <vipul@chelsio.com> wrote:
>> This patch series adds device specific reset method for Chelsio T4 adapters.
>>
>> ...
> Applied to my "next" branch for v3.12, thanks!
>
Thanks Bjorn! Do you have an idea when these commits will hit Linus'
repository and what their git commit IDs will be? We have a customer
using SLES11sp2 who needs this and once the commits hit Linus'
repository we'll need to send a request to Novell to pull the change
sets into SLES11sp2. Thanks!
Casey
^ permalink raw reply
* [PATCH 5/6] 6lowpan: lowpan_uncompress_addr with address_mode
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch drop the pre and postcount calculation from the
lowpan_uncompress_addr function.
We use instead a switch case over address_mode value, it's easier
to understand what's going on there.
Signed-off-by: Alexander Aring <alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.c | 144 +++++++++++++++++++++++++----------------------
net/ieee802154/6lowpan.h | 8 ++-
2 files changed, 82 insertions(+), 70 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 0df8874..d299560 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -67,30 +67,6 @@ static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
static LIST_HEAD(lowpan_devices);
-/*
- * Uncompression of linklocal:
- * 0 -> 16 bytes from packet
- * 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet
- * 2 -> 2 bytes from prefix - zeroes + 2 from packet
- * 3 -> 2 bytes from prefix - infer 8 bytes from lladdr
- *
- * NOTE: => the uncompress function does change 0xf to 0x10
- * NOTE: 0x00 => no-autoconfig => unspecified
- */
-static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
-
-/*
- * Uncompression of ctx-based:
- * 0 -> 0 bits from packet [unspecified / reserved]
- * 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet
- * 2 -> 8 bytes from prefix - zeroes + 2 from packet
- * 3 -> 8 bytes from prefix - infer 8 bytes from lladdr
- */
-static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
-
-/* Link local prefix */
-static const u8 lowpan_llprefix[] = {0xfe, 0x80};
-
/* private device info */
struct lowpan_dev_info {
struct net_device *real_dev; /* real WPAN device ptr */
@@ -182,50 +158,86 @@ lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
return rol8(val, shift);
}
-static void
-lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr)
-{
- memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ADDR_LEN);
- /* second bit-flip (Universe/Local) is done according RFC2464 */
- ipaddr->s6_addr[8] ^= 0x02;
-}
-
/*
- * Uncompress addresses based on a prefix and a postfix with zeroes in
- * between. If the postfix is zero in length it will use the link address
- * to configure the IP address (autoconf style).
- * pref_post_count takes a byte where the first nibble specify prefix count
- * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
+ * Uncompress address function for source and
+ * destination address(non-multicast).
+ *
+ * address_mode is sam value or dam value.
*/
static int
-lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
- u8 const *prefix, u8 pref_post_count, unsigned char *lladdr)
+lowpan_uncompress_addr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 address_mode,
+ const struct ieee802154_addr *lladdr)
{
- u8 prefcount = pref_post_count >> 4;
- u8 postcount = pref_post_count & 0x0f;
-
- /* full nibble 15 => 16 */
- prefcount = (prefcount == 15 ? 16 : prefcount);
- postcount = (postcount == 15 ? 16 : postcount);
-
- if (lladdr)
- lowpan_raw_dump_inline(__func__, "linklocal address",
- lladdr, IEEE802154_ADDR_LEN);
- if (prefcount > 0)
- memcpy(ipaddr, prefix, prefcount);
-
- if (postcount > 0) {
- memcpy(&ipaddr->s6_addr[16 - postcount], skb->data, postcount);
- skb_pull(skb, postcount);
- } else if (prefcount > 0) {
- if (lladdr == NULL)
+ bool fail;
+
+ switch (address_mode) {
+ case LOWPAN_IPHC_ADDR_00:
+ /* for global link addresses */
+ fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+ break;
+ case LOWPAN_IPHC_ADDR_01:
+ /* fe:80::XXXX:XXXX:XXXX:XXXX */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
+ break;
+ case LOWPAN_IPHC_ADDR_02:
+ /* fe:80::ff:fe00:XXXX */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ ipaddr->s6_addr[11] = 0xFF;
+ ipaddr->s6_addr[12] = 0xFE;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
+ break;
+ case LOWPAN_IPHC_ADDR_03:
+ fail = false;
+ switch (lladdr->addr_type) {
+ case IEEE802154_ADDR_LONG:
+ /* fe:80::XXXX:XXXX:XXXX:XXXX
+ * \_________________/
+ * hwaddr
+ */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr,
+ IEEE802154_ADDR_LEN);
+ /* second bit-flip (Universe/Local)
+ * is done according RFC2464
+ */
+ ipaddr->s6_addr[8] ^= 0x02;
+ break;
+ case IEEE802154_ADDR_SHORT:
+ /* fe:80::ff:fe00:XXXX
+ * \__/
+ * short_addr
+ *
+ * Universe/Local bit is zero.
+ */
+ ipaddr->s6_addr[0] = 0xFE;
+ ipaddr->s6_addr[1] = 0x80;
+ ipaddr->s6_addr[11] = 0xFF;
+ ipaddr->s6_addr[12] = 0xFE;
+ memcpy(&ipaddr->s6_addr[14], &lladdr->short_addr,
+ UIP_802154_SHORTADDR_LEN);
+ break;
+ default:
+ pr_debug("Invalid addr_type set\n");
return -EINVAL;
+ }
+ break;
+ default:
+ pr_debug("Invalid address mode value: 0x%x\n", address_mode);
+ return -EINVAL;
+ }
- /* no IID based configuration if no prefix and no data */
- lowpan_uip_ds6_set_addr_iid(ipaddr, lladdr);
+ if (fail) {
+ pr_debug("Failed to fetch skb data\n");
+ return -EIO;
}
- pr_debug("uncompressing %d + %d => ", prefcount, postcount);
+ pr_debug("Reconstructed ipv6 addr is:\n");
lowpan_raw_dump_inline(NULL, NULL, ipaddr->s6_addr, 16);
return 0;
@@ -775,7 +787,7 @@ lowpan_process_data(struct sk_buff *skb)
{
struct ipv6hdr hdr = {};
u8 tmp, iphc0, iphc1, num_context = 0;
- u8 *_saddr, *_daddr;
+ const struct ieee802154_addr *_saddr, *_daddr;
int err;
lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
@@ -878,8 +890,8 @@ lowpan_process_data(struct sk_buff *skb)
if (lowpan_fetch_skb_u8(skb, &iphc1))
goto drop;
- _saddr = mac_cb(skb)->sa.hwaddr;
- _daddr = mac_cb(skb)->da.hwaddr;
+ _saddr = &mac_cb(skb)->sa;
+ _daddr = &mac_cb(skb)->da;
pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1);
@@ -961,8 +973,7 @@ lowpan_process_data(struct sk_buff *skb)
/* Source address uncompression */
pr_debug("source address stateless compression\n");
- err = lowpan_uncompress_addr(skb, &hdr.saddr, lowpan_llprefix,
- lowpan_unc_llconf[tmp], skb->data);
+ err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
if (err)
goto drop;
@@ -982,8 +993,7 @@ lowpan_process_data(struct sk_buff *skb)
}
} else {
pr_debug("dest: stateless compression\n");
- err = lowpan_uncompress_addr(skb, &hdr.daddr, lowpan_llprefix,
- lowpan_unc_llconf[tmp], skb->data);
+ err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr);
if (err)
goto drop;
}
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index e3348ec..6596644 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -196,10 +196,12 @@
/* Values of fields within the IPHC encoding second byte */
#define LOWPAN_IPHC_CID 0x80
+#define LOWPAN_IPHC_ADDR_00 0x00
+#define LOWPAN_IPHC_ADDR_01 0x01
+#define LOWPAN_IPHC_ADDR_02 0x02
+#define LOWPAN_IPHC_ADDR_03 0x03
+
#define LOWPAN_IPHC_SAC 0x40
-#define LOWPAN_IPHC_SAM_00 0x00
-#define LOWPAN_IPHC_SAM_01 0x10
-#define LOWPAN_IPHC_SAM_10 0x20
#define LOWPAN_IPHC_SAM 0x30
#define LOWPAN_IPHC_SAM_BIT 4
--
1.8.3.3
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead.
Download for free and get started troubleshooting in minutes.
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
^ permalink raw reply related
* [PATCH 3/6] 6lowpan: introduce lowpan_fetch_skb function
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch adds a helper function to parse the ipv6 header to a
6lowpan header in stream.
This function checks first if we can pull data with a specific
length from a skb. If this seems to be okay, we copy skb data to
a destination pointer and run skb_pull.
Signed-off-by: Alexander Aring <alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index 61f0ce9..e3348ec 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -233,4 +233,16 @@
dest = 16 bit inline */
#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
+static inline bool lowpan_fetch_skb(struct sk_buff *skb,
+ void *data, const unsigned int len)
+{
+ if (unlikely(!pskb_may_pull(skb, len)))
+ return true;
+
+ skb_copy_from_linear_data(skb, data, len);
+ skb_pull(skb, len);
+
+ return false;
+}
+
#endif /* __6LOWPAN_H__ */
--
1.8.3.3
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead.
Download for free and get started troubleshooting in minutes.
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
^ permalink raw reply related
* [PATCH 2/6] 6lowpan: Fix fragmentation with link-local compressed addresses
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
David Hauweele, davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: David Hauweele <david-1EggE+PRa6vk1uMJSBkQmQ@public.gmane.org>
When a new 6lowpan fragment is received, a skbuff is allocated for
the reassembled packet. However when a 6lowpan packet compresses
link-local addresses based on link-layer addresses, the processing
function relies on the skb mac control block to find the related
link-layer address.
This patch copies the control block from the first fragment into
the newly allocated skb to keep a trace of the link-layer addresses
in case of a link-local compressed address.
Edit: small changes on comment issue
Signed-off-by: David Hauweele <david-1EggE+PRa6vk1uMJSBkQmQ@public.gmane.org>
Signed-off-by: Alexander Aring <alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 92429db..632b3fd 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -698,6 +698,12 @@ lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
skb_reserve(frame->skb, sizeof(struct ipv6hdr));
skb_put(frame->skb, frame->length);
+ /* copy the first control block to keep a
+ * trace of the link-layer addresses in case
+ * of a link-local compressed address
+ */
+ memcpy(frame->skb->cb, skb->cb, sizeof(skb->cb));
+
init_timer(&frame->timer);
/* time out is the same as for ipv6 - 60 sec */
frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT;
--
1.8.3.3
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead.
Download for free and get started troubleshooting in minutes.
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
^ permalink raw reply related
* [PATCH 1/6] 6lowpan: init ipv6hdr buffer to zero
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch simplify the handling to set fields inside of struct ipv6hdr
to zero. Instead of setting some memory regions with memset to zero we
initialize the whole ipv6hdr to zero.
This is a optimization for parsing the 6lowpan header and not a bug fix.
Signed-off-by: Alexander Aring <alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
net/ieee802154/6lowpan.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 3b9d5f2..92429db 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -223,10 +223,6 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
if (prefcount > 0)
memcpy(ipaddr, prefix, prefcount);
- if (prefcount + postcount < 16)
- memset(&ipaddr->s6_addr[prefcount], 0,
- 16 - (prefcount + postcount));
-
if (postcount > 0) {
memcpy(&ipaddr->s6_addr[16 - postcount], skb->data, postcount);
skb_pull(skb, postcount);
@@ -723,7 +719,7 @@ frame_err:
static int
lowpan_process_data(struct sk_buff *skb)
{
- struct ipv6hdr hdr;
+ struct ipv6hdr hdr = {};
u8 tmp, iphc0, iphc1, num_context = 0;
u8 *_saddr, *_daddr;
int err;
@@ -868,8 +864,6 @@ lowpan_process_data(struct sk_buff *skb)
hdr.priority = ((tmp >> 2) & 0x0f);
hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
- hdr.flow_lbl[1] = 0;
- hdr.flow_lbl[2] = 0;
break;
/*
* Flow Label carried in-line
@@ -885,10 +879,6 @@ lowpan_process_data(struct sk_buff *skb)
break;
/* Traffic Class and Flow Label are elided */
case 3: /* 11b */
- hdr.priority = 0;
- hdr.flow_lbl[0] = 0;
- hdr.flow_lbl[1] = 0;
- hdr.flow_lbl[2] = 0;
break;
default:
break;
--
1.8.3.3
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead.
Download for free and get started troubleshooting in minutes.
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
^ permalink raw reply related
* [PATCH 6/6] 6lowpan: handle context based source address
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov
Cc: dbaryshkov, davem, linux-zigbee-devel, netdev, Alexander Aring
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring@gmail.com>
Handle context based address when a unspecific address is specified.
For other context based address we print a warning and drop the packet
currently because we don't support it right now.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
net/ieee802154/6lowpan.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index d299560..90eddce 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -243,6 +243,39 @@ lowpan_uncompress_addr(struct sk_buff *skb,
return 0;
}
+/* Uncompress address function for source context
+ * based address(non-multicast).
+ */
+static int
+lowpan_uncompress_context_based_src_addr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 sam)
+{
+ switch (sam) {
+ case LOWPAN_IPHC_ADDR_00:
+ /* unspec address ::
+ * Do nothing, address is already ::
+ */
+ break;
+ case LOWPAN_IPHC_ADDR_01:
+ /* TODO */
+ case LOWPAN_IPHC_ADDR_02:
+ /* TODO */
+ case LOWPAN_IPHC_ADDR_03:
+ /* TODO */
+ netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
+ return -EINVAL;
+ default:
+ pr_debug("Invalid sam value: 0x%x\n", sam);
+ return -EINVAL;
+ }
+
+ pr_debug("Reconstructed context based ipv6 src addr is:\n");
+ lowpan_raw_dump_inline(NULL, NULL, ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
/* Uncompress function for multicast destination address,
* when M bit is set.
*/
@@ -971,9 +1004,18 @@ lowpan_process_data(struct sk_buff *skb)
/* Extract SAM to the tmp variable */
tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
- /* Source address uncompression */
- pr_debug("source address stateless compression\n");
- err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
+ if (iphc1 & LOWPAN_IPHC_SAC) {
+ /* Source address context based uncompression */
+ pr_debug("SAC bit is set. Handle context based source address.\n");
+ err = lowpan_uncompress_context_based_src_addr(
+ skb, &hdr.saddr, tmp);
+ } else {
+ /* Source address uncompression */
+ pr_debug("source address stateless compression\n");
+ err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
+ }
+
+ /* Check on error of previous branch */
if (err)
goto drop;
--
1.8.3.3
^ permalink raw reply related
* [PATCH 4/6] 6lowpan: add function to uncompress multicast addr
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov
Cc: dbaryshkov, davem, linux-zigbee-devel, netdev, Alexander Aring
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring@gmail.com>
Add function to uncompress multicast address.
This function split the uncompress function for a multicast address
in a seperate function.
To uncompress a multicast address is different than a other
non-multicasts addresses according to rfc6282.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
net/ieee802154/6lowpan.c | 78 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 59 insertions(+), 19 deletions(-)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 632b3fd..0df8874 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -88,15 +88,6 @@ static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
*/
static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
-/*
- * Uncompression of ctx-base
- * 0 -> 0 bits from packet
- * 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet
- * 2 -> 2 bytes from prefix - zeroes + 3 from packet
- * 3 -> 2 bytes from prefix - infer 1 bytes from lladdr
- */
-static const u8 lowpan_unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
-
/* Link local prefix */
static const u8 lowpan_llprefix[] = {0xfe, 0x80};
@@ -240,6 +231,63 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
return 0;
}
+/* Uncompress function for multicast destination address,
+ * when M bit is set.
+ */
+static int
+lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
+ struct in6_addr *ipaddr,
+ const u8 dam)
+{
+ bool fail;
+
+ switch (dam) {
+ case LOWPAN_IPHC_DAM_00:
+ /* 00: 128 bits. The full address
+ * is carried in-line.
+ */
+ fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+ break;
+ case LOWPAN_IPHC_DAM_01:
+ /* 01: 48 bits. The address takes
+ * the form ffXX::00XX:XXXX:XXXX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+ fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
+ break;
+ case LOWPAN_IPHC_DAM_10:
+ /* 10: 32 bits. The address takes
+ * the form ffXX::00XX:XXXX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+ fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
+ break;
+ case LOWPAN_IPHC_DAM_11:
+ /* 11: 8 bits. The address takes
+ * the form ff02::00XX.
+ */
+ ipaddr->s6_addr[0] = 0xFF;
+ ipaddr->s6_addr[1] = 0x02;
+ fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
+ break;
+ default:
+ pr_debug("DAM value has a wrong value: 0x%x\n", dam);
+ return -EINVAL;
+ }
+
+ if (fail) {
+ pr_debug("Failed to fetch skb data\n");
+ return -EIO;
+ }
+
+ pr_debug("Reconstructed ipv6 multicast addr is:\n");
+ lowpan_raw_dump_inline(NULL, NULL, ipaddr->s6_addr, 16);
+
+ return 0;
+}
+
static void
lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
{
@@ -927,16 +975,8 @@ lowpan_process_data(struct sk_buff *skb)
pr_debug("dest: context-based mcast compression\n");
/* TODO: implement this */
} else {
- u8 prefix[] = {0xff, 0x02};
-
- pr_debug("dest: non context-based mcast compression\n");
- if (0 < tmp && tmp < 3) {
- if (lowpan_fetch_skb_u8(skb, &prefix[1]))
- goto drop;
- }
-
- err = lowpan_uncompress_addr(skb, &hdr.daddr, prefix,
- lowpan_unc_mxconf[tmp], NULL);
+ err = lowpan_uncompress_multicast_daddr(
+ skb, &hdr.daddr, tmp);
if (err)
goto drop;
}
--
1.8.3.3
^ permalink raw reply related
* [PATCH 0/6] 6lowpan: uncompress of addresses fix
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov
Cc: dbaryshkov, davem, linux-zigbee-devel, netdev, Alexander Aring
In-Reply-To: <1376430813-30982-1-git-send-email-alex.aring@gmail.com>
The current implementation to uncompress addresses in a 6lowpan header
is completely broken.
This patch series fixes the parsing of addresses in a 6lowpan header.
It contains a major rewrite of the uncompress address function to parse
the address in a correct way.
Alexander Aring (5):
6lowpan: init ipv6hdr buffer to zero
6lowpan: introduce lowpan_fetch_skb function
6lowpan: add function to uncompress multicast addr
6lowpan: lowpan_uncompress_addr with address_mode
6lowpan: handle context based source address
David Hauweele (1):
6lowpan: Fix fragmentation with link-local compressed addresses
net/ieee802154/6lowpan.c | 284 +++++++++++++++++++++++++++++++----------------
net/ieee802154/6lowpan.h | 20 +++-
2 files changed, 203 insertions(+), 101 deletions(-)
--
1.8.3.3
^ permalink raw reply
* [PATCH] 6lowpan: handle only real link-local addresses
From: Alexander Aring @ 2013-08-13 21:53 UTC (permalink / raw)
To: alex.bluesman.smirnov
Cc: dbaryshkov, davem, linux-zigbee-devel, netdev, Alexander Aring
A link-local address isn't fe80::/10 it's fe80::/64
see http://tools.ietf.org/html/rfc4291#section-2.5.6
for more details.
Also fix a comment issue "local link" -> "link-local"
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
net/ieee802154/6lowpan.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index 4b8f917..61f0ce9 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -83,8 +83,11 @@
#define ipaddr_prefixcmp(addr1, addr2, length) \
(memcmp(addr1, addr2, length >> 3) == 0)
-/* local link, i.e. FE80::/10 */
-#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80))
+/* link-local, i.e. FE80::/64 */
+#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80) && \
+ (((a)->s6_addr16[1]) == 0) && \
+ (((a)->s6_addr16[2]) == 0) && \
+ (((a)->s6_addr16[3]) == 0))
/*
* check whether we can compress the IID to 16 bits,
--
1.8.3.3
^ permalink raw reply related
* Re: Find vlanid with non-root user
From: Stephen Hemminger @ 2013-08-13 21:46 UTC (permalink / raw)
To: Amador Pahim; +Cc: netdev
In-Reply-To: <CAEFY+qzCQqEpLjjM1iBjtHmDh70ktpx+GCHgTuCceu1A53-1Tw@mail.gmail.com>
On Tue, 13 Aug 2013 17:46:45 -0300
Amador Pahim <amador@pahim.org> wrote:
> Hello,
>
> Is there a way to get vlanid from a vlan interface as a regular user?
> Default permissions to /proc/net/vlan/ is 600.
> -rw-------. 1 root root 0 Aug 13 17:23 /proc/net/vlan/eth1.10-fcoe
ip command will work as non-root user and show vlan (with -d)
$ ip -d li show dev eth0vlan
13: eth0vlan@eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT
link/ether 10:bf:48:84:6f:5a brd ff:ff:ff:ff:ff:ff
vlan id 10 <REORDER_HDR>
> Not sure if deducting vlanid from vlan name is a reasonable way to do so.
No. Vlan can be made with any name.
# ip li add link eth0 name eth0vlan type vlan id 10
> Thank you in advance,.
>
> Best Regards,
^ permalink raw reply
* Re: [PATCH] SolutionEngine SH771x: remove Ether support
From: Sergei Shtylyov @ 2013-08-13 21:32 UTC (permalink / raw)
To: linux-sh, lethal; +Cc: netdev, Nobuhiro Iwamatsu
In-Reply-To: <201308130217.03133.sergei.shtylyov@cogentembedded.com>
Hello.
On 08/13/2013 02:17 AM, I wrote:
> The 'sh_eth' driver's probe will crash as the platform code is hopelessly behind
> the platform data -- it passes PHY ID instead of 'struct sh_eth_plat_data *'.
> Even if it's fixed, the driver probe will fail as the 'struct sh_eth_cpu_data'
> indicates presence of TSU but the platform device resource for it is absent.
> Since I have no data to fix it, I think it's best to remove the erratic code.
After looking at the original driver, it seems I've got the necessary
data... but both Ether controllers seems to have shared TSU which is not yet
supported by the driver (there was a patch from Iwamatsu-san to implement it
but it hasn't been merged).
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
WBR, Sergei
^ permalink raw reply
* Re: [PATCH] r8169: remember WOL preferences on driver load
From: Francois Romieu @ 2013-08-13 21:28 UTC (permalink / raw)
To: Peter Wu; +Cc: netdev, nic_swsd, Hayes Wang
In-Reply-To: <1376425145-30142-1-git-send-email-lekensteyn@gmail.com>
Peter Wu <lekensteyn@gmail.com> :
> Do not clear Broadcast/Multicast/Unicast Wake Flag or LanWake in
> Config5. This is necessary to preserve WOL state when the driver is
> loaded.
Ok, it makes sense.
> The r8168 vendor driver used to write to both Config1 and Config5, but
> in recent versions, this is commented out. Here we keep writing PMEnable
> to Config1 because there may be older chips where PMEnable is not sticky.
<sneak regression paranoia>
Please include the bits you want to keep in the "&" mask.
</sneak regression paranoia>
Hayes, any advice (especially regarding Config5) ?
[...]
> diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
> index 28af01c..7bdf322 100644
> --- a/drivers/net/ethernet/realtek/r8169.c
> +++ b/drivers/net/ethernet/realtek/r8169.c
> @@ -7093,7 +7093,6 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>
> RTL_W8(Cfg9346, Cfg9346_Unlock);
> RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
> - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
> if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
> tp->features |= RTL_FEATURE_WOL;
> if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
> --
> 1.8.3.4
^ permalink raw reply
* [PATCH 2/2] realtek: update devices to 3.11
From: Peter Wu @ 2013-08-13 21:25 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, Francois Romieu, lekensteyn
In-Reply-To: <1376429119-31380-1-git-send-email-lekensteyn@gmail.com>
RTL8168_8111Bb/RTL8168_8111Bef is like RTL8111B/RTL8168B, RTL8100E and RTL8101E
(datasheet revision 1.0 from 26 January 2006). Assume that RTL8101e is also
similar (I may be very wrong at that though...).
Note that the scanning heuristics is the same as the r8169 module: newer devices
with stronger masks come before the others. Perhaps the older 8139 cards should
be appended to the list, after all r8169 chips.
Signed-off-by: Peter Wu <lekensteyn@gmail.com>
---
realtek.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 177 insertions(+), 44 deletions(-)
diff --git a/realtek.c b/realtek.c
index 17b0b7e..e437466 100644
--- a/realtek.c
+++ b/realtek.c
@@ -19,17 +19,50 @@ enum chip_type {
RTL8101,
/* chips not handled by 8139too/8139cp module */
- RTL8169,
- RTL8169S,
- RTL8110S,
- RTL8169_8110SB,
- RTL8169_8110SCd,
- RTL8169_8110SCe,
- RTL8168_8111Bb,
- RTL8168_8111Bef,
- RTL8101Ebc,
- RTL8100E1,
- RTL8100E2,
+ RTL_GIGA_MAC_VER_01,
+ RTL_GIGA_MAC_VER_02,
+ RTL_GIGA_MAC_VER_03,
+ RTL_GIGA_MAC_VER_04,
+ RTL_GIGA_MAC_VER_05,
+ RTL_GIGA_MAC_VER_06,
+ RTL_GIGA_MAC_VER_07,
+ RTL_GIGA_MAC_VER_08,
+ RTL_GIGA_MAC_VER_09,
+ RTL_GIGA_MAC_VER_10,
+ RTL_GIGA_MAC_VER_11,
+ RTL_GIGA_MAC_VER_12,
+ RTL_GIGA_MAC_VER_13,
+ RTL_GIGA_MAC_VER_14,
+ RTL_GIGA_MAC_VER_15,
+ RTL_GIGA_MAC_VER_16,
+ RTL_GIGA_MAC_VER_17,
+ RTL_GIGA_MAC_VER_18,
+ RTL_GIGA_MAC_VER_19,
+ RTL_GIGA_MAC_VER_20,
+ RTL_GIGA_MAC_VER_21,
+ RTL_GIGA_MAC_VER_22,
+ RTL_GIGA_MAC_VER_23,
+ RTL_GIGA_MAC_VER_24,
+ RTL_GIGA_MAC_VER_25,
+ RTL_GIGA_MAC_VER_26,
+ RTL_GIGA_MAC_VER_27,
+ RTL_GIGA_MAC_VER_28,
+ RTL_GIGA_MAC_VER_29,
+ RTL_GIGA_MAC_VER_30,
+ RTL_GIGA_MAC_VER_31,
+ RTL_GIGA_MAC_VER_32,
+ RTL_GIGA_MAC_VER_33,
+ RTL_GIGA_MAC_VER_34,
+ RTL_GIGA_MAC_VER_35,
+ RTL_GIGA_MAC_VER_36,
+ RTL_GIGA_MAC_VER_37,
+ RTL_GIGA_MAC_VER_38,
+ RTL_GIGA_MAC_VER_39,
+ RTL_GIGA_MAC_VER_40,
+ RTL_GIGA_MAC_VER_41,
+ RTL_GIGA_MAC_VER_42,
+ RTL_GIGA_MAC_VER_43,
+ RTL_GIGA_MAC_VER_44,
};
static const char * const chip_names[] = {
@@ -46,17 +79,50 @@ static const char * const chip_names[] = {
[RTL8101] = "8101",
/* chips not handled by 8139too/8139cp module */
- [RTL8169] = "8169",
- [RTL8169S] = "8169S",
- [RTL8110S] = "8110S",
- [RTL8169_8110SB] = "8169/8110SB",
- [RTL8169_8110SCd] = "8169/8110SCd",
- [RTL8169_8110SCe] = "8169/8110SCe",
- [RTL8168_8111Bb] = "8168/8111Bb",
- [RTL8168_8111Bef] = "8168/8111Bef",
- [RTL8101Ebc] = "8101Ebc",
- [RTL8100E1] = "8100E(1)",
- [RTL8100E2] = "8100E(2)",
+ [RTL_GIGA_MAC_VER_01] = "8169",
+ [RTL_GIGA_MAC_VER_02] = "8169s",
+ [RTL_GIGA_MAC_VER_03] = "8110s",
+ [RTL_GIGA_MAC_VER_04] = "8169sb/8110sb",
+ [RTL_GIGA_MAC_VER_05] = "8169sc/8110sc",
+ [RTL_GIGA_MAC_VER_06] = "8169sc/8110sc",
+ [RTL_GIGA_MAC_VER_07] = "8102e",
+ [RTL_GIGA_MAC_VER_08] = "8102e",
+ [RTL_GIGA_MAC_VER_09] = "8102e",
+ [RTL_GIGA_MAC_VER_10] = "8101e",
+ [RTL_GIGA_MAC_VER_11] = "8168b/8111b",
+ [RTL_GIGA_MAC_VER_12] = "8168b/8111b",
+ [RTL_GIGA_MAC_VER_13] = "8101e",
+ [RTL_GIGA_MAC_VER_14] = "8100e",
+ [RTL_GIGA_MAC_VER_15] = "8100e",
+ [RTL_GIGA_MAC_VER_16] = "8101e",
+ [RTL_GIGA_MAC_VER_17] = "8168b/8111b",
+ [RTL_GIGA_MAC_VER_18] = "8168cp/8111cp",
+ [RTL_GIGA_MAC_VER_19] = "8168c/8111c",
+ [RTL_GIGA_MAC_VER_20] = "8168c/8111c",
+ [RTL_GIGA_MAC_VER_21] = "8168c/8111c",
+ [RTL_GIGA_MAC_VER_22] = "8168c/8111c",
+ [RTL_GIGA_MAC_VER_23] = "8168cp/8111cp",
+ [RTL_GIGA_MAC_VER_24] = "8168cp/8111cp",
+ [RTL_GIGA_MAC_VER_25] = "8168d/8111d",
+ [RTL_GIGA_MAC_VER_26] = "8168d/8111d",
+ [RTL_GIGA_MAC_VER_27] = "8168dp/8111dp",
+ [RTL_GIGA_MAC_VER_28] = "8168dp/8111dp",
+ [RTL_GIGA_MAC_VER_29] = "8105e",
+ [RTL_GIGA_MAC_VER_30] = "8105e",
+ [RTL_GIGA_MAC_VER_31] = "8168dp/8111dp",
+ [RTL_GIGA_MAC_VER_32] = "8168e/8111e",
+ [RTL_GIGA_MAC_VER_33] = "8168e/8111e",
+ [RTL_GIGA_MAC_VER_34] = "8168evl/8111evl",
+ [RTL_GIGA_MAC_VER_35] = "8168f/8111f",
+ [RTL_GIGA_MAC_VER_36] = "8168f/8111f",
+ [RTL_GIGA_MAC_VER_37] = "8402",
+ [RTL_GIGA_MAC_VER_38] = "8411",
+ [RTL_GIGA_MAC_VER_39] = "8106e",
+ [RTL_GIGA_MAC_VER_40] = "8168g/8111g",
+ [RTL_GIGA_MAC_VER_41] = "8168g/8111g",
+ [RTL_GIGA_MAC_VER_42] = "8168g/8111g",
+ [RTL_GIGA_MAC_VER_43] = "8106e",
+ [RTL_GIGA_MAC_VER_44] = "8411",
};
static struct chip_info {
@@ -77,17 +143,82 @@ static struct chip_info {
{ 0xfcc00000, 0x74c00000, RTL8101 },
/* chips not handled by 8139too/8139cp module */
- { 0xfcc00000, 0x00000000, RTL8169 },
- { 0xfcc00000, 0x00800000, RTL8169S },
- { 0xfcc00000, 0x04000000, RTL8110S },
- { 0xfcc00000, 0x10000000, RTL8169_8110SB },
- { 0xfcc00000, 0x18000000, RTL8169_8110SCd },
- { 0xfcc00000, 0x98000000, RTL8169_8110SCe },
- { 0xfcc00000, 0x30000000, RTL8168_8111Bb },
- { 0xfcc00000, 0x38000000, RTL8168_8111Bef },
- { 0xfcc00000, 0x34000000, RTL8101Ebc },
- { 0xfcc00000, 0x30800000, RTL8100E1 },
- { 0xfcc00000, 0x38800000, RTL8100E2 },
+ /* 8168G family. */
+ { 0x7cf00000, 0x5c800000, RTL_GIGA_MAC_VER_44 },
+ { 0x7cf00000, 0x50900000, RTL_GIGA_MAC_VER_42 },
+ { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
+ { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
+
+ /* 8168F family. */
+ { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
+ { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
+ { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
+
+ /* 8168E family. */
+ { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
+ { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
+ { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
+ { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
+
+ /* 8168D family. */
+ { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
+ { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
+ { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
+
+ /* 8168DP family. */
+ { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
+ { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
+ { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
+
+ /* 8168C family. */
+ { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
+ { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
+ { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
+ { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
+ { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
+ { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
+ { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
+ { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
+ { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
+
+ /* 8168B family. */
+ { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
+ { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
+
+ /* 8101 family. */
+ { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
+ { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
+ { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
+ { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
+ { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
+ { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
+ { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
+ { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
+ { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
+ { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
+ { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
+ { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
+ { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
+ { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
+ { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
+ { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
+ { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
+ { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
+ { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
+ /* FIXME: where did these entries come from ? -- FR */
+ { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
+ { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
+
+ /* 8110 family. */
+ { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
+ { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
+ { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
+ { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
+ { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
+ { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
+
{ }
};
@@ -151,7 +282,7 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
data[0x08 >> 2],
data[0x0c >> 2]);
- if (board_type == RTL8139Cp || board_type >= RTL8169) {
+ if (board_type == RTL8139Cp || board_type >= RTL_GIGA_MAC_VER_01) {
fprintf(stdout,
"0x10: Dump Tally Counter Command 0x%08x 0x%08x\n",
data[0x10 >> 2],
@@ -187,8 +318,9 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
data[0x2C >> 2]);
}
- if (board_type != RTL8168_8111Bb && board_type != RTL8168_8111Bef) {
- if (board_type >= RTL8169) {
+ if (board_type < RTL_GIGA_MAC_VER_11 ||
+ board_type > RTL_GIGA_MAC_VER_17) {
+ if (board_type >= RTL_GIGA_MAC_VER_01) {
fprintf(stdout,
"0x30: Flash memory read/write 0x%08x\n",
data[0x30 >> 2]);
@@ -224,7 +356,7 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
v & (1 << 2) ? "on" : "off",
v & (1 << 4) ? ", RESET" : "");
- if (board_type < RTL8169) {
+ if (board_type < RTL_GIGA_MAC_VER_01) {
fprintf(stdout,
"0x38: Current Address of Packet Read (C mode) 0x%04x\n"
"0x3A: Current Rx buffer address (C mode) 0x%04x\n",
@@ -259,7 +391,7 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
data8[0x51],
data8[0x52]);
- if (board_type >= RTL8169) {
+ if (board_type >= RTL_GIGA_MAC_VER_01) {
fprintf(stdout,
"0x53: Config 2 0x%02x\n"
"0x54: Config 3 0x%02x\n"
@@ -298,12 +430,13 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
"0x5C: Multiple Interrupt Select 0x%04x\n",
data[0x5c >> 2] & 0xffff);
- if (board_type >= RTL8169) {
+ if (board_type >= RTL_GIGA_MAC_VER_01) {
fprintf(stdout,
"0x60: PHY access 0x%08x\n",
data[0x60 >> 2]);
- if (board_type != RTL8168_8111Bb && board_type != RTL8168_8111Bef) {
+ if (board_type < RTL_GIGA_MAC_VER_11 ||
+ board_type > RTL_GIGA_MAC_VER_17) {
fprintf(stdout,
"0x64: TBI control and status 0x%08x\n",
data[0x64 >> 2]);
@@ -492,7 +625,7 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
}
}
- if (board_type == RTL8139Cp || board_type >= RTL8169) {
+ if (board_type == RTL8139Cp || board_type >= RTL_GIGA_MAC_VER_01) {
v = data[0xE0 >> 2] & 0xffff;
fprintf(stdout,
"0xE0: C+ Command 0x%04x\n",
@@ -536,9 +669,9 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
fprintf(stdout,
"0xFC: External MII register 0x%08x\n",
data[0xFC >> 2]);
- } else if (board_type >= RTL8169 &&
- board_type != RTL8168_8111Bb &&
- board_type != RTL8168_8111Bef) {
+ } else if (board_type >= RTL_GIGA_MAC_VER_01 &&
+ (board_type < RTL_GIGA_MAC_VER_11 ||
+ board_type > RTL_GIGA_MAC_VER_17)) {
fprintf(stdout,
"0xF0: Func Event 0x%08x\n"
"0xF4: Func Event Mask 0x%08x\n"
--
1.8.3.4
^ permalink raw reply related
* [PATCH 1/2] realtek: convert to per-chip mask
From: Peter Wu @ 2013-08-13 21:25 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, Francois Romieu, lekensteyn
In-Reply-To: <1376429119-31380-1-git-send-email-lekensteyn@gmail.com>
The previous HW_REVID macro did not make identifiers more readable
(compared to hex values like 0x12345678) and only allowed for one static
mask. To make it easier to update the chips list, let's use similar
structures as r8169 and remove HW_REVID.
Names are removed and separated from the table and separated because the
mac_version does not have to be unique.
While at it, change "RTL-xxxx" to "RTLxxxx" to match the names of
Realtek and r8169 driver. Besides that, the only output change is when
a chip is not recognized in which case "TxConfig" is now mentioned
instead of "mask". Since the mask can be anything, the displayed word is
not masked either.
Signed-off-by: Peter Wu <lekensteyn@gmail.com>
---
realtek.c | 108 ++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 63 insertions(+), 45 deletions(-)
diff --git a/realtek.c b/realtek.c
index c3d7ae5..17b0b7e 100644
--- a/realtek.c
+++ b/realtek.c
@@ -5,13 +5,8 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#define HW_REVID(b31, b30, b29, b28, b27, b26, b23, b22) \
- (b31<<31 | b30<<30 | b29<<29 | b28<<28 | \
- b27<<27 | b26<<26 | b23<<23 | b22<<22)
-
enum chip_type {
- RTLNONE,
- RTL8139,
+ RTL8139 = 1,
RTL8139_K,
RTL8139A,
RTL8139A_G,
@@ -22,6 +17,8 @@ enum chip_type {
RTL8100B_8139D,
RTL8139Cp,
RTL8101,
+
+ /* chips not handled by 8139too/8139cp module */
RTL8169,
RTL8169S,
RTL8110S,
@@ -35,36 +32,62 @@ enum chip_type {
RTL8100E2,
};
-enum {
- chip_type_mask = HW_REVID(1, 1, 1, 1, 1, 1, 1, 1)
+static const char * const chip_names[] = {
+ [RTL8139] = "8139",
+ [RTL8139_K] = "8139-K",
+ [RTL8139A] = "8139A",
+ [RTL8139A_G] = "8139A-G",
+ [RTL8139B] = "8139B",
+ [RTL8130] = "8130",
+ [RTL8139C] = "8139C",
+ [RTL8100] = "8100",
+ [RTL8100B_8139D] = "8100B/8139D",
+ [RTL8139Cp] = "8139C+",
+ [RTL8101] = "8101",
+
+ /* chips not handled by 8139too/8139cp module */
+ [RTL8169] = "8169",
+ [RTL8169S] = "8169S",
+ [RTL8110S] = "8110S",
+ [RTL8169_8110SB] = "8169/8110SB",
+ [RTL8169_8110SCd] = "8169/8110SCd",
+ [RTL8169_8110SCe] = "8169/8110SCe",
+ [RTL8168_8111Bb] = "8168/8111Bb",
+ [RTL8168_8111Bef] = "8168/8111Bef",
+ [RTL8101Ebc] = "8101Ebc",
+ [RTL8100E1] = "8100E(1)",
+ [RTL8100E2] = "8100E(2)",
};
static struct chip_info {
- const char *name;
u32 id_mask;
+ u32 id_val;
+ int mac_version;
} rtl_info_tbl[] = {
- { "RTL-8139", HW_REVID(0, 1, 0, 0, 0, 0, 0, 0) },
- { "RTL-8139-K", HW_REVID(0, 1, 1, 0, 0, 0, 0, 0) },
- { "RTL-8139A", HW_REVID(0, 1, 1, 1, 0, 0, 0, 0) },
- { "RTL-8139A-G", HW_REVID(0, 1, 1, 1, 0, 0, 1, 0) },
- { "RTL-8139B", HW_REVID(0, 1, 1, 1, 1, 0, 0, 0) },
- { "RTL-8130", HW_REVID(0, 1, 1, 1, 1, 1, 0, 0) },
- { "RTL-8139C", HW_REVID(0, 1, 1, 1, 0, 1, 0, 0) },
- { "RTL-8100", HW_REVID(0, 1, 1, 1, 1, 0, 1, 0) },
- { "RTL-8100B/8139D", HW_REVID(0, 1, 1, 1, 0, 1, 0, 1) },
- { "RTL-8139C+", HW_REVID(0, 1, 1, 1, 0, 1, 1, 0) },
- { "RTL-8101", HW_REVID(0, 1, 1, 1, 0, 1, 1, 1) },
- { "RTL-8169", HW_REVID(0, 0, 0, 0, 0, 0, 0, 0) },
- { "RTL-8169S", HW_REVID(0, 0, 0, 0, 0, 0, 1, 0) },
- { "RTL-8110S", HW_REVID(0, 0, 0, 0, 0, 1, 0, 0) },
- { "RTL-8169/8110SB", HW_REVID(0, 0, 0, 1, 0, 0, 0, 0) },
- { "RTL-8169/8110SCd", HW_REVID(0, 0, 0, 1, 1, 0, 0, 0) },
- { "RTL-8169/8110SCe", HW_REVID(1, 0, 0, 1, 1, 0, 0, 0) },
- { "RTL-8168/8111Bb", HW_REVID(0, 0, 1, 1, 0, 0, 0, 0) },
- { "RTL-8168/8111Bef", HW_REVID(0, 0, 1, 1, 1, 0, 0, 0) },
- { "RTL-8101Ebc", HW_REVID(0, 0, 1, 1, 0, 1, 0, 0) },
- { "RTL-8100E(1)", HW_REVID(0, 0, 1, 1, 0, 0, 1, 0) },
- { "RTL-8100E(2)", HW_REVID(0, 0, 1, 1, 1, 0, 1, 0) },
+ { 0xfcc00000, 0x40000000, RTL8139 },
+ { 0xfcc00000, 0x60000000, RTL8139_K },
+ { 0xfcc00000, 0x70000000, RTL8139A },
+ { 0xfcc00000, 0x70800000, RTL8139A_G },
+ { 0xfcc00000, 0x78000000, RTL8139B },
+ { 0xfcc00000, 0x7c000000, RTL8130 },
+ { 0xfcc00000, 0x74000000, RTL8139C },
+ { 0xfcc00000, 0x78800000, RTL8100 },
+ { 0xfcc00000, 0x74400000, RTL8100B_8139D },
+ { 0xfcc00000, 0x74800000, RTL8139Cp },
+ { 0xfcc00000, 0x74c00000, RTL8101 },
+
+ /* chips not handled by 8139too/8139cp module */
+ { 0xfcc00000, 0x00000000, RTL8169 },
+ { 0xfcc00000, 0x00800000, RTL8169S },
+ { 0xfcc00000, 0x04000000, RTL8110S },
+ { 0xfcc00000, 0x10000000, RTL8169_8110SB },
+ { 0xfcc00000, 0x18000000, RTL8169_8110SCd },
+ { 0xfcc00000, 0x98000000, RTL8169_8110SCe },
+ { 0xfcc00000, 0x30000000, RTL8168_8111Bb },
+ { 0xfcc00000, 0x38000000, RTL8168_8111Bef },
+ { 0xfcc00000, 0x34000000, RTL8101Ebc },
+ { 0xfcc00000, 0x30800000, RTL8100E1 },
+ { 0xfcc00000, 0x38800000, RTL8100E2 },
{ }
};
@@ -93,31 +116,26 @@ realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
u8 *data8 = (u8 *) regs->data;
u32 v;
struct chip_info *ci;
- unsigned int board_type = RTLNONE, i;
+ unsigned int board_type;
- v = data[0x40 >> 2] & chip_type_mask;
+ v = data[0x40 >> 2]; /* TxConfig */
ci = &rtl_info_tbl[0];
- while (ci->name) {
- if (v == ci->id_mask)
+ while (ci->mac_version) {
+ if ((v & ci->id_mask) == ci->id_val)
break;
ci++;
}
- if (v != ci->id_mask) {
- fprintf(stderr, "Unknown RealTek chip (mask: 0x%08x)\n", v);
+ board_type = ci->mac_version;
+ if (!board_type) {
+ fprintf(stderr, "Unknown RealTek chip (TxConfig: 0x%08x)\n", v);
return 91;
}
- for (i = 0; i < ARRAY_SIZE(rtl_info_tbl); i++) {
- if (ci == &rtl_info_tbl[i])
- board_type = i + 1;
- }
- if (board_type == RTLNONE)
- abort();
fprintf(stdout,
- "RealTek %s registers:\n"
+ "RealTek RTL%s registers:\n"
"--------------------------------------------------------\n",
- ci->name);
+ chip_names[board_type]);
fprintf(stdout,
"0x00: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n",
--
1.8.3.4
^ permalink raw reply related
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