diff options
134 files changed, 3588 insertions, 1023 deletions
diff --git a/Documentation/devicetree/bindings/misc/allwinner,syscon.txt b/Documentation/devicetree/bindings/misc/allwinner,syscon.txt index cb5769137c6c..31494a24fe69 100644 --- a/Documentation/devicetree/bindings/misc/allwinner,syscon.txt +++ b/Documentation/devicetree/bindings/misc/allwinner,syscon.txt @@ -9,6 +9,7 @@ Required properties for the system controller: - reg: address and length of the register for the device. - compatible: should be "syscon" and one of the following string: "allwinner,sun8i-h3-system-controller" + "allwinner,sun8i-v3s-system-controller" "allwinner,sun50i-a64-system-controller" "allwinner,sun8i-a83t-system-controller" diff --git a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt index 08e708c73193..725f3b187886 100644 --- a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt +++ b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt @@ -7,6 +7,7 @@ Required properties: - compatible: should be one of the following string: "allwinner,sun8i-a83t-emac" "allwinner,sun8i-h3-emac" + "allwinner,sun8i-v3s-emac" "allwinner,sun50i-a64-emac" - reg: address and length of the register for the device. - interrupts: interrupt for the device @@ -22,6 +23,7 @@ Required properties: - syscon: A phandle to the syscon of the SoC with one of the following compatible string: - allwinner,sun8i-h3-system-controller + - allwinner,sun8i-v3s-system-controller - allwinner,sun50i-a64-system-controller - allwinner,sun8i-a83t-system-controller @@ -31,7 +33,9 @@ Optional properties: Both delay properties need to be a multiple of 100. They control the delay for external PHY. -Optional properties for "allwinner,sun8i-h3-emac": +Optional properties for the following compatibles: + - "allwinner,sun8i-h3-emac", + - "allwinner,sun8i-v3s-emac": - allwinner,leds-active-low: EPHY LEDs are active low Required child node of emac: @@ -44,7 +48,9 @@ Required properties of the mdio node: The device node referenced by "phy" or "phy-handle" should be a child node of the mdio node. See phy.txt for the generic PHY bindings. -Required properties of the phy node with "allwinner,sun8i-h3-emac": +Required properties of the phy node with the following compatibles: + - "allwinner,sun8i-h3-emac", + - "allwinner,sun8i-v3s-emac": - clocks: a phandle to the reference clock for the EPHY - resets: a phandle to the reset control for the EPHY diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h index 8acf482162ed..88162bb5c190 100644 --- a/arch/s390/include/asm/diag.h +++ b/arch/s390/include/asm/diag.h @@ -8,6 +8,7 @@ #ifndef _ASM_S390_DIAG_H #define _ASM_S390_DIAG_H +#include <linux/if_ether.h> #include <linux/percpu.h> enum diag_stat_enum { @@ -24,6 +25,7 @@ enum diag_stat_enum { DIAG_STAT_X224, DIAG_STAT_X250, DIAG_STAT_X258, + DIAG_STAT_X26C, DIAG_STAT_X288, DIAG_STAT_X2C4, DIAG_STAT_X2FC, @@ -225,6 +227,30 @@ struct diag204_x_phys_block { struct diag204_x_phys_cpu cpus[]; } __packed; +enum diag26c_sc { + DIAG26C_MAC_SERVICES = 0x00000030 +}; + +enum diag26c_version { + DIAG26C_VERSION2 = 0x00000002 /* z/VM 5.4.0 */ +}; + +#define DIAG26C_GET_MAC 0x0000 +struct diag26c_mac_req { + u32 resp_buf_len; + u32 resp_version; + u16 op_code; + u16 devno; + u8 res[4]; +}; + +struct diag26c_mac_resp { + u32 version; + u8 mac[ETH_ALEN]; + u8 res[2]; +} __aligned(8); + int diag204(unsigned long subcode, unsigned long size, void *addr); int diag224(void *ptr); +int diag26c(void *req, void *resp, enum diag26c_sc subcode); #endif /* _ASM_S390_DIAG_H */ diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c index ac6abcd3fe6a..349914571772 100644 --- a/arch/s390/kernel/diag.c +++ b/arch/s390/kernel/diag.c @@ -38,6 +38,7 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = { [DIAG_STAT_X224] = { .code = 0x224, .name = "EBCDIC-Name Table" }, [DIAG_STAT_X250] = { .code = 0x250, .name = "Block I/O" }, [DIAG_STAT_X258] = { .code = 0x258, .name = "Page-Reference Services" }, + [DIAG_STAT_X26C] = { .code = 0x26c, .name = "Certain System Information" }, [DIAG_STAT_X288] = { .code = 0x288, .name = "Time Bomb" }, [DIAG_STAT_X2C4] = { .code = 0x2c4, .name = "FTP Services" }, [DIAG_STAT_X2FC] = { .code = 0x2fc, .name = "Guest Performance Data" }, @@ -236,3 +237,31 @@ int diag224(void *ptr) return rc; } EXPORT_SYMBOL(diag224); + +/* + * Diagnose 26C: Access Certain System Information + */ +static inline int __diag26c(void *req, void *resp, enum diag26c_sc subcode) +{ + register unsigned long _req asm("2") = (addr_t) req; + register unsigned long _resp asm("3") = (addr_t) resp; + register unsigned long _subcode asm("4") = subcode; + register unsigned long _rc asm("5") = -EOPNOTSUPP; + + asm volatile( + " sam31\n" + " diag %[rx],%[ry],0x26c\n" + "0: sam64\n" + EX_TABLE(0b,0b) + : "+d" (_rc) + : [rx] "d" (_req), "d" (_resp), [ry] "d" (_subcode) + : "cc", "memory"); + return _rc; +} + +int diag26c(void *req, void *resp, enum diag26c_sc subcode) +{ + diag_stat_inc(DIAG_STAT_X26C); + return __diag26c(req, resp, subcode); +} +EXPORT_SYMBOL(diag26c); diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c index 92185ab6797d..b75b8beed68f 100644 --- a/drivers/crypto/chelsio/chcr_algo.c +++ b/drivers/crypto/chelsio/chcr_algo.c @@ -604,8 +604,7 @@ static struct sk_buff if (!skb) return ERR_PTR(-ENOMEM); skb_reserve(skb, sizeof(struct sge_opaque_hdr)); - chcr_req = __skb_put(skb, transhdr_len); - memset(chcr_req, 0, transhdr_len); + chcr_req = __skb_put_zero(skb, transhdr_len); chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(ctx->dev->rx_channel_id, 2, 1); @@ -881,8 +880,7 @@ static struct sk_buff *create_hash_wr(struct ahash_request *req, return skb; skb_reserve(skb, sizeof(struct sge_opaque_hdr)); - chcr_req = __skb_put(skb, transhdr_len); - memset(chcr_req, 0, transhdr_len); + chcr_req = __skb_put_zero(skb, transhdr_len); chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(ctx->dev->rx_channel_id, 2, 0); @@ -1447,8 +1445,7 @@ static struct sk_buff *create_authenc_wr(struct aead_request *req, skb_reserve(skb, sizeof(struct sge_opaque_hdr)); /* Write WR */ - chcr_req = __skb_put(skb, transhdr_len); - memset(chcr_req, 0, transhdr_len); + chcr_req = __skb_put_zero(skb, transhdr_len); stop_offset = (op_type == CHCR_ENCRYPT_OP) ? 0 : authsize; @@ -1779,8 +1776,7 @@ static struct sk_buff *create_aead_ccm_wr(struct aead_request *req, skb_reserve(skb, sizeof(struct sge_opaque_hdr)); - chcr_req = __skb_put(skb, transhdr_len); - memset(chcr_req, 0, transhdr_len); + chcr_req = __skb_put_zero(skb, transhdr_len); fill_sec_cpl_for_aead(&chcr_req->sec_cpl, dst_size, req, op_type, ctx); @@ -1892,8 +1888,7 @@ static struct sk_buff *create_gcm_wr(struct aead_request *req, /* NIC driver is going to write the sge hdr. */ skb_reserve(skb, sizeof(struct sge_opaque_hdr)); - chcr_req = __skb_put(skb, transhdr_len); - memset(chcr_req, 0, transhdr_len); + chcr_req = __skb_put_zero(skb, transhdr_len); if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) req->assoclen -= 8; diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 76fb39415e18..e49b34c3b136 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1900,8 +1900,7 @@ static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) int win; skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); - req = __skb_put(skb, sizeof(*req)); - memset(req, 0, sizeof(*req)); + req = __skb_put_zero(skb, sizeof(*req)); req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); req->le.filter = cpu_to_be32(cxgb4_select_ntuple( @@ -3803,8 +3802,7 @@ static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); if (!req_skb) return; - req = __skb_put(req_skb, sizeof(*req)); - memset(req, 0, sizeof(*req)); + req = __skb_put_zero(req_skb, sizeof(*req)); req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F); req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F); diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 394cfe2625fe..e16fcaf6b5a3 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -44,8 +44,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq, wr_len = sizeof *res_wr + sizeof *res; set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); - res_wr = __skb_put(skb, wr_len); - memset(res_wr, 0, wr_len); + res_wr = __skb_put_zero(skb, wr_len); res_wr->op_nres = cpu_to_be32( FW_WR_OP_V(FW_RI_RES_WR) | FW_RI_RES_WR_NRES_V(1) | @@ -114,8 +113,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq, } set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); - res_wr = __skb_put(skb, wr_len); - memset(res_wr, 0, wr_len); + res_wr = __skb_put_zero(skb, wr_len); res_wr->op_nres = cpu_to_be32( FW_WR_OP_V(FW_RI_RES_WR) | FW_RI_RES_WR_NRES_V(1) | diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index ca992e4b66e4..5332f06b99ba 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -81,8 +81,7 @@ static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr, } set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); - req = __skb_put(skb, wr_len); - memset(req, 0, wr_len); + req = __skb_put_zero(skb, wr_len); INIT_ULPTX_WR(req, wr_len, 0, 0); req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR) | (wait ? FW_WR_COMPL_F : 0)); @@ -142,8 +141,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len, } set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); - req = __skb_put(skb, wr_len); - memset(req, 0, wr_len); + req = __skb_put_zero(skb, wr_len); INIT_ULPTX_WR(req, wr_len, 0, 0); if (i == (num_wqe-1)) { diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index b23a0b057347..bfc77596acbe 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -293,8 +293,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, } set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); - res_wr = __skb_put(skb, wr_len); - memset(res_wr, 0, wr_len); + res_wr = __skb_put_zero(skb, wr_len); res_wr->op_nres = cpu_to_be32( FW_WR_OP_V(FW_RI_RES_WR) | FW_RI_RES_WR_NRES_V(2) | diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index 485c1fef238b..b5851fd67d4f 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -37,7 +37,7 @@ #include <linux/iommu.h> #include <linux/pci.h> #include <net/addrconf.h> -#include <linux/qed/qede_roce.h> + #include <linux/qed/qed_chain.h> #include <linux/qed/qed_if.h> #include "qedr.h" @@ -276,7 +276,7 @@ static int qedr_alloc_resources(struct qedr_dev *dev) QED_CHAIN_CNT_TYPE_U16, n_entries, sizeof(struct regpair *), - &cnq->pbl); + &cnq->pbl, NULL); if (rc) goto err4; @@ -902,7 +902,7 @@ static void qedr_mac_address_change(struct qedr_dev *dev) * initialization done before RoCE driver notifies * event to stack. */ -static void qedr_notify(struct qedr_dev *dev, enum qede_roce_event event) +static void qedr_notify(struct qedr_dev *dev, enum qede_rdma_event event) { switch (event) { case QEDE_UP: @@ -931,12 +931,12 @@ static struct qedr_driver qedr_drv = { static int __init qedr_init_module(void) { - return qede_roce_register_driver(&qedr_drv); + return qede_rdma_register_driver(&qedr_drv); } static void __exit qedr_exit_module(void) { - qede_roce_unregister_driver(&qedr_drv); + qede_rdma_unregister_driver(&qedr_drv); } module_init(qedr_init_module); diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h index 80333ec2c8b6..2376019a48ae 100644 --- a/drivers/infiniband/hw/qedr/qedr.h +++ b/drivers/infiniband/hw/qedr/qedr.h @@ -37,7 +37,7 @@ #include <linux/qed/qed_if.h> #include <linux/qed/qed_chain.h> #include <linux/qed/qed_roce_if.h> -#include <linux/qed/qede_roce.h> +#include <linux/qed/qede_rdma.h> #include <linux/qed/roce_common.h> #include "qedr_hsi_rdma.h" diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 17685cfea6a2..80df89b5a9ce 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -925,7 +925,7 @@ struct ib_cq *qedr_create_cq(struct ib_device *ibdev, QED_CHAIN_CNT_TYPE_U32, chain_entries, sizeof(union rdma_cqe), - &cq->pbl); + &cq->pbl, NULL); if (rc) goto err1; @@ -1413,7 +1413,7 @@ qedr_roce_create_kernel_qp(struct qedr_dev *dev, QED_CHAIN_CNT_TYPE_U32, n_sq_elems, QEDR_SQE_ELEMENT_SIZE, - &qp->sq.pbl); + &qp->sq.pbl, NULL); if (rc) return rc; @@ -1427,7 +1427,7 @@ qedr_roce_create_kernel_qp(struct qedr_dev *dev, QED_CHAIN_CNT_TYPE_U32, n_rq_elems, QEDR_RQE_ELEMENT_SIZE, - &qp->rq.pbl); + &qp->rq.pbl, NULL); if (rc) return rc; diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 4caecdcc6f29..bc208557f783 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -264,7 +264,7 @@ byte_stuff: /* skip remainder of packet */ bcs->rx_skb = skb = NULL; } else { - *(u8 *)__skb_put(skb, 1) = c; + __skb_put_u8(skb, c); fcs = crc_ccitt_byte(fcs, c); } } @@ -315,7 +315,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) /* regular data byte: append to current skb */ inputstate |= INS_have_data; - *(u8 *)__skb_put(skb, 1) = bitrev8(c); + __skb_put_u8(skb, bitrev8(c)); } /* pass data up */ diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 74e250664ce9..97e00118ccfe 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -511,7 +511,7 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) bcs->rx_skb = NULL; return; } - *(u8 *)__skb_put(bcs->rx_skb, 1) = c; + __skb_put_u8(bcs->rx_skb, c); } /* hdlc_flush diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 87119b517508..eac0f51a0f60 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -173,8 +173,8 @@ hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl, } skb_put_data(skb, &len, sizeof(__u16)); skb_put_data(skb, &appl, sizeof(__u16)); - memcpy(skb_put(skb, sizeof(__u8)), &_command, sizeof(_command)); - memcpy(skb_put(skb, sizeof(__u8)), &_subcommand, sizeof(_subcommand)); + skb_put_data(skb, &_command, sizeof(__u8)); + skb_put_data(skb, &_subcommand, sizeof(__u8)); skb_put_data(skb, &MessageNumber, sizeof(__u16)); skb_put_data(skb, &MessageBufferSize, sizeof(__u16)); skb_put_data(skb, &(rp->level3cnt), sizeof(__u16)); @@ -281,8 +281,8 @@ static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl) } skb_put_data(skb, &len, sizeof(__u16)); skb_put_data(skb, &appl, sizeof(__u16)); - memcpy(skb_put(skb, sizeof(__u8)), &_command, sizeof(_command)); - memcpy(skb_put(skb, sizeof(__u8)), &_subcommand, sizeof(_subcommand)); + skb_put_data(skb, &_command, sizeof(__u8)); + skb_put_data(skb, &_subcommand, sizeof(__u8)); skb_put_data(skb, &MessageNumber, sizeof(__u16)); hycapi_send_message(ctrl, skb); hycapi_applications[appl - 1].ctrl_mask &= ~(1 << (ctrl->cnr - 1)); diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c index 3035210a6119..5b64a1389a7c 100644 --- a/drivers/isdn/i4l/isdn_bsdcomp.c +++ b/drivers/isdn/i4l/isdn_bsdcomp.c @@ -472,7 +472,7 @@ static int bsd_compress(void *state, struct sk_buff *skb_in, struct sk_buff *skb accm |= ((ent) << bitno); \ do { \ if (skb_out && skb_tailroom(skb_out) > 0) \ - *(u8 *)skb_put(skb_out, 1) = (u8)(accm >> 24); \ + skb_put(skb_out, (u8)(accm >> 24)); \ accm <<= 8; \ bitno += 8; \ } while (bitno <= 24); \ diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index b7e3f1cde683..88e5a025cea7 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -2258,7 +2258,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, /* Now stuff remaining bytes */ if (len) { - p = skb_put_data(skb, data, len); + skb_put_data(skb, data, len); } /* skb is now ready for xmit */ diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index b796db7dd621..c02cc817a490 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -925,7 +925,6 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], struct learning_pkt pkt; struct sk_buff *skb; int size = sizeof(struct learning_pkt); - char *data; memset(&pkt, 0, size); ether_addr_copy(pkt.mac_dst, mac_addr); @@ -936,7 +935,7 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[], if (!skb) return; - data = skb_put_data(skb, &pkt, size); + skb_put_data(skb, &pkt, size); skb_reset_mac_header(skb); skb->network_header = skb->mac_header + ETH_HLEN; diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index 4534326e20ac..11ba6e3eea22 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -426,7 +426,6 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi) /* Check for embedded CAIF frame. */ if (desc->offset) { struct sk_buff *skb; - u8 *dst = NULL; int len = 0; pfrm = ((u8 *)desc) + desc->offset; @@ -454,7 +453,7 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi) } caif_assert(skb != NULL); - dst = skb_put_data(skb, pfrm, len); + skb_put_data(skb, pfrm, len); skb->protocol = htons(ETH_P_CAIF); skb_reset_mac_header(skb); @@ -555,7 +554,6 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi) /* Parse payload. */ while (nfrms < CFHSI_MAX_PKTS && *plen) { struct sk_buff *skb; - u8 *dst = NULL; u8 *pcffrm = NULL; int len; @@ -584,7 +582,7 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi) } caif_assert(skb != NULL); - dst = skb_put_data(skb, pcffrm, len); + skb_put_data(skb, pcffrm, len); skb->protocol = htons(ETH_P_CAIF); skb_reset_mac_header(skb); diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 5c57be2082ba..709838e4c062 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -171,7 +171,6 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data, struct sk_buff *skb = NULL; struct ser_device *ser; int ret; - u8 *p; ser = tty->disc_data; @@ -198,7 +197,7 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data, skb = netdev_alloc_skb(ser->dev, count+1); if (skb == NULL) return; - p = skb_put_data(skb, data, count); + skb_put_data(skb, data, count); skb->protocol = htons(ETH_P_CAIF); skb_reset_mac_header(skb); diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 24a5f5ca2037..207cb8423de0 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -526,7 +526,6 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) struct sk_buff *skb = NULL; int spad = 0; int epad = 0; - u8 *dst = NULL; int pkt_len = 0; /* @@ -548,7 +547,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) skb = netdev_alloc_skb(cfspi->ndev, pkt_len + 1); caif_assert(skb != NULL); - dst = skb_put_data(skb, src, pkt_len); + skb_put_data(skb, src, pkt_len); src += pkt_len; skb->protocol = htons(ETH_P_CAIF); diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 19772e3dd67e..53b088166c28 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -941,6 +941,26 @@ static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip) return mv88e6xxx_g1_atu_set_age_time(chip, 300000); } +static int mv88e6xxx_irl_setup(struct mv88e6xxx_chip *chip) +{ + int port; + int err; + + if (!chip->info->ops->irl_init_all) + return 0; + + for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { + /* Disable ingress rate limiting by resetting all per port + * ingress rate limit resources to their initial state. + */ + err = chip->info->ops->irl_init_all(chip, port); + if (err) + return err; + } + + return 0; +} + static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port) { u16 pvlan = 0; @@ -2102,6 +2122,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) goto unlock; } + err = mv88e6xxx_irl_setup(chip); + if (err) + goto unlock; + err = mv88e6xxx_phy_setup(chip); if (err) goto unlock; @@ -2339,6 +2363,7 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds, static const struct mv88e6xxx_ops mv88e6085_ops = { /* MV88E6XXX_FAMILY_6097 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6185_phy_ppu_read, .phy_write = mv88e6185_phy_ppu_write, @@ -2393,6 +2418,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { static const struct mv88e6xxx_ops mv88e6097_ops = { /* MV88E6XXX_FAMILY_6097 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -2423,6 +2449,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { static const struct mv88e6xxx_ops mv88e6123_ops = { /* MV88E6XXX_FAMILY_6165 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -2479,6 +2506,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { static const struct mv88e6xxx_ops mv88e6141_ops = { /* MV88E6XXX_FAMILY_6341 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2512,6 +2540,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { static const struct mv88e6xxx_ops mv88e6161_ops = { /* MV88E6XXX_FAMILY_6165 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -2542,6 +2571,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { static const struct mv88e6xxx_ops mv88e6165_ops = { /* MV88E6XXX_FAMILY_6165 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6165_phy_read, .phy_write = mv88e6165_phy_write, @@ -2565,6 +2595,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { static const struct mv88e6xxx_ops mv88e6171_ops = { /* MV88E6XXX_FAMILY_6351 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -2596,6 +2627,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { static const struct mv88e6xxx_ops mv88e6172_ops = { /* MV88E6XXX_FAMILY_6352 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2630,6 +2662,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { static const struct mv88e6xxx_ops mv88e6175_ops = { /* MV88E6XXX_FAMILY_6351 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -2661,6 +2694,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { static const struct mv88e6xxx_ops mv88e6176_ops = { /* MV88E6XXX_FAMILY_6352 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2722,6 +2756,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { static const struct mv88e6xxx_ops mv88e6190_ops = { /* MV88E6XXX_FAMILY_6390 */ + .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2755,6 +2790,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { static const struct mv88e6xxx_ops mv88e6190x_ops = { /* MV88E6XXX_FAMILY_6390 */ + .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2788,6 +2824,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { static const struct mv88e6xxx_ops mv88e6191_ops = { /* MV88E6XXX_FAMILY_6390 */ + .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2821,6 +2858,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { static const struct mv88e6xxx_ops mv88e6240_ops = { /* MV88E6XXX_FAMILY_6352 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2855,6 +2893,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { static const struct mv88e6xxx_ops mv88e6290_ops = { /* MV88E6XXX_FAMILY_6390 */ + .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2889,6 +2928,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { static const struct mv88e6xxx_ops mv88e6320_ops = { /* MV88E6XXX_FAMILY_6320 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2920,6 +2960,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { static const struct mv88e6xxx_ops mv88e6321_ops = { /* MV88E6XXX_FAMILY_6321 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2950,6 +2991,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { static const struct mv88e6xxx_ops mv88e6341_ops = { /* MV88E6XXX_FAMILY_6341 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -2983,6 +3025,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { static const struct mv88e6xxx_ops mv88e6350_ops = { /* MV88E6XXX_FAMILY_6351 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -3014,6 +3057,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { static const struct mv88e6xxx_ops mv88e6351_ops = { /* MV88E6XXX_FAMILY_6351 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, @@ -3045,6 +3089,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { static const struct mv88e6xxx_ops mv88e6352_ops = { /* MV88E6XXX_FAMILY_6352 */ + .irl_init_all = mv88e6352_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom16, .set_eeprom = mv88e6xxx_g2_set_eeprom16, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -3079,6 +3124,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { static const struct mv88e6xxx_ops mv88e6390_ops = { /* MV88E6XXX_FAMILY_6390 */ + .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, @@ -3115,6 +3161,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { static const struct mv88e6xxx_ops mv88e6390x_ops = { /* MV88E6XXX_FAMILY_6390 */ + .irl_init_all = mv88e6390_g2_irl_init_all, .get_eeprom = mv88e6xxx_g2_get_eeprom8, .set_eeprom = mv88e6xxx_g2_set_eeprom8, .set_switch_mac = mv88e6xxx_g2_set_switch_mac, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 409452ebc4b9..086444016352 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -121,8 +121,6 @@ enum mv88e6xxx_cap { MV88E6XXX_CAP_G2_INT, /* (0x00) Interrupt Status */ MV88E6XXX_CAP_G2_MGMT_EN_2X, /* (0x02) MGMT Enable Register 2x */ MV88E6XXX_CAP_G2_MGMT_EN_0X, /* (0x03) MGMT Enable Register 0x */ - MV88E6XXX_CAP_G2_IRL_CMD, /* (0x09) Ingress Rate Command */ - MV88E6XXX_CAP_G2_IRL_DATA, /* (0x0a) Ingress Rate Data */ MV88E6XXX_CAP_G2_POT, /* (0x0f) Priority Override Table */ /* Per VLAN Spanning Tree Unit (STU). @@ -149,15 +147,8 @@ enum mv88e6xxx_cap { #define MV88E6XXX_FLAG_G2_INT BIT_ULL(MV88E6XXX_CAP_G2_INT) #define MV88E6XXX_FLAG_G2_MGMT_EN_2X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X) #define MV88E6XXX_FLAG_G2_MGMT_EN_0X BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X) -#define MV88E6XXX_FLAG_G2_IRL_CMD BIT_ULL(MV88E6XXX_CAP_G2_IRL_CMD) -#define MV88E6XXX_FLAG_G2_IRL_DATA BIT_ULL(MV88E6XXX_CAP_G2_IRL_DATA) #define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT) -/* Ingress Rate Limit unit */ -#define MV88E6XXX_FLAGS_IRL \ - (MV88E6XXX_FLAG_G2_IRL_CMD | \ - MV88E6XXX_FLAG_G2_IRL_DATA) - /* Multi-chip Addressing Mode */ #define MV88E6XXX_FLAGS_MULTI_CHIP \ (MV88E6XXX_FLAG_SMI_CMD | \ @@ -175,7 +166,6 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) #define MV88E6XXX_FLAGS_FAMILY_6165 \ @@ -185,7 +175,6 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) #define MV88E6XXX_FLAGS_FAMILY_6185 \ @@ -200,7 +189,6 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) #define MV88E6XXX_FLAGS_FAMILY_6341 \ @@ -209,7 +197,6 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_POT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) #define MV88E6XXX_FLAGS_FAMILY_6351 \ @@ -219,7 +206,6 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) #define MV88E6XXX_FLAGS_FAMILY_6352 \ @@ -230,14 +216,12 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_POT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) #define MV88E6XXX_FLAGS_FAMILY_6390 \ (MV88E6XXX_FLAG_EEE | \ MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_G2_INT | \ - MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_MULTI_CHIP) struct mv88e6xxx_ops; @@ -358,6 +342,9 @@ struct mv88e6xxx_mdio_bus { }; struct mv88e6xxx_ops { + /* Ingress Rate Limit unit (IRL) operations */ + int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port); + int (*get_eeprom)(struct mv88e6xxx_chip *chip, struct ethtool_eeprom *eeprom, u8 *data); int (*set_eeprom)(struct mv88e6xxx_chip *chip, diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 8e8bc4ee464f..158d0f499874 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1,6 +1,5 @@ /* - * Marvell 88E6xxx Switch Global 2 Registers support (device address - * 0x1C) + * Marvell 88E6xxx Switch Global 2 Registers support * * Copyright (c) 2008 Marvell Semiconductor * @@ -13,6 +12,7 @@ * (at your option) any later version. */ +#include <linux/bitfield.h> #include <linux/interrupt.h> #include <linux/irqdomain.h> @@ -22,22 +22,22 @@ static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val) { - return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val); + return mv88e6xxx_read(chip, MV88E6XXX_G2, reg, val); } static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val) { - return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val); + return mv88e6xxx_write(chip, MV88E6XXX_G2, reg, val); } static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update) { - return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update); + return mv88e6xxx_update(chip, MV88E6XXX_G2, reg, update); } static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) { - return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask); + return mv88e6xxx_wait(chip, MV88E6XXX_G2, reg, mask); } /* Offset 0x02: Management Enable 2x */ @@ -51,7 +51,7 @@ int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) * addresses matching 01:80:c2:00:00:2x as MGMT. */ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) { - err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_2X, 0xffff); if (err) return err; } @@ -60,7 +60,8 @@ int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) * addresses matching 01:80:c2:00:00:0x as MGMT. */ if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) - return mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MGMT_EN_0X, + 0xffff); return 0; } @@ -72,7 +73,7 @@ static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, { u16 val = (target << 8) | (port & 0xf); - return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val); + return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_DEVICE_MAPPING, val); } static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip) @@ -101,15 +102,14 @@ static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip) /* Offset 0x07: Trunk Mask Table register */ static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, - bool hask, u16 mask) + bool hash, u16 mask) { - const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; - u16 val = (num << 12) | (mask & port_mask); + u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip)); - if (hask) - val |= GLOBAL2_TRUNK_MASK_HASK; + if (hash) + val |= MV88E6XXX_G2_TRUNK_MASK_HASH; - return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val); + return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MASK, val); } /* Offset 0x08: Trunk Mapping Table register */ @@ -120,7 +120,7 @@ static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; u16 val = (id << 11) | (map & port_mask); - return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val); + return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_TRUNK_MAPPING, val); } static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip) @@ -149,27 +149,36 @@ static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip) * Offset 0x0A: Ingress Rate Data register */ -static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip) +static int mv88e6xxx_g2_irl_wait(struct mv88e6xxx_chip *chip) { - int port, err; + return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_IRL_CMD, + MV88E6XXX_G2_IRL_CMD_BUSY); +} - /* Init all Ingress Rate Limit resources of all ports */ - for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) { - /* XXX newer chips (like 88E6390) have different 2-bit ops */ - err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD, - GLOBAL2_IRL_CMD_OP_INIT_ALL | - (port << 8)); - if (err) - break; +static int mv88e6xxx_g2_irl_op(struct mv88e6xxx_chip *chip, u16 op, int port, + int res, int reg) +{ + int err; - /* Wait for the operation to complete */ - err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD, - GLOBAL2_IRL_CMD_BUSY); - if (err) - break; - } + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_IRL_CMD, + MV88E6XXX_G2_IRL_CMD_BUSY | op | (port << 8) | + (res << 5) | reg); + if (err) + return err; - return err; + return mv88e6xxx_g2_irl_wait(chip); +} + +int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port) +{ + return mv88e6xxx_g2_irl_op(chip, MV88E6352_G2_IRL_CMD_OP_INIT_ALL, port, + 0, 0); +} + +int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port) +{ + return mv88e6xxx_g2_irl_op(chip, MV88E6390_G2_IRL_CMD_OP_INIT_ALL, port, + 0, 0); } /* Offset 0x0B: Cross-chip Port VLAN (Addr) Register @@ -178,7 +187,8 @@ static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip) static int mv88e6xxx_g2_pvt_op_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, GLOBAL2_PVT_ADDR, GLOBAL2_PVT_ADDR_BUSY); + return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_PVT_ADDR, + MV88E6XXX_G2_PVT_ADDR_BUSY); } static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev, @@ -186,13 +196,14 @@ static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev, { int err; - /* 9-bit Cross-chip PVT pointer: with GLOBAL2_MISC_5_BIT_PORT cleared, - * source device is 5-bit, source port is 4-bit. + /* 9-bit Cross-chip PVT pointer: with MV88E6XXX_G2_MISC_5_BIT_PORT + * cleared, source device is 5-bit, source port is 4-bit. */ + op |= MV88E6XXX_G2_PVT_ADDR_BUSY; op |= (src_dev & 0x1f) << 4; op |= (src_port & 0xf); - err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR, op); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_ADDR, op); if (err) return err; @@ -208,12 +219,12 @@ int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, if (err) return err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_DATA, data); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_PVT_DATA, data); if (err) return err; return mv88e6xxx_g2_pvt_op(chip, src_dev, src_port, - GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN); + MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN); } /* Offset 0x0D: Switch MAC/WoL/WoF register */ @@ -223,7 +234,7 @@ static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip, { u16 val = (pointer << 8) | data; - return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val); + return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_SWITCH_MAC, val); } int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr) @@ -246,7 +257,7 @@ static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer, { u16 val = (pointer << 8) | (data & 0x7); - return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val); + return mv88e6xxx_g2_update(chip, MV88E6XXX_G2_PRIO_OVERRIDE, val); } static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip) @@ -270,16 +281,17 @@ static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip) static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD, - GLOBAL2_EEPROM_CMD_BUSY | - GLOBAL2_EEPROM_CMD_RUNNING); + return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_EEPROM_CMD, + MV88E6XXX_G2_EEPROM_CMD_BUSY | + MV88E6XXX_G2_EEPROM_CMD_RUNNING); } static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd) { int err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_EEPROM_CMD, + MV88E6XXX_G2_EEPROM_CMD_BUSY | cmd); if (err) return err; @@ -289,14 +301,14 @@ static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd) static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip, u16 addr, u8 *data) { - u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ; + u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ; int err; err = mv88e6xxx_g2_eeprom_wait(chip); if (err) return err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr); + err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr); if (err) return err; @@ -304,7 +316,7 @@ static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip, if (err) return err; - err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &cmd); + err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &cmd); if (err) return err; @@ -316,14 +328,15 @@ static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip, static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip, u16 addr, u8 data) { - u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | GLOBAL2_EEPROM_CMD_WRITE_EN; + u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | + MV88E6XXX_G2_EEPROM_CMD_WRITE_EN; int err; err = mv88e6xxx_g2_eeprom_wait(chip); if (err) return err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr); + err = mv88e6xxx_g2_write(chip, MV88E6390_G2_EEPROM_ADDR, addr); if (err) return err; @@ -333,7 +346,7 @@ static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip, static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip, u8 addr, u16 *data) { - u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr; + u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_READ | addr; int err; err = mv88e6xxx_g2_eeprom_wait(chip); @@ -344,20 +357,20 @@ static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip, if (err) return err; - return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data); + return mv88e6xxx_g2_read(chip, MV88E6352_G2_EEPROM_DATA, data); } static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip, u8 addr, u16 data) { - u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr; + u16 cmd = MV88E6XXX_G2_EEPROM_CMD_OP_WRITE | addr; int err; err = mv88e6xxx_g2_eeprom_wait(chip); if (err) return err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data); + err = mv88e6xxx_g2_write(chip, MV88E6352_G2_EEPROM_DATA, data); if (err) return err; @@ -469,11 +482,11 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, int err; /* Ensure the RO WriteEn bit is set */ - err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val); + err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_EEPROM_CMD, &val); if (err) return err; - if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN)) + if (!(val & MV88E6XXX_G2_EEPROM_CMD_WRITE_EN)) return -EROFS; eeprom->len = 0; @@ -532,178 +545,213 @@ int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD, - GLOBAL2_SMI_PHY_CMD_BUSY); + return mv88e6xxx_g2_wait(chip, MV88E6XXX_G2_SMI_PHY_CMD, + MV88E6XXX_G2_SMI_PHY_CMD_BUSY); } static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd) { int err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_CMD, + MV88E6XXX_G2_SMI_PHY_CMD_BUSY | cmd); if (err) return err; return mv88e6xxx_g2_smi_phy_wait(chip); } -static int mv88e6xxx_g2_smi_phy_write_addr(struct mv88e6xxx_chip *chip, - int addr, int device, int reg, - bool external) +static int mv88e6xxx_g2_smi_phy_access(struct mv88e6xxx_chip *chip, + bool external, bool c45, u16 op, int dev, + int reg) { - int cmd = SMI_CMD_OP_45_WRITE_ADDR | (addr << 5) | device; - int err; + u16 cmd = op; if (external) - cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL; + cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL; + else + cmd |= MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL; /* empty mask */ - err = mv88e6xxx_g2_smi_phy_wait(chip); - if (err) - return err; + if (c45) + cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_45; /* empty mask */ + else + cmd |= MV88E6XXX_G2_SMI_PHY_CMD_MODE_22; - err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, reg); - if (err) - return err; + dev <<= __bf_shf(MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK); + cmd |= dev & MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK; + cmd |= reg & MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK; return mv88e6xxx_g2_smi_phy_cmd(chip, cmd); } -static int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip, - int addr, int reg_c45, u16 *val, - bool external) +static int mv88e6xxx_g2_smi_phy_access_c22(struct mv88e6xxx_chip *chip, + bool external, u16 op, int dev, + int reg) +{ + return mv88e6xxx_g2_smi_phy_access(chip, external, false, op, dev, reg); +} + +/* IEEE 802.3 Clause 22 Read Data Register */ +static int mv88e6xxx_g2_smi_phy_read_data_c22(struct mv88e6xxx_chip *chip, + bool external, int dev, int reg, + u16 *data) { - int device = (reg_c45 >> 16) & 0x1f; - int reg = reg_c45 & 0xffff; + u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA; int err; - u16 cmd; - err = mv88e6xxx_g2_smi_phy_write_addr(chip, addr, device, reg, - external); + err = mv88e6xxx_g2_smi_phy_wait(chip); if (err) return err; - cmd = GLOBAL2_SMI_PHY_CMD_OP_45_READ_DATA | (addr << 5) | device; + err = mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg); + if (err) + return err; - if (external) - cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL; + return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data); +} - err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd); +/* IEEE 802.3 Clause 22 Write Data Register */ +static int mv88e6xxx_g2_smi_phy_write_data_c22(struct mv88e6xxx_chip *chip, + bool external, int dev, int reg, + u16 data) +{ + u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA; + int err; + + err = mv88e6xxx_g2_smi_phy_wait(chip); if (err) return err; - err = mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data); if (err) return err; - err = *val; + return mv88e6xxx_g2_smi_phy_access_c22(chip, external, op, dev, reg); +} - return 0; +static int mv88e6xxx_g2_smi_phy_access_c45(struct mv88e6xxx_chip *chip, + bool external, u16 op, int port, + int dev) +{ + return mv88e6xxx_g2_smi_phy_access(chip, external, true, op, port, dev); } -static int mv88e6xxx_g2_smi_phy_read_c22(struct mv88e6xxx_chip *chip, - int addr, int reg, u16 *val, - bool external) +/* IEEE 802.3 Clause 45 Write Address Register */ +static int mv88e6xxx_g2_smi_phy_write_addr_c45(struct mv88e6xxx_chip *chip, + bool external, int port, int dev, + int addr) { - u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg; + u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_ADDR; int err; - if (external) - cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL; - err = mv88e6xxx_g2_smi_phy_wait(chip); if (err) return err; - err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, addr); if (err) return err; - return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val); + return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev); } -int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, - struct mii_bus *bus, - int addr, int reg, u16 *val) +/* IEEE 802.3 Clause 45 Read Data Register */ +static int mv88e6xxx_g2_smi_phy_read_data_c45(struct mv88e6xxx_chip *chip, + bool external, int port, int dev, + u16 *data) { - struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; - bool external = mdio_bus->external; + u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_READ_DATA; + int err; - if (reg & MII_ADDR_C45) - return mv88e6xxx_g2_smi_phy_read_c45(chip, addr, reg, val, - external); - return mv88e6xxx_g2_smi_phy_read_c22(chip, addr, reg, val, external); + err = mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev); + if (err) + return err; + + return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_SMI_PHY_DATA, data); } -static int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip, - int addr, int reg_c45, u16 val, - bool external) +static int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip, + bool external, int port, int reg, + u16 *data) { - int device = (reg_c45 >> 16) & 0x1f; - int reg = reg_c45 & 0xffff; + int dev = (reg >> 16) & 0x1f; + int addr = reg & 0xffff; int err; - u16 cmd; - err = mv88e6xxx_g2_smi_phy_write_addr(chip, addr, device, reg, - external); + err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev, + addr); if (err) return err; - cmd = GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_DATA | (addr << 5) | device; - - if (external) - cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL; + return mv88e6xxx_g2_smi_phy_read_data_c45(chip, external, port, dev, + data); +} - err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val); - if (err) - return err; +/* IEEE 802.3 Clause 45 Write Data Register */ +static int mv88e6xxx_g2_smi_phy_write_data_c45(struct mv88e6xxx_chip *chip, + bool external, int port, int dev, + u16 data) +{ + u16 op = MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_DATA; + int err; - err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd); + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SMI_PHY_DATA, data); if (err) return err; - return 0; + return mv88e6xxx_g2_smi_phy_access_c45(chip, external, op, port, dev); } -static int mv88e6xxx_g2_smi_phy_write_c22(struct mv88e6xxx_chip *chip, - int addr, int reg, u16 val, - bool external) +static int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip, + bool external, int port, int reg, + u16 data) { - u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg; + int dev = (reg >> 16) & 0x1f; + int addr = reg & 0xffff; int err; - if (external) - cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL; - - err = mv88e6xxx_g2_smi_phy_wait(chip); + err = mv88e6xxx_g2_smi_phy_write_addr_c45(chip, external, port, dev, + addr); if (err) return err; - err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val); - if (err) - return err; + return mv88e6xxx_g2_smi_phy_write_data_c45(chip, external, port, dev, + data); +} - return mv88e6xxx_g2_smi_phy_cmd(chip, cmd); +int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus, + int addr, int reg, u16 *val) +{ + struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; + bool external = mdio_bus->external; + + if (reg & MII_ADDR_C45) + return mv88e6xxx_g2_smi_phy_read_c45(chip, external, addr, reg, + val); + + return mv88e6xxx_g2_smi_phy_read_data_c22(chip, external, addr, reg, + val); } -int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, - struct mii_bus *bus, +int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, struct mii_bus *bus, int addr, int reg, u16 val) { struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; bool external = mdio_bus->external; if (reg & MII_ADDR_C45) - return mv88e6xxx_g2_smi_phy_write_c45(chip, addr, reg, val, - external); + return mv88e6xxx_g2_smi_phy_write_c45(chip, external, addr, reg, + val); - return mv88e6xxx_g2_smi_phy_write_c22(chip, addr, reg, val, external); + return mv88e6xxx_g2_smi_phy_write_data_c22(chip, external, addr, reg, + val); } static int mv88e6097_watchdog_action(struct mv88e6xxx_chip *chip, int irq) { u16 reg; - mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, ®); + mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, ®); dev_info(chip->dev, "Watchdog event: 0x%04x", reg); @@ -714,20 +762,20 @@ static void mv88e6097_watchdog_free(struct mv88e6xxx_chip *chip) { u16 reg; - mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, ®); + mv88e6xxx_g2_read(chip, MV88E6352_G2_WDOG_CTL, ®); - reg &= ~(GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE | - GLOBAL2_WDOG_CONTROL_QC_ENABLE); + reg &= ~(MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE | + MV88E6352_G2_WDOG_CTL_QC_ENABLE); - mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, reg); + mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL, reg); } static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, - GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE | - GLOBAL2_WDOG_CONTROL_QC_ENABLE | - GLOBAL2_WDOG_CONTROL_SWRESET); + return mv88e6xxx_g2_write(chip, MV88E6352_G2_WDOG_CTL, + MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE | + MV88E6352_G2_WDOG_CTL_QC_ENABLE | + MV88E6352_G2_WDOG_CTL_SWRESET); } const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = { @@ -738,12 +786,12 @@ const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = { static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip) { - return mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL, - GLOBAL2_WDOG_INT_ENABLE | - GLOBAL2_WDOG_CUT_THROUGH | - GLOBAL2_WDOG_QUEUE_CONTROLLER | - GLOBAL2_WDOG_EGRESS | - GLOBAL2_WDOG_FORCE_IRQ); + return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL, + MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE | + MV88E6390_G2_WDOG_CTL_CUT_THROUGH | + MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER | + MV88E6390_G2_WDOG_CTL_EGRESS | + MV88E6390_G2_WDOG_CTL_FORCE_IRQ); } static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq) @@ -751,17 +799,19 @@ static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq) int err; u16 reg; - mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_EVENT); - err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, ®); + mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL, + MV88E6390_G2_WDOG_CTL_PTR_EVENT); + err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, ®); dev_info(chip->dev, "Watchdog event: 0x%04x", - reg & GLOBAL2_WDOG_DATA_MASK); + reg & MV88E6390_G2_WDOG_CTL_DATA_MASK); - mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_HISTORY); - err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, ®); + mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL, + MV88E6390_G2_WDOG_CTL_PTR_HISTORY); + err = mv88e6xxx_g2_read(chip, MV88E6390_G2_WDOG_CTL, ®); dev_info(chip->dev, "Watchdog history: 0x%04x", - reg & GLOBAL2_WDOG_DATA_MASK); + reg & MV88E6390_G2_WDOG_CTL_DATA_MASK); /* Trigger a software reset to try to recover the switch */ if (chip->info->ops->reset) @@ -774,8 +824,8 @@ static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq) static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip) { - mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL, - GLOBAL2_WDOG_INT_ENABLE); + mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL, + MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE); } const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = { @@ -813,7 +863,7 @@ static int mv88e6xxx_g2_watchdog_setup(struct mv88e6xxx_chip *chip) int err; chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain, - GLOBAL2_INT_SOURCE_WATCHDOG); + MV88E6XXX_G2_INT_SOURCE_WATCHDOG); if (chip->watchdog_irq < 0) return chip->watchdog_irq; @@ -840,16 +890,16 @@ static int mv88e6xxx_g2_misc_5_bit_port(struct mv88e6xxx_chip *chip, u16 val; int err; - err = mv88e6xxx_g2_read(chip, GLOBAL2_MISC, &val); + err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_MISC, &val); if (err) return err; if (port_5_bit) - val |= GLOBAL2_MISC_5_BIT_PORT; + val |= MV88E6XXX_G2_MISC_5_BIT_PORT; else - val &= ~GLOBAL2_MISC_5_BIT_PORT; + val &= ~MV88E6XXX_G2_MISC_5_BIT_PORT; - return mv88e6xxx_g2_write(chip, GLOBAL2_MISC, val); + return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_MISC, val); } int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) @@ -883,7 +933,7 @@ static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id) u16 reg; mutex_lock(&chip->reg_lock); - err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, ®); + err = mv88e6xxx_g2_read(chip, MV88E6XXX_G2_INT_SOURCE, ®); mutex_unlock(&chip->reg_lock); if (err) goto out; @@ -910,7 +960,7 @@ static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d) { struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d); - mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked); + mv88e6xxx_g2_write(chip, MV88E6XXX_G2_INT_MASK, ~chip->g2_irq.masked); mutex_unlock(&chip->reg_lock); } @@ -1012,11 +1062,11 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) * highest, and send all special multicast frames to the CPU * port at the highest priority. */ - reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4); + reg = MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI | (0x7 << 4); if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) || mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) - reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7; - err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg); + reg |= MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU | 0x7; + err = mv88e6xxx_g2_write(chip, MV88E6XXX_G2_SWITCH_MGMT, reg); if (err) return err; @@ -1030,15 +1080,6 @@ int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip) if (err) return err; - if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) { - /* Disable ingress rate limiting by resetting all per port - * ingress rate limit resources to their initial state. - */ - err = mv88e6xxx_g2_clear_irl(chip); - if (err) - return err; - } - if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) { /* Clear the priority override table. */ err = mv88e6xxx_g2_clear_pot(chip); diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 479d42971706..317ffd8f323d 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -1,5 +1,5 @@ /* - * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C) + * Marvell 88E6xxx Switch Global 2 Registers support * * Copyright (c) 2008 Marvell Semiconductor * @@ -17,108 +17,198 @@ #include "chip.h" -#define ADDR_GLOBAL2 0x1c - -#define GLOBAL2_INT_SOURCE 0x00 -#define GLOBAL2_INT_SOURCE_WATCHDOG 15 -#define GLOBAL2_INT_MASK 0x01 -#define GLOBAL2_MGMT_EN_2X 0x02 -#define GLOBAL2_MGMT_EN_0X 0x03 -#define GLOBAL2_FLOW_CONTROL 0x04 -#define GLOBAL2_SWITCH_MGMT 0x05 -#define GLOBAL2_SWITCH_MGMT_USE_DOUBLE_TAG_DATA BIT(15) -#define GLOBAL2_SWITCH_MGMT_PREVENT_LOOPS BIT(14) -#define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG BIT(13) -#define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI BIT(7) -#define GLOBAL2_SWITCH_MGMT_RSVD2CPU BIT(3) -#define GLOBAL2_DEVICE_MAPPING 0x06 -#define GLOBAL2_DEVICE_MAPPING_UPDATE BIT(15) -#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT 8 -#define GLOBAL2_DEVICE_MAPPING_PORT_MASK 0x0f -#define GLOBAL2_TRUNK_MASK 0x07 -#define GLOBAL2_TRUNK_MASK_UPDATE BIT(15) -#define GLOBAL2_TRUNK_MASK_NUM_SHIFT 12 -#define GLOBAL2_TRUNK_MASK_HASK BIT(11) -#define GLOBAL2_TRUNK_MAPPING 0x08 -#define GLOBAL2_TRUNK_MAPPING_UPDATE BIT(15) -#define GLOBAL2_TRUNK_MAPPING_ID_SHIFT 11 -#define GLOBAL2_IRL_CMD 0x09 -#define GLOBAL2_IRL_CMD_BUSY BIT(15) -#define GLOBAL2_IRL_CMD_OP_INIT_ALL ((0x001 << 12) | GLOBAL2_IRL_CMD_BUSY) -#define GLOBAL2_IRL_CMD_OP_INIT_SEL ((0x010 << 12) | GLOBAL2_IRL_CMD_BUSY) -#define GLOBAL2_IRL_CMD_OP_WRITE_SEL ((0x011 << 12) | GLOBAL2_IRL_CMD_BUSY) -#define GLOBAL2_IRL_CMD_OP_READ_SEL ((0x100 << 12) | GLOBAL2_IRL_CMD_BUSY) -#define GLOBAL2_IRL_DATA 0x0a -#define GLOBAL2_PVT_ADDR 0x0b -#define GLOBAL2_PVT_ADDR_BUSY BIT(15) -#define GLOBAL2_PVT_ADDR_OP_INIT_ONES ((0x01 << 12) | GLOBAL2_PVT_ADDR_BUSY) -#define GLOBAL2_PVT_ADDR_OP_WRITE_PVLAN ((0x03 << 12) | GLOBAL2_PVT_ADDR_BUSY) -#define GLOBAL2_PVT_ADDR_OP_READ ((0x04 << 12) | GLOBAL2_PVT_ADDR_BUSY) -#define GLOBAL2_PVT_DATA 0x0c -#define GLOBAL2_SWITCH_MAC 0x0d -#define GLOBAL2_ATU_STATS 0x0e -#define GLOBAL2_PRIO_OVERRIDE 0x0f -#define GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP BIT(7) -#define GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT 4 -#define GLOBAL2_PRIO_OVERRIDE_FORCE_ARP BIT(3) -#define GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT 0 -#define GLOBAL2_EEPROM_CMD 0x14 -#define GLOBAL2_EEPROM_CMD_BUSY BIT(15) -#define GLOBAL2_EEPROM_CMD_OP_WRITE ((0x3 << 12) | GLOBAL2_EEPROM_CMD_BUSY) -#define GLOBAL2_EEPROM_CMD_OP_READ ((0x4 << 12) | GLOBAL2_EEPROM_CMD_BUSY) -#define GLOBAL2_EEPROM_CMD_OP_LOAD ((0x6 << 12) | GLOBAL2_EEPROM_CMD_BUSY) -#define GLOBAL2_EEPROM_CMD_RUNNING BIT(11) -#define GLOBAL2_EEPROM_CMD_WRITE_EN BIT(10) -#define GLOBAL2_EEPROM_CMD_ADDR_MASK 0xff -#define GLOBAL2_EEPROM_DATA 0x15 -#define GLOBAL2_EEPROM_ADDR 0x15 /* 6390, 6341 */ -#define GLOBAL2_PTP_AVB_OP 0x16 -#define GLOBAL2_PTP_AVB_DATA 0x17 -#define GLOBAL2_SMI_PHY_CMD 0x18 -#define GLOBAL2_SMI_PHY_CMD_BUSY BIT(15) -#define GLOBAL2_SMI_PHY_CMD_EXTERNAL BIT(13) -#define GLOBAL2_SMI_PHY_CMD_MODE_22 BIT(12) -#define GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA ((0x1 << 10) | \ - GLOBAL2_SMI_PHY_CMD_MODE_22 | \ - GLOBAL2_SMI_PHY_CMD_BUSY) -#define GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA ((0x2 << 10) | \ - GLOBAL2_SMI_PHY_CMD_MODE_22 | \ - GLOBAL2_SMI_PHY_CMD_BUSY) -#define GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_ADDR ((0x0 << 10) | \ - GLOBAL2_SMI_PHY_CMD_BUSY) -#define GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_DATA ((0x1 << 10) | \ - GLOBAL2_SMI_PHY_CMD_BUSY) -#define GLOBAL2_SMI_PHY_CMD_OP_45_READ_DATA ((0x3 << 10) | \ - GLOBAL2_SMI_PHY_CMD_BUSY) - -#define GLOBAL2_SMI_PHY_DATA 0x19 -#define GLOBAL2_SCRATCH_MISC 0x1a -#define GLOBAL2_SCRATCH_BUSY BIT(15) -#define GLOBAL2_SCRATCH_REGISTER_SHIFT 8 -#define GLOBAL2_SCRATCH_VALUE_MASK 0xff -#define GLOBAL2_WDOG_CONTROL 0x1b -#define GLOBAL2_WDOG_CONTROL_EGRESS_EVENT BIT(7) -#define GLOBAL2_WDOG_CONTROL_RMU_TIMEOUT BIT(6) -#define GLOBAL2_WDOG_CONTROL_QC_ENABLE BIT(5) -#define GLOBAL2_WDOG_CONTROL_EGRESS_HISTORY BIT(4) -#define GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE BIT(3) -#define GLOBAL2_WDOG_CONTROL_FORCE_IRQ BIT(2) -#define GLOBAL2_WDOG_CONTROL_HISTORY BIT(1) -#define GLOBAL2_WDOG_CONTROL_SWRESET BIT(0) -#define GLOBAL2_WDOG_UPDATE BIT(15) -#define GLOBAL2_WDOG_INT_SOURCE (0x00 << 8) -#define GLOBAL2_WDOG_INT_STATUS (0x10 << 8) -#define GLOBAL2_WDOG_INT_ENABLE (0x11 << 8) -#define GLOBAL2_WDOG_EVENT (0x12 << 8) -#define GLOBAL2_WDOG_HISTORY (0x13 << 8) -#define GLOBAL2_WDOG_DATA_MASK 0xff -#define GLOBAL2_WDOG_CUT_THROUGH BIT(3) -#define GLOBAL2_WDOG_QUEUE_CONTROLLER BIT(2) -#define GLOBAL2_WDOG_EGRESS BIT(1) -#define GLOBAL2_WDOG_FORCE_IRQ BIT(0) -#define GLOBAL2_QOS_WEIGHT 0x1c -#define GLOBAL2_MISC 0x1d -#define GLOBAL2_MISC_5_BIT_PORT BIT(14) +#define MV88E6XXX_G2 0x1c + +/* Offset 0x00: Interrupt Source Register */ +#define MV88E6XXX_G2_INT_SOURCE 0x00 +#define MV88E6XXX_G2_INT_SOURCE_WATCHDOG 15 + +/* Offset 0x01: Interrupt Mask Register */ +#define MV88E6XXX_G2_INT_MASK 0x01 + +/* Offset 0x02: MGMT Enable Register 2x */ +#define MV88E6XXX_G2_MGMT_EN_2X 0x02 + +/* Offset 0x03: MGMT Enable Register 0x */ +#define MV88E6XXX_G2_MGMT_EN_0X 0x03 + +/* Offset 0x04: Flow Control Delay Register */ +#define MV88E6XXX_G2_FLOW_CTL 0x04 + +/* Offset 0x05: Switch Management Register */ +#define MV88E6XXX_G2_SWITCH_MGMT 0x05 +#define MV88E6XXX_G2_SWITCH_MGMT_USE_DOUBLE_TAG_DATA 0x8000 +#define MV88E6XXX_G2_SWITCH_MGMT_PREVENT_LOOPS 0x4000 +#define MV88E6XXX_G2_SWITCH_MGMT_FLOW_CTL_MSG 0x2000 +#define MV88E6XXX_G2_SWITCH_MGMT_FORCE_FLOW_CTL_PRI 0x0080 +#define MV88E6XXX_G2_SWITCH_MGMT_RSVD2CPU 0x0008 + +/* Offset 0x06: Device Mapping Table Register */ +#define MV88E6XXX_G2_DEVICE_MAPPING 0x06 +#define MV88E6XXX_G2_DEVICE_MAPPING_UPDATE 0x8000 +#define MV88E6XXX_G2_DEVICE_MAPPING_DEV_MASK 0x1f00 +#define MV88E6XXX_G2_DEVICE_MAPPING_PORT_MASK 0x000f + +/* Offset 0x07: Trunk Mask Table Register */ +#define MV88E6XXX_G2_TRUNK_MASK 0x07 +#define MV88E6XXX_G2_TRUNK_MASK_UPDATE 0x8000 +#define MV88E6XXX_G2_TRUNK_MASK_NUM_MASK 0x7000 +#define MV88E6XXX_G2_TRUNK_MASK_HASH 0x0800 + +/* Offset 0x08: Trunk Mapping Table Register */ +#define MV88E6XXX_G2_TRUNK_MAPPING 0x08 +#define MV88E6XXX_G2_TRUNK_MAPPING_UPDATE 0x8000 +#define MV88E6XXX_G2_TRUNK_MAPPING_ID_MASK 0x7800 + +/* Offset 0x09: Ingress Rate Command Register */ +#define MV88E6XXX_G2_IRL_CMD 0x09 +#define MV88E6XXX_G2_IRL_CMD_BUSY 0x8000 +#define MV88E6352_G2_IRL_CMD_OP_MASK 0x7000 +#define MV88E6352_G2_IRL_CMD_OP_NOOP 0x0000 +#define MV88E6352_G2_IRL_CMD_OP_INIT_ALL 0x1000 +#define MV88E6352_G2_IRL_CMD_OP_INIT_RES 0x2000 +#define MV88E6352_G2_IRL_CMD_OP_WRITE_REG 0x3000 +#define MV88E6352_G2_IRL_CMD_OP_READ_REG 0x4000 +#define MV88E6390_G2_IRL_CMD_OP_MASK 0x6000 +#define MV88E6390_G2_IRL_CMD_OP_READ_REG 0x0000 +#define MV88E6390_G2_IRL_CMD_OP_INIT_ALL 0x2000 +#define MV88E6390_G2_IRL_CMD_OP_INIT_RES 0x4000 +#define MV88E6390_G2_IRL_CMD_OP_WRITE_REG 0x6000 +#define MV88E6352_G2_IRL_CMD_PORT_MASK 0x0f00 +#define MV88E6390_G2_IRL_CMD_PORT_MASK 0x1f00 +#define MV88E6XXX_G2_IRL_CMD_RES_MASK 0x00e0 +#define MV88E6XXX_G2_IRL_CMD_REG_MASK 0x000f + +/* Offset 0x0A: Ingress Rate Data Register */ +#define MV88E6XXX_G2_IRL_DATA 0x0a +#define MV88E6XXX_G2_IRL_DATA_MASK 0xffff + +/* Offset 0x0B: Cross-chip Port VLAN Register */ +#define MV88E6XXX_G2_PVT_ADDR 0x0b +#define MV88E6XXX_G2_PVT_ADDR_BUSY 0x8000 +#define MV88E6XXX_G2_PVT_ADDR_OP_MASK 0x7000 +#define MV88E6XXX_G2_PVT_ADDR_OP_INIT_ONES 0x1000 +#define MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN 0x3000 +#define MV88E6XXX_G2_PVT_ADDR_OP_READ 0x4000 +#define MV88E6XXX_G2_PVT_ADDR_PTR_MASK 0x01ff + +/* Offset 0x0C: Cross-chip Port VLAN Data Register */ +#define MV88E6XXX_G2_PVT_DATA 0x0c +#define MV88E6XXX_G2_PVT_DATA_MASK 0x7f + +/* Offset 0x0D: Switch MAC/WoL/WoF Register */ +#define MV88E6XXX_G2_SWITCH_MAC 0x0d +#define MV88E6XXX_G2_SWITCH_MAC_UPDATE 0x8000 +#define MV88E6XXX_G2_SWITCH_MAC_PTR_MASK 0x1f00 +#define MV88E6XXX_G2_SWITCH_MAC_DATA_MASK 0x00ff + +/* Offset 0x0E: ATU Stats Register */ +#define MV88E6XXX_G2_ATU_STATS 0x0e + +/* Offset 0x0F: Priority Override Table */ +#define MV88E6XXX_G2_PRIO_OVERRIDE 0x0f +#define MV88E6XXX_G2_PRIO_OVERRIDE_UPDATE 0x8000 +#define MV88E6XXX_G2_PRIO_OVERRIDE_FPRISET 0x1000 +#define MV88E6XXX_G2_PRIO_OVERRIDE_PTR_MASK 0x0f00 +#define MV88E6352_G2_PRIO_OVERRIDE_QPRIAVBEN 0x0080 +#define MV88E6352_G2_PRIO_OVERRIDE_DATAAVB_MASK 0x0030 +#define MV88E6XXX_G2_PRIO_OVERRIDE_QFPRIEN 0x0008 +#define MV88E6XXX_G2_PRIO_OVERRIDE_DATA_MASK 0x0007 + +/* Offset 0x14: EEPROM Command */ +#define MV88E6XXX_G2_EEPROM_CMD 0x14 +#define MV88E6XXX_G2_EEPROM_CMD_BUSY 0x8000 +#define MV88E6XXX_G2_EEPROM_CMD_OP_MASK 0x7000 +#define MV88E6XXX_G2_EEPROM_CMD_OP_WRITE 0x3000 +#define MV88E6XXX_G2_EEPROM_CMD_OP_READ 0x4000 +#define MV88E6XXX_G2_EEPROM_CMD_OP_LOAD 0x6000 +#define MV88E6XXX_G2_EEPROM_CMD_RUNNING 0x0800 +#define MV88E6XXX_G2_EEPROM_CMD_WRITE_EN 0x0400 +#define MV88E6352_G2_EEPROM_CMD_ADDR_MASK 0x00ff +#define MV88E6390_G2_EEPROM_CMD_DATA_MASK 0x00ff + +/* Offset 0x15: EEPROM Data */ +#define MV88E6352_G2_EEPROM_DATA 0x15 +#define MV88E6352_G2_EEPROM_DATA_MASK 0xffff + +/* Offset 0x15: EEPROM Addr */ +#define MV88E6390_G2_EEPROM_ADDR 0x15 +#define MV88E6390_G2_EEPROM_ADDR_MASK 0xffff + +/* Offset 0x16: AVB Command Register */ +#define MV88E6352_G2_AVB_CMD 0x16 + +/* Offset 0x17: AVB Data Register */ +#define MV88E6352_G2_AVB_DATA 0x17 + +/* Offset 0x18: SMI PHY Command Register */ +#define MV88E6XXX_G2_SMI_PHY_CMD 0x18 +#define MV88E6XXX_G2_SMI_PHY_CMD_BUSY 0x8000 +#define MV88E6390_G2_SMI_PHY_CMD_FUNC_MASK 0x6000 +#define MV88E6390_G2_SMI_PHY_CMD_FUNC_INTERNAL 0x0000 +#define MV88E6390_G2_SMI_PHY_CMD_FUNC_EXTERNAL 0x2000 +#define MV88E6390_G2_SMI_PHY_CMD_FUNC_SETUP 0x4000 +#define MV88E6XXX_G2_SMI_PHY_CMD_MODE_MASK 0x1000 +#define MV88E6XXX_G2_SMI_PHY_CMD_MODE_45 0x0000 +#define MV88E6XXX_G2_SMI_PHY_CMD_MODE_22 0x1000 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_MASK 0x0c00 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_22_WRITE_DATA 0x0400 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_22_READ_DATA 0x0800 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_ADDR 0x0000 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_45_WRITE_DATA 0x0400 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_45_READ_DATA_INC 0x0800 +#define MV88E6XXX_G2_SMI_PHY_CMD_OP_45_READ_DATA 0x0c00 +#define MV88E6XXX_G2_SMI_PHY_CMD_DEV_ADDR_MASK 0x03e0 +#define MV88E6XXX_G2_SMI_PHY_CMD_REG_ADDR_MASK 0x001f +#define MV88E6XXX_G2_SMI_PHY_CMD_SETUP_PTR_MASK 0x03ff + +/* Offset 0x19: SMI PHY Data Register */ +#define MV88E6XXX_G2_SMI_PHY_DATA 0x19 + +/* Offset 0x1A: Scratch and Misc. Register */ +#define MV88E6XXX_G2_SCRATCH_MISC_MISC 0x1a +#define MV88E6XXX_G2_SCRATCH_MISC_UPDATE 0x8000 +#define MV88E6XXX_G2_SCRATCH_MISC_PTR_MASK 0x7f00 +#define MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK 0x00ff + +/* Offset 0x1B: Watch Dog Control Register */ +#define MV88E6352_G2_WDOG_CTL 0x1b +#define MV88E6352_G2_WDOG_CTL_EGRESS_EVENT 0x0080 +#define MV88E6352_G2_WDOG_CTL_RMU_TIMEOUT 0x0040 +#define MV88E6352_G2_WDOG_CTL_QC_ENABLE 0x0020 +#define MV88E6352_G2_WDOG_CTL_EGRESS_HISTORY 0x0010 +#define MV88E6352_G2_WDOG_CTL_EGRESS_ENABLE 0x0008 +#define MV88E6352_G2_WDOG_CTL_FORCE_IRQ 0x0004 +#define MV88E6352_G2_WDOG_CTL_HISTORY 0x0002 +#define MV88E6352_G2_WDOG_CTL_SWRESET 0x0001 + +/* Offset 0x1B: Watch Dog Control Register */ +#define MV88E6390_G2_WDOG_CTL 0x1b +#define MV88E6390_G2_WDOG_CTL_UPDATE 0x8000 +#define MV88E6390_G2_WDOG_CTL_PTR_MASK 0x7f00 +#define MV88E6390_G2_WDOG_CTL_PTR_INT_SOURCE 0x0000 +#define MV88E6390_G2_WDOG_CTL_PTR_INT_STS 0x1000 +#define MV88E6390_G2_WDOG_CTL_PTR_INT_ENABLE 0x1100 +#define MV88E6390_G2_WDOG_CTL_PTR_EVENT 0x1200 +#define MV88E6390_G2_WDOG_CTL_PTR_HISTORY 0x1300 +#define MV88E6390_G2_WDOG_CTL_DATA_MASK 0x00ff +#define MV88E6390_G2_WDOG_CTL_CUT_THROUGH 0x0008 +#define MV88E6390_G2_WDOG_CTL_QUEUE_CONTROLLER 0x0004 +#define MV88E6390_G2_WDOG_CTL_EGRESS 0x0002 +#define MV88E6390_G2_WDOG_CTL_FORCE_IRQ 0x0001 + +/* Offset 0x1C: QoS Weights Register */ +#define MV88E6XXX_G2_QOS_WEIGHTS 0x1c +#define MV88E6XXX_G2_QOS_WEIGHTS_UPDATE 0x8000 +#define MV88E6352_G2_QOS_WEIGHTS_PTR_MASK 0x3f00 +#define MV88E6390_G2_QOS_WEIGHTS_PTR_MASK 0x7f00 +#define MV88E6XXX_G2_QOS_WEIGHTS_DATA_MASK 0x00ff + +/* Offset 0x1D: Misc Register */ +#define MV88E6XXX_G2_MISC 0x1d +#define MV88E6XXX_G2_MISC_5_BIT_PORT 0x4000 +#define MV88E6352_G2_NOEGR_POLICY 0x2000 +#define MV88E6390_G2_LAG_ID_4 0x2000 #ifdef CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 @@ -127,6 +217,9 @@ static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip) return 0; } +int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port); +int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, int port); + int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus, int addr, int reg, u16 *val); @@ -169,6 +262,18 @@ static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip) return 0; } +static inline int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, + int port) +{ + return -EOPNOTSUPP; +} + +static inline int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, + int port) +{ + return -EOPNOTSUPP; +} + static inline int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus, int addr, int reg, u16 *val) diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 73d825e08be3..a7801f6668a5 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -12,6 +12,7 @@ * (at your option) any later version. */ +#include <linux/bitfield.h> #include <linux/if_bridge.h> #include <linux/phy.h> @@ -912,15 +913,13 @@ int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port) } static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip, - int port, u16 table, - u8 pointer, u16 data) + int port, u16 table, u8 ptr, u16 data) { u16 reg; - reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | - table | - (pointer << MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) | - data; + reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table | + (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) | + (data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK); return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg); diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 8a34ea7c868a..8f3991bf1851 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -222,6 +222,7 @@ /* Offset 0x18: IEEE Priority Mapping Table */ #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000 +#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_MASK 0x7000 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP 0x0000 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP 0x1000 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP 0x2000 @@ -229,7 +230,8 @@ #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP 0x5000 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP 0x6000 #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP 0x7000 -#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT 9 +#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK 0x0e00 +#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK 0x01ff /* Offset 0x18: Port IEEE Priority Remapping Registers (0-3) */ #define MV88E6095_PORT_IEEE_PRIO_REMAP_0123 0x18 diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index e1a50c87c9a9..0bc6a4ffce30 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -471,8 +471,7 @@ static int init_tp_parity(struct adapter *adap) if (!skb) goto alloc_skb_fail; - req = __skb_put(skb, sizeof(*req)); - memset(req, 0, sizeof(*req)); + req = __skb_put_zero(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i)); req->mtu_idx = NMTUS - 1; @@ -495,8 +494,7 @@ static int init_tp_parity(struct adapter *adap) if (!skb) goto alloc_skb_fail; - req = __skb_put(skb, sizeof(*req)); - memset(req, 0, sizeof(*req)); + req = __skb_put_zero(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, i)); req->params = htonl(V_L2T_W_IDX(i)); @@ -518,8 +516,7 @@ static int init_tp_parity(struct adapter *adap) if (!skb) goto alloc_skb_fail; - req = __skb_put(skb, sizeof(*req)); - memset(req, 0, sizeof(*req)); + req = __skb_put_zero(skb, sizeof(*req)); req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RTE_WRITE_REQ, i)); req->l2t_idx = htonl(V_L2T_W_IDX(i)); @@ -538,8 +535,7 @@ static int init_tp_parity(struct adapter *adap) if (!skb) goto alloc_skb_fail; - greq = __skb_put(skb, sizeof(*greq)); - memset(greq, 0, sizeof(*greq)); + greq = __skb_put_zero(skb, sizeof(*greq)); greq->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); OPCODE_TID(greq) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, 0)); greq->mask = cpu_to_be64(1); diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 1b9d154f1149..e2d342647b19 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -2282,7 +2282,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, if (!skb) goto no_mem; - memcpy(__skb_put(skb, AN_PKT_SIZE), r, AN_PKT_SIZE); + __skb_put_data(skb, r, AN_PKT_SIZE); skb->data[0] = CPL_ASYNC_NOTIF; rss_hi = htonl(CPL_ASYNC_NOTIF << 24); q->async_notif++; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c index a0fab65e80e8..45b5853ca2f1 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c @@ -231,8 +231,7 @@ int set_filter_wr(struct adapter *adapter, int fidx) } } - fwr = __skb_put(skb, sizeof(*fwr)); - memset(fwr, 0, sizeof(*fwr)); + fwr = __skb_put_zero(skb, sizeof(*fwr)); /* It would be nice to put most of the following in t4_hw.c but most * of the work is translating the cxgbtool ch_filter_specification diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 2b23f46b34d3..ba032ac9ae86 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.3.0.31" +#define DRV_VERSION "2.3.0.42" #define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 @@ -47,7 +47,7 @@ struct enic_msix_entry { int requested; - char devname[IFNAMSIZ]; + char devname[IFNAMSIZ + 8]; irqreturn_t (*isr)(int, void *); void *devid; cpumask_var_t affinity_mask; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 6a9c8878aca0..d24ee1ad3be1 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1737,7 +1737,7 @@ static int enic_request_intr(struct enic *enic) intr = enic_msix_rq_intr(enic, i); snprintf(enic->msix[intr].devname, sizeof(enic->msix[intr].devname), - "%.11s-rx-%u", netdev->name, i); + "%s-rx-%u", netdev->name, i); enic->msix[intr].isr = enic_isr_msix; enic->msix[intr].devid = &enic->napi[i]; } @@ -1748,7 +1748,7 @@ static int enic_request_intr(struct enic *enic) intr = enic_msix_wq_intr(enic, i); snprintf(enic->msix[intr].devname, sizeof(enic->msix[intr].devname), - "%.11s-tx-%u", netdev->name, i); + "%s-tx-%u", netdev->name, i); enic->msix[intr].isr = enic_isr_msix; enic->msix[intr].devid = &enic->napi[wq]; } @@ -1756,14 +1756,14 @@ static int enic_request_intr(struct enic *enic) intr = enic_msix_err_intr(enic); snprintf(enic->msix[intr].devname, sizeof(enic->msix[intr].devname), - "%.11s-err", netdev->name); + "%s-err", netdev->name); enic->msix[intr].isr = enic_isr_msix_err; enic->msix[intr].devid = enic; intr = enic_msix_notify_intr(enic); snprintf(enic->msix[intr].devname, sizeof(enic->msix[intr].devname), - "%.11s-notify", netdev->name); + "%s-notify", netdev->name); enic->msix[intr].isr = enic_isr_msix_notify; enic->msix[intr].devid = enic; diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 722daf55d757..013509544632 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -3859,6 +3859,9 @@ static int ibmvnic_resume(struct device *dev) struct ibmvnic_adapter *adapter = netdev_priv(netdev); int i; + if (adapter->state != VNIC_OPEN) + return 0; + /* kick the interrupt handlers just in case we lost an interrupt */ for (i = 0; i < adapter->req_rx_queues; i++) ibmvnic_interrupt_rx(adapter->rx_scrq[i]->irq, diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 962975d192d1..adaaafc20532 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -221,6 +221,9 @@ static void mtk_phy_link_adjust(struct net_device *dev) netif_carrier_on(dev); else netif_carrier_off(dev); + + if (!of_phy_is_fixed_link(mac->of_node)) + phy_print_status(dev->phydev); } static int mtk_phy_connect_node(struct mtk_eth *eth, struct mtk_mac *mac, @@ -369,28 +372,48 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth) mdiobus_unregister(eth->mii_bus); } -static inline void mtk_irq_disable(struct mtk_eth *eth, - unsigned reg, u32 mask) +static inline void mtk_tx_irq_disable(struct mtk_eth *eth, u32 mask) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(ð->tx_irq_lock, flags); + val = mtk_r32(eth, MTK_QDMA_INT_MASK); + mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK); + spin_unlock_irqrestore(ð->tx_irq_lock, flags); +} + +static inline void mtk_tx_irq_enable(struct mtk_eth *eth, u32 mask) { unsigned long flags; u32 val; - spin_lock_irqsave(ð->irq_lock, flags); - val = mtk_r32(eth, reg); - mtk_w32(eth, val & ~mask, reg); - spin_unlock_irqrestore(ð->irq_lock, flags); + spin_lock_irqsave(ð->tx_irq_lock, flags); + val = mtk_r32(eth, MTK_QDMA_INT_MASK); + mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK); + spin_unlock_irqrestore(ð->tx_irq_lock, flags); } -static inline void mtk_irq_enable(struct mtk_eth *eth, - unsigned reg, u32 mask) +static inline void mtk_rx_irq_disable(struct mtk_eth *eth, u32 mask) { unsigned long flags; u32 val; - spin_lock_irqsave(ð->irq_lock, flags); - val = mtk_r32(eth, reg); - mtk_w32(eth, val | mask, reg); - spin_unlock_irqrestore(ð->irq_lock, flags); + spin_lock_irqsave(ð->rx_irq_lock, flags); + val = mtk_r32(eth, MTK_PDMA_INT_MASK); + mtk_w32(eth, val & ~mask, MTK_PDMA_INT_MASK); + spin_unlock_irqrestore(ð->rx_irq_lock, flags); +} + +static inline void mtk_rx_irq_enable(struct mtk_eth *eth, u32 mask) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(ð->rx_irq_lock, flags); + val = mtk_r32(eth, MTK_PDMA_INT_MASK); + mtk_w32(eth, val | mask, MTK_PDMA_INT_MASK); + spin_unlock_irqrestore(ð->rx_irq_lock, flags); } static int mtk_set_mac_address(struct net_device *dev, void *p) @@ -969,6 +992,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, RX_DMA_VID(trxd.rxd3)) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), RX_DMA_VID(trxd.rxd3)); + skb_record_rx_queue(skb, 0); napi_gro_receive(napi, skb); ring->data[idx] = new_data; @@ -1098,7 +1122,7 @@ static int mtk_napi_tx(struct napi_struct *napi, int budget) return budget; napi_complete(napi); - mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); return tx_done; } @@ -1132,7 +1156,7 @@ poll_again: goto poll_again; } napi_complete(napi); - mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); + mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); return rx_done + budget - remain_budget; } @@ -1667,7 +1691,7 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) if (likely(napi_schedule_prep(ð->rx_napi))) { __napi_schedule(ð->rx_napi); - mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); } return IRQ_HANDLED; @@ -1679,7 +1703,7 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) if (likely(napi_schedule_prep(ð->tx_napi))) { __napi_schedule(ð->tx_napi); - mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); } return IRQ_HANDLED; @@ -1691,11 +1715,11 @@ static void mtk_poll_controller(struct net_device *dev) struct mtk_mac *mac = netdev_priv(dev); struct mtk_eth *eth = mac->hw; - mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); - mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); mtk_handle_irq_rx(eth->irq[2], dev); - mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); - mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); + mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); } #endif @@ -1736,8 +1760,8 @@ static int mtk_open(struct net_device *dev) napi_enable(ð->tx_napi); napi_enable(ð->rx_napi); - mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); - mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); + mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); } atomic_inc(ð->dma_refcnt); @@ -1782,8 +1806,8 @@ static int mtk_stop(struct net_device *dev) if (!atomic_dec_and_test(ð->dma_refcnt)) return 0; - mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); - mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); napi_disable(ð->tx_napi); napi_disable(ð->rx_napi); @@ -1858,11 +1882,13 @@ static int mtk_hw_init(struct mtk_eth *eth) /* Enable RX VLan Offloading */ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); + /* enable interrupt delay for RX */ + mtk_w32(eth, MTK_PDMA_DELAY_RX_DELAY, MTK_PDMA_DELAY_INT); + /* disable delay and normal interrupt */ mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); - mtk_w32(eth, 0, MTK_PDMA_DELAY_INT); - mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); - mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); + mtk_tx_irq_disable(eth, ~0); + mtk_rx_irq_disable(eth, ~0); mtk_w32(eth, RST_GL_PSE, MTK_RST_GL); mtk_w32(eth, 0, MTK_RST_GL); @@ -1933,8 +1959,8 @@ static void mtk_uninit(struct net_device *dev) phy_disconnect(dev->phydev); if (of_phy_is_fixed_link(mac->of_node)) of_phy_deregister_fixed_link(mac->of_node); - mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); - mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); + mtk_tx_irq_disable(eth, ~0); + mtk_rx_irq_disable(eth, ~0); } static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -2394,7 +2420,8 @@ static int mtk_probe(struct platform_device *pdev) return PTR_ERR(eth->base); spin_lock_init(ð->page_lock); - spin_lock_init(ð->irq_lock); + spin_lock_init(ð->tx_irq_lock); + spin_lock_init(ð->rx_irq_lock); eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mediatek,ethsys"); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 3c46a3b613b9..5868a09f623a 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -125,7 +125,14 @@ #define MTK_PST_DRX_IDX_CFG(x) (MTK_PST_DRX_IDX0 << (x)) /* PDMA Delay Interrupt Register */ -#define MTK_PDMA_DELAY_INT 0xa0c +#define MTK_PDMA_DELAY_INT 0xa0c +#define MTK_PDMA_DELAY_RX_EN BIT(15) +#define MTK_PDMA_DELAY_RX_PINT 4 +#define MTK_PDMA_DELAY_RX_PINT_SHIFT 8 +#define MTK_PDMA_DELAY_RX_PTIME 4 +#define MTK_PDMA_DELAY_RX_DELAY \ + (MTK_PDMA_DELAY_RX_EN | MTK_PDMA_DELAY_RX_PTIME | \ + (MTK_PDMA_DELAY_RX_PINT << MTK_PDMA_DELAY_RX_PINT_SHIFT)) /* PDMA Interrupt Status Register */ #define MTK_PDMA_INT_STATUS 0xa20 @@ -206,6 +213,7 @@ /* QDMA Interrupt Status Register */ #define MTK_QMTK_INT_STATUS 0x1A18 +#define MTK_RX_DONE_DLY BIT(30) #define MTK_RX_DONE_INT3 BIT(19) #define MTK_RX_DONE_INT2 BIT(18) #define MTK_RX_DONE_INT1 BIT(17) @@ -214,8 +222,7 @@ #define MTK_TX_DONE_INT2 BIT(2) #define MTK_TX_DONE_INT1 BIT(1) #define MTK_TX_DONE_INT0 BIT(0) -#define MTK_RX_DONE_INT (MTK_RX_DONE_INT0 | MTK_RX_DONE_INT1 | \ - MTK_RX_DONE_INT2 | MTK_RX_DONE_INT3) +#define MTK_RX_DONE_INT MTK_RX_DONE_DLY #define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \ MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3) @@ -512,6 +519,8 @@ struct mtk_rx_ring { * @dev: The device pointer * @base: The mapped register i/o base * @page_lock: Make sure that register operations are atomic + * @tx_irq__lock: Make sure that IRQ register operations are atomic + * @rx_irq__lock: Make sure that IRQ register operations are atomic * @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a * dummy for NAPI to work * @netdev: The netdev instances @@ -540,7 +549,8 @@ struct mtk_eth { struct device *dev; void __iomem *base; spinlock_t page_lock; - spinlock_t irq_lock; + spinlock_t tx_irq_lock; + spinlock_t rx_irq_lock; struct net_device dummy_dev; struct net_device *netdev[MTK_MAX_DEVS]; struct mtk_mac *mac[MTK_MAX_DEVS]; diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 828bfd93cb54..08381ef8bdb4 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -919,7 +919,6 @@ static int __lpc_handle_recv(struct net_device *ndev, int budget) struct sk_buff *skb; u32 rxconsidx, len, ethst; struct rx_status_t *prxstat; - u8 *prdbuf; int rx_done = 0; /* Get the current RX buffer indexes */ @@ -960,9 +959,9 @@ static int __lpc_handle_recv(struct net_device *ndev, int budget) ndev->stats.rx_dropped++; } else { /* Copy packet from buffer */ - prdbuf = skb_put_data(skb, - pldat->rx_buff_v + rxconsidx * ENET_MAXF_SIZE, - len); + skb_put_data(skb, + pldat->rx_buff_v + rxconsidx * ENET_MAXF_SIZE, + len); /* Pass to upper layer */ skb->protocol = eth_type_trans(skb, ndev); diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index 8b026dbf0d8d..482b85e4d665 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c @@ -1495,8 +1495,8 @@ static int hamachi_rx(struct net_device *dev) hmp->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma - + entry*sizeof(*desc), pkt_len); + skb_put_data(skb, hmp->rx_ring_dma + + entry*sizeof(*desc), pkt_len); #endif pci_dma_sync_single_for_device(hmp->pci_dev, leXX_to_cpu(hmp->rx_ring[entry].addr), diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c index e2a62c091b80..f888045e1ae9 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c @@ -44,6 +44,7 @@ #include "qed_hsi.h" #include "qed_sp.h" #include "qed_sriov.h" +#include "qed_roce.h" #ifdef CONFIG_DCB #include <linux/qed/qed_eth_if.h> #endif @@ -892,10 +893,33 @@ qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn, /* update storm FW with negotiation results */ qed_sp_pf_update(p_hwfn); + + /* for roce PFs, we may want to enable/disable DPM + * when DCBx change occurs + */ + if (p_hwfn->hw_info.personality == + QED_PCI_ETH_ROCE) + qed_roce_dpm_dcbx(p_hwfn, p_ptt); } } qed_dcbx_get_params(p_hwfn, &p_hwfn->p_dcbx_info->get, type); + + if (type == QED_DCBX_OPERATIONAL_MIB) { + struct qed_dcbx_results *p_data; + u16 val; + + /* Configure in NIG which protocols support EDPM and should + * honor PFC. + */ + p_data = &p_hwfn->p_dcbx_info->results; + val = (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE].tc) | + (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE_V2].tc); + val <<= NIG_REG_TX_EDPM_CTRL_TX_EDPM_TC_EN_SHIFT; + val |= NIG_REG_TX_EDPM_CTRL_TX_EDPM_EN; + qed_wr(p_hwfn, p_ptt, NIG_REG_TX_EDPM_CTRL, val); + } + qed_dcbx_aen(p_hwfn, type); return rc; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 65fe4940f20d..8b140541736a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -3075,12 +3075,15 @@ static void qed_chain_free_pbl(struct qed_dev *cdev, struct qed_chain *p_chain) } pbl_size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE; - dma_free_coherent(&cdev->pdev->dev, - pbl_size, - p_chain->pbl_sp.p_virt_table, - p_chain->pbl_sp.p_phys_table); + + if (!p_chain->b_external_pbl) + dma_free_coherent(&cdev->pdev->dev, + pbl_size, + p_chain->pbl_sp.p_virt_table, + p_chain->pbl_sp.p_phys_table); out: vfree(p_chain->pbl.pp_virt_addr_tbl); + p_chain->pbl.pp_virt_addr_tbl = NULL; } void qed_chain_free(struct qed_dev *cdev, struct qed_chain *p_chain) @@ -3174,7 +3177,10 @@ qed_chain_alloc_single(struct qed_dev *cdev, struct qed_chain *p_chain) return 0; } -static int qed_chain_alloc_pbl(struct qed_dev *cdev, struct qed_chain *p_chain) +static int +qed_chain_alloc_pbl(struct qed_dev *cdev, + struct qed_chain *p_chain, + struct qed_chain_ext_pbl *ext_pbl) { u32 page_cnt = p_chain->page_cnt, size, i; dma_addr_t p_phys = 0, p_pbl_phys = 0; @@ -3194,8 +3200,16 @@ static int qed_chain_alloc_pbl(struct qed_dev *cdev, struct qed_chain *p_chain) * should be saved to allow its freeing during the error flow. */ size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE; - p_pbl_virt = dma_alloc_coherent(&cdev->pdev->dev, - size, &p_pbl_phys, GFP_KERNEL); + + if (!ext_pbl) { + p_pbl_virt = dma_alloc_coherent(&cdev->pdev->dev, + size, &p_pbl_phys, GFP_KERNEL); + } else { + p_pbl_virt = ext_pbl->p_pbl_virt; + p_pbl_phys = ext_pbl->p_pbl_phys; + p_chain->b_external_pbl = true; + } + qed_chain_init_pbl_mem(p_chain, p_pbl_virt, p_pbl_phys, pp_virt_addr_tbl); if (!p_pbl_virt) @@ -3228,7 +3242,10 @@ int qed_chain_alloc(struct qed_dev *cdev, enum qed_chain_use_mode intended_use, enum qed_chain_mode mode, enum qed_chain_cnt_type cnt_type, - u32 num_elems, size_t elem_size, struct qed_chain *p_chain) + u32 num_elems, + size_t elem_size, + struct qed_chain *p_chain, + struct qed_chain_ext_pbl *ext_pbl) { u32 page_cnt; int rc = 0; @@ -3259,7 +3276,7 @@ int qed_chain_alloc(struct qed_dev *cdev, rc = qed_chain_alloc_single(cdev, p_chain); break; case QED_CHAIN_MODE_PBL: - rc = qed_chain_alloc_pbl(cdev, p_chain); + rc = qed_chain_alloc_pbl(cdev, p_chain, ext_pbl); break; } if (rc) diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index 12d16c096e36..1f1df1bf127c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -307,6 +307,7 @@ int qed_dmae_host2host(struct qed_hwfn *p_hwfn, * @param num_elems * @param elem_size * @param p_chain + * @param ext_pbl - a possible external PBL * * @return int */ @@ -315,7 +316,9 @@ qed_chain_alloc(struct qed_dev *cdev, enum qed_chain_use_mode intended_use, enum qed_chain_mode mode, enum qed_chain_cnt_type cnt_type, - u32 num_elems, size_t elem_size, struct qed_chain *p_chain); + u32 num_elems, + size_t elem_size, + struct qed_chain *p_chain, struct qed_chain_ext_pbl *ext_pbl); /** * @brief qed_chain_free - Free chain DMA memory diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c index 6103723d7118..813c77cc857f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c @@ -62,6 +62,22 @@ #include "qed_sriov.h" #include "qed_reg_addr.h" +static int +qed_iscsi_async_event(struct qed_hwfn *p_hwfn, + u8 fw_event_code, + u16 echo, union event_ring_data *data, u8 fw_return_code) +{ + if (p_hwfn->p_iscsi_info->event_cb) { + struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info; + + return p_iscsi->event_cb(p_iscsi->event_context, + fw_event_code, data); + } else { + DP_NOTICE(p_hwfn, "iSCSI async completion is not set\n"); + return -EINVAL; + } +} + struct qed_iscsi_conn { struct list_head list_entry; bool free_on_delete; @@ -265,6 +281,9 @@ qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn, p_hwfn->p_iscsi_info->event_context = event_context; p_hwfn->p_iscsi_info->event_cb = async_event_cb; + qed_spq_register_async_cb(p_hwfn, PROTOCOLID_ISCSI, + qed_iscsi_async_event); + return qed_spq_post(p_hwfn, p_ent, NULL); } @@ -631,7 +650,10 @@ static int qed_sp_iscsi_func_stop(struct qed_hwfn *p_hwfn, p_ramrod = &p_ent->ramrod.iscsi_destroy; p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_DESTROY_FUNC; - return qed_spq_post(p_hwfn, p_ent, NULL); + rc = qed_spq_post(p_hwfn, p_ent, NULL); + + qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_ISCSI); + return rc; } static void __iomem *qed_iscsi_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid) @@ -752,7 +774,7 @@ static int qed_iscsi_allocate_connection(struct qed_hwfn *p_hwfn, QED_CHAIN_USE_TO_CONSUME_PRODUCE, QED_CHAIN_MODE_PBL, QED_CHAIN_CNT_TYPE_U16, - r2tq_num_elements, 0x80, &p_conn->r2tq); + r2tq_num_elements, 0x80, &p_conn->r2tq, NULL); if (rc) goto nomem_r2tq; @@ -763,7 +785,7 @@ static int qed_iscsi_allocate_connection(struct qed_hwfn *p_hwfn, QED_CHAIN_MODE_PBL, QED_CHAIN_CNT_TYPE_U16, uhq_num_elements, - sizeof(struct iscsi_uhqe), &p_conn->uhq); + sizeof(struct iscsi_uhqe), &p_conn->uhq, NULL); if (rc) goto nomem_uhq; @@ -773,7 +795,7 @@ static int qed_iscsi_allocate_connection(struct qed_hwfn *p_hwfn, QED_CHAIN_MODE_PBL, QED_CHAIN_CNT_TYPE_U16, xhq_num_elements, - sizeof(struct iscsi_xhqe), &p_conn->xhq); + sizeof(struct iscsi_xhqe), &p_conn->xhq, NULL); if (rc) goto nomem; diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c index 0e26193156e4..f9c51cb8585e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c @@ -1056,7 +1056,7 @@ qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn, QED_CHAIN_CNT_TYPE_U16, p_ll2_info->input.rx_num_desc, sizeof(struct core_rx_bd), - &p_ll2_info->rx_queue.rxq_chain); + &p_ll2_info->rx_queue.rxq_chain, NULL); if (rc) { DP_NOTICE(p_hwfn, "Failed to allocate ll2 rxq chain\n"); goto out; @@ -1078,7 +1078,7 @@ qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn, QED_CHAIN_CNT_TYPE_U16, p_ll2_info->input.rx_num_desc, sizeof(struct core_rx_fast_path_cqe), - &p_ll2_info->rx_queue.rcq_chain); + &p_ll2_info->rx_queue.rcq_chain, NULL); if (rc) { DP_NOTICE(p_hwfn, "Failed to allocate ll2 rcq chain\n"); goto out; @@ -1108,7 +1108,7 @@ static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn, QED_CHAIN_CNT_TYPE_U16, p_ll2_info->input.tx_num_desc, sizeof(struct core_tx_bd), - &p_ll2_info->tx_queue.txq_chain); + &p_ll2_info->tx_queue.txq_chain, NULL); if (rc) goto out; diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index 7e4639c9207a..0cdb4337b3a0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -1564,6 +1564,12 @@ #define NIG_REG_TSGEN_FREECNT_UPDATE_K2 0x509008UL #define CNIG_REG_NIG_PORT0_CONF_K2 0x218200UL +#define NIG_REG_TX_EDPM_CTRL 0x501f0cUL +#define NIG_REG_TX_EDPM_CTRL_TX_EDPM_EN (0x1 << 0) +#define NIG_REG_TX_EDPM_CTRL_TX_EDPM_EN_SHIFT 0 +#define NIG_REG_TX_EDPM_CTRL_TX_EDPM_TC_EN (0xff << 1) +#define NIG_REG_TX_EDPM_CTRL_TX_EDPM_TC_EN_SHIFT 1 + #define PRS_REG_SEARCH_GFT 0x1f11bcUL #define PRS_REG_CM_HDR_GFT 0x1f11c8UL #define PRS_REG_GFT_CAM 0x1f1100UL diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c index 4bc2f6c47f69..673f80aa690d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.c +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c @@ -68,12 +68,14 @@ static void qed_roce_free_real_icid(struct qed_hwfn *p_hwfn, u16 icid); -void qed_roce_async_event(struct qed_hwfn *p_hwfn, - u8 fw_event_code, union rdma_eqe_data *rdma_data) +static int +qed_roce_async_event(struct qed_hwfn *p_hwfn, + u8 fw_event_code, + u16 echo, union event_ring_data *data, u8 fw_return_code) { if (fw_event_code == ROCE_ASYNC_EVENT_DESTROY_QP_DONE) { u16 icid = - (u16)le32_to_cpu(rdma_data->rdma_destroy_qp_data.cid); + (u16)le32_to_cpu(data->rdma_data.rdma_destroy_qp_data.cid); /* icid release in this async event can occur only if the icid * was offloaded to the FW. In case it wasn't offloaded this is @@ -85,8 +87,10 @@ void qed_roce_async_event(struct qed_hwfn *p_hwfn, events->affiliated_event(p_hwfn->p_rdma_info->events.context, fw_event_code, - &rdma_data->async_handle); + (void *)&data->rdma_data.async_handle); } + + return 0; } static int qed_rdma_bmap_alloc(struct qed_hwfn *p_hwfn, @@ -162,6 +166,11 @@ static int qed_bmap_test_id(struct qed_hwfn *p_hwfn, return test_bit(id_num, bmap->bitmap); } +static bool qed_bmap_is_empty(struct qed_bmap *bmap) +{ + return bmap->max_count == find_first_bit(bmap->bitmap, bmap->max_count); +} + static u32 qed_rdma_get_sb_id(void *p_hwfn, u32 rel_sb_id) { /* First sb id for RoCE is after all the l2 sb */ @@ -367,22 +376,7 @@ end: static void qed_rdma_resc_free(struct qed_hwfn *p_hwfn) { - struct qed_bmap *rcid_map = &p_hwfn->p_rdma_info->real_cid_map; struct qed_rdma_info *p_rdma_info = p_hwfn->p_rdma_info; - int wait_count = 0; - - /* when destroying a_RoCE QP the control is returned to the user after - * the synchronous part. The asynchronous part may take a little longer. - * We delay for a short while if an async destroy QP is still expected. - * Beyond the added delay we clear the bitmap anyway. - */ - while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) { - msleep(100); - if (wait_count++ > 20) { - DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n"); - break; - } - } qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->cid_map, 1); qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->pd_map, 1); @@ -696,9 +690,32 @@ static int qed_rdma_setup(struct qed_hwfn *p_hwfn, if (rc) return rc; + qed_spq_register_async_cb(p_hwfn, PROTOCOLID_ROCE, + qed_roce_async_event); + return qed_rdma_start_fw(p_hwfn, params, p_ptt); } +void qed_roce_stop(struct qed_hwfn *p_hwfn) +{ + struct qed_bmap *rcid_map = &p_hwfn->p_rdma_info->real_cid_map; + int wait_count = 0; + + /* when destroying a_RoCE QP the control is returned to the user after + * the synchronous part. The asynchronous part may take a little longer. + * We delay for a short while if an async destroy QP is still expected. + * Beyond the added delay we clear the bitmap anyway. + */ + while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) { + msleep(100); + if (wait_count++ > 20) { + DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n"); + break; + } + } + qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_ROCE); +} + static int qed_rdma_stop(void *rdma_cxt) { struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt; @@ -728,6 +745,7 @@ static int qed_rdma_stop(void *rdma_cxt) qed_wr(p_hwfn, p_ptt, PRS_REG_LIGHT_L2_ETHERTYPE_EN, (ll2_ethertype_en & 0xFFFE)); + qed_roce_stop(p_hwfn); qed_ptt_release(p_hwfn, p_ptt); /* Get SPQ entry */ @@ -2638,6 +2656,23 @@ static void *qed_rdma_get_rdma_ctx(struct qed_dev *cdev) return QED_LEADING_HWFN(cdev); } +static bool qed_rdma_allocated_qps(struct qed_hwfn *p_hwfn) +{ + bool result; + + /* if rdma info has not been allocated, naturally there are no qps */ + if (!p_hwfn->p_rdma_info) + return false; + + spin_lock_bh(&p_hwfn->p_rdma_info->lock); + if (!p_hwfn->p_rdma_info->cid_map.bitmap) + result = false; + else + result = !qed_bmap_is_empty(&p_hwfn->p_rdma_info->cid_map); + spin_unlock_bh(&p_hwfn->p_rdma_info->lock); + return result; +} + static void qed_rdma_dpm_conf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { u32 val; @@ -2650,6 +2685,20 @@ static void qed_rdma_dpm_conf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) val, p_hwfn->dcbx_no_edpm, p_hwfn->db_bar_no_edpm); } +void qed_roce_dpm_dcbx(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) +{ + u8 val; + + /* if any QPs are already active, we want to disable DPM, since their + * context information contains information from before the latest DCBx + * update. Otherwise enable it. + */ + val = qed_rdma_allocated_qps(p_hwfn) ? true : false; + p_hwfn->dcbx_no_edpm = (u8)val; + + qed_rdma_dpm_conf(p_hwfn, p_ptt); +} + void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { p_hwfn->db_bar_no_edpm = true; diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.h b/drivers/net/ethernet/qlogic/qed/qed_roce.h index 94be3b5a39c4..b178d9994a45 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.h +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.h @@ -168,12 +168,11 @@ struct qed_rdma_qp { #if IS_ENABLED(CONFIG_QED_RDMA) void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); -void qed_roce_async_event(struct qed_hwfn *p_hwfn, - u8 fw_event_code, union rdma_eqe_data *rdma_data); +void qed_roce_dpm_dcbx(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); #else static inline void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {} -static inline void qed_roce_async_event(struct qed_hwfn *p_hwfn, - u8 fw_event_code, - union rdma_eqe_data *rdma_data) {} + +static inline void qed_roce_dpm_dcbx(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) {} #endif #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index 00dd50f8c42f..56c95fb9a26d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -174,6 +174,22 @@ struct qed_consq { struct qed_chain chain; }; +typedef int +(*qed_spq_async_comp_cb)(struct qed_hwfn *p_hwfn, + u8 opcode, + u16 echo, + union event_ring_data *data, + u8 fw_return_code); + +int +qed_spq_register_async_cb(struct qed_hwfn *p_hwfn, + enum protocol_type protocol_id, + qed_spq_async_comp_cb cb); + +void +qed_spq_unregister_async_cb(struct qed_hwfn *p_hwfn, + enum protocol_type protocol_id); + struct qed_spq { spinlock_t lock; /* SPQ lock */ @@ -203,6 +219,7 @@ struct qed_spq { u32 comp_count; u32 cid; + qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE]; }; /** diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index dede73f41e61..78954d2c596e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -302,32 +302,16 @@ static int qed_async_event_completion(struct qed_hwfn *p_hwfn, struct event_ring_entry *p_eqe) { - switch (p_eqe->protocol_id) { -#if IS_ENABLED(CONFIG_QED_RDMA) - case PROTOCOLID_ROCE: - qed_roce_async_event(p_hwfn, p_eqe->opcode, - &p_eqe->data.rdma_data); - return 0; -#endif - case PROTOCOLID_COMMON: - return qed_sriov_eqe_event(p_hwfn, - p_eqe->opcode, - p_eqe->echo, &p_eqe->data); - case PROTOCOLID_ISCSI: - if (!IS_ENABLED(CONFIG_QED_ISCSI)) - return -EINVAL; + qed_spq_async_comp_cb cb; - if (p_hwfn->p_iscsi_info->event_cb) { - struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info; + if (!p_hwfn->p_spq || (p_eqe->protocol_id >= MAX_PROTOCOL_TYPE)) + return -EINVAL; - return p_iscsi->event_cb(p_iscsi->event_context, - p_eqe->opcode, &p_eqe->data); - } else { - DP_NOTICE(p_hwfn, - "iSCSI async completion is not set\n"); - return -EINVAL; - } - default: + cb = p_hwfn->p_spq->async_comp_cb[p_eqe->protocol_id]; + if (cb) { + return cb(p_hwfn, p_eqe->opcode, p_eqe->echo, + &p_eqe->data, p_eqe->fw_return_code); + } else { DP_NOTICE(p_hwfn, "Unknown Async completion for protocol: %d\n", p_eqe->protocol_id); @@ -335,6 +319,28 @@ qed_async_event_completion(struct qed_hwfn *p_hwfn, } } +int +qed_spq_register_async_cb(struct qed_hwfn *p_hwfn, + enum protocol_type protocol_id, + qed_spq_async_comp_cb cb) +{ + if (!p_hwfn->p_spq || (protocol_id >= MAX_PROTOCOL_TYPE)) + return -EINVAL; + + p_hwfn->p_spq->async_comp_cb[protocol_id] = cb; + return 0; +} + +void +qed_spq_unregister_async_cb(struct qed_hwfn *p_hwfn, + enum protocol_type protocol_id) +{ + if (!p_hwfn->p_spq || (protocol_id >= MAX_PROTOCOL_TYPE)) + return; + + p_hwfn->p_spq->async_comp_cb[protocol_id] = NULL; +} + /*************************************************************************** * EQ API ***************************************************************************/ @@ -419,7 +425,7 @@ int qed_eq_alloc(struct qed_hwfn *p_hwfn, u16 num_elem) QED_CHAIN_CNT_TYPE_U16, num_elem, sizeof(union event_ring_element), - &p_eq->chain)) + &p_eq->chain, NULL)) goto eq_allocate_fail; /* register EQ completion on the SP SB */ @@ -547,7 +553,7 @@ int qed_spq_alloc(struct qed_hwfn *p_hwfn) QED_CHAIN_CNT_TYPE_U16, 0, /* N/A when the mode is SINGLE */ sizeof(struct slow_path_element), - &p_spq->chain)) + &p_spq->chain, NULL)) goto spq_allocate_fail; /* allocate and fill the SPQ elements (incl. ramrod data list) */ @@ -953,7 +959,7 @@ int qed_consq_alloc(struct qed_hwfn *p_hwfn) QED_CHAIN_MODE_PBL, QED_CHAIN_CNT_TYPE_U16, QED_CHAIN_PAGE_SIZE / 0x80, - 0x80, &p_consq->chain)) + 0x80, &p_consq->chain, NULL)) goto consq_allocate_fail; p_hwfn->p_consq = p_consq; diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index e39ad22947cf..2cfd3bd9a031 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -44,6 +44,11 @@ #include "qed_sp.h" #include "qed_sriov.h" #include "qed_vf.h" +static int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, + u8 opcode, + __le16 echo, + union event_ring_data *data, u8 fw_return_code); + static u8 qed_vf_calculate_legacy(struct qed_vf_info *p_vf) { @@ -565,6 +570,9 @@ int qed_iov_alloc(struct qed_hwfn *p_hwfn) p_hwfn->pf_iov_info = p_sriov; + qed_spq_register_async_cb(p_hwfn, PROTOCOLID_COMMON, + qed_sriov_eqe_event); + return qed_iov_allocate_vfdb(p_hwfn); } @@ -578,6 +586,8 @@ void qed_iov_setup(struct qed_hwfn *p_hwfn) void qed_iov_free(struct qed_hwfn *p_hwfn) { + qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_COMMON); + if (IS_PF_SRIOV_ALLOC(p_hwfn)) { qed_iov_free_vfdb(p_hwfn); kfree(p_hwfn->pf_iov_info); @@ -3833,8 +3843,10 @@ static void qed_sriov_vfpf_malicious(struct qed_hwfn *p_hwfn, } } -int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, - u8 opcode, __le16 echo, union event_ring_data *data) +static int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, + u8 opcode, + __le16 echo, + union event_ring_data *data, u8 fw_return_code) { switch (opcode) { case COMMON_EVENT_VF_PF_CHANNEL: diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h index 95f55ae2ee8b..c2e44bce398c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h @@ -344,17 +344,6 @@ void qed_iov_free(struct qed_hwfn *p_hwfn); void qed_iov_free_hw_info(struct qed_dev *cdev); /** - * @brief qed_sriov_eqe_event - handle async sriov event arrived on eqe. - * - * @param p_hwfn - * @param opcode - * @param echo - * @param data - */ -int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, - u8 opcode, __le16 echo, union event_ring_data *data); - -/** * @brief Mark structs of vfs that have been FLR-ed. * * @param p_hwfn @@ -418,13 +407,6 @@ static inline void qed_iov_free_hw_info(struct qed_dev *cdev) { } -static inline int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn, - u8 opcode, - __le16 echo, union event_ring_data *data) -{ - return -EINVAL; -} - static inline bool qed_iov_mark_vf_flr(struct qed_hwfn *p_hwfn, u32 *disabled_vfs) { diff --git a/drivers/net/ethernet/qlogic/qede/Makefile b/drivers/net/ethernet/qlogic/qede/Makefile index bc5f7c3b277d..75408fbb7680 100644 --- a/drivers/net/ethernet/qlogic/qede/Makefile +++ b/drivers/net/ethernet/qlogic/qede/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_QEDE) := qede.o qede-y := qede_main.o qede_fp.o qede_filter.o qede_ethtool.o qede_ptp.o qede-$(CONFIG_DCB) += qede_dcbnl.o -qede-$(CONFIG_QED_RDMA) += qede_roce.o +qede-$(CONFIG_QED_RDMA) += qede_rdma.o diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 694c09b8997e..4dfb238221f9 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -40,6 +40,7 @@ #include <linux/kernel.h> #include <linux/mutex.h> #include <linux/bpf.h> +#include <linux/qed/qede_rdma.h> #include <linux/io.h> #ifdef CONFIG_RFS_ACCEL #include <linux/cpu_rmap.h> @@ -153,8 +154,8 @@ struct qede_vlan { struct qede_rdma_dev { struct qedr_dev *qedr_dev; struct list_head entry; - struct list_head roce_event_list; - struct workqueue_struct *roce_wq; + struct list_head rdma_event_list; + struct workqueue_struct *rdma_wq; }; struct qede_ptp; diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index fdf04bc5406e..06ca13dd9ddb 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -60,7 +60,6 @@ #include <net/ip6_checksum.h> #include <linux/bitops.h> #include <linux/vmalloc.h> -#include <linux/qed/qede_roce.h> #include "qede.h" #include "qede_ptp.h" @@ -263,7 +262,7 @@ static int qede_netdev_event(struct notifier_block *this, unsigned long event, break; case NETDEV_CHANGEADDR: edev = netdev_priv(ndev); - qede_roce_event_changeaddr(edev); + qede_rdma_event_changeaddr(edev); break; } @@ -978,7 +977,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, qede_init_ndev(edev); - rc = qede_roce_dev_add(edev); + rc = qede_rdma_dev_add(edev); if (rc) goto err3; @@ -1014,7 +1013,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, return 0; err4: - qede_roce_dev_remove(edev); + qede_rdma_dev_remove(edev); err3: free_netdev(edev->ndev); err2: @@ -1065,7 +1064,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) qede_ptp_disable(edev); - qede_roce_dev_remove(edev); + qede_rdma_dev_remove(edev); edev->ops->common->set_power_state(cdev, PCI_D0); @@ -1317,8 +1316,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq) QED_CHAIN_CNT_TYPE_U16, RX_RING_SIZE, sizeof(struct eth_rx_bd), - &rxq->rx_bd_ring); - + &rxq->rx_bd_ring, NULL); if (rc) goto err; @@ -1329,7 +1327,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq) QED_CHAIN_CNT_TYPE_U16, RX_RING_SIZE, sizeof(union eth_rx_cqe), - &rxq->rx_comp_ring); + &rxq->rx_comp_ring, NULL); if (rc) goto err; @@ -1387,7 +1385,8 @@ static int qede_alloc_mem_txq(struct qede_dev *edev, struct qede_tx_queue *txq) QED_CHAIN_MODE_PBL, QED_CHAIN_CNT_TYPE_U16, txq->num_tx_buffers, - sizeof(*p_virt), &txq->tx_pbl); + sizeof(*p_virt), + &txq->tx_pbl, NULL); if (rc) goto err; @@ -1965,7 +1964,7 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, edev->state = QEDE_STATE_CLOSED; - qede_roce_dev_event_close(edev); + qede_rdma_dev_event_close(edev); /* Close OS Tx */ netif_tx_disable(edev->ndev); @@ -2070,7 +2069,7 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode, link_params.link_up = true; edev->ops->common->set_link(edev->cdev, &link_params); - qede_roce_dev_event_open(edev); + qede_rdma_dev_event_open(edev); edev->state = QEDE_STATE_OPEN; diff --git a/drivers/net/ethernet/qlogic/qede/qede_roce.c b/drivers/net/ethernet/qlogic/qede/qede_rdma.c index c0030fb8d842..50b142fad6b8 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_roce.c +++ b/drivers/net/ethernet/qlogic/qede/qede_rdma.c @@ -33,19 +33,19 @@ #include <linux/netdevice.h> #include <linux/list.h> #include <linux/mutex.h> -#include <linux/qed/qede_roce.h> +#include <linux/qed/qede_rdma.h> #include "qede.h" static struct qedr_driver *qedr_drv; static LIST_HEAD(qedr_dev_list); static DEFINE_MUTEX(qedr_dev_list_lock); -bool qede_roce_supported(struct qede_dev *dev) +bool qede_rdma_supported(struct qede_dev *dev) { return dev->dev_info.common.rdma_supported; } -static void _qede_roce_dev_add(struct qede_dev *edev) +static void _qede_rdma_dev_add(struct qede_dev *edev) { if (!qedr_drv) return; @@ -54,11 +54,11 @@ static void _qede_roce_dev_add(struct qede_dev *edev) edev->ndev); } -static int qede_roce_create_wq(struct qede_dev *edev) +static int qede_rdma_create_wq(struct qede_dev *edev) { - INIT_LIST_HEAD(&edev->rdma_info.roce_event_list); - edev->rdma_info.roce_wq = create_singlethread_workqueue("roce_wq"); - if (!edev->rdma_info.roce_wq) { + INIT_LIST_HEAD(&edev->rdma_info.rdma_event_list); + edev->rdma_info.rdma_wq = create_singlethread_workqueue("rdma_wq"); + if (!edev->rdma_info.rdma_wq) { DP_NOTICE(edev, "qedr: Could not create workqueue\n"); return -ENOMEM; } @@ -66,14 +66,14 @@ static int qede_roce_create_wq(struct qede_dev *edev) return 0; } -static void qede_roce_cleanup_event(struct qede_dev *edev) +static void qede_rdma_cleanup_event(struct qede_dev *edev) { - struct list_head *head = &edev->rdma_info.roce_event_list; - struct qede_roce_event_work *event_node; + struct list_head *head = &edev->rdma_info.rdma_event_list; + struct qede_rdma_event_work *event_node; - flush_workqueue(edev->rdma_info.roce_wq); + flush_workqueue(edev->rdma_info.rdma_wq); while (!list_empty(head)) { - event_node = list_entry(head->next, struct qede_roce_event_work, + event_node = list_entry(head->next, struct qede_rdma_event_work, list); cancel_work_sync(&event_node->work); list_del(&event_node->list); @@ -81,85 +81,85 @@ static void qede_roce_cleanup_event(struct qede_dev *edev) } } -static void qede_roce_destroy_wq(struct qede_dev *edev) +static void qede_rdma_destroy_wq(struct qede_dev *edev) { - qede_roce_cleanup_event(edev); - destroy_workqueue(edev->rdma_info.roce_wq); + qede_rdma_cleanup_event(edev); + destroy_workqueue(edev->rdma_info.rdma_wq); } -int qede_roce_dev_add(struct qede_dev *edev) +int qede_rdma_dev_add(struct qede_dev *edev) { int rc = 0; - if (qede_roce_supported(edev)) { - rc = qede_roce_create_wq(edev); + if (qede_rdma_supported(edev)) { + rc = qede_rdma_create_wq(edev); if (rc) return rc; INIT_LIST_HEAD(&edev->rdma_info.entry); mutex_lock(&qedr_dev_list_lock); list_add_tail(&edev->rdma_info.entry, &qedr_dev_list); - _qede_roce_dev_add(edev); + _qede_rdma_dev_add(edev); mutex_unlock(&qedr_dev_list_lock); } return rc; } -static void _qede_roce_dev_remove(struct qede_dev *edev) +static void _qede_rdma_dev_remove(struct qede_dev *edev) { if (qedr_drv && qedr_drv->remove && edev->rdma_info.qedr_dev) qedr_drv->remove(edev->rdma_info.qedr_dev); edev->rdma_info.qedr_dev = NULL; } -void qede_roce_dev_remove(struct qede_dev *edev) +void qede_rdma_dev_remove(struct qede_dev *edev) { - if (!qede_roce_supported(edev)) + if (!qede_rdma_supported(edev)) return; - qede_roce_destroy_wq(edev); + qede_rdma_destroy_wq(edev); mutex_lock(&qedr_dev_list_lock); - _qede_roce_dev_remove(edev); + _qede_rdma_dev_remove(edev); list_del(&edev->rdma_info.entry); mutex_unlock(&qedr_dev_list_lock); } -static void _qede_roce_dev_open(struct qede_dev *edev) +static void _qede_rdma_dev_open(struct qede_dev *edev) { if (qedr_drv && edev->rdma_info.qedr_dev && qedr_drv->notify) qedr_drv->notify(edev->rdma_info.qedr_dev, QEDE_UP); } -static void qede_roce_dev_open(struct qede_dev *edev) +static void qede_rdma_dev_open(struct qede_dev *edev) { - if (!qede_roce_supported(edev)) + if (!qede_rdma_supported(edev)) return; mutex_lock(&qedr_dev_list_lock); - _qede_roce_dev_open(edev); + _qede_rdma_dev_open(edev); mutex_unlock(&qedr_dev_list_lock); } -static void _qede_roce_dev_close(struct qede_dev *edev) +static void _qede_rdma_dev_close(struct qede_dev *edev) { if (qedr_drv && edev->rdma_info.qedr_dev && qedr_drv->notify) qedr_drv->notify(edev->rdma_info.qedr_dev, QEDE_DOWN); } -static void qede_roce_dev_close(struct qede_dev *edev) +static void qede_rdma_dev_close(struct qede_dev *edev) { - if (!qede_roce_supported(edev)) + if (!qede_rdma_supported(edev)) return; mutex_lock(&qedr_dev_list_lock); - _qede_roce_dev_close(edev); + _qede_rdma_dev_close(edev); mutex_unlock(&qedr_dev_list_lock); } -static void qede_roce_dev_shutdown(struct qede_dev *edev) +static void qede_rdma_dev_shutdown(struct qede_dev *edev) { - if (!qede_roce_supported(edev)) + if (!qede_rdma_supported(edev)) return; mutex_lock(&qedr_dev_list_lock); @@ -168,7 +168,7 @@ static void qede_roce_dev_shutdown(struct qede_dev *edev) mutex_unlock(&qedr_dev_list_lock); } -int qede_roce_register_driver(struct qedr_driver *drv) +int qede_rdma_register_driver(struct qedr_driver *drv) { struct qede_dev *edev; u8 qedr_counter = 0; @@ -184,52 +184,52 @@ int qede_roce_register_driver(struct qedr_driver *drv) struct net_device *ndev; qedr_counter++; - _qede_roce_dev_add(edev); + _qede_rdma_dev_add(edev); ndev = edev->ndev; if (netif_running(ndev) && netif_oper_up(ndev)) - _qede_roce_dev_open(edev); + _qede_rdma_dev_open(edev); } mutex_unlock(&qedr_dev_list_lock); - pr_notice("qedr: discovered and registered %d RoCE funcs\n", + pr_notice("qedr: discovered and registered %d RDMA funcs\n", qedr_counter); return 0; } -EXPORT_SYMBOL(qede_roce_register_driver); +EXPORT_SYMBOL(qede_rdma_register_driver); -void qede_roce_unregister_driver(struct qedr_driver *drv) +void qede_rdma_unregister_driver(struct qedr_driver *drv) { struct qede_dev *edev; mutex_lock(&qedr_dev_list_lock); list_for_each_entry(edev, &qedr_dev_list, rdma_info.entry) { if (edev->rdma_info.qedr_dev) - _qede_roce_dev_remove(edev); + _qede_rdma_dev_remove(edev); } qedr_drv = NULL; mutex_unlock(&qedr_dev_list_lock); } -EXPORT_SYMBOL(qede_roce_unregister_driver); +EXPORT_SYMBOL(qede_rdma_unregister_driver); -static void qede_roce_changeaddr(struct qede_dev *edev) +static void qede_rdma_changeaddr(struct qede_dev *edev) { - if (!qede_roce_supported(edev)) + if (!qede_rdma_supported(edev)) return; if (qedr_drv && edev->rdma_info.qedr_dev && qedr_drv->notify) qedr_drv->notify(edev->rdma_info.qedr_dev, QEDE_CHANGE_ADDR); } -static struct qede_roce_event_work * -qede_roce_get_free_event_node(struct qede_dev *edev) +static struct qede_rdma_event_work * +qede_rdma_get_free_event_node(struct qede_dev *edev) { - struct qede_roce_event_work *event_node = NULL; + struct qede_rdma_event_work *event_node = NULL; struct list_head *list_node = NULL; bool found = false; - list_for_each(list_node, &edev->rdma_info.roce_event_list) { - event_node = list_entry(list_node, struct qede_roce_event_work, + list_for_each(list_node, &edev->rdma_info.rdma_event_list) { + event_node = list_entry(list_node, struct qede_rdma_event_work, list); if (!work_pending(&event_node->work)) { found = true; @@ -241,74 +241,74 @@ qede_roce_get_free_event_node(struct qede_dev *edev) event_node = kzalloc(sizeof(*event_node), GFP_KERNEL); if (!event_node) { DP_NOTICE(edev, - "qedr: Could not allocate memory for roce work\n"); + "qedr: Could not allocate memory for rdma work\n"); return NULL; } list_add_tail(&event_node->list, - &edev->rdma_info.roce_event_list); + &edev->rdma_info.rdma_event_list); } return event_node; } -static void qede_roce_handle_event(struct work_struct *work) +static void qede_rdma_handle_event(struct work_struct *work) { - struct qede_roce_event_work *event_node; - enum qede_roce_event event; + struct qede_rdma_event_work *event_node; + enum qede_rdma_event event; struct qede_dev *edev; - event_node = container_of(work, struct qede_roce_event_work, work); + event_node = container_of(work, struct qede_rdma_event_work, work); event = event_node->event; edev = event_node->ptr; switch (event) { case QEDE_UP: - qede_roce_dev_open(edev); + qede_rdma_dev_open(edev); break; case QEDE_DOWN: - qede_roce_dev_close(edev); + qede_rdma_dev_close(edev); break; case QEDE_CLOSE: - qede_roce_dev_shutdown(edev); + qede_rdma_dev_shutdown(edev); break; case QEDE_CHANGE_ADDR: - qede_roce_changeaddr(edev); + qede_rdma_changeaddr(edev); break; default: - DP_NOTICE(edev, "Invalid roce event %d", event); + DP_NOTICE(edev, "Invalid rdma event %d", event); } } -static void qede_roce_add_event(struct qede_dev *edev, - enum qede_roce_event event) +static void qede_rdma_add_event(struct qede_dev *edev, + enum qede_rdma_event event) { - struct qede_roce_event_work *event_node; + struct qede_rdma_event_work *event_node; if (!edev->rdma_info.qedr_dev) return; - event_node = qede_roce_get_free_event_node(edev); + event_node = qede_rdma_get_free_event_node(edev); if (!event_node) return; event_node->event = event; event_node->ptr = edev; - INIT_WORK(&event_node->work, qede_roce_handle_event); - queue_work(edev->rdma_info.roce_wq, &event_node->work); + INIT_WORK(&event_node->work, qede_rdma_handle_event); + queue_work(edev->rdma_info.rdma_wq, &event_node->work); } -void qede_roce_dev_event_open(struct qede_dev *edev) +void qede_rdma_dev_event_open(struct qede_dev *edev) { - qede_roce_add_event(edev, QEDE_UP); + qede_rdma_add_event(edev, QEDE_UP); } -void qede_roce_dev_event_close(struct qede_dev *edev) +void qede_rdma_dev_event_close(struct qede_dev *edev) { - qede_roce_add_event(edev, QEDE_DOWN); + qede_rdma_add_event(edev, QEDE_DOWN); } -void qede_roce_event_changeaddr(struct qede_dev *edev) +void qede_rdma_event_changeaddr(struct qede_dev *edev) { - qede_roce_add_event(edev, QEDE_CHANGE_ADDR); + qede_rdma_add_event(edev, QEDE_CHANGE_ADDR); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 54f93ee53ef7..fffd6d5fc907 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -81,6 +81,12 @@ static const struct emac_variant emac_variant_h3 = { .support_rgmii = true }; +static const struct emac_variant emac_variant_v3s = { + .default_syscon_value = 0x38000, + .internal_phy = PHY_INTERFACE_MODE_MII, + .support_mii = true +}; + static const struct emac_variant emac_variant_a83t = { .default_syscon_value = 0, .internal_phy = 0, @@ -185,6 +191,7 @@ static const struct emac_variant emac_variant_a64 = { /* H3 specific bits for EPHY */ #define H3_EPHY_ADDR_SHIFT 20 +#define H3_EPHY_CLK_SEL BIT(18) /* 1: 24MHz, 0: 25MHz */ #define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */ #define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */ #define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */ @@ -656,6 +663,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) else reg &= ~H3_EPHY_LED_POL; + /* Force EPHY xtal frequency to 24MHz. */ + reg |= H3_EPHY_CLK_SEL; + ret = of_mdio_parse_addr(priv->device, priv->plat->phy_node); if (ret < 0) { @@ -971,6 +981,8 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) static const struct of_device_id sun8i_dwmac_match[] = { { .compatible = "allwinner,sun8i-h3-emac", .data = &emac_variant_h3 }, + { .compatible = "allwinner,sun8i-v3s-emac", + .data = &emac_variant_v3s }, { .compatible = "allwinner,sun8i-a83t-emac", .data = &emac_variant_a83t }, { .compatible = "allwinner,sun50i-a64-emac", diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 6a1cb59728fe..fefbf817399a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2965,7 +2965,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) /* Manage oversized TCP frames for GMAC4 device */ if (skb_is_gso(skb) && priv->tso) { - if (ip_hdr(skb)->protocol == IPPROTO_TCP) + if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) return stmmac_tso_xmit(skb, dev); } @@ -4126,7 +4126,7 @@ int stmmac_dvr_probe(struct device *device, NETIF_F_RXCSUM; if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { - ndev->hw_features |= NETIF_F_TSO; + ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; priv->tso = true; dev_info(priv->device, "TSO feature enabled\n"); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 3840529344ed..a366b3747eeb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -313,6 +313,7 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, { .compatible = "snps,dwc-qos-ethernet-4.10" }, { .compatible = "allwinner,sun8i-a83t-emac" }, { .compatible = "allwinner,sun8i-h3-emac" }, + { .compatible = "allwinner,sun8i-v3s-emac" }, { .compatible = "allwinner,sun50i-a64-emac" }, }; diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 8d198a1f0031..09d215177fff 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -152,7 +152,6 @@ static int lxt973a2_read_status(struct phy_device *phydev) int adv; int err; int lpa; - int lpagb = 0; /* Update the link, but return if there was an error */ err = lxt973a2_update_link(phydev); @@ -178,18 +177,15 @@ static int lxt973a2_read_status(struct phy_device *phydev) */ } while (lpa == adv && retry--); + phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(lpa); + lpa &= adv; phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = phydev->asym_pause = 0; - if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { - phydev->speed = SPEED_1000; - - if (lpagb & LPA_1000FULL) - phydev->duplex = DUPLEX_FULL; - } else if (lpa & (LPA_100FULL | LPA_100HALF)) { + if (lpa & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; if (lpa & LPA_100FULL) @@ -222,6 +218,7 @@ static int lxt973a2_read_status(struct phy_device *phydev) phydev->speed = SPEED_10; phydev->pause = phydev->asym_pause = 0; + phydev->lp_advertising = 0; } return 0; diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index ef08590db873..7868c29071d4 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -697,7 +697,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf, goto err; } - p = skb_put_data(skb, buf, count); + skb_put_data(skb, buf, count); /* strip address/control field if present */ p = skb->data; diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 90facc5ecab0..7847436c441e 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -113,7 +113,6 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, while (offset + sizeof(u16) <= skb->len) { u16 copy_length; - unsigned char *data; if (!rx->remaining) { if (skb->len - offset == sizeof(u16)) { @@ -167,8 +166,8 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, } if (rx->ax_skb) { - data = skb_put_data(rx->ax_skb, skb->data + offset, - copy_length); + skb_put_data(rx->ax_skb, skb->data + offset, + copy_length); if (!rx->remaining) usbnet_skb_return(dev, rx->ax_skb); } diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index bcb974707118..2067743f51ca 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1069,7 +1069,7 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_ /* push a new empty NDP */ if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) - ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size); + ndp16 = skb_put_zero(skb, ctx->max_ndp_size); else ndp16 = ctx->delayed_ndp16; @@ -1120,7 +1120,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) goto exit_no_skb; } /* fill out the initial 16-bit NTB header */ - nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16)); + nth16 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth16)); nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN); nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16)); nth16->wSequence = cpu_to_le16(ctx->tx_seq++); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 908ada4ca21c..d7a3379ea668 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -861,7 +861,6 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, unsigned short temp_bytes; unsigned short buffer_offset = 0; unsigned short frame_len; - unsigned char *tmp_rx_buf; /* log if needed */ hso_dbg(0x1, "Rx %d bytes\n", count); @@ -911,9 +910,9 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, /* Copy what we got so far. make room for iphdr * after tail. */ - tmp_rx_buf = skb_put_data(odev->skb_rx_buf, - (char *)&(odev->rx_ip_hdr), - sizeof(struct iphdr)); + skb_put_data(odev->skb_rx_buf, + (char *)&(odev->rx_ip_hdr), + sizeof(struct iphdr)); /* ETH_HLEN */ odev->rx_buf_size = sizeof(struct iphdr); @@ -932,9 +931,9 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt, /* Copy the rest of the bytes that are left in the * buffer into the waiting sk_buf. */ /* Make room for temp_bytes after tail. */ - tmp_rx_buf = skb_put_data(odev->skb_rx_buf, - ip_pkt + buffer_offset, - temp_bytes); + skb_put_data(odev->skb_rx_buf, + ip_pkt + buffer_offset, + temp_bytes); odev->rx_buf_missing -= temp_bytes; count -= temp_bytes; diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c index be63a829b8fe..ae2b2563460b 100644 --- a/drivers/net/usb/int51x1.c +++ b/drivers/net/usb/int51x1.c @@ -110,7 +110,7 @@ static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev, *len = cpu_to_le16(pack_len); if(need_tail) - memset(__skb_put(skb, need_tail), 0, need_tail); + __skb_put_zero(skb, need_tail); return skb; } diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 94ce98229828..653b2bb32be1 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -226,7 +226,8 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, return NULL; } -static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni) +static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, int ifindex, + __be32 vni) { struct vxlan_dev *vxlan; @@ -235,17 +236,27 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni) vni = 0; hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { - if (vxlan->default_dst.remote_vni == vni) - return vxlan; + if (vxlan->default_dst.remote_vni != vni) + continue; + + if (IS_ENABLED(CONFIG_IPV6)) { + const struct vxlan_config *cfg = &vxlan->cfg; + + if ((cfg->flags & VXLAN_F_IPV6_LINKLOCAL) && + cfg->remote_ifindex != ifindex) + continue; + } + + return vxlan; } return NULL; } /* Look up VNI in a per net namespace table */ -static struct vxlan_dev *vxlan_find_vni(struct net *net, __be32 vni, - sa_family_t family, __be16 port, - u32 flags) +static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex, + __be32 vni, sa_family_t family, + __be16 port, u32 flags) { struct vxlan_sock *vs; @@ -253,7 +264,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, __be32 vni, if (!vs) return NULL; - return vxlan_vs_find_vni(vs, vni); + return vxlan_vs_find_vni(vs, ifindex, vni); } /* Fill in neighbour message in skbuff. */ @@ -305,7 +316,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, if (rdst->remote_vni != vxlan->default_dst.remote_vni && nla_put_u32(skb, NDA_VNI, be32_to_cpu(rdst->remote_vni))) goto nla_put_failure; - if ((vxlan->flags & VXLAN_F_COLLECT_METADATA) && fdb->vni && + if ((vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) && fdb->vni && nla_put_u32(skb, NDA_SRC_VNI, be32_to_cpu(fdb->vni))) goto nla_put_failure; @@ -419,7 +430,7 @@ static u32 eth_vni_hash(const unsigned char *addr, __be32 vni) static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni) { - if (vxlan->flags & VXLAN_F_COLLECT_METADATA) + if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) return &vxlan->fdb_head[eth_vni_hash(mac, vni)]; else return &vxlan->fdb_head[eth_hash(mac)]; @@ -434,7 +445,7 @@ static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, hlist_for_each_entry_rcu(f, head, hlist) { if (ether_addr_equal(mac, f->eth_addr)) { - if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { + if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) { if (vni == f->vni) return f; } else { @@ -957,16 +968,24 @@ out: */ static bool vxlan_snoop(struct net_device *dev, union vxlan_addr *src_ip, const u8 *src_mac, - __be32 vni) + u32 src_ifindex, __be32 vni) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb *f; + u32 ifindex = 0; + +#if IS_ENABLED(CONFIG_IPV6) + if (src_ip->sa.sa_family == AF_INET6 && + (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)) + ifindex = src_ifindex; +#endif f = vxlan_find_mac(vxlan, src_mac, vni); if (likely(f)) { struct vxlan_rdst *rdst = first_remote_rcu(f); - if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip))) + if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) && + rdst->remote_ifindex == ifindex)) return false; /* Don't migrate static entries, drop packets */ @@ -993,7 +1012,7 @@ static bool vxlan_snoop(struct net_device *dev, vxlan->cfg.dst_port, vni, vxlan->default_dst.remote_vni, - 0, NTF_SELF); + ifindex, NTF_SELF); spin_unlock(&vxlan->hash_lock); } @@ -1264,6 +1283,7 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan, struct sk_buff *skb, __be32 vni) { union vxlan_addr saddr; + u32 ifindex = skb->dev->ifindex; skb_reset_mac_header(skb); skb->protocol = eth_type_trans(skb, vxlan->dev); @@ -1284,8 +1304,8 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan, #endif } - if ((vxlan->flags & VXLAN_F_LEARN) && - vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, vni)) + if ((vxlan->cfg.flags & VXLAN_F_LEARN) && + vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, ifindex, vni)) return false; return true; @@ -1351,7 +1371,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) vni = vxlan_vni(vxlan_hdr(skb)->vx_vni); - vxlan = vxlan_vs_find_vni(vs, vni); + vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni); if (!vxlan) goto drop; @@ -1507,7 +1527,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; - } else if (vxlan->flags & VXLAN_F_L3MISS) { + } else if (vxlan->cfg.flags & VXLAN_F_L3MISS) { union vxlan_addr ipa = { .sin.sin_addr.s_addr = tip, .sin.sin_family = AF_INET, @@ -1665,7 +1685,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; - } else if (vxlan->flags & VXLAN_F_L3MISS) { + } else if (vxlan->cfg.flags & VXLAN_F_L3MISS) { union vxlan_addr ipa = { .sin6.sin6_addr = msg->target, .sin6.sin6_family = AF_INET6, @@ -1698,7 +1718,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) return false; pip = ip_hdr(skb); n = neigh_lookup(&arp_tbl, &pip->daddr, dev); - if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { + if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { .sin.sin_addr.s_addr = pip->daddr, .sin.sin_family = AF_INET, @@ -1719,7 +1739,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) return false; pip6 = ipv6_hdr(skb); n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev); - if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { + if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { .sin6.sin6_addr = pip6->daddr, .sin6.sin6_family = AF_INET6, @@ -1993,8 +2013,9 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, #endif } - if (dst_vxlan->flags & VXLAN_F_LEARN) - vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, vni); + if (dst_vxlan->cfg.flags & VXLAN_F_LEARN) + vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0, + vni); u64_stats_update_begin(&tx_stats->syncp); tx_stats->tx_packets++; @@ -2012,8 +2033,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, } static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev, - struct vxlan_dev *vxlan, union vxlan_addr *daddr, - __be16 dst_port, __be32 vni, struct dst_entry *dst, + struct vxlan_dev *vxlan, + union vxlan_addr *daddr, + __be16 dst_port, int dst_ifindex, __be32 vni, + struct dst_entry *dst, u32 rt_flags) { #if IS_ENABLED(CONFIG_IPV6) @@ -2029,9 +2052,9 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev, struct vxlan_dev *dst_vxlan; dst_release(dst); - dst_vxlan = vxlan_find_vni(vxlan->net, vni, + dst_vxlan = vxlan_find_vni(vxlan->net, dst_ifindex, vni, daddr->sa.sa_family, dst_port, - vxlan->flags); + vxlan->cfg.flags); if (!dst_vxlan) { dev->stats.tx_errors++; kfree_skb(skb); @@ -2061,8 +2084,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct dst_entry *ndst = NULL; __be32 vni, label; __u8 tos, ttl; + int ifindex; int err; - u32 flags = vxlan->flags; + u32 flags = vxlan->cfg.flags; bool udp_sum = false; bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); @@ -2081,6 +2105,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; vni = (rdst->remote_vni) ? : default_vni; + ifindex = rdst->remote_ifindex; local_ip = vxlan->cfg.saddr; dst_cache = &rdst->dst_cache; md->gbp = skb->mark; @@ -2114,6 +2139,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst = &remote_ip; dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = tunnel_id_to_key32(info->key.tun_id); + ifindex = 0; dst_cache = &info->dst_cache; if (info->options_len) md = ip_tunnel_info_opts(info); @@ -2131,8 +2157,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct rtable *rt; __be16 df = 0; - rt = vxlan_get_route(vxlan, dev, sock4, skb, - rdst ? rdst->remote_ifindex : 0, tos, + rt = vxlan_get_route(vxlan, dev, sock4, skb, ifindex, tos, dst->sin.sin_addr.s_addr, &local_ip.sin.sin_addr.s_addr, dst_port, src_port, @@ -2145,8 +2170,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, /* Bypass encapsulation if the destination is local */ if (!info) { err = encap_bypass_if_local(skb, dev, vxlan, dst, - dst_port, vni, &rt->dst, - rt->rt_flags); + dst_port, ifindex, vni, + &rt->dst, rt->rt_flags); if (err) goto out_unlock; } else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) { @@ -2168,8 +2193,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } else { struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock); - ndst = vxlan6_get_route(vxlan, dev, sock6, skb, - rdst ? rdst->remote_ifindex : 0, tos, + ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ifindex, tos, label, &dst->sin6.sin6_addr, &local_ip.sin6.sin6_addr, dst_port, src_port, @@ -2184,8 +2208,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; err = encap_bypass_if_local(skb, dev, vxlan, dst, - dst_port, vni, ndst, - rt6i_flags); + dst_port, ifindex, vni, + ndst, rt6i_flags); if (err) goto out_unlock; } @@ -2244,7 +2268,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); - if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { + if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) { if (info && info->mode & IP_TUNNEL_INFO_BRIDGE && info->mode & IP_TUNNEL_INFO_TX) { vni = tunnel_id_to_key32(info->key.tun_id); @@ -2257,7 +2281,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) } } - if (vxlan->flags & VXLAN_F_PROXY) { + if (vxlan->cfg.flags & VXLAN_F_PROXY) { eth = eth_hdr(skb); if (ntohs(eth->h_proto) == ETH_P_ARP) return arp_reduce(dev, skb, vni); @@ -2277,7 +2301,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) f = vxlan_find_mac(vxlan, eth->h_dest, vni); did_rsc = false; - if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) && + if (f && (f->flags & NTF_ROUTER) && (vxlan->cfg.flags & VXLAN_F_RSC) && (ntohs(eth->h_proto) == ETH_P_IP || ntohs(eth->h_proto) == ETH_P_IPV6)) { did_rsc = route_shortcircuit(dev, skb); @@ -2288,7 +2312,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) if (f == NULL) { f = vxlan_find_mac(vxlan, all_zeros_mac, vni); if (f == NULL) { - if ((vxlan->flags & VXLAN_F_L2MISS) && + if ((vxlan->cfg.flags & VXLAN_F_L2MISS) && !is_multicast_ether_addr(eth->h_dest)) vxlan_fdb_miss(vxlan, eth->h_dest); @@ -2484,10 +2508,7 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) struct vxlan_rdst *dst = &vxlan->default_dst; struct net_device *lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex); - bool use_ipv6 = false; - - if (dst->remote_ip.sa.sa_family == AF_INET6) - use_ipv6 = true; + bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6); /* This check is different than dev->max_mtu, because it looks at * the lowerdev->mtu, rather than the static dev->max_mtu @@ -2623,6 +2644,10 @@ static void vxlan_setup(struct net_device *dev) netif_keep_dst(dev); dev->priv_flags |= IFF_NO_QUEUE; + /* MTU range: 68 - 65535 */ + dev->min_mtu = ETH_MIN_MTU; + dev->max_mtu = ETH_MAX_MTU; + INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); @@ -2630,9 +2655,8 @@ static void vxlan_setup(struct net_device *dev) vxlan->age_timer.function = vxlan_cleanup; vxlan->age_timer.data = (unsigned long) vxlan; - vxlan->cfg.dst_port = htons(vxlan_port); - vxlan->dev = dev; + vxlan->net = dev_net(dev); gro_cells_init(&vxlan->gro_cells, dev); @@ -2701,11 +2725,19 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) } } + if (tb[IFLA_MTU]) { + u32 mtu = nla_get_u32(data[IFLA_MTU]); + + if (mtu < ETH_MIN_MTU || mtu > ETH_MAX_MTU) + return -EINVAL; + } + if (!data) return -EINVAL; if (data[IFLA_VXLAN_ID]) { - __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); + u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); + if (id >= VXLAN_N_VID) return -ERANGE; } @@ -2821,7 +2853,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6) if (!vxlan->cfg.no_share) { spin_lock(&vn->sock_lock); vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET, - vxlan->cfg.dst_port, vxlan->flags); + vxlan->cfg.dst_port, vxlan->cfg.flags); if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) { spin_unlock(&vn->sock_lock); return -EBUSY; @@ -2830,7 +2862,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6) } if (!vs) vs = vxlan_socket_create(vxlan->net, ipv6, - vxlan->cfg.dst_port, vxlan->flags); + vxlan->cfg.dst_port, vxlan->cfg.flags); if (IS_ERR(vs)) return PTR_ERR(vs); #if IS_ENABLED(CONFIG_IPV6) @@ -2845,8 +2877,8 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6) static int vxlan_sock_add(struct vxlan_dev *vxlan) { - bool metadata = vxlan->flags & VXLAN_F_COLLECT_METADATA; - bool ipv6 = vxlan->flags & VXLAN_F_IPV6 || metadata; + bool metadata = vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA; + bool ipv6 = vxlan->cfg.flags & VXLAN_F_IPV6 || metadata; bool ipv4 = !ipv6 || metadata; int ret = 0; @@ -2866,116 +2898,172 @@ static int vxlan_sock_add(struct vxlan_dev *vxlan) return ret; } -static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, - struct vxlan_config *conf, - bool changelink) +static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf, + struct net_device **lower, + struct vxlan_dev *old) { struct vxlan_net *vn = net_generic(src_net, vxlan_net_id); - struct vxlan_dev *vxlan = netdev_priv(dev), *tmp; - struct vxlan_rdst *dst = &vxlan->default_dst; - unsigned short needed_headroom = ETH_HLEN; + struct vxlan_dev *tmp; bool use_ipv6 = false; - __be16 default_port = vxlan->cfg.dst_port; - struct net_device *lowerdev = NULL; - if (!changelink) { - if (conf->flags & VXLAN_F_GPE) { - /* For now, allow GPE only together with - * COLLECT_METADATA. This can be relaxed later; in such - * case, the other side of the PtP link will have to be - * provided. - */ - if ((conf->flags & ~VXLAN_F_ALLOWED_GPE) || - !(conf->flags & VXLAN_F_COLLECT_METADATA)) { - pr_info("unsupported combination of extensions\n"); - return -EINVAL; - } - vxlan_raw_setup(dev); - } else { - vxlan_ether_setup(dev); + if (conf->flags & VXLAN_F_GPE) { + /* For now, allow GPE only together with + * COLLECT_METADATA. This can be relaxed later; in such + * case, the other side of the PtP link will have to be + * provided. + */ + if ((conf->flags & ~VXLAN_F_ALLOWED_GPE) || + !(conf->flags & VXLAN_F_COLLECT_METADATA)) { + return -EINVAL; } - - /* MTU range: 68 - 65535 */ - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = ETH_MAX_MTU; - vxlan->net = src_net; } - dst->remote_vni = conf->vni; + if (!conf->remote_ip.sa.sa_family && !conf->saddr.sa.sa_family) { + /* Unless IPv6 is explicitly requested, assume IPv4 */ + conf->remote_ip.sa.sa_family = AF_INET; + conf->saddr.sa.sa_family = AF_INET; + } else if (!conf->remote_ip.sa.sa_family) { + conf->remote_ip.sa.sa_family = conf->saddr.sa.sa_family; + } else if (!conf->saddr.sa.sa_family) { + conf->saddr.sa.sa_family = conf->remote_ip.sa.sa_family; + } - memcpy(&dst->remote_ip, &conf->remote_ip, sizeof(conf->remote_ip)); + if (conf->saddr.sa.sa_family != conf->remote_ip.sa.sa_family) + return -EINVAL; - /* Unless IPv6 is explicitly requested, assume IPv4 */ - if (!dst->remote_ip.sa.sa_family) - dst->remote_ip.sa.sa_family = AF_INET; + if (vxlan_addr_multicast(&conf->saddr)) + return -EINVAL; - if (dst->remote_ip.sa.sa_family == AF_INET6 || - vxlan->cfg.saddr.sa.sa_family == AF_INET6) { + if (conf->saddr.sa.sa_family == AF_INET6) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; use_ipv6 = true; - vxlan->flags |= VXLAN_F_IPV6; + conf->flags |= VXLAN_F_IPV6; + + if (!(conf->flags & VXLAN_F_COLLECT_METADATA)) { + int local_type = + ipv6_addr_type(&conf->saddr.sin6.sin6_addr); + int remote_type = + ipv6_addr_type(&conf->remote_ip.sin6.sin6_addr); + + if (local_type & IPV6_ADDR_LINKLOCAL) { + if (!(remote_type & IPV6_ADDR_LINKLOCAL) && + (remote_type != IPV6_ADDR_ANY)) + return -EINVAL; + + conf->flags |= VXLAN_F_IPV6_LINKLOCAL; + } else { + if (remote_type == + (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)) + return -EINVAL; + + conf->flags &= ~VXLAN_F_IPV6_LINKLOCAL; + } + } } - if (conf->label && !use_ipv6) { - pr_info("label only supported in use with IPv6\n"); + if (conf->label && !use_ipv6) return -EINVAL; - } - if (conf->remote_ifindex && - conf->remote_ifindex != vxlan->cfg.remote_ifindex) { - lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); - dst->remote_ifindex = conf->remote_ifindex; + if (conf->remote_ifindex) { + struct net_device *lowerdev; - if (!lowerdev) { - pr_info("ifindex %d does not exist\n", - dst->remote_ifindex); + lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); + if (!lowerdev) return -ENODEV; - } #if IS_ENABLED(CONFIG_IPV6) if (use_ipv6) { struct inet6_dev *idev = __in6_dev_get(lowerdev); - if (idev && idev->cnf.disable_ipv6) { - pr_info("IPv6 is disabled via sysctl\n"); + if (idev && idev->cnf.disable_ipv6) return -EPERM; - } } #endif - if (!conf->mtu) - dev->mtu = lowerdev->mtu - - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); + *lower = lowerdev; + } else { + if (vxlan_addr_multicast(&conf->remote_ip)) + return -EINVAL; - needed_headroom = lowerdev->hard_header_len; - } else if (!conf->remote_ifindex && - vxlan_addr_multicast(&dst->remote_ip)) { - pr_info("multicast destination requires interface to be specified\n"); - return -EINVAL; +#if IS_ENABLED(CONFIG_IPV6) + if (conf->flags & VXLAN_F_IPV6_LINKLOCAL) + return -EINVAL; +#endif + + *lower = NULL; } - if (lowerdev) { - dev->gso_max_size = lowerdev->gso_max_size; - dev->gso_max_segs = lowerdev->gso_max_segs; + if (!conf->dst_port) { + if (conf->flags & VXLAN_F_GPE) + conf->dst_port = htons(4790); /* IANA VXLAN-GPE port */ + else + conf->dst_port = htons(vxlan_port); } - if (conf->mtu) { - int max_mtu = ETH_MAX_MTU; + if (!conf->age_interval) + conf->age_interval = FDB_AGE_DEFAULT; - if (lowerdev) - max_mtu = lowerdev->mtu; + list_for_each_entry(tmp, &vn->vxlan_list, next) { + if (tmp == old) + continue; - max_mtu -= (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); + if (tmp->cfg.vni != conf->vni) + continue; + if (tmp->cfg.dst_port != conf->dst_port) + continue; + if ((tmp->cfg.flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) != + (conf->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6))) + continue; - if (conf->mtu < dev->min_mtu || conf->mtu > dev->max_mtu) - return -EINVAL; + if ((conf->flags & VXLAN_F_IPV6_LINKLOCAL) && + tmp->cfg.remote_ifindex != conf->remote_ifindex) + continue; + + return -EEXIST; + } + + return 0; +} + +static void vxlan_config_apply(struct net_device *dev, + struct vxlan_config *conf, + struct net_device *lowerdev, bool changelink) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_rdst *dst = &vxlan->default_dst; + unsigned short needed_headroom = ETH_HLEN; + bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6); + int max_mtu = ETH_MAX_MTU; + + if (!changelink) { + if (conf->flags & VXLAN_F_GPE) + vxlan_raw_setup(dev); + else + vxlan_ether_setup(dev); + + if (conf->mtu) + dev->mtu = conf->mtu; + } + + dst->remote_vni = conf->vni; + + memcpy(&dst->remote_ip, &conf->remote_ip, sizeof(conf->remote_ip)); + + if (lowerdev) { + dst->remote_ifindex = conf->remote_ifindex; - dev->mtu = conf->mtu; + dev->gso_max_size = lowerdev->gso_max_size; + dev->gso_max_segs = lowerdev->gso_max_segs; - if (conf->mtu > max_mtu) - dev->mtu = max_mtu; + needed_headroom = lowerdev->hard_header_len; + + max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : + VXLAN_HEADROOM); } + if (dev->mtu > max_mtu) + dev->mtu = max_mtu; + if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) needed_headroom += VXLAN6_HEADROOM; else @@ -2983,31 +3071,21 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, dev->needed_headroom = needed_headroom; memcpy(&vxlan->cfg, conf, sizeof(*conf)); - if (!vxlan->cfg.dst_port) { - if (conf->flags & VXLAN_F_GPE) - vxlan->cfg.dst_port = htons(4790); /* IANA VXLAN-GPE port */ - else - vxlan->cfg.dst_port = default_port; - } - vxlan->flags |= conf->flags; +} - if (!vxlan->cfg.age_interval) - vxlan->cfg.age_interval = FDB_AGE_DEFAULT; +static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, + struct vxlan_config *conf, + bool changelink) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct net_device *lowerdev; + int ret; - if (changelink) - return 0; + ret = vxlan_config_validate(src_net, conf, &lowerdev, vxlan); + if (ret) + return ret; - list_for_each_entry(tmp, &vn->vxlan_list, next) { - if (tmp->cfg.vni == conf->vni && - (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 || - tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 && - tmp->cfg.dst_port == vxlan->cfg.dst_port && - (tmp->flags & VXLAN_F_RCV_FLAGS) == - (vxlan->flags & VXLAN_F_RCV_FLAGS)) { - pr_info("duplicate VNI %u\n", be32_to_cpu(conf->vni)); - return -EEXIST; - } - } + vxlan_config_apply(dev, conf, lowerdev, changelink); return 0; } @@ -3071,22 +3149,35 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], } if (data[IFLA_VXLAN_GROUP]) { + if (changelink && (conf->remote_ip.sa.sa_family != AF_INET)) + return -EOPNOTSUPP; + conf->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); + conf->remote_ip.sa.sa_family = AF_INET; } else if (data[IFLA_VXLAN_GROUP6]) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; + if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6)) + return -EOPNOTSUPP; + conf->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); conf->remote_ip.sa.sa_family = AF_INET6; } if (data[IFLA_VXLAN_LOCAL]) { + if (changelink && (conf->saddr.sa.sa_family != AF_INET)) + return -EOPNOTSUPP; + conf->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]); conf->saddr.sa.sa_family = AF_INET; } else if (data[IFLA_VXLAN_LOCAL6]) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; + if (changelink && (conf->saddr.sa.sa_family != AF_INET6)) + return -EOPNOTSUPP; + /* TODO: respect scope id */ conf->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]); conf->saddr.sa.sa_family = AF_INET6; @@ -3106,12 +3197,10 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], IPV6_FLOWLABEL_MASK; if (data[IFLA_VXLAN_LEARNING]) { - if (nla_get_u8(data[IFLA_VXLAN_LEARNING])) { + if (nla_get_u8(data[IFLA_VXLAN_LEARNING])) conf->flags |= VXLAN_F_LEARN; - } else { + else conf->flags &= ~VXLAN_F_LEARN; - vxlan->flags &= ~VXLAN_F_LEARN; - } } else if (!changelink) { /* default to learn on a new device */ conf->flags |= VXLAN_F_LEARN; @@ -3394,43 +3483,44 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) || nla_put_be32(skb, IFLA_VXLAN_LABEL, vxlan->cfg.label) || nla_put_u8(skb, IFLA_VXLAN_LEARNING, - !!(vxlan->flags & VXLAN_F_LEARN)) || + !!(vxlan->cfg.flags & VXLAN_F_LEARN)) || nla_put_u8(skb, IFLA_VXLAN_PROXY, - !!(vxlan->flags & VXLAN_F_PROXY)) || - nla_put_u8(skb, IFLA_VXLAN_RSC, !!(vxlan->flags & VXLAN_F_RSC)) || + !!(vxlan->cfg.flags & VXLAN_F_PROXY)) || + nla_put_u8(skb, IFLA_VXLAN_RSC, + !!(vxlan->cfg.flags & VXLAN_F_RSC)) || nla_put_u8(skb, IFLA_VXLAN_L2MISS, - !!(vxlan->flags & VXLAN_F_L2MISS)) || + !!(vxlan->cfg.flags & VXLAN_F_L2MISS)) || nla_put_u8(skb, IFLA_VXLAN_L3MISS, - !!(vxlan->flags & VXLAN_F_L3MISS)) || + !!(vxlan->cfg.flags & VXLAN_F_L3MISS)) || nla_put_u8(skb, IFLA_VXLAN_COLLECT_METADATA, - !!(vxlan->flags & VXLAN_F_COLLECT_METADATA)) || + !!(vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA)) || nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->cfg.age_interval) || nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->cfg.addrmax) || nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->cfg.dst_port) || nla_put_u8(skb, IFLA_VXLAN_UDP_CSUM, - !(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM_TX)) || + !(vxlan->cfg.flags & VXLAN_F_UDP_ZERO_CSUM_TX)) || nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, - !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) || + !!(vxlan->cfg.flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) || nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, - !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) || + !!(vxlan->cfg.flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) || nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX, - !!(vxlan->flags & VXLAN_F_REMCSUM_TX)) || + !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_TX)) || nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX, - !!(vxlan->flags & VXLAN_F_REMCSUM_RX))) + !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX))) goto nla_put_failure; if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) goto nla_put_failure; - if (vxlan->flags & VXLAN_F_GBP && + if (vxlan->cfg.flags & VXLAN_F_GBP && nla_put_flag(skb, IFLA_VXLAN_GBP)) goto nla_put_failure; - if (vxlan->flags & VXLAN_F_GPE && + if (vxlan->cfg.flags & VXLAN_F_GPE && nla_put_flag(skb, IFLA_VXLAN_GPE)) goto nla_put_failure; - if (vxlan->flags & VXLAN_F_REMCSUM_NOPARTIAL && + if (vxlan->cfg.flags & VXLAN_F_REMCSUM_NOPARTIAL && nla_put_flag(skb, IFLA_VXLAN_REMCSUM_NOPARTIAL)) goto nla_put_failure; diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 85d09fdef8dc..64a354fa78ab 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -298,7 +298,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, u16 headroom = sizeof(struct htc_frame_hdr) + sizeof(struct wmi_cmd_hdr); struct sk_buff *skb; - u8 *data; unsigned long time_left; int ret = 0; @@ -312,7 +311,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, skb_reserve(skb, headroom); if (cmd_len != 0 && cmd_buf != NULL) { - data = skb_put_data(skb, cmd_buf, cmd_len); + skb_put_data(skb, cmd_buf, cmd_len); } mutex_lock(&wmi->op_mutex); diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index a9e2b06b3175..2300e796c6ab 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -239,7 +239,6 @@ static int if_sdio_handle_data(struct if_sdio_card *card, { int ret; struct sk_buff *skb; - char *data; if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_deb_sdio("response packet too large (%d bytes)\n", @@ -256,7 +255,7 @@ static int if_sdio_handle_data(struct if_sdio_card *card, skb_reserve(skb, NET_IP_ALIGN); - data = skb_put_data(skb, buffer, size); + skb_put_data(skb, buffer, size); lbs_process_rxed_packet(card->priv, skb); diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index f6ac39973b5d..90d7d09a6c63 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -33,9 +33,7 @@ static inline void qtnf_cmd_skb_put_action(struct sk_buff *skb, u16 action) static inline void qtnf_cmd_skb_put_buffer(struct sk_buff *skb, const u8 *buf_src, size_t len) { - u8 *buf_dst; - - buf_dst = skb_put_data(skb, buf_src, len); + skb_put_data(skb, buf_src, len); } static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb, diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 0c1f8307e179..df5f6795f650 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -729,13 +729,12 @@ static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw, dev_kfree_skb_any(skb); } else { struct sk_buff *uskb = NULL; - u8 *pdata; uskb = dev_alloc_skb(skb->len + 128); if (likely(uskb)) { memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status)); - pdata = skb_put_data(uskb, skb->data, skb->len); + skb_put_data(uskb, skb->data, skb->len); dev_kfree_skb_any(skb); ieee80211_rx_irqsafe(hw, uskb); } else { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index c7a77467b20e..015476e3f7e5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -647,8 +647,7 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); + skb_put_data(skb, &reserved_page_packet, totalpacketlen); if (cmd_send_packet) rtstatus = cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index 88faeab2574f..f4129cf96e7c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -668,8 +668,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) if (!skb) { dlok = false; } else { - memcpy((u8 *) skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); + skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = _rtl92d_cmd_send_packet(hw, skb); if (rtstatus) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c index 1f42ce5f8f27..6f8f75ad0881 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c @@ -708,8 +708,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); + skb_put_data(skb, &reserved_page_packet, totalpacketlen); b_dlok = true; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c index a954a87b0ed9..bf9859f74b6f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c @@ -470,8 +470,7 @@ void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); + skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c index 4fc839b1d601..01205578a3f4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c @@ -527,8 +527,7 @@ void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, u1rsvdpageloc, sizeof(u1rsvdpageloc)); skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); + skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index 73350103b736..67aec20cdbf0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c @@ -1588,8 +1588,7 @@ out: &reserved_page_packet_8812[0], totalpacketlen); skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet_8812, totalpacketlen); + skb_put_data(skb, &reserved_page_packet_8812, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); @@ -1725,8 +1724,7 @@ out: &reserved_page_packet_8821[0], totalpacketlen); skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet_8821, totalpacketlen); + skb_put_data(skb, &reserved_page_packet_8821, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 4433cec4367c..a0f04371d93b 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -389,9 +389,7 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common, struct ieee80211_tx_info *info; struct skb_info *rx_params; u8 pad_bytes = msg[4]; - u8 pkt_recv; struct sk_buff *skb; - char *buffer; if (type == RX_DOT11_MGMT) { if (!adapter->sc_nvifs) @@ -412,11 +410,9 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common, return -ENOMEM; } - buffer = skb_put_data(skb, - (u8 *)(msg + FRAME_DESC_SZ + pad_bytes), - msg_len); - - pkt_recv = buffer[0]; + skb_put_data(skb, + (u8 *)(msg + FRAME_DESC_SZ + pad_bytes), + msg_len); info = IEEE80211_SKB_CB(skb); rx_params = (struct skb_info *)info->driver_data; diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 53cd6d4d5b50..0f15696195f8 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -117,7 +117,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, struct wl1271_rx_descriptor *desc; struct sk_buff *skb; struct ieee80211_hdr *hdr; - u8 *buf; u8 beacon = 0; u8 is_data = 0; u8 reserved = 0, offset_to_data = 0; @@ -180,7 +179,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, * packets copy the packets in offset of 2 bytes guarantee IP header * payload aligned to 4 bytes. */ - buf = skb_put_data(skb, data + sizeof(*desc), pkt_data_len); + skb_put_data(skb, data + sizeof(*desc), pkt_data_len); if (rx_align == WLCORE_RX_BUF_PADDED) skb_pull(skb, RX_BUF_ALIGN); diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index c8a8f5badb5b..c05cb637ba92 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -1006,7 +1006,7 @@ static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) { struct sk_buff *skb; - u8 *felica, *nfcid3, *gb; + u8 *felica, *nfcid3; u8 *gbytes = dev->gb; size_t gbytes_len = dev->gb_len; @@ -1048,7 +1048,7 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) /* General bytes */ skb_put_u8(skb, gbytes_len); - gb = skb_put_data(skb, gbytes, gbytes_len); + skb_put_data(skb, gbytes, gbytes_len); /* Len Tk */ skb_put_u8(skb, 0); diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 0efc54a4d82f..7a0ffc71b25d 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -986,6 +986,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *, int qeth_set_features(struct net_device *, netdev_features_t); int qeth_recover_features(struct net_device *); netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); +int qeth_vm_request_mac(struct qeth_card *card); /* exports for OSN */ int qeth_osn_assist(struct net_device *, void *, int); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 08338f27c82c..3b657d5b7e49 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -27,6 +27,9 @@ #include <asm/io.h> #include <asm/sysinfo.h> #include <asm/compat.h> +#include <asm/diag.h> +#include <asm/cio.h> +#include <asm/ccwdev.h> #include "qeth_core.h" @@ -4103,7 +4106,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, flush_count); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); - return -EBUSY; + rc = -EBUSY; + goto out; } } } @@ -4122,19 +4126,21 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, * In that case we will enter this loop */ while (atomic_dec_return(&queue->state)) { - flush_count = 0; start_index = queue->next_buf_to_fill; /* check if we can go back to non-packing state */ - flush_count += qeth_switch_to_nonpacking_if_needed(queue); + tmp = qeth_switch_to_nonpacking_if_needed(queue); /* * check if we need to flush a packing buffer to get a pci * flag out on the queue */ - if (!flush_count && !atomic_read(&queue->set_pci_flags_count)) - flush_count += qeth_prep_flush_pack_buffer(queue); - if (flush_count) - qeth_flush_buffers(queue, start_index, flush_count); + if (!tmp && !atomic_read(&queue->set_pci_flags_count)) + tmp = qeth_prep_flush_pack_buffer(queue); + if (tmp) { + qeth_flush_buffers(queue, start_index, tmp); + flush_count += tmp; + } } +out: /* at this point the queue is UNLOCKED again */ if (queue->card->options.performance_stats && do_pack) queue->card->perf_stats.bufs_sent_pack += flush_count; @@ -4770,6 +4776,64 @@ static int qeth_query_card_info(struct qeth_card *card, (void *)carrier_info); } +/** + * qeth_vm_request_mac() - Request a hypervisor-managed MAC address + * @card: pointer to a qeth_card + * + * Returns + * 0, if a MAC address has been set for the card's netdevice + * a return code, for various error conditions + */ +int qeth_vm_request_mac(struct qeth_card *card) +{ + struct diag26c_mac_resp *response; + struct diag26c_mac_req *request; + struct ccw_dev_id id; + int rc; + + QETH_DBF_TEXT(SETUP, 2, "vmreqmac"); + + if (!card->dev) + return -ENODEV; + + request = kzalloc(sizeof(*request), GFP_KERNEL | GFP_DMA); + response = kzalloc(sizeof(*response), GFP_KERNEL | GFP_DMA); + if (!request || !response) { + rc = -ENOMEM; + goto out; + } + + ccw_device_get_id(CARD_DDEV(card), &id); + request->resp_buf_len = sizeof(*response); + request->resp_version = DIAG26C_VERSION2; + request->op_code = DIAG26C_GET_MAC; + request->devno = id.devno; + + rc = diag26c(request, response, DIAG26C_MAC_SERVICES); + if (rc) + goto out; + + if (request->resp_buf_len < sizeof(*response) || + response->version != request->resp_version) { + rc = -EIO; + QETH_DBF_TEXT(SETUP, 2, "badresp"); + QETH_DBF_HEX(SETUP, 2, &request->resp_buf_len, + sizeof(request->resp_buf_len)); + } else if (!is_valid_ether_addr(response->mac)) { + rc = -EINVAL; + QETH_DBF_TEXT(SETUP, 2, "badmac"); + QETH_DBF_HEX(SETUP, 2, response->mac, ETH_ALEN); + } else { + ether_addr_copy(card->dev->dev_addr, response->mac); + } + +out: + kfree(response); + kfree(request); + return rc; +} +EXPORT_SYMBOL_GPL(qeth_vm_request_mac); + static inline int qeth_get_qdio_q_format(struct qeth_card *card) { if (card->info.type == QETH_CARD_TYPE_IQD) diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index ab9b1376467f..6dd7d05e5693 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/drivers/s390/net/qeth_core_mpc.c @@ -170,12 +170,18 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_TRACE_ALREADY_ACTIVE, "trace already active"}, {IPA_RC_INVALID_FORMAT, "invalid format or length"}, {IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"}, + {IPA_RC_SBP_IQD_NOT_CONFIGURED, "Not configured for bridgeport"}, {IPA_RC_DUP_IPV6_HOME, "ipv6 address already registered"}, {IPA_RC_UNREGISTERED_ADDR, "Address not registered"}, {IPA_RC_NO_ID_AVAILABLE, "No identifiers available"}, {IPA_RC_ID_NOT_FOUND, "Identifier not found"}, + {IPA_RC_SBP_IQD_ANO_DEV_PRIMARY, "Primary bridgeport exists already"}, + {IPA_RC_SBP_IQD_CURRENT_SECOND, "Bridgeport is currently secondary"}, + {IPA_RC_SBP_IQD_LIMIT_SECOND, "Limit of secondary bridgeports reached"}, {IPA_RC_INVALID_IP_VERSION, "IP version incorrect"}, + {IPA_RC_SBP_IQD_CURRENT_PRIMARY, "Bridgeport is currently primary"}, {IPA_RC_LAN_FRAME_MISMATCH, "LAN and frame mismatch"}, + {IPA_RC_SBP_IQD_NO_QDIO_QUEUES, "QDIO queues not established"}, {IPA_RC_L2_UNSUPPORTED_CMD, "Unsupported layer 2 command"}, {IPA_RC_L2_DUP_MAC, "Duplicate MAC address"}, {IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"}, @@ -187,6 +193,14 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"}, {IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"}, {IPA_RC_L2_VLAN_ID_NOT_FOUND, "L2 vlan id not found"}, + {IPA_RC_SBP_OSA_NOT_CONFIGURED, "Not configured for bridgeport"}, + {IPA_RC_SBP_OSA_OS_MISMATCH, "OS mismatch"}, + {IPA_RC_SBP_OSA_ANO_DEV_PRIMARY, "Primary bridgeport exists already"}, + {IPA_RC_SBP_OSA_CURRENT_SECOND, "Bridgeport is currently secondary"}, + {IPA_RC_SBP_OSA_LIMIT_SECOND, "Limit of secondary bridgeports reached"}, + {IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN, "Not authorized by zManager"}, + {IPA_RC_SBP_OSA_CURRENT_PRIMARY, "Bridgeport is currently primary"}, + {IPA_RC_SBP_OSA_NO_QDIO_QUEUES, "QDIO queues not established"}, {IPA_RC_DATA_MISMATCH, "Data field mismatch (v4/v6 mixed)"}, {IPA_RC_INVALID_MTU_SIZE, "Invalid MTU size"}, {IPA_RC_INVALID_LANTYPE, "Invalid LAN type"}, diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 45bbea2843bf..912e0107de8f 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -142,12 +142,18 @@ enum qeth_ipa_return_codes { IPA_RC_TRACE_ALREADY_ACTIVE = 0x0005, IPA_RC_INVALID_FORMAT = 0x0006, IPA_RC_DUP_IPV6_REMOTE = 0x0008, + IPA_RC_SBP_IQD_NOT_CONFIGURED = 0x000C, IPA_RC_DUP_IPV6_HOME = 0x0010, IPA_RC_UNREGISTERED_ADDR = 0x0011, IPA_RC_NO_ID_AVAILABLE = 0x0012, IPA_RC_ID_NOT_FOUND = 0x0013, + IPA_RC_SBP_IQD_ANO_DEV_PRIMARY = 0x0014, + IPA_RC_SBP_IQD_CURRENT_SECOND = 0x0018, + IPA_RC_SBP_IQD_LIMIT_SECOND = 0x001C, IPA_RC_INVALID_IP_VERSION = 0x0020, + IPA_RC_SBP_IQD_CURRENT_PRIMARY = 0x0024, IPA_RC_LAN_FRAME_MISMATCH = 0x0040, + IPA_RC_SBP_IQD_NO_QDIO_QUEUES = 0x00EB, IPA_RC_L2_UNSUPPORTED_CMD = 0x2003, IPA_RC_L2_DUP_MAC = 0x2005, IPA_RC_L2_ADDR_TABLE_FULL = 0x2006, @@ -159,6 +165,14 @@ enum qeth_ipa_return_codes { IPA_RC_L2_INVALID_VLAN_ID = 0x2015, IPA_RC_L2_DUP_VLAN_ID = 0x2016, IPA_RC_L2_VLAN_ID_NOT_FOUND = 0x2017, + IPA_RC_SBP_OSA_NOT_CONFIGURED = 0x2B0C, + IPA_RC_SBP_OSA_OS_MISMATCH = 0x2B10, + IPA_RC_SBP_OSA_ANO_DEV_PRIMARY = 0x2B14, + IPA_RC_SBP_OSA_CURRENT_SECOND = 0x2B18, + IPA_RC_SBP_OSA_LIMIT_SECOND = 0x2B1C, + IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN = 0x2B20, + IPA_RC_SBP_OSA_CURRENT_PRIMARY = 0x2B24, + IPA_RC_SBP_OSA_NO_QDIO_QUEUES = 0x2BEB, IPA_RC_DATA_MISMATCH = 0xe001, IPA_RC_INVALID_MTU_SIZE = 0xe002, IPA_RC_INVALID_LANTYPE = 0xe003, @@ -187,6 +201,10 @@ enum qeth_ipa_return_codes { #define IPA_RC_INVALID_SUBCMD IPA_RC_IP_TABLE_FULL #define IPA_RC_HARDWARE_AUTH_ERROR IPA_RC_UNKNOWN_ERROR +/* for SETBRIDGEPORT (double occupancies) */ +#define IPA_RC_SBP_IQD_OS_MISMATCH IPA_RC_DUP_IPV6_HOME +#define IPA_RC_SBP_IQD_NOT_AUTHD_BY_ZMAN IPA_RC_INVALID_IP_VERSION + /* IPA function flags; each flag marks availability of respective function */ enum qeth_ipa_funcs { IPA_ARP_PROCESSING = 0x00000001L, diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c6bc63b8b295..ad110abfdd47 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -21,6 +21,7 @@ #include <linux/hash.h> #include <linux/hashtable.h> #include <linux/string.h> +#include <asm/setup.h> #include "qeth_core.h" #include "qeth_l2.h" @@ -505,9 +506,19 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) int rc = 0; char vendor_pre[] = {0x02, 0x00, 0x00}; - QETH_DBF_TEXT(SETUP, 2, "doL2init"); + QETH_DBF_TEXT(SETUP, 2, "l2reqmac"); QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); + if (MACHINE_IS_VM) { + rc = qeth_vm_request_mac(card); + if (!rc) + goto out; + QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n", + CARD_BUS_ID(card), rc); + QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc); + /* fall back to alternative mechanism: */ + } + if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { rc = qeth_query_setadapterparms(card); if (rc) { @@ -528,11 +539,12 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc); return rc; } - QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN); } else { eth_random_addr(card->dev->dev_addr); memcpy(card->dev->dev_addr, vendor_pre, 3); } +out: + QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len); return 0; } @@ -1650,27 +1662,27 @@ static int qeth_bridgeport_makerc(struct qeth_card *card, if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) || (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc))) switch (cbctl->cmd_rc) { - case 0x0000: + case IPA_RC_SUCCESS: rc = 0; break; - case 0x2B04: - case 0x0004: + case IPA_RC_L2_UNSUPPORTED_CMD: + case IPA_RC_UNSUPPORTED_COMMAND: rc = -EOPNOTSUPP; break; - case 0x2B0C: - case 0x000C: /* Not configured as bridge Port */ + case IPA_RC_SBP_OSA_NOT_CONFIGURED: + case IPA_RC_SBP_IQD_NOT_CONFIGURED: rc = -ENODEV; /* maybe not the best code here? */ dev_err(&card->gdev->dev, "The device is not configured as a Bridge Port\n"); break; - case 0x2B10: - case 0x0010: /* OS mismatch */ + case IPA_RC_SBP_OSA_OS_MISMATCH: + case IPA_RC_SBP_IQD_OS_MISMATCH: rc = -EPERM; dev_err(&card->gdev->dev, "A Bridge Port is already configured by a different operating system\n"); break; - case 0x2B14: - case 0x0014: /* Another device is Primary */ + case IPA_RC_SBP_OSA_ANO_DEV_PRIMARY: + case IPA_RC_SBP_IQD_ANO_DEV_PRIMARY: switch (setcmd) { case IPA_SBP_SET_PRIMARY_BRIDGE_PORT: rc = -EEXIST; @@ -1686,26 +1698,26 @@ static int qeth_bridgeport_makerc(struct qeth_card *card, rc = -EIO; } break; - case 0x2B18: - case 0x0018: /* This device is currently Secondary */ + case IPA_RC_SBP_OSA_CURRENT_SECOND: + case IPA_RC_SBP_IQD_CURRENT_SECOND: rc = -EBUSY; dev_err(&card->gdev->dev, "The device is already a secondary Bridge Port\n"); break; - case 0x2B1C: - case 0x001C: /* Limit for Secondary devices reached */ + case IPA_RC_SBP_OSA_LIMIT_SECOND: + case IPA_RC_SBP_IQD_LIMIT_SECOND: rc = -EEXIST; dev_err(&card->gdev->dev, "The LAN cannot have more secondary Bridge Ports\n"); break; - case 0x2B24: - case 0x0024: /* This device is currently Primary */ + case IPA_RC_SBP_OSA_CURRENT_PRIMARY: + case IPA_RC_SBP_IQD_CURRENT_PRIMARY: rc = -EBUSY; dev_err(&card->gdev->dev, "The device is already a primary Bridge Port\n"); break; - case 0x2B20: - case 0x0020: /* Not authorized by zManager */ + case IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN: + case IPA_RC_SBP_IQD_NOT_AUTHD_BY_ZMAN: rc = -EACCES; dev_err(&card->gdev->dev, "The device is not authorized to be a Bridge Port\n"); diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index ff4119e8de42..31f35025d19e 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -251,8 +251,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) if ((skb_tail_pointer(skb) + add_bytes) <= skb_end_pointer(skb)) - memset(__skb_put(skb, add_bytes), 0, - add_bytes); + __skb_put_zero(skb, add_bytes); } } } diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 14173cf6e1e7..afb9dadc1cfe 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1510,7 +1510,6 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) u8 nr_subframes, i; unsigned char *pdata; struct rx_pkt_attrib *pattrib; - unsigned char *data_ptr; struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; struct recv_priv *precvpriv = &padapter->recvpriv; struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue); @@ -1544,8 +1543,7 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) sub_skb = dev_alloc_skb(nSubframe_Length + 12); if (sub_skb) { skb_reserve(sub_skb, 12); - data_ptr = skb_put_data(sub_skb, pdata, - nSubframe_Length); + skb_put_data(sub_skb, pdata, nSubframe_Length); } else { sub_skb = skb_clone(prframe->pkt, GFP_ATOMIC); if (sub_skb) { diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index bae98ca0a9b6..03a81ba136b2 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -782,7 +782,6 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, u8 nPadding_Length = 0; u16 SeqNum = 0; struct sk_buff *sub_skb; - u8 *data_ptr; /* just for debug purpose */ SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl)); if ((RTLLIB_QOS_HAS_SEQ(fc)) && @@ -817,7 +816,7 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, if (!sub_skb) return 0; skb_reserve(sub_skb, 12); - data_ptr = skb_put_data(sub_skb, skb->data, skb->len); + skb_put_data(sub_skb, skb->data, skb->len); sub_skb->dev = ieee->dev; rxb->subframes[0] = sub_skb; @@ -869,7 +868,7 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, if (!sub_skb) return 0; skb_reserve(sub_skb, 12); - data_ptr = skb_put_data(sub_skb, skb->data, nSubframe_Length); + skb_put_data(sub_skb, skb->data, nSubframe_Length); sub_skb->dev = ieee->dev; rxb->subframes[rxb->nr_subframes++] = sub_skb; diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 5f2751d4d464..09d2c8649171 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -1264,7 +1264,7 @@ rtllib_association_req(struct rtllib_network *beacon, hdr->info_element[0].id = MFIE_TYPE_SSID; hdr->info_element[0].len = beacon->ssid_len; - tag = skb_put_data(skb, beacon->ssid, beacon->ssid_len); + skb_put_data(skb, beacon->ssid, beacon->ssid_len); tag = skb_put(skb, rate_len); @@ -1340,7 +1340,7 @@ rtllib_association_req(struct rtllib_network *beacon, } if (wpa_ie_len) { - tag = skb_put_data(skb, ieee->wpa_ie, ieee->wpa_ie_len); + skb_put_data(skb, ieee->wpa_ie, ieee->wpa_ie_len); if (PMKCacheIdx >= 0) { tag = skb_put(skb, 18); @@ -1356,12 +1356,13 @@ rtllib_association_req(struct rtllib_network *beacon, } if (wps_ie_len && ieee->wps_ie) { - tag = skb_put_data(skb, ieee->wps_ie, wps_ie_len); + skb_put_data(skb, ieee->wps_ie, wps_ie_len); } - tag = skb_put(skb, turbo_info_len); - if (turbo_info_len) + if (turbo_info_len) { + tag = skb_put(skb, turbo_info_len); rtllib_TURBO_Info(ieee, &tag); + } if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) { if (ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index c0e2f711cb4e..a4aedb489e92 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -780,7 +780,6 @@ static u8 parse_subframe(struct sk_buff *skb, u16 SeqNum=0; struct sk_buff *sub_skb; - u8 *data_ptr; /* just for debug purpose */ SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl)); @@ -848,8 +847,7 @@ static u8 parse_subframe(struct sk_buff *skb, if (!sub_skb) return 0; skb_reserve(sub_skb, 12); - data_ptr = skb_put_data(sub_skb, skb->data, - nSubframe_Length); + skb_put_data(sub_skb, skb->data, nSubframe_Length); #endif rxb->subframes[rxb->nr_subframes++] = sub_skb; if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 107069180ed2..fe6f38b7ec35 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -1112,7 +1112,7 @@ ieee80211_association_req(struct ieee80211_network *beacon, hdr->info_element[0].id = MFIE_TYPE_SSID; hdr->info_element[0].len = beacon->ssid_len; - tag = skb_put_data(skb, beacon->ssid, beacon->ssid_len); + skb_put_data(skb, beacon->ssid, beacon->ssid_len); tag = skb_put(skb, rate_len); @@ -1184,18 +1184,17 @@ ieee80211_association_req(struct ieee80211_network *beacon, //choose what wpa_supplicant gives to associate. - tag = skb_put(skb, wpa_ie_len); if (wpa_ie_len) { - memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); + skb_put_data(skb, ieee->wpa_ie, wpa_ie_len); } - tag = skb_put(skb, wmm_info_len); if (wmm_info_len) { - ieee80211_WMM_Info(ieee, &tag); + tag = skb_put(skb, wmm_info_len); + ieee80211_WMM_Info(ieee, &tag); } #ifdef THOMAS_TURBO - tag = skb_put(skb, turbo_info_len); if (turbo_info_len) { + tag = skb_put(skb, turbo_info_len); ieee80211_TURBO_Info(ieee, &tag); } #endif diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index c3cf01c842a3..87ab3ba760fc 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -31,7 +31,6 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) struct r8192_priv *priv = ieee80211_priv(dev); struct sk_buff *skb; struct cb_desc *tcb_desc; - unsigned char *ptr_buf; /* Get TCB and local buffer from common pool. * (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) @@ -45,7 +44,7 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL; tcb_desc->bLastIniPkt = 0; skb_reserve(skb, USB_HWDESC_HEADER_LEN); - ptr_buf = skb_put_data(skb, pData, DataLen); + skb_put_data(skb, pData, DataLen); tcb_desc->txbuf_size = (u16)DataLen; if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index f96c558b3c6a..ea3eb94b28b3 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -340,7 +340,7 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) int a_len, padding_len; u16 eth_type, nSubframe_Length; u8 nr_subframes, i; - unsigned char *data_ptr, *pdata; + unsigned char *pdata; struct rx_pkt_attrib *pattrib; _pkt *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; struct recv_priv *precvpriv = &padapter->recvpriv; @@ -372,7 +372,7 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) if (!sub_skb) break; skb_reserve(sub_skb, 12); - data_ptr = skb_put_data(sub_skb, pdata, nSubframe_Length); + skb_put_data(sub_skb, pdata, nSubframe_Length); subframes[nr_subframes++] = sub_skb; if (nr_subframes >= MAX_SUBFRAME_COUNT) { netdev_warn(padapter->pnetdev, "r8712u: ParseSubframe(): Too many Subframes! Packets dropped!\n"); diff --git a/drivers/staging/rtl8723bs/os_dep/recv_linux.c b/drivers/staging/rtl8723bs/os_dep/recv_linux.c index 1a6443dc3ff0..f42e00081e0e 100644 --- a/drivers/staging/rtl8723bs/os_dep/recv_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/recv_linux.c @@ -72,7 +72,6 @@ int rtw_os_recvbuf_resource_free(struct adapter *padapter, struct recv_buf *prec _pkt *rtw_os_alloc_msdu_pkt(union recv_frame *prframe, u16 nSubframe_Length, u8 *pdata) { u16 eth_type; - u8 *data_ptr; _pkt *sub_skb; struct rx_pkt_attrib *pattrib; @@ -82,8 +81,7 @@ _pkt *rtw_os_alloc_msdu_pkt(union recv_frame *prframe, u16 nSubframe_Length, u8 if (sub_skb) { skb_reserve(sub_skb, 12); - data_ptr = skb_put_data(sub_skb, (pdata + ETH_HLEN), - nSubframe_Length); + skb_put_data(sub_skb, (pdata + ETH_HLEN), nSubframe_Length); } else { diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 1de67f209f2c..83ea8ab4f2f4 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -3530,7 +3530,7 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, /* Copy the 802.11 header to the skb * (ctl frames may be less than a full header) */ - datap = skb_put_data(skb, &rxdesc->frame_control, hdrlen); + skb_put_data(skb, &rxdesc->frame_control, hdrlen); /* If any, copy the data from the card to the skb */ if (datalen > 0) { diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c b/drivers/target/iscsi/cxgbit/cxgbit_cm.c index 15cd1e33b16b..e583dd8a418b 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c @@ -1085,8 +1085,7 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req) return; } - rpl5 = __skb_put(skb, len); - memset(rpl5, 0, len); + rpl5 = __skb_put_zero(skb, len); INIT_TP_WR(rpl5, csk->tid); OPCODE_TID(rpl5) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, @@ -1367,8 +1366,7 @@ u32 cxgbit_send_tx_flowc_wr(struct cxgbit_sock *csk) flowclen16 = cxgbit_tx_flowc_wr_credits(csk, &nparams, &flowclen); skb = __skb_dequeue(&csk->skbq); - flowc = __skb_put(skb, flowclen); - memset(flowc, 0, flowclen); + flowc = __skb_put_zero(skb, flowclen); flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS_V(nparams)); @@ -1439,8 +1437,7 @@ int cxgbit_setup_conn_digest(struct cxgbit_sock *csk) return -ENOMEM; /* set up ulp submode */ - req = __skb_put(skb, len); - memset(req, 0, len); + req = __skb_put_zero(skb, len); INIT_TP_WR(req, csk->tid); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid)); @@ -1476,8 +1473,7 @@ int cxgbit_setup_conn_pgidx(struct cxgbit_sock *csk, u32 pg_idx) if (!skb) return -ENOMEM; - req = __skb_put(skb, len); - memset(req, 0, len); + req = __skb_put_zero(skb, len); INIT_TP_WR(req, csk->tid); OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid)); diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index a9c28c72c1c7..24e34cfcb4bd 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1004,16 +1004,15 @@ static struct sk_buff *package_for_tx(struct f_ncm *ncm) } /* Insert NDP alignment. */ - ntb_iter = skb_put_zero(skb2, ndp_pad); + skb_put_zero(skb2, ndp_pad); /* Copy NTB across. */ - ntb_iter = skb_put_data(skb2, ncm->skb_tx_ndp->data, - ncm->skb_tx_ndp->len); + skb_put_data(skb2, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len); dev_consume_skb_any(ncm->skb_tx_ndp); ncm->skb_tx_ndp = NULL; /* Insert zero'd datagram. */ - ntb_iter = skb_put_zero(skb2, dgram_idx_len); + skb_put_zero(skb2, dgram_idx_len); return skb2; } @@ -1127,8 +1126,8 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port, ncm->ndp_dgram_count++; /* Add the new data to the skb */ - ntb_data = skb_put_zero(ncm->skb_tx_data, dgram_pad); - ntb_data = skb_put_data(ncm->skb_tx_data, skb->data, skb->len); + skb_put_zero(ncm->skb_tx_data, dgram_pad); + skb_put_data(ncm->skb_tx_data, skb->data, skb->len); dev_consume_skb_any(skb); skb = NULL; diff --git a/include/linux/qed/qed_chain.h b/include/linux/qed/qed_chain.h index 5cd7a4608c9b..59ddf9af909e 100644 --- a/include/linux/qed/qed_chain.h +++ b/include/linux/qed/qed_chain.h @@ -80,6 +80,11 @@ struct qed_chain_pbl_u32 { u32 cons_page_idx; }; +struct qed_chain_ext_pbl { + dma_addr_t p_pbl_phys; + void *p_pbl_virt; +}; + struct qed_chain_u16 { /* Cyclic index of next element to produce/consme */ u16 prod_idx; @@ -155,6 +160,8 @@ struct qed_chain { u32 size; u8 intended_use; + + bool b_external_pbl; }; #define QED_CHAIN_PBL_ENTRY_SIZE (8) diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 74f6b99754aa..ef39c7f40ae6 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -634,7 +634,8 @@ struct qed_common_ops { enum qed_chain_cnt_type cnt_type, u32 num_elems, size_t elem_size, - struct qed_chain *p_chain); + struct qed_chain *p_chain, + struct qed_chain_ext_pbl *ext_pbl); void (*chain_free)(struct qed_dev *cdev, struct qed_chain *p_chain); diff --git a/include/linux/qed/qede_roce.h b/include/linux/qed/qede_rdma.h index 3b8dd551a98c..1348a16e5e4b 100644 --- a/include/linux/qed/qede_roce.h +++ b/include/linux/qed/qede_rdma.h @@ -32,22 +32,27 @@ #ifndef QEDE_ROCE_H #define QEDE_ROCE_H +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/types.h> +#include <linux/workqueue.h> + struct qedr_dev; struct qed_dev; struct qede_dev; -enum qede_roce_event { +enum qede_rdma_event { QEDE_UP, QEDE_DOWN, QEDE_CHANGE_ADDR, QEDE_CLOSE }; -struct qede_roce_event_work { +struct qede_rdma_event_work { struct list_head list; struct work_struct work; void *ptr; - enum qede_roce_event event; + enum qede_rdma_event event; }; struct qedr_driver { @@ -57,32 +62,33 @@ struct qedr_driver { struct net_device *); void (*remove)(struct qedr_dev *); - void (*notify)(struct qedr_dev *, enum qede_roce_event); + void (*notify)(struct qedr_dev *, enum qede_rdma_event); }; -/* APIs for RoCE driver to register callback handlers, +/* APIs for RDMA driver to register callback handlers, * which will be invoked when device is added, removed, ifup, ifdown */ -int qede_roce_register_driver(struct qedr_driver *drv); -void qede_roce_unregister_driver(struct qedr_driver *drv); +int qede_rdma_register_driver(struct qedr_driver *drv); +void qede_rdma_unregister_driver(struct qedr_driver *drv); -bool qede_roce_supported(struct qede_dev *dev); +bool qede_rdma_supported(struct qede_dev *dev); #if IS_ENABLED(CONFIG_QED_RDMA) -int qede_roce_dev_add(struct qede_dev *dev); -void qede_roce_dev_event_open(struct qede_dev *dev); -void qede_roce_dev_event_close(struct qede_dev *dev); -void qede_roce_dev_remove(struct qede_dev *dev); -void qede_roce_event_changeaddr(struct qede_dev *qedr); +int qede_rdma_dev_add(struct qede_dev *dev); +void qede_rdma_dev_event_open(struct qede_dev *dev); +void qede_rdma_dev_event_close(struct qede_dev *dev); +void qede_rdma_dev_remove(struct qede_dev *dev); +void qede_rdma_event_changeaddr(struct qede_dev *edr); + #else -static inline int qede_roce_dev_add(struct qede_dev *dev) +static inline int qede_rdma_dev_add(struct qede_dev *dev); { return 0; } -static inline void qede_roce_dev_event_open(struct qede_dev *dev) {} -static inline void qede_roce_dev_event_close(struct qede_dev *dev) {} -static inline void qede_roce_dev_remove(struct qede_dev *dev) {} -static inline void qede_roce_event_changeaddr(struct qede_dev *qedr) {} +static inline void qede_rdma_dev_event_open(struct qede_dev *dev) {} +static inline void qede_rdma_dev_event_close(struct qede_dev *dev) {} +static inline void qede_rdma_dev_remove(struct qede_dev *dev) {} +static inline void qede_rdma_event_changeaddr(struct qede_dev *edr) {} #endif #endif diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 852feacf4bbf..a17e235639ae 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1904,6 +1904,28 @@ static inline void *__skb_put(struct sk_buff *skb, unsigned int len) return tmp; } +static inline void *__skb_put_zero(struct sk_buff *skb, unsigned int len) +{ + void *tmp = __skb_put(skb, len); + + memset(tmp, 0, len); + return tmp; +} + +static inline void *__skb_put_data(struct sk_buff *skb, const void *data, + unsigned int len) +{ + void *tmp = __skb_put(skb, len); + + memcpy(tmp, data, len); + return tmp; +} + +static inline void __skb_put_u8(struct sk_buff *skb, u8 val) +{ + *(u8 *)__skb_put(skb, 1) = val; +} + static inline void *skb_put_zero(struct sk_buff *skb, unsigned int len) { void *tmp = skb_put(skb, len); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 5051317162df..e26763bfabd6 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1953,8 +1953,8 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *, const union sctp_addr *, const union sctp_addr *); void sctp_assoc_migrate(struct sctp_association *, struct sock *); -void sctp_assoc_update(struct sctp_association *old, - struct sctp_association *new); +int sctp_assoc_update(struct sctp_association *old, + struct sctp_association *new); __u32 sctp_association_get_next_tsn(struct sctp_association *); diff --git a/include/net/tcp.h b/include/net/tcp.h index e17ec286e8df..d0751b79d99c 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1441,6 +1441,7 @@ struct tcp_md5sig_key { u8 keylen; u8 family; /* AF_INET or AF_INET6 */ union tcp_md5_addr addr; + u8 prefixlen; u8 key[TCP_MD5SIG_MAXKEYLEN]; struct rcu_head rcu; }; @@ -1484,9 +1485,10 @@ struct tcp_md5sig_pool { int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, const struct sock *sk, const struct sk_buff *skb); int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, - int family, const u8 *newkey, u8 newkeylen, gfp_t gfp); + int family, u8 prefixlen, const u8 *newkey, u8 newkeylen, + gfp_t gfp); int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, - int family); + int family, u8 prefixlen); struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, const struct sock *addr_sk); @@ -1846,6 +1848,7 @@ struct tcp_sock_af_ops { const struct sock *sk, const struct sk_buff *skb); int (*md5_parse)(struct sock *sk, + int optname, char __user *optval, int optlen); #endif diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 49a59202f85e..b816a0a6686e 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -232,7 +232,6 @@ struct vxlan_dev { struct net_device *dev; struct net *net; /* netns for packet i/o */ struct vxlan_rdst default_dst; /* default destination */ - u32 flags; /* VXLAN_F_* in vxlan.h */ struct timer_list age_timer; spinlock_t hash_lock; @@ -259,6 +258,7 @@ struct vxlan_dev { #define VXLAN_F_REMCSUM_NOPARTIAL 0x1000 #define VXLAN_F_COLLECT_METADATA 0x2000 #define VXLAN_F_GPE 0x4000 +#define VXLAN_F_IPV6_LINKLOCAL 0x8000 /* Flags that are used in the receive path. These flags must match in * order for a socket to be shareable @@ -273,6 +273,7 @@ struct vxlan_dev { /* Flags that can be set together with VXLAN_F_GPE. */ #define VXLAN_F_ALLOWED_GPE (VXLAN_F_GPE | \ VXLAN_F_IPV6 | \ + VXLAN_F_IPV6_LINKLOCAL | \ VXLAN_F_UDP_ZERO_CSUM_TX | \ VXLAN_F_UDP_ZERO_CSUM6_TX | \ VXLAN_F_UDP_ZERO_CSUM6_RX | \ diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 8204dcebc6f3..a5507c977497 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -117,7 +117,8 @@ enum { #define TCP_SAVED_SYN 28 /* Get SYN headers recorded for connection */ #define TCP_REPAIR_WINDOW 29 /* Get/set window parameters */ #define TCP_FASTOPEN_CONNECT 30 /* Attempt FastOpen with connect */ -#define TCP_ULP 31 /* Attach a ULP to a TCP connection */ +#define TCP_ULP 31 /* Attach a ULP to a TCP connection */ +#define TCP_MD5SIG_EXT 32 /* TCP MD5 Signature with extensions */ struct tcp_repair_opt { __u32 opt_code; @@ -235,11 +236,15 @@ enum { /* for TCP_MD5SIG socket option */ #define TCP_MD5SIG_MAXKEYLEN 80 +/* tcp_md5sig extension flags for TCP_MD5SIG_EXT */ +#define TCP_MD5SIG_FLAG_PREFIX 1 /* address prefix length */ + struct tcp_md5sig { struct __kernel_sockaddr_storage tcpm_addr; /* address associated */ - __u16 __tcpm_pad1; /* zero */ + __u8 tcpm_flags; /* extension flags */ + __u8 tcpm_prefixlen; /* address prefix */ __u16 tcpm_keylen; /* key length */ - __u32 __tcpm_pad2; /* zero */ + __u32 __tcpm_pad; /* zero */ __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ }; diff --git a/lib/nlattr.c b/lib/nlattr.c index a0c738aa6a79..fb52435be42d 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -398,11 +398,7 @@ EXPORT_SYMBOL(__nla_reserve_64bit); */ void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen) { - void *start; - - start = skb_put_zero(skb, NLA_ALIGN(attrlen)); - - return start; + return skb_put_zero(skb, NLA_ALIGN(attrlen)); } EXPORT_SYMBOL(__nla_reserve_nohdr); diff --git a/lib/test_bpf.c b/lib/test_bpf.c index c871e0e76c2a..d9d5a410955c 100644 --- a/lib/test_bpf.c +++ b/lib/test_bpf.c @@ -5717,7 +5717,7 @@ static struct sk_buff *populate_skb(char *buf, int size) if (!skb) return NULL; - memcpy(__skb_put(skb, size), buf, size); + __skb_put_data(skb, buf, size); /* Initialize a fake skb with test pattern. */ skb_reset_mac_header(skb); diff --git a/net/802/garp.c b/net/802/garp.c index a9a266569293..2dac647ff420 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -232,7 +232,7 @@ static int garp_pdu_append_end_mark(struct garp_applicant *app) { if (skb_tailroom(app->pdu) < sizeof(u8)) return -1; - *(u8 *)__skb_put(app->pdu, sizeof(u8)) = GARP_END_MARK; + __skb_put_u8(app->pdu, GARP_END_MARK); return 0; } diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index fbf251fef70f..9a40013da915 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -374,25 +374,22 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) /* Decompress header and construct ether frame */ switch (type & BNEP_TYPE_MASK) { case BNEP_COMPRESSED: - memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN); + __skb_put_data(nskb, &s->eh, ETH_HLEN); break; case BNEP_COMPRESSED_SRC_ONLY: - memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN); - memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), ETH_ALEN); + __skb_put_data(nskb, s->eh.h_dest, ETH_ALEN); + __skb_put_data(nskb, skb_mac_header(skb), ETH_ALEN); put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); break; case BNEP_COMPRESSED_DST_ONLY: - memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), - ETH_ALEN); - memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, - ETH_ALEN + 2); + __skb_put_data(nskb, skb_mac_header(skb), ETH_ALEN); + __skb_put_data(nskb, s->eh.h_source, ETH_ALEN + 2); break; case BNEP_GENERAL: - memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb), - ETH_ALEN * 2); + __skb_put_data(nskb, skb_mac_header(skb), ETH_ALEN * 2); put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); break; } diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 2b875edf77e1..1d4d7d415730 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -75,16 +75,16 @@ static void bnep_net_set_mc_list(struct net_device *dev) u8 start[ETH_ALEN] = { 0x01 }; /* Request all addresses */ - memcpy(__skb_put(skb, ETH_ALEN), start, ETH_ALEN); - memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); + __skb_put_data(skb, start, ETH_ALEN); + __skb_put_data(skb, dev->broadcast, ETH_ALEN); r->len = htons(ETH_ALEN * 2); } else { struct netdev_hw_addr *ha; int i, len = skb->len; if (dev->flags & IFF_BROADCAST) { - memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); - memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); + __skb_put_data(skb, dev->broadcast, ETH_ALEN); + __skb_put_data(skb, dev->broadcast, ETH_ALEN); } /* FIXME: We should group addresses here. */ @@ -93,8 +93,8 @@ static void bnep_net_set_mc_list(struct net_device *dev) netdev_for_each_mc_addr(ha, dev) { if (i == BNEP_MAX_MULTICAST_FILTERS) break; - memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); - memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN); + __skb_put_data(skb, ha->addr, ETH_ALEN); + __skb_put_data(skb, ha->addr, ETH_ALEN); i++; } diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 5881fbc114a9..1b75d6bf12bd 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -50,7 +50,7 @@ static void br_send_bpdu(struct net_bridge_port *p, skb->priority = TC_PRIO_CONTROL; skb_reserve(skb, LLC_RESERVE); - memcpy(__skb_put(skb, length), data, length); + __skb_put_data(skb, data, length); llc_pdu_header_init(skb, LLC_PDU_TYPE_U, LLC_SAP_BSPAN, LLC_SAP_BSPAN, LLC_PDU_CMD); diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index a05775afa44b..eaf05de37f75 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c @@ -107,7 +107,6 @@ static void nft_reject_br_send_v4_unreach(struct net *net, struct iphdr *niph; struct icmphdr *icmph; unsigned int len; - void *payload; __wsum csum; u8 proto; @@ -151,7 +150,7 @@ static void nft_reject_br_send_v4_unreach(struct net *net, icmph->type = ICMP_DEST_UNREACH; icmph->code = code; - payload = skb_put_data(nskb, skb_network_header(oldskb), len); + skb_put_data(nskb, skb_network_header(oldskb), len); csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0); icmph->checksum = csum_fold(csum); @@ -247,7 +246,6 @@ static void nft_reject_br_send_v6_unreach(struct net *net, struct ipv6hdr *nip6h; struct icmp6hdr *icmp6h; unsigned int len; - void *payload; if (!nft_bridge_ip6hdr_validate(oldskb)) return; @@ -277,7 +275,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net, icmp6h->icmp6_type = ICMPV6_DEST_UNREACH; icmp6h->icmp6_code = code; - payload = skb_put_data(nskb, skb_network_header(oldskb), len); + skb_put_data(nskb, skb_network_header(oldskb), len); nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr)); icmp6h->icmp6_cksum = diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index f75482bdee9a..f85d901f4e3f 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1033,33 +1033,34 @@ static int __init dccp_v4_init(void) { int err = proto_register(&dccp_v4_prot, 1); - if (err != 0) + if (err) goto out; - err = inet_add_protocol(&dccp_v4_protocol, IPPROTO_DCCP); - if (err != 0) - goto out_proto_unregister; - inet_register_protosw(&dccp_v4_protosw); err = register_pernet_subsys(&dccp_v4_ops); if (err) goto out_destroy_ctl_sock; + + err = inet_add_protocol(&dccp_v4_protocol, IPPROTO_DCCP); + if (err) + goto out_proto_unregister; + out: return err; +out_proto_unregister: + unregister_pernet_subsys(&dccp_v4_ops); out_destroy_ctl_sock: inet_unregister_protosw(&dccp_v4_protosw); - inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); -out_proto_unregister: proto_unregister(&dccp_v4_prot); goto out; } static void __exit dccp_v4_exit(void) { + inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); unregister_pernet_subsys(&dccp_v4_ops); inet_unregister_protosw(&dccp_v4_protosw); - inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP); proto_unregister(&dccp_v4_prot); } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 992621172220..4fccc0c37fbd 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1098,33 +1098,33 @@ static int __init dccp_v6_init(void) { int err = proto_register(&dccp_v6_prot, 1); - if (err != 0) + if (err) goto out; - err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP); - if (err != 0) - goto out_unregister_proto; - inet6_register_protosw(&dccp_v6_protosw); err = register_pernet_subsys(&dccp_v6_ops); - if (err != 0) + if (err) goto out_destroy_ctl_sock; + + err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP); + if (err) + goto out_unregister_proto; + out: return err; - +out_unregister_proto: + unregister_pernet_subsys(&dccp_v6_ops); out_destroy_ctl_sock: - inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); inet6_unregister_protosw(&dccp_v6_protosw); -out_unregister_proto: proto_unregister(&dccp_v6_prot); goto out; } static void __exit dccp_v6_exit(void) { - unregister_pernet_subsys(&dccp_v6_ops); inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP); + unregister_pernet_subsys(&dccp_v6_ops); inet6_unregister_protosw(&dccp_v6_protosw); proto_unregister(&dccp_v6_prot); } diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index 172f13167896..b09e56214005 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -43,8 +43,7 @@ static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev) kfree_skb(skb); if (padlen) { - u8 *pad = skb_put(nskb, padlen); - memset(pad, 0, padlen); + skb_put_zero(nskb, padlen); } trailer = skb_put(nskb, 4); diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 0a0a392dc2bd..4e7bdb213cd0 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -284,12 +284,12 @@ static void send_hsr_supervision_frame(struct hsr_port *master, skb_reset_mac_header(skb); if (hsrVer > 0) { - hsr_tag = (typeof(hsr_tag)) skb_put(skb, sizeof(struct hsr_tag)); + hsr_tag = skb_put(skb, sizeof(struct hsr_tag)); hsr_tag->encap_proto = htons(ETH_P_PRP); set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE); } - hsr_stag = (typeof(hsr_stag)) skb_put(skb, sizeof(struct hsr_sup_tag)); + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); set_hsr_stag_path(hsr_stag, (hsrVer ? 0x0 : 0xf)); set_hsr_stag_HSR_Ver(hsr_stag, hsrVer); @@ -311,7 +311,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master, hsr_stag->HSR_TLV_Length = hsrVer ? sizeof(struct hsr_sup_payload) : 12; /* Payload: MacAddressA */ - hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(struct hsr_sup_payload)); + hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); ether_addr_copy(hsr_sp->MacAddressA, master->dev->dev_addr); skb_put_padto(skb, ETH_ZLEN + HSR_HLEN); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 11e4ee281aa0..058f509ca98e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2714,8 +2714,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level, #ifdef CONFIG_TCP_MD5SIG case TCP_MD5SIG: + case TCP_MD5SIG_EXT: /* Read the IP->Key mappings from userspace */ - err = tp->af_specific->md5_parse(sk, optval, optlen); + err = tp->af_specific->md5_parse(sk, optname, optval, optlen); break; #endif case TCP_USER_TIMEOUT: diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index eec2ff907279..bf407f3e20dd 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -80,6 +80,7 @@ #include <linux/stddef.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/inetdevice.h> #include <crypto/hash.h> #include <linux/scatterlist.h> @@ -908,6 +909,9 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk, struct tcp_md5sig_key *key; unsigned int size = sizeof(struct in_addr); const struct tcp_md5sig_info *md5sig; + __be32 mask; + struct tcp_md5sig_key *best_match = NULL; + bool match; /* caller either holds rcu_read_lock() or socket lock */ md5sig = rcu_dereference_check(tp->md5sig_info, @@ -921,12 +925,55 @@ struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk, hlist_for_each_entry_rcu(key, &md5sig->head, node) { if (key->family != family) continue; - if (!memcmp(&key->addr, addr, size)) + + if (family == AF_INET) { + mask = inet_make_mask(key->prefixlen); + match = (key->addr.a4.s_addr & mask) == + (addr->a4.s_addr & mask); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + match = ipv6_prefix_equal(&key->addr.a6, &addr->a6, + key->prefixlen); +#endif + } else { + match = false; + } + + if (match && (!best_match || + key->prefixlen > best_match->prefixlen)) + best_match = key; + } + return best_match; +} +EXPORT_SYMBOL(tcp_md5_do_lookup); + +struct tcp_md5sig_key *tcp_md5_do_lookup_exact(const struct sock *sk, + const union tcp_md5_addr *addr, + int family, u8 prefixlen) +{ + const struct tcp_sock *tp = tcp_sk(sk); + struct tcp_md5sig_key *key; + unsigned int size = sizeof(struct in_addr); + const struct tcp_md5sig_info *md5sig; + + /* caller either holds rcu_read_lock() or socket lock */ + md5sig = rcu_dereference_check(tp->md5sig_info, + lockdep_sock_is_held(sk)); + if (!md5sig) + return NULL; +#if IS_ENABLED(CONFIG_IPV6) + if (family == AF_INET6) + size = sizeof(struct in6_addr); +#endif + hlist_for_each_entry_rcu(key, &md5sig->head, node) { + if (key->family != family) + continue; + if (!memcmp(&key->addr, addr, size) && + key->prefixlen == prefixlen) return key; } return NULL; } -EXPORT_SYMBOL(tcp_md5_do_lookup); struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, const struct sock *addr_sk) @@ -940,14 +987,15 @@ EXPORT_SYMBOL(tcp_v4_md5_lookup); /* This can be called on a newly created socket, from other files */ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, - int family, const u8 *newkey, u8 newkeylen, gfp_t gfp) + int family, u8 prefixlen, const u8 *newkey, u8 newkeylen, + gfp_t gfp) { /* Add Key to the list */ struct tcp_md5sig_key *key; struct tcp_sock *tp = tcp_sk(sk); struct tcp_md5sig_info *md5sig; - key = tcp_md5_do_lookup(sk, addr, family); + key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen); if (key) { /* Pre-existing entry - just update that one. */ memcpy(key->key, newkey, newkeylen); @@ -978,6 +1026,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, memcpy(key->key, newkey, newkeylen); key->keylen = newkeylen; key->family = family; + key->prefixlen = prefixlen; memcpy(&key->addr, addr, (family == AF_INET6) ? sizeof(struct in6_addr) : sizeof(struct in_addr)); @@ -986,11 +1035,12 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, } EXPORT_SYMBOL(tcp_md5_do_add); -int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) +int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family, + u8 prefixlen) { struct tcp_md5sig_key *key; - key = tcp_md5_do_lookup(sk, addr, family); + key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen); if (!key) return -ENOENT; hlist_del_rcu(&key->node); @@ -1016,11 +1066,12 @@ static void tcp_clear_md5_list(struct sock *sk) } } -static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, - int optlen) +static int tcp_v4_parse_md5_keys(struct sock *sk, int optname, + char __user *optval, int optlen) { struct tcp_md5sig cmd; struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; + u8 prefixlen = 32; if (optlen < sizeof(cmd)) return -EINVAL; @@ -1031,15 +1082,22 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, if (sin->sin_family != AF_INET) return -EINVAL; + if (optname == TCP_MD5SIG_EXT && + cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) { + prefixlen = cmd.tcpm_prefixlen; + if (prefixlen > 32) + return -EINVAL; + } + if (!cmd.tcpm_keylen) return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, - AF_INET); + AF_INET, prefixlen); if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) return -EINVAL; return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, - AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, + AF_INET, prefixlen, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); } @@ -1342,7 +1400,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, * across. Shucks. */ tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr, - AF_INET, key->key, key->keylen, GFP_ATOMIC); + AF_INET, 32, key->key, key->keylen, GFP_ATOMIC); sk_nocaps_add(newsk, NETIF_F_GSO_MASK); } #endif diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6264917fe4c7..68dc7472b44d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -515,11 +515,12 @@ static struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk, return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr); } -static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval, - int optlen) +static int tcp_v6_parse_md5_keys(struct sock *sk, int optname, + char __user *optval, int optlen) { struct tcp_md5sig cmd; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; + u8 prefixlen; if (optlen < sizeof(cmd)) return -EINVAL; @@ -530,12 +531,22 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval, if (sin6->sin6_family != AF_INET6) return -EINVAL; + if (optname == TCP_MD5SIG_EXT && + cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) { + prefixlen = cmd.tcpm_prefixlen; + if (prefixlen > 128 || (ipv6_addr_v4mapped(&sin6->sin6_addr) && + prefixlen > 32)) + return -EINVAL; + } else { + prefixlen = ipv6_addr_v4mapped(&sin6->sin6_addr) ? 32 : 128; + } + if (!cmd.tcpm_keylen) { if (ipv6_addr_v4mapped(&sin6->sin6_addr)) return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3], - AF_INET); + AF_INET, prefixlen); return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr, - AF_INET6); + AF_INET6, prefixlen); } if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) @@ -543,10 +554,12 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval, if (ipv6_addr_v4mapped(&sin6->sin6_addr)) return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3], - AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); + AF_INET, prefixlen, cmd.tcpm_key, + cmd.tcpm_keylen, GFP_KERNEL); return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr, - AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); + AF_INET6, prefixlen, cmd.tcpm_key, + cmd.tcpm_keylen, GFP_KERNEL); } static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp, @@ -1186,7 +1199,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * * across. Shucks. */ tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr, - AF_INET6, key->key, key->keylen, + AF_INET6, 128, key->key, key->keylen, sk_gfp_mask(sk, GFP_ATOMIC)); } #endif diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 82e71e5622c2..debda3de4726 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -392,7 +392,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s, info[0] = discovery->data.charset; len = IRDA_MIN(discovery->name_len, skb_tailroom(tx_skb)); - info = skb_put_data(tx_skb, discovery->data.info, len); + skb_put_data(tx_skb, discovery->data.info, len); } irlap_queue_xmit(self, tx_skb); } @@ -1194,7 +1194,6 @@ void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr, { struct sk_buff *tx_skb; struct test_frame *frame; - __u8 *info; tx_skb = alloc_skb(cmd->len + sizeof(struct test_frame), GFP_ATOMIC); if (!tx_skb) @@ -1214,7 +1213,7 @@ void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr, frame->control = TEST_RSP | PF_BIT; /* Copy info */ - info = skb_put_data(tx_skb, cmd->data, cmd->len); + skb_put_data(tx_skb, cmd->data, cmd->len); /* Return to sender */ irlap_wait_min_turn_around(self, &self->qos_tx); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7be7917e1541..b588e593b0ec 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -796,8 +796,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) after_ric, ARRAY_SIZE(after_ric), offset); - pos = skb_put_data(skb, assoc_data->ie + offset, - noffset - offset); + skb_put_data(skb, assoc_data->ie + offset, noffset - offset); offset = noffset; } @@ -834,8 +833,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, before_vht, ARRAY_SIZE(before_vht), offset); - pos = skb_put_data(skb, assoc_data->ie + offset, - noffset - offset); + skb_put_data(skb, assoc_data->ie + offset, noffset - offset); offset = noffset; } @@ -848,8 +846,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) noffset = ieee80211_ie_split_vendor(assoc_data->ie, assoc_data->ie_len, offset); - pos = skb_put_data(skb, assoc_data->ie + offset, - noffset - offset); + skb_put_data(skb, assoc_data->ie + offset, noffset - offset); offset = noffset; } @@ -868,8 +865,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) /* add any remaining custom (i.e. vendor specific here) IEs */ if (assoc_data->ie_len) { noffset = assoc_data->ie_len; - pos = skb_put_data(skb, assoc_data->ie + offset, - noffset - offset); + skb_put_data(skb, assoc_data->ie + offset, noffset - offset); } if (assoc_data->fils_kek_len && diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index 709ef02fe67e..91093d4a2f84 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -388,7 +388,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, before_ext_cap, ARRAY_SIZE(before_ext_cap), offset); - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); offset = noffset; } @@ -417,7 +417,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, before_ht_cap, ARRAY_SIZE(before_ht_cap), offset); - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); offset = noffset; } @@ -488,7 +488,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, before_vht_cap, ARRAY_SIZE(before_vht_cap), offset); - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); offset = noffset; } @@ -529,7 +529,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, /* add any remaining IEs */ if (extra_ies_len) { noffset = extra_ies_len; - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); } } @@ -571,7 +571,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, before_qos, ARRAY_SIZE(before_qos), offset); - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); offset = noffset; } @@ -591,7 +591,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, before_ht_op, ARRAY_SIZE(before_ht_op), offset); - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); offset = noffset; } @@ -632,7 +632,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, /* add any remaining IEs */ if (extra_ies_len) { noffset = extra_ies_len; - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); } } @@ -645,7 +645,6 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata, { struct ieee80211_tdls_data *tf; size_t offset = 0, noffset; - u8 *pos; if (WARN_ON_ONCE(!chandef)) return; @@ -663,7 +662,7 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata, before_lnkie, ARRAY_SIZE(before_lnkie), offset); - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); offset = noffset; } @@ -672,7 +671,7 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata, /* add any remaining IEs */ if (extra_ies_len) { noffset = extra_ies_len; - pos = skb_put_data(skb, extra_ies + offset, noffset - offset); + skb_put_data(skb, extra_ies + offset, noffset - offset); } } diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 869acb3b3d3f..7e6301b2ec4d 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c @@ -40,14 +40,14 @@ static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb) if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, ntohs(dst_port))) return -EMSGSIZE; - if (vxlan->flags & VXLAN_F_GBP) { + if (vxlan->cfg.flags & VXLAN_F_GBP) { struct nlattr *exts; exts = nla_nest_start(skb, OVS_TUNNEL_ATTR_EXTENSION); if (!exts) return -EMSGSIZE; - if (vxlan->flags & VXLAN_F_GBP && + if (vxlan->cfg.flags & VXLAN_F_GBP && nla_put_flag(skb, OVS_VXLAN_EXT_GBP)) return -EMSGSIZE; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 72b07dd9b959..757be416f778 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1112,8 +1112,8 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk) } /* Update an association (possibly from unexpected COOKIE-ECHO processing). */ -void sctp_assoc_update(struct sctp_association *asoc, - struct sctp_association *new) +int sctp_assoc_update(struct sctp_association *asoc, + struct sctp_association *new) { struct sctp_transport *trans; struct list_head *pos, *temp; @@ -1124,8 +1124,10 @@ void sctp_assoc_update(struct sctp_association *asoc, asoc->peer.sack_needed = new->peer.sack_needed; asoc->peer.auth_capable = new->peer.auth_capable; asoc->peer.i = new->peer.i; - sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, - asoc->peer.i.initial_tsn, GFP_ATOMIC); + + if (!sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, + asoc->peer.i.initial_tsn, GFP_ATOMIC)) + return -ENOMEM; /* Remove any peer addresses not present in the new association. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { @@ -1169,11 +1171,11 @@ void sctp_assoc_update(struct sctp_association *asoc, } else { /* Add any peer addresses from the new association. */ list_for_each_entry(trans, &new->peer.transport_addr_list, - transports) { - if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) - sctp_assoc_add_peer(asoc, &trans->ipaddr, - GFP_ATOMIC, trans->state); - } + transports) + if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) && + !sctp_assoc_add_peer(asoc, &trans->ipaddr, + GFP_ATOMIC, trans->state)) + return -ENOMEM; asoc->ctsn_ack_point = asoc->next_tsn - 1; asoc->adv_peer_ack_point = asoc->ctsn_ack_point; @@ -1182,7 +1184,8 @@ void sctp_assoc_update(struct sctp_association *asoc, sctp_stream_update(&asoc->stream, &new->stream); /* get a new assoc id if we don't have one yet. */ - sctp_assoc_set_id(asoc, GFP_ATOMIC); + if (sctp_assoc_set_id(asoc, GFP_ATOMIC)) + return -ENOMEM; } /* SCTP-AUTH: Save the peer parameters from the new associations @@ -1200,7 +1203,7 @@ void sctp_assoc_update(struct sctp_association *asoc, asoc->peer.peer_hmacs = new->peer.peer_hmacs; new->peer.peer_hmacs = NULL; - sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); + return sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); } /* Update the retran path for sending a retransmitted packet. diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 2c196b3e9cd3..4b1967997c16 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1474,11 +1474,10 @@ void sctp_chunk_put(struct sctp_chunk *ch) void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) { void *target; - void *padding; int chunklen = ntohs(chunk->chunk_hdr->length); int padlen = SCTP_PAD4(chunklen) - chunklen; - padding = skb_put_zero(chunk->skb, padlen); + skb_put_zero(chunk->skb, padlen); target = skb_put_data(chunk->skb, data, len); /* Adjust the chunk length field. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 25384fa82ba9..dfe1fcb520ba 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -818,6 +818,28 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; } +static void sctp_cmd_assoc_update(sctp_cmd_seq_t *cmds, + struct sctp_association *asoc, + struct sctp_association *new) +{ + struct net *net = sock_net(asoc->base.sk); + struct sctp_chunk *abort; + + if (!sctp_assoc_update(asoc, new)) + return; + + abort = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t)); + if (abort) { + sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); + sctp_add_cmd_sf(cmds, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + } + sctp_add_cmd_sf(cmds, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); + sctp_add_cmd_sf(cmds, SCTP_CMD_ASSOC_FAILED, + SCTP_PERR(SCTP_ERROR_RSRC_LOW)); + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); +} + /* Helper function to change the state of an association. */ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, @@ -1294,7 +1316,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, break; case SCTP_CMD_UPDATE_ASSOC: - sctp_assoc_update(asoc, cmd->obj.asoc); + sctp_cmd_assoc_update(commands, asoc, cmd->obj.asoc); break; case SCTP_CMD_PURGE_OUTQUEUE: @@ -1748,6 +1770,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, break; case SCTP_CMD_SET_ASOC: + if (asoc && local_cork) { + sctp_outq_uncork(&asoc->outqueue, gfp); + local_cork = 0; + } asoc = cmd->obj.asoc; break; diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 7d6ee03f2762..edba7ab97563 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -90,7 +90,6 @@ out_pkt: static struct sk_buff *virtio_transport_build_skb(void *opaque) { struct virtio_vsock_pkt *pkt = opaque; - unsigned char *t_hdr, *payload; struct af_vsockmon_hdr *hdr; struct sk_buff *skb; @@ -132,10 +131,10 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) break; } - t_hdr = skb_put_data(skb, &pkt->hdr, sizeof(pkt->hdr)); + skb_put_data(skb, &pkt->hdr, sizeof(pkt->hdr)); if (pkt->len) { - payload = skb_put_data(skb, pkt->buf, pkt->len); + skb_put_data(skb, pkt->buf, pkt->len); } return skb; diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index eb466ece1730..db0b1315d577 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -188,14 +188,14 @@ void x25_write_internal(struct sock *sk, int frametype) *dptr++ = X25_CALL_REQUEST; len = x25_addr_aton(addresses, &x25->dest_addr, &x25->source_addr); - dptr = skb_put_data(skb, addresses, len); + skb_put_data(skb, addresses, len); len = x25_create_facilities(facilities, &x25->facilities, &x25->dte_facilities, x25->neighbour->global_facil_mask); - dptr = skb_put_data(skb, facilities, len); - dptr = skb_put_data(skb, x25->calluserdata.cuddata, - x25->calluserdata.cudlength); + skb_put_data(skb, facilities, len); + skb_put_data(skb, x25->calluserdata.cuddata, + x25->calluserdata.cudlength); x25->calluserdata.cudlength = 0; break; @@ -207,15 +207,15 @@ void x25_write_internal(struct sock *sk, int frametype) &x25->facilities, &x25->dte_facilities, x25->vc_facil_mask); - dptr = skb_put_data(skb, facilities, len); + skb_put_data(skb, facilities, len); /* fast select with no restriction on response allows call user data. Userland must ensure it is ours and not theirs */ if(x25->facilities.reverse & 0x80) { - dptr = skb_put_data(skb, - x25->calluserdata.cuddata, - x25->calluserdata.cudlength); + skb_put_data(skb, + x25->calluserdata.cuddata, + x25->calluserdata.cudlength); } x25->calluserdata.cudlength = 0; break; diff --git a/tools/testing/selftests/tc-testing/.gitignore b/tools/testing/selftests/tc-testing/.gitignore new file mode 100644 index 000000000000..c18dd8d83cee --- /dev/null +++ b/tools/testing/selftests/tc-testing/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/tools/testing/selftests/tc-testing/README b/tools/testing/selftests/tc-testing/README new file mode 100644 index 000000000000..970ff294fec8 --- /dev/null +++ b/tools/testing/selftests/tc-testing/README @@ -0,0 +1,102 @@ +tdc - Linux Traffic Control (tc) unit testing suite + +Author: Lucas Bates - lucasb@mojatatu.com + +tdc is a Python script to load tc unit tests from a separate JSON file and +execute them inside a network namespace dedicated to the task. + + +REQUIREMENTS +------------ + +* Minimum Python version of 3.4. Earlier 3.X versions may work but are not + guaranteed. + +* The kernel must have network namespace support + +* The kernel must have veth support available, as a veth pair is created + prior to running the tests. + +* All tc-related features must be built in or available as modules. + To check what is required in current setup run: + ./tdc.py -c + + Note: + In the current release, tdc run will abort due to a failure in setup or + teardown commands - which includes not being able to run a test simply + because the kernel did not support a specific feature. (This will be + handled in a future version - the current workaround is to run the tests + on specific test categories that your kernel supports) + + +BEFORE YOU RUN +-------------- + +The path to the tc executable that will be most commonly tested can be defined +in the tdc_config.py file. Find the 'TC' entry in the NAMES dictionary and +define the path. + +If you need to test a different tc executable on the fly, you can do so by +using the -p option when running tdc: + ./tdc.py -p /path/to/tc + + +RUNNING TDC +----------- + +To use tdc, root privileges are required. tdc will not run otherwise. + +All tests are executed inside a network namespace to prevent conflicts +within the host. + +Running tdc without any arguments will run all tests. Refer to the section +on command line arguments for more information, or run: + ./tdc.py -h + +tdc will list the test names as they are being run, and print a summary in +TAP (Test Anything Protocol) format when they are done. If tests fail, +output captured from the failing test will be printed immediately following +the failed test in the TAP output. + + +USER-DEFINED CONSTANTS +---------------------- + +The tdc_config.py file contains multiple values that can be altered to suit +your needs. Any value in the NAMES dictionary can be altered without affecting +the tests to be run. These values are used in the tc commands that will be +executed as part of the test. More will be added as test cases require. + +Example: + $TC qdisc add dev $DEV1 ingress + + +COMMAND LINE ARGUMENTS +---------------------- + +Run tdc.py -h to see the full list of available arguments. + +-p PATH Specify the tc executable located at PATH to be used on this + test run +-c Show the available test case categories in this test file +-c CATEGORY Run only tests that belong to CATEGORY +-f FILE Read test cases from the JSON file named FILE +-l [CATEGORY] List all test cases in the JSON file. If CATEGORY is + specified, list test cases matching that category. +-s ID Show the test case matching ID +-e ID Execute the test case identified by ID +-i Generate unique ID numbers for test cases with no existing + ID number + + +ACKNOWLEDGEMENTS +---------------- + +Thanks to: + +Jamal Hadi Salim, for providing valuable test cases +Keara Leibovitz, who wrote the CLI test driver that I used as a base for the + first version of the tc testing suite. This work was presented at + Netdev 1.2 Tokyo in October 2016. +Samir Hussain, for providing help while I dove into Python for the first time + and being a second eye for this code. diff --git a/tools/testing/selftests/tc-testing/TODO.txt b/tools/testing/selftests/tc-testing/TODO.txt new file mode 100644 index 000000000000..6a266d811a78 --- /dev/null +++ b/tools/testing/selftests/tc-testing/TODO.txt @@ -0,0 +1,10 @@ +tc Testing Suite To-Do list: + +- Determine what tc features are supported in the kernel. If features are not + present, prevent the related categories from running. + +- Add support for multiple versions of tc to run successively + +- Improve error messages when tdc aborts its run + +- Allow tdc to write its results to file diff --git a/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt new file mode 100644 index 000000000000..4e09257bc443 --- /dev/null +++ b/tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt @@ -0,0 +1,69 @@ +tdc - Adding test cases for tdc + +Author: Lucas Bates - lucasb@mojatatu.com + +ADDING TEST CASES +----------------- + +User-defined tests should be added by defining a separate JSON file. This +will help prevent conflicts when updating the repository. Refer to +template.json for the required JSON format for test cases. + +Include the 'id' field, but do not assign a value. Running tdc with the -i +option will generate a unique ID for that test case. + +tdc will recursively search the 'tc' subdirectory for .json files. Any +test case files you create in these directories will automatically be included. +If you wish to store your custom test cases elsewhere, be sure to run tdc +with the -f argument and the path to your file. + +Be aware of required escape characters in the JSON data - particularly when +defining the match pattern. Refer to the tctests.json file for examples when +in doubt. + + +TEST CASE STRUCTURE +------------------- + +Each test case has required data: + +id: A unique alphanumeric value to identify a particular test case +name: Descriptive name that explains the command under test +category: A list of single-word descriptions covering what the command + under test is testing. Example: filter, actions, u32, gact, etc. +setup: The list of commands required to ensure the command under test + succeeds. For example: if testing a filter, the command to create + the qdisc would appear here. +cmdUnderTest: The tc command being tested itself. +expExitCode: The code returned by the command under test upon its termination. + tdc will compare this value against the actual returned value. +verifyCmd: The tc command to be run to verify successful execution. + For example: if the command under test creates a gact action, + verifyCmd should be "$TC actions show action gact" +matchPattern: A regular expression to be applied against the output of the + verifyCmd to prove the command under test succeeded. This pattern + should be as specific as possible so that a false positive is not + matched. +matchCount: How many times the regex in matchPattern should match. A value + of 0 is acceptable. +teardown: The list of commands to clean up after the test is completed. + The environment should be returned to the same state as when + this test was started: qdiscs deleted, actions flushed, etc. + + +SETUP/TEARDOWN ERRORS +--------------------- + +If an error is detected during the setup/teardown process, execution of the +tests will immediately stop with an error message and the namespace in which +the tests are run will be destroyed. This is to prevent inaccurate results +in the test cases. + +Repeated failures of the setup/teardown may indicate a problem with the test +case, or possibly even a bug in one of the commands that are not being tested. + +It's possible to include acceptable exit codes with the setup/teardown command +so that it doesn't halt the script for an error that doesn't matter. Turn the +individual command into a list, with the command being first, followed by all +acceptable exit codes for the command. + diff --git a/tools/testing/selftests/tc-testing/creating-testcases/template.json b/tools/testing/selftests/tc-testing/creating-testcases/template.json new file mode 100644 index 000000000000..87971744bdd4 --- /dev/null +++ b/tools/testing/selftests/tc-testing/creating-testcases/template.json @@ -0,0 +1,40 @@ +[ + { + "id": "", + "name": "", + "category": [ + "", + "" + ], + "setup": [ + "" + ], + "cmdUnderTest": "", + "expExitCode": "", + "verifyCmd": "", + "matchPattern": "", + "matchCount": "", + "teardown": [ + "" + ] + }, + { + "id": "", + "name": "", + "category": [ + "", + "" + ], + "setup": [ + "" + ], + "cmdUnderTest": "", + "expExitCode": "", + "verifyCmd": "", + "matchPattern": "", + "matchCount": "", + "teardown": [ + "" + ] + } +] diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json new file mode 100644 index 000000000000..af519bc97a8e --- /dev/null +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/tests.json @@ -0,0 +1,1115 @@ +[ + { + "id": "e89a", + "name": "Add valid pass action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action pass index 8", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action pass.*index 8 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "a02c", + "name": "Add valid pipe action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action pipe index 6", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action pipe.*index 6 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "feef", + "name": "Add valid reclassify action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action reclassify index 5", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action reclassify.*index 5 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "8a7a", + "name": "Add valid drop action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action drop index 30", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action drop.*index 30 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "9a52", + "name": "Add valid continue action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action continue index 432", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action continue.*index 432 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "d700", + "name": "Add invalid action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action pump index 386", + "expExitCode": "255", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action.*index 386 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "9215", + "name": "Add action with duplicate index", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action pipe index 15" + ], + "cmdUnderTest": "$TC actions add action drop index 15", + "expExitCode": "255", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action drop.*index 15 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "798e", + "name": "Add action with index exceeding 32-bit maximum", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action drop index 4294967296", + "expExitCode": "255", + "verifyCmd": "actions list action gact", + "matchPattern": "action order [0-9]*: gact action drop.*index 4294967296 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "22be", + "name": "Add action with index at 32-bit maximum", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action drop index 4294967295", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action drop.*index 4294967295 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "ac2a", + "name": "List actions", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action reclassify index 101", + "$TC actions add action reclassify index 102", + "$TC actions add action reclassify index 103", + "$TC actions add action reclassify index 104", + "$TC actions add action reclassify index 105" + ], + "cmdUnderTest": "$TC actions list action gact", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action reclassify", + "matchCount": "5", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "63ec", + "name": "Delete pass action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action pass index 1" + ], + "cmdUnderTest": "$TC actions del action gact index 1", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action pass.*index 1 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "46be", + "name": "Delete pipe action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action pipe index 9" + ], + "cmdUnderTest": "$TC actions del action gact index 9", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action pipe.*index 9 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "2e08", + "name": "Delete reclassify action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action reclassify index 65536" + ], + "cmdUnderTest": "$TC actions del action gact index 65536", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action reclassify.*index 65536 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "99c4", + "name": "Delete drop action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action drop index 16" + ], + "cmdUnderTest": "$TC actions del action gact index 16", + "expExitCode": "0", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action drop.*index 16 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "fb6b", + "name": "Delete continue action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action continue index 32" + ], + "cmdUnderTest": "$TC actions del action gact index 32", + "expExitCode": "0", + "verifyCmd": "actions list action gact", + "matchPattern": "action order [0-9]*: gact action continue.*index 32 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "0eb3", + "name": "Delete non-existent action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions del action gact index 2", + "expExitCode": "255", + "verifyCmd": "$TC actions list action gact", + "matchPattern": "action order [0-9]*: gact action", + "matchCount": "0", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "5124", + "name": "Add mirred mirror to egress action", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action mirred egress mirror index 1 dev lo", + "expExitCode": "0", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 1 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "6fb4", + "name": "Add mirred redirect to egress action", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action mirred egress redirect index 2 dev lo action pipe", + "expExitCode": "0", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 2 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "ba38", + "name": "Get mirred actions", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ], + "$TC actions add action mirred egress mirror index 1 dev lo", + "$TC actions add action mirred egress redirect index 2 dev lo" + ], + "cmdUnderTest": "$TC actions show action mirred", + "expExitCode": "0", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "[Mirror|Redirect] to device lo", + "matchCount": "2", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "d7c0", + "name": "Add invalid mirred direction", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action mirred inbound mirror index 20 dev lo", + "expExitCode": "255", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 20 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "e213", + "name": "Add invalid mirred action", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action mirred egress remirror index 20 dev lo", + "expExitCode": "255", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(Egress.*to device lo\\).*index 20 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "2d89", + "name": "Add mirred action with invalid device", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action mirred egress mirror index 20 dev eltoh", + "expExitCode": "255", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(.*to device eltoh\\).*index 20 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "300b", + "name": "Add mirred action with duplicate index", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ], + "$TC actions add action mirred egress redirect index 15 dev lo" + ], + "cmdUnderTest": "$TC actions add action mirred egress mirror index 15 dev lo", + "expExitCode": "255", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 15 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "a70e", + "name": "Delete mirred mirror action", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ], + "$TC actions add action mirred egress mirror index 5 dev lo" + ], + "cmdUnderTest": "$TC actions del action mirred index 5", + "expExitCode": "0", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 5 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "3fb3", + "name": "Delete mirred redirect action", + "category": [ + "actions", + "mirred" + ], + "setup": [ + [ + "$TC actions flush action mirred", + 0, + 1, + 255 + ], + "$TC actions add action mirred egress redirect index 5 dev lo" + ], + "cmdUnderTest": "$TC actions del action mirred index 5", + "expExitCode": "0", + "verifyCmd": "$TC actions list action mirred", + "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 5 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action mirred" + ] + }, + { + "id": "b078", + "name": "Add simple action", + "category": [ + "actions", + "simple" + ], + "setup": [ + [ + "$TC actions flush action simple", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action simple sdata \"A triumph\" index 60", + "expExitCode": "0", + "verifyCmd": "$TC actions list action simple", + "matchPattern": "action order [0-9]*: Simple <A triumph>.*index 60 ref", + "matchCount": "1", + "teardown": [ + "$TC actions flush action simple" + ] + }, + { + "id": "6d4c", + "name": "Add simple action with duplicate index", + "category": [ + "actions", + "simple" + ], + "setup": [ + [ + "$TC actions flush action simple", + 0, + 1, + 255 + ], + "$TC actions add action simple sdata \"Aruba\" index 4" + ], + "cmdUnderTest": "$TC actions add action simple sdata \"Jamaica\" index 4", + "expExitCode": "255", + "verifyCmd": "$TC actions list action simple", + "matchPattern": "action order [0-9]*: Simple <Jamaica>.*ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action simple" + ] + }, + { + "id": "2542", + "name": "List simple actions", + "category": [ + "actions", + "simple" + ], + "setup": [ + [ + "$TC actions flush action simple", + 0, + 1, + 255 + ], + "$TC actions add action simple sdata \"Rock\"", + "$TC actions add action simple sdata \"Paper\"", + "$TC actions add action simple sdata \"Scissors\" index 98" + ], + "cmdUnderTest": "$TC actions list action simple", + "expExitCode": "0", + "verifyCmd": "$TC actions list action simple", + "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>", + "matchCount": "3", + "teardown": [ + "$TC actions flush action simple" + ] + }, + { + "id": "ea67", + "name": "Delete simple action", + "category": [ + "actions", + "simple" + ], + "setup": [ + [ + "$TC actions flush action simple", + 0, + 1, + 255 + ], + "$TC actions add action simple sdata \"Blinkenlights\" index 1" + ], + "cmdUnderTest": "$TC actions delete action simple index 1", + "expExitCode": "0", + "verifyCmd": "$TC actions list action simple", + "matchPattern": "action order [0-9]*: Simple <Blinkenlights>.*index 1 ref", + "matchCount": "0", + "teardown": [ + "$TC actions flush action simple" + ] + }, + { + "id": "8ff1", + "name": "Flush simple actions", + "category": [ + "actions", + "simple" + ], + "setup": [ + [ + "$TC actions flush action simple", + 0, + 1, + 255 + ], + "$TC actions add action simple sdata \"Kirk\"", + "$TC actions add action simple sdata \"Spock\" index 50", + "$TC actions add action simple sdata \"McCoy\" index 9" + ], + "cmdUnderTest": "$TC actions flush action simple", + "expExitCode": "0", + "verifyCmd": "$TC actions list action simple", + "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>", + "matchCount": "0", + "teardown": [ + "" + ] + }, + { + "id": "6236", + "name": "Add skbedit action with valid mark", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit mark 1", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit mark 1", + "matchCount": "1", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "407b", + "name": "Add skbedit action with invalid mark", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit mark 666777888999", + "expExitCode": "255", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit mark", + "matchCount": "0", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "081d", + "name": "Add skbedit action with priority", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit prio 99", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit priority :99", + "matchCount": "1", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "cc37", + "name": "Add skbedit action with invalid priority", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit prio foo", + "expExitCode": "255", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit priority", + "matchCount": "0", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "3c95", + "name": "Add skbedit action with queue_mapping", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit queue_mapping 909", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit queue_mapping 909", + "matchCount": "1", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "985c", + "name": "Add skbedit action with invalid queue_mapping", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit queue_mapping 67000", + "expExitCode": "255", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit queue_mapping", + "matchCount": "0", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "224f", + "name": "Add skbedit action with ptype host", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit ptype host", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit ptype host", + "matchCount": "1", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "d1a3", + "name": "Add skbedit action with ptype otherhost", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit ptype otherhost", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit ptype otherhost", + "matchCount": "1", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "b9c6", + "name": "Add skbedit action with invalid ptype", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit ptype openair", + "expExitCode": "255", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit ptype openair", + "matchCount": "0", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "5172", + "name": "List skbedit actions", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ], + "$TC actions add action skbedit ptype otherhost", + "$TC actions add action skbedit ptype broadcast", + "$TC actions add action skbedit mark 59", + "$TC actions add action skbedit mark 409" + ], + "cmdUnderTest": "$TC actions list action skbedit", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit", + "matchCount": "4", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "a6d6", + "name": "Add skbedit action with index", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ] + ], + "cmdUnderTest": "$TC actions add action skbedit mark 808 index 4040404040", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "index 4040404040", + "matchCount": "1", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "38f3", + "name": "Delete skbedit action", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + [ + "$TC actions flush action skbedit", + 0, + 1, + 255 + ], + "$TC actions add action skbedit mark 42 index 9009" + ], + "cmdUnderTest": "$TC actions del action skbedit index 9009", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit mark 42", + "matchCount": "0", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "ce97", + "name": "Flush skbedit actions", + "category": [ + "actions", + "skbedit" + ], + "setup": [ + "$TC actions add action skbedit mark 500", + "$TC actions add action skbedit mark 501", + "$TC actions add action skbedit mark 502", + "$TC actions add action skbedit mark 503", + "$TC actions add action skbedit mark 504", + "$TC actions add action skbedit mark 505", + "$TC actions add action skbedit mark 506" + ], + "cmdUnderTest": "$TC actions flush action skbedit", + "expExitCode": "0", + "verifyCmd": "$TC actions list action skbedit", + "matchPattern": "action order [0-9]*: skbedit", + "matchCount": "0", + "teardown": [ + "$TC actions flush action skbedit" + ] + }, + { + "id": "f02c", + "name": "Replace gact action", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action drop index 10", + "$TC actions add action drop index 12" + ], + "cmdUnderTest": "$TC actions replace action ok index 12", + "expExitCode": "0", + "verifyCmd": "$TC actions ls action gact", + "matchPattern": "action order [0-9]*: gact action pass", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + }, + { + "id": "525f", + "name": "Get gact action by index", + "category": [ + "actions", + "gact" + ], + "setup": [ + [ + "$TC actions flush action gact", + 0, + 1, + 255 + ], + "$TC actions add action drop index 3900800700" + ], + "cmdUnderTest": "$TC actions get action gact index 3900800700", + "expExitCode": "0", + "verifyCmd": "$TC actions get action gact index 3900800700", + "matchPattern": "index 3900800700", + "matchCount": "1", + "teardown": [ + "$TC actions flush action gact" + ] + } +]
\ No newline at end of file diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json new file mode 100644 index 000000000000..c727b96a59b0 --- /dev/null +++ b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json @@ -0,0 +1,21 @@ +[ + { + "id": "e9a3", + "name": "Add u32 with source match", + "category": [ + "filter", + "u32" + ], + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 parent ffff:", + "matchPattern": "match 7f000002/ffffffff at 12", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + } +]
\ No newline at end of file diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py new file mode 100755 index 000000000000..cd61b7844c0d --- /dev/null +++ b/tools/testing/selftests/tc-testing/tdc.py @@ -0,0 +1,413 @@ +#!/usr/bin/env python3 + +""" +tdc.py - Linux tc (Traffic Control) unit test driver + +Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> +""" + +import re +import os +import sys +import argparse +import json +import subprocess +from collections import OrderedDict +from string import Template + +from tdc_config import * +from tdc_helper import * + + +USE_NS = True + + +def replace_keywords(cmd): + """ + For a given executable command, substitute any known + variables contained within NAMES with the correct values + """ + tcmd = Template(cmd) + subcmd = tcmd.safe_substitute(NAMES) + return subcmd + + +def exec_cmd(command, nsonly=True): + """ + Perform any required modifications on an executable command, then run + it in a subprocess and return the results. + """ + if (USE_NS and nsonly): + command = 'ip netns exec $NS ' + command + + if '$' in command: + command = replace_keywords(command) + + proc = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (rawout, serr) = proc.communicate() + + if proc.returncode != 0: + foutput = serr.decode("utf-8") + else: + foutput = rawout.decode("utf-8") + + proc.stdout.close() + proc.stderr.close() + return proc, foutput + + +def prepare_env(cmdlist): + """ + Execute the setup/teardown commands for a test case. Optionally + terminate test execution if the command fails. + """ + for cmdinfo in cmdlist: + if (type(cmdinfo) == list): + exit_codes = cmdinfo[1:] + cmd = cmdinfo[0] + else: + exit_codes = [0] + cmd = cmdinfo + + if (len(cmd) == 0): + continue + + (proc, foutput) = exec_cmd(cmd) + + if proc.returncode not in exit_codes: + print + print("Could not execute:") + print(cmd) + print("\nError message:") + print(foutput) + print("\nAborting test run.") + ns_destroy() + exit(1) + + +def test_runner(filtered_tests): + """ + Driver function for the unit tests. + + Prints information about the tests being run, executes the setup and + teardown commands and the command under test itself. Also determines + success/failure based on the information in the test case and generates + TAP output accordingly. + """ + testlist = filtered_tests + tcount = len(testlist) + index = 1 + tap = str(index) + ".." + str(tcount) + "\n" + + for tidx in testlist: + result = True + tresult = "" + print("Test " + tidx["id"] + ": " + tidx["name"]) + prepare_env(tidx["setup"]) + (p, procout) = exec_cmd(tidx["cmdUnderTest"]) + exit_code = p.returncode + + if (exit_code != int(tidx["expExitCode"])): + result = False + print("exit:", exit_code, int(tidx["expExitCode"])) + print(procout) + else: + match_pattern = re.compile(str(tidx["matchPattern"]), re.DOTALL) + (p, procout) = exec_cmd(tidx["verifyCmd"]) + match_index = re.findall(match_pattern, procout) + if len(match_index) != int(tidx["matchCount"]): + result = False + + if result == True: + tresult += "ok " + else: + tresult += "not ok " + tap += tresult + str(index) + " " + tidx["id"] + " " + tidx["name"] + "\n" + + if result == False: + tap += procout + + prepare_env(tidx["teardown"]) + index += 1 + + return tap + + +def ns_create(): + """ + Create the network namespace in which the tests will be run and set up + the required network devices for it. + """ + if (USE_NS): + cmd = 'ip netns add $NS' + exec_cmd(cmd, False) + cmd = 'ip link add $DEV0 type veth peer name $DEV1' + exec_cmd(cmd, False) + cmd = 'ip link set $DEV1 netns $NS' + exec_cmd(cmd, False) + cmd = 'ip link set $DEV0 up' + exec_cmd(cmd, False) + cmd = 'ip -s $NS link set $DEV1 up' + exec_cmd(cmd, False) + + +def ns_destroy(): + """ + Destroy the network namespace for testing (and any associated network + devices as well) + """ + if (USE_NS): + cmd = 'ip netns delete $NS' + exec_cmd(cmd, False) + + +def has_blank_ids(idlist): + """ + Search the list for empty ID fields and return true/false accordingly. + """ + return not(all(k for k in idlist)) + + +def load_from_file(filename): + """ + Open the JSON file containing the test cases and return them as an + ordered dictionary object. + """ + with open(filename) as test_data: + testlist = json.load(test_data, object_pairs_hook=OrderedDict) + idlist = get_id_list(testlist) + if (has_blank_ids(idlist)): + for k in testlist: + k['filename'] = filename + return testlist + + +def args_parse(): + """ + Create the argument parser. + """ + parser = argparse.ArgumentParser(description='Linux TC unit tests') + return parser + + +def set_args(parser): + """ + Set the command line arguments for tdc. + """ + parser.add_argument('-p', '--path', type=str, + help='The full path to the tc executable to use') + parser.add_argument('-c', '--category', type=str, nargs='?', const='+c', + help='Run tests only from the specified category, or if no category is specified, list known categories.') + parser.add_argument('-f', '--file', type=str, + help='Run tests from the specified file') + parser.add_argument('-l', '--list', type=str, nargs='?', const="", metavar='CATEGORY', + help='List all test cases, or those only within the specified category') + parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID', + help='Display the test case with specified id') + parser.add_argument('-e', '--execute', type=str, nargs=1, metavar='ID', + help='Execute the single test case with specified ID') + parser.add_argument('-i', '--id', action='store_true', dest='gen_id', + help='Generate ID numbers for new test cases') + return parser + return parser + + +def check_default_settings(args): + """ + Process any arguments overriding the default settings, and ensure the + settings are correct. + """ + # Allow for overriding specific settings + global NAMES + + if args.path != None: + NAMES['TC'] = args.path + if not os.path.isfile(NAMES['TC']): + print("The specified tc path " + NAMES['TC'] + " does not exist.") + exit(1) + + +def get_id_list(alltests): + """ + Generate a list of all IDs in the test cases. + """ + return [x["id"] for x in alltests] + + +def check_case_id(alltests): + """ + Check for duplicate test case IDs. + """ + idl = get_id_list(alltests) + return [x for x in idl if idl.count(x) > 1] + + +def does_id_exist(alltests, newid): + """ + Check if a given ID already exists in the list of test cases. + """ + idl = get_id_list(alltests) + return (any(newid == x for x in idl)) + + +def generate_case_ids(alltests): + """ + If a test case has a blank ID field, generate a random hex ID for it + and then write the test cases back to disk. + """ + import random + for c in alltests: + if (c["id"] == ""): + while True: + newid = str('%04x' % random.randrange(16**4)) + if (does_id_exist(alltests, newid)): + continue + else: + c['id'] = newid + break + + ufilename = [] + for c in alltests: + if ('filename' in c): + ufilename.append(c['filename']) + ufilename = get_unique_item(ufilename) + for f in ufilename: + testlist = [] + for t in alltests: + if 'filename' in t: + if t['filename'] == f: + del t['filename'] + testlist.append(t) + outfile = open(f, "w") + json.dump(testlist, outfile, indent=4) + outfile.close() + + +def get_test_cases(args): + """ + If a test case file is specified, retrieve tests from that file. + Otherwise, glob for all json files in subdirectories and load from + each one. + """ + import fnmatch + if args.file != None: + if not os.path.isfile(args.file): + print("The specified test case file " + args.file + " does not exist.") + exit(1) + flist = [args.file] + else: + flist = [] + for root, dirnames, filenames in os.walk('tc-tests'): + for filename in fnmatch.filter(filenames, '*.json'): + flist.append(os.path.join(root, filename)) + alltests = list() + for casefile in flist: + alltests = alltests + (load_from_file(casefile)) + return alltests + + +def set_operation_mode(args): + """ + Load the test case data and process remaining arguments to determine + what the script should do for this run, and call the appropriate + function. + """ + alltests = get_test_cases(args) + + if args.gen_id: + idlist = get_id_list(alltests) + if (has_blank_ids(idlist)): + alltests = generate_case_ids(alltests) + else: + print("No empty ID fields found in test files.") + exit(0) + + duplicate_ids = check_case_id(alltests) + if (len(duplicate_ids) > 0): + print("The following test case IDs are not unique:") + print(str(set(duplicate_ids))) + print("Please correct them before continuing.") + exit(1) + + ucat = get_test_categories(alltests) + + if args.showID: + show_test_case_by_id(alltests, args.showID[0]) + exit(0) + + if args.execute: + target_id = args.execute[0] + else: + target_id = "" + + if args.category: + if (args.category == '+c'): + print("Available categories:") + print_sll(ucat) + exit(0) + else: + target_category = args.category + else: + target_category = "" + + + testcases = get_categorized_testlist(alltests, ucat) + + if args.list: + if (len(args.list) == 0): + list_test_cases(alltests) + exit(0) + elif(len(args.list > 0)): + if (args.list not in ucat): + print("Unknown category " + args.list) + print("Available categories:") + print_sll(ucat) + exit(1) + list_test_cases(testcases[args.list]) + exit(0) + + if (os.geteuid() != 0): + print("This script must be run with root privileges.\n") + exit(1) + + ns_create() + + if (len(target_category) == 0): + if (len(target_id) > 0): + alltests = list(filter(lambda x: target_id in x['id'], alltests)) + if (len(alltests) == 0): + print("Cannot find a test case with ID matching " + target_id) + exit(1) + catresults = test_runner(alltests) + print("All test results: " + "\n\n" + catresults) + elif (len(target_category) > 0): + if (target_category not in ucat): + print("Specified category is not present in this file.") + exit(1) + else: + catresults = test_runner(testcases[target_category]) + print("Category " + target_category + "\n\n" + catresults) + + ns_destroy() + + +def main(): + """ + Start of execution; set up argument parser and get the arguments, + and start operations. + """ + parser = args_parse() + parser = set_args(parser) + (args, remaining) = parser.parse_known_args() + check_default_settings(args) + + set_operation_mode(args) + + exit(0) + + +if __name__ == "__main__": + main() diff --git a/tools/testing/selftests/tc-testing/tdc_config.py b/tools/testing/selftests/tc-testing/tdc_config.py new file mode 100644 index 000000000000..01087375a7c3 --- /dev/null +++ b/tools/testing/selftests/tc-testing/tdc_config.py @@ -0,0 +1,17 @@ +""" +tdc_config.py - tdc user-specified values + +Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> +""" + +# Dictionary containing all values that can be substituted in executable +# commands. +NAMES = { + # Substitute your own tc path here + 'TC': '/sbin/tc', + # Name of veth devices to be created for the namespace + 'DEV0': 'v0p0', + 'DEV1': 'v0p1', + # Name of the namespace to use + 'NS': 'tcut' + } diff --git a/tools/testing/selftests/tc-testing/tdc_helper.py b/tools/testing/selftests/tc-testing/tdc_helper.py new file mode 100644 index 000000000000..c3254f861fb2 --- /dev/null +++ b/tools/testing/selftests/tc-testing/tdc_helper.py @@ -0,0 +1,75 @@ +""" +tdc_helper.py - tdc helper functions + +Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> +""" + +def get_categorized_testlist(alltests, ucat): + """ Sort the master test list into categories. """ + testcases = dict() + + for category in ucat: + testcases[category] = list(filter(lambda x: category in x['category'], alltests)) + + return(testcases) + + +def get_unique_item(lst): + """ For a list, return a set of the unique items in the list. """ + return list(set(lst)) + + +def get_test_categories(alltests): + """ Discover all unique test categories present in the test case file. """ + ucat = [] + for t in alltests: + ucat.extend(get_unique_item(t['category'])) + ucat = get_unique_item(ucat) + return ucat + +def list_test_cases(testlist): + """ Print IDs and names of all test cases. """ + for curcase in testlist: + print(curcase['id'] + ': (' + ', '.join(curcase['category']) + ") " + curcase['name']) + + +def list_categories(testlist): + """ Show all categories that are present in a test case file. """ + categories = set(map(lambda x: x['category'], testlist)) + print("Available categories:") + print(", ".join(str(s) for s in categories)) + print("") + + +def print_list(cmdlist): + """ Print a list of strings prepended with a tab. """ + for l in cmdlist: + if (type(l) == list): + print("\t" + str(l[0])) + else: + print("\t" + str(l)) + + +def print_sll(items): + print("\n".join(str(s) for s in items)) + + +def print_test_case(tcase): + """ Pretty-printing of a given test case. """ + for k in tcase.keys(): + if (type(tcase[k]) == list): + print(k + ":") + print_list(tcase[k]) + else: + print(k + ": " + tcase[k]) + + +def show_test_case_by_id(testlist, caseID): + """ Find the specified test case to pretty-print. """ + if not any(d.get('id', None) == caseID for d in testlist): + print("That ID does not exist.") + exit(1) + else: + print_test_case(next((d for d in testlist if d['id'] == caseID))) + + |