* [PATCH net-next 5/5] cnic: Update version to 2.5.18.
From: Michael Chan @ 2013-09-02 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1378147352-9076-5-git-send-email-mchan@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/ethernet/broadcom/cnic_if.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 95aff76..0658b43 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -14,8 +14,8 @@
#include "bnx2x/bnx2x_mfw_req.h"
-#define CNIC_MODULE_VERSION "2.5.17"
-#define CNIC_MODULE_RELDATE "July 28, 2013"
+#define CNIC_MODULE_VERSION "2.5.18"
+#define CNIC_MODULE_RELDATE "Sept 01, 2013"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 2/5] cnic: Redefine BNX2X_HW_CID using existing bnx2x macros
From: Michael Chan @ 2013-09-02 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1378147352-9076-2-git-send-email-mchan@broadcom.com>
to avoid duplication of the same logic.
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/ethernet/broadcom/cnic.c | 25 ++++++++++++++++---------
drivers/net/ethernet/broadcom/cnic.h | 5 ++---
2 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 3dadc81..750b9a6 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1384,6 +1384,7 @@ static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid,
u32 type, union l5cm_specific_data *l5_data)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct l5cm_spe kwqe;
struct kwqe_16 *kwq[1];
u16 type_16;
@@ -1391,7 +1392,7 @@ static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid,
kwqe.hdr.conn_and_cmd_data =
cpu_to_le32(((cmd << SPE_HDR_CMD_ID_SHIFT) |
- BNX2X_HW_CID(cp, cid)));
+ BNX2X_HW_CID(bp, cid)));
type_16 = (type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
type_16 |= (cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
@@ -1690,7 +1691,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
struct cnic_context *ctx = &cp->ctx_tbl[req1->iscsi_conn_id];
struct cnic_iscsi *iscsi = ctx->proto.iscsi;
u32 cid = ctx->cid;
- u32 hw_cid = BNX2X_HW_CID(cp, cid);
+ u32 hw_cid = BNX2X_HW_CID(bp, cid);
struct iscsi_context *ictx;
struct regpair context_addr;
int i, j, n = 2, n_max;
@@ -1870,6 +1871,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
struct iscsi_kwqe_conn_offload1 *req1;
struct iscsi_kwqe_conn_offload2 *req2;
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_context *ctx;
struct iscsi_kcqe kcqe;
struct kcqe *cqes[1];
@@ -1923,7 +1925,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
}
kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
- kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp, cp->ctx_tbl[l5_cid].cid);
+ kcqe.iscsi_conn_context_id = BNX2X_HW_CID(bp, cp->ctx_tbl[l5_cid].cid);
done:
cqes[0] = (struct kcqe *) &kcqe;
@@ -1959,6 +1961,7 @@ static int cnic_bnx2x_iscsi_update(struct cnic_dev *dev, struct kwqe *kwqe)
static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
union l5cm_specific_data l5_data;
int ret;
@@ -1967,7 +1970,7 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
init_waitqueue_head(&ctx->waitq);
ctx->wait_cond = 0;
memset(&l5_data, 0, sizeof(l5_data));
- hw_cid = BNX2X_HW_CID(cp, ctx->cid);
+ hw_cid = BNX2X_HW_CID(bp, ctx->cid);
ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
hw_cid, NONE_CONNECTION_TYPE, &l5_data);
@@ -2252,11 +2255,12 @@ static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe)
struct fcoe_stat_ramrod_params *fcoe_stat;
union l5cm_specific_data l5_data;
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
int ret;
u32 cid;
req = (struct fcoe_kwqe_stat *) kwqe;
- cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
+ cid = BNX2X_HW_CID(bp, cp->fcoe_init_cid);
fcoe_stat = cnic_get_kwqe_16_data(cp, BNX2X_FCOE_L5_CID_BASE, &l5_data);
if (!fcoe_stat)
@@ -2275,6 +2279,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
{
int ret;
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
u32 cid;
struct fcoe_init_ramrod_params *fcoe_init;
struct fcoe_kwqe_init1 *req1;
@@ -2319,7 +2324,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
fcoe_init->sb_id = HC_INDEX_FCOE_EQ_CONS;
cp->kcq2.sw_prod_idx = 0;
- cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
+ cid = BNX2X_HW_CID(bp, cp->fcoe_init_cid);
ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid,
FCOE_CONNECTION_TYPE, &l5_data);
*work = 3;
@@ -2332,6 +2337,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
int ret = 0;
u32 cid = -1, l5_cid;
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct fcoe_kwqe_conn_offload1 *req1;
struct fcoe_kwqe_conn_offload2 *req2;
struct fcoe_kwqe_conn_offload3 *req3;
@@ -2374,7 +2380,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
fctx = cnic_get_bnx2x_ctx(dev, cid, 1, &ctx_addr);
if (fctx) {
- u32 hw_cid = BNX2X_HW_CID(cp, cid);
+ u32 hw_cid = BNX2X_HW_CID(bp, cid);
u32 val;
val = CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_XCM_AG,
@@ -2398,7 +2404,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
memcpy(&fcoe_offload->offload_kwqe3, req3, sizeof(*req3));
memcpy(&fcoe_offload->offload_kwqe4, req4, sizeof(*req4));
- cid = BNX2X_HW_CID(cp, cid);
+ cid = BNX2X_HW_CID(bp, cid);
ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_OFFLOAD_CONN, cid,
FCOE_CONNECTION_TYPE, &l5_data);
if (!ret)
@@ -2556,13 +2562,14 @@ static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
struct fcoe_kwqe_destroy *req;
union l5cm_specific_data l5_data;
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
int ret;
u32 cid;
cnic_bnx2x_delete_wait(dev, MAX_ISCSI_TBL_SZ);
req = (struct fcoe_kwqe_destroy *) kwqe;
- cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
+ cid = BNX2X_HW_CID(bp, cp->fcoe_init_cid);
memset(&l5_data, 0, sizeof(l5_data));
ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid,
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index 519f587..0408ae2 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -401,10 +401,9 @@ struct bnx2x_bd_chain_next {
#define CNIC_PORT(cp) ((cp)->pfid & 1)
#define CNIC_FUNC(cp) ((cp)->func)
-#define CNIC_E1HVN(cp) ((cp)->pfid >> 1)
-#define BNX2X_HW_CID(cp, x) ((CNIC_PORT(cp) << 23) | \
- (CNIC_E1HVN(cp) << 17) | (x))
+#define BNX2X_HW_CID(bp, x) ((BP_PORT(bp) << 23) | \
+ (BP_VN(bp) << 17) | (x))
#define BNX2X_SW_CID(x) (x & 0x1ffff)
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 3/5] cnic: Eliminate CNIC_PORT macro and port_mode in local struct.
From: Michael Chan @ 2013-09-02 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1378147352-9076-3-git-send-email-mchan@broadcom.com>
Use BP_PORT and chip_port_mode directly from bnx2x.h to avoid duplication.
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/ethernet/broadcom/cnic.c | 13 ++++++-------
drivers/net/ethernet/broadcom/cnic.h | 2 --
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 750b9a6..435a167 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1695,7 +1695,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
struct iscsi_context *ictx;
struct regpair context_addr;
int i, j, n = 2, n_max;
- u8 port = CNIC_PORT(cp);
+ u8 port = BP_PORT(bp);
ctx->ctx_flags = 0;
if (!req2->num_additional_wqes)
@@ -1750,7 +1750,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
ictx->xstorm_st_context.common.ethernet.reserved_vlan_type =
ETH_P_8021Q;
if (BNX2X_CHIP_IS_E2_PLUS(bp) &&
- cp->port_mode == CHIP_2_PORT_MODE) {
+ bp->common.chip_port_mode == CHIP_2_PORT_MODE) {
port = 0;
}
@@ -3050,8 +3050,8 @@ static irqreturn_t cnic_irq(int irq, void *dev_instance)
static inline void cnic_ack_bnx2x_int(struct cnic_dev *dev, u8 id, u8 storm,
u16 index, u8 op, u8 update)
{
- struct cnic_local *cp = dev->cnic_priv;
- u32 hc_addr = (HC_REG_COMMAND_REG + CNIC_PORT(cp) * 32 +
+ struct bnx2x *bp = netdev_priv(dev->netdev);
+ u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp) * 32 +
COMMAND_REG_INT_ACK);
struct igu_ack_register igu_ack;
@@ -4231,7 +4231,7 @@ static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
struct cnic_local *cp = dev->cnic_priv;
struct bnx2x *bp = netdev_priv(dev->netdev);
u32 pfid = cp->pfid;
- u32 port = CNIC_PORT(cp);
+ u32 port = BP_PORT(bp);
cnic_init_bnx2x_mac(dev);
cnic_bnx2x_set_tcp_options(dev, 0, 1);
@@ -5090,7 +5090,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
u32 pfid;
dev->stats_addr = ethdev->addr_drv_info_to_mcp;
- cp->port_mode = bp->common.chip_port_mode;
cp->pfid = bp->pfid;
cp->func = bp->pf_num;
@@ -5190,7 +5189,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
off = BAR_USTRORM_INTMEM +
(BNX2X_CHIP_IS_E2_PLUS(bp) ?
USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
- USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
+ USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), cli));
for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++)
CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]);
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index 0408ae2..10531f6 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -304,7 +304,6 @@ struct cnic_local {
u32 chip_id;
int func;
u32 pfid;
- u8 port_mode;
u32 shmem_base;
@@ -399,7 +398,6 @@ struct bnx2x_bd_chain_next {
#define ETH_MAX_RX_CLIENTS_E2 ETH_MAX_RX_CLIENTS_E1H
#endif
-#define CNIC_PORT(cp) ((cp)->pfid & 1)
#define CNIC_FUNC(cp) ((cp)->func)
#define BNX2X_HW_CID(bp, x) ((BP_PORT(bp) << 23) | \
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 0/5] cnic: Remove duplicate bnx2x definitions
From: Michael Chan @ 2013-09-02 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev
Adapt the code to use existing macros and struct fields in bnx2x.h to
avoid duplication.
Michael Chan (5):
cnic: Use CHIP_NUM macros from bnx2x.h
cnic: Redefine BNX2X_HW_CID using existing bnx2x macros
cnic: Eliminate CNIC_PORT macro and port_mode in local struct.
cnic: Eliminate local copy of pfid.
cnic: Update version to 2.5.18.
drivers/net/ethernet/broadcom/cnic.c | 104 ++++++++++++++++--------------
drivers/net/ethernet/broadcom/cnic.h | 67 +++-----------------
drivers/net/ethernet/broadcom/cnic_if.h | 4 +-
3 files changed, 67 insertions(+), 108 deletions(-)
^ permalink raw reply
* [PATCH net-next 1/5] cnic: Use CHIP_NUM macros from bnx2x.h
From: Michael Chan @ 2013-09-02 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1378147352-9076-1-git-send-email-mchan@broadcom.com>
This eliminates duplication and ensures that all bnx2x chips will be
supported.
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/ethernet/broadcom/cnic.c | 37 ++++++++++++---------
drivers/net/ethernet/broadcom/cnic.h | 59 ++++-----------------------------
2 files changed, 29 insertions(+), 67 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 4f8a535..3dadc81 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1184,6 +1184,7 @@ error:
static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
int ctx_blk_size = cp->ethdev->ctx_blk_size;
int total_mem, blks, i;
@@ -1201,7 +1202,7 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
cp->ctx_blks = blks;
cp->ctx_blk_size = ctx_blk_size;
- if (!BNX2X_CHIP_IS_57710(cp->chip_id))
+ if (!CHIP_IS_E1(bp))
cp->ctx_align = 0;
else
cp->ctx_align = ctx_blk_size;
@@ -1231,6 +1232,7 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_eth_dev *ethdev = cp->ethdev;
u32 start_cid = ethdev->starting_cid;
int i, j, n, ret, pages;
@@ -1240,7 +1242,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
cp->iscsi_start_cid = start_cid;
cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(bp)) {
cp->max_cid_space += dev->max_fcoe_conn;
cp->fcoe_init_cid = ethdev->fcoe_init_cid;
if (!cp->fcoe_init_cid)
@@ -1288,7 +1290,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
if (ret)
goto error;
- if (CNIC_SUPPORTS_FCOE(cp)) {
+ if (CNIC_SUPPORTS_FCOE(bp)) {
ret = cnic_alloc_kcq(dev, &cp->kcq2, true);
if (ret)
goto error;
@@ -1679,6 +1681,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
u32 num)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct iscsi_kwqe_conn_offload1 *req1 =
(struct iscsi_kwqe_conn_offload1 *) wqes[0];
struct iscsi_kwqe_conn_offload2 *req2 =
@@ -1745,7 +1748,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T;
ictx->xstorm_st_context.common.ethernet.reserved_vlan_type =
ETH_P_8021Q;
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
+ if (BNX2X_CHIP_IS_E2_PLUS(bp) &&
cp->port_mode == CHIP_2_PORT_MODE) {
port = 0;
@@ -2716,7 +2719,7 @@ static int cnic_submit_bnx2x_iscsi_kwqes(struct cnic_dev *dev,
static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
struct kwqe *wqes[], u32 num_wqes)
{
- struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
int i, work, ret;
u32 opcode;
struct kwqe *kwqe;
@@ -2724,7 +2727,7 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
return -EAGAIN; /* bnx2 is down */
- if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
+ if (!BNX2X_CHIP_IS_E2_PLUS(bp))
return -EINVAL;
for (i = 0; i < num_wqes; ) {
@@ -4902,6 +4905,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
struct client_init_ramrod_data *data)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_uio_dev *udev = cp->udev;
union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
dma_addr_t buf_map, ring_map = udev->l2_ring_map;
@@ -4930,7 +4934,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
start_bd->general_data &= ~ETH_TX_START_BD_PARSE_NBDS;
start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
+ if (BNX2X_CHIP_IS_E2_PLUS(bp))
pbd_e2->parsing_data = (UNICAST_ADDRESS <<
ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
else
@@ -4967,6 +4971,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
struct client_init_ramrod_data *data)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct bnx2x *bp = netdev_priv(dev->netdev);
struct cnic_uio_dev *udev = cp->udev;
struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
BNX2_PAGE_SIZE);
@@ -4975,7 +4980,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
int i;
u32 cli = cp->ethdev->iscsi_l2_client_id;
- int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
+ int cl_qzone_id = BNX2X_CL_QZONE_ID(bp, cli);
u32 val;
dma_addr_t ring_map = udev->l2_ring_map;
@@ -5040,7 +5045,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
cp->kcq1.sw_prod_idx = 0;
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(bp)) {
struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
cp->kcq1.hw_prod_idx_ptr =
@@ -5056,7 +5061,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
&sb->sb.running_index[SM_RX_ID];
}
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(bp)) {
struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
cp->kcq2.io_addr = BAR_USTRORM_INTMEM +
@@ -5091,7 +5096,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
if (ret)
return -ENOMEM;
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(bp)) {
ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl, dev->max_fcoe_conn,
cp->fcoe_start_cid, 0);
@@ -5173,10 +5178,10 @@ static void cnic_init_rings(struct cnic_dev *dev)
rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
barrier();
- cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
+ cl_qzone_id = BNX2X_CL_QZONE_ID(bp, cli);
off = BAR_USTRORM_INTMEM +
- (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ?
+ (BNX2X_CHIP_IS_E2_PLUS(bp) ?
USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
@@ -5365,7 +5370,7 @@ static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
cnic_free_irq(dev);
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(bp)) {
idx_off = offsetof(struct hc_status_block_e2, index_values) +
(hc_index * sizeof(u16));
@@ -5556,7 +5561,7 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI))
cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
- if (CNIC_SUPPORTS_FCOE(cp)) {
+ if (CNIC_SUPPORTS_FCOE(bp)) {
cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
cdev->max_fcoe_exchanges = ethdev->max_fcoe_exchanges;
}
@@ -5576,7 +5581,7 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
cp->stop_cm = cnic_cm_stop_bnx2x_hw;
cp->enable_int = cnic_enable_bnx2x_int;
cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
- if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E2_PLUS(bp)) {
cp->ack_int = cnic_ack_bnx2x_e2_msix;
cp->arm_int = cnic_arm_bnx2x_e2_msix;
} else {
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index e7a2474..519f587 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -364,47 +364,7 @@ struct bnx2x_bd_chain_next {
#define BNX2X_FCOE_L5_CID_BASE MAX_ISCSI_TBL_SZ
-#define BNX2X_CHIP_NUM_57710 0x164e
-#define BNX2X_CHIP_NUM_57711 0x164f
-#define BNX2X_CHIP_NUM_57711E 0x1650
-#define BNX2X_CHIP_NUM_57712 0x1662
-#define BNX2X_CHIP_NUM_57712E 0x1663
-#define BNX2X_CHIP_NUM_57713 0x1651
-#define BNX2X_CHIP_NUM_57713E 0x1652
-#define BNX2X_CHIP_NUM_57800 0x168a
-#define BNX2X_CHIP_NUM_57810 0x168e
-#define BNX2X_CHIP_NUM_57840 0x168d
-
-#define BNX2X_CHIP_NUM(x) (x >> 16)
-#define BNX2X_CHIP_IS_57710(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57710)
-#define BNX2X_CHIP_IS_57711(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711)
-#define BNX2X_CHIP_IS_57711E(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711E)
-#define BNX2X_CHIP_IS_E1H(x) \
- (BNX2X_CHIP_IS_57711(x) || BNX2X_CHIP_IS_57711E(x))
-#define BNX2X_CHIP_IS_57712(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712)
-#define BNX2X_CHIP_IS_57712E(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712E)
-#define BNX2X_CHIP_IS_57713(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
-#define BNX2X_CHIP_IS_57713E(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
-#define BNX2X_CHIP_IS_57800(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57800)
-#define BNX2X_CHIP_IS_57810(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57810)
-#define BNX2X_CHIP_IS_57840(x) \
- (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57840)
-#define BNX2X_CHIP_IS_E2(x) \
- (BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
- BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
-#define BNX2X_CHIP_IS_E3(x) \
- (BNX2X_CHIP_IS_57800(x) || BNX2X_CHIP_IS_57810(x) || \
- BNX2X_CHIP_IS_57840(x))
-#define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
+#define BNX2X_CHIP_IS_E2_PLUS(bp) (CHIP_IS_E2(bp) || CHIP_IS_E3(bp))
#define BNX2X_RX_DESC_CNT (BNX2_PAGE_SIZE / \
sizeof(struct eth_rx_bd))
@@ -441,8 +401,6 @@ struct bnx2x_bd_chain_next {
#define CNIC_PORT(cp) ((cp)->pfid & 1)
#define CNIC_FUNC(cp) ((cp)->func)
-#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? \
- 0 : (CNIC_FUNC(cp) & 1))
#define CNIC_E1HVN(cp) ((cp)->pfid >> 1)
#define BNX2X_HW_CID(cp, x) ((CNIC_PORT(cp) << 23) | \
@@ -450,20 +408,19 @@ struct bnx2x_bd_chain_next {
#define BNX2X_SW_CID(x) (x & 0x1ffff)
-#define BNX2X_CL_QZONE_ID(cp, cli) \
- (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? cli : \
- cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
+#define BNX2X_CL_QZONE_ID(bp, cli) \
+ (BNX2X_CHIP_IS_E2_PLUS(bp) ? cli : \
+ cli + (BP_PORT(bp) * ETH_MAX_RX_CLIENTS_E1H))
#ifndef MAX_STAT_COUNTER_ID
#define MAX_STAT_COUNTER_ID \
- (BNX2X_CHIP_IS_E1H((cp)->chip_id) ? MAX_STAT_COUNTER_ID_E1H : \
- ((BNX2X_CHIP_IS_E2_PLUS((cp)->chip_id)) ? MAX_STAT_COUNTER_ID_E2 :\
+ (CHIP_IS_E1H(bp) ? MAX_STAT_COUNTER_ID_E1H : \
+ ((BNX2X_CHIP_IS_E2_PLUS(bp)) ? MAX_STAT_COUNTER_ID_E2 : \
MAX_STAT_COUNTER_ID_E1))
#endif
-#define CNIC_SUPPORTS_FCOE(cp) \
- (BNX2X_CHIP_IS_E2_PLUS((cp)->chip_id) && \
- !((cp)->ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
+#define CNIC_SUPPORTS_FCOE(cp) \
+ (BNX2X_CHIP_IS_E2_PLUS(bp) && !NO_FCOE(bp))
#define CNIC_RAMROD_TMO (HZ / 4)
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 4/5] cnic: Eliminate local copy of pfid.
From: Michael Chan @ 2013-09-02 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1378147352-9076-4-git-send-email-mchan@broadcom.com>
Use bp->pfid from bnx2x instead to avoid duplication.
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/ethernet/broadcom/cnic.c | 29 ++++++++++++-----------------
drivers/net/ethernet/broadcom/cnic.h | 1 -
2 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 435a167..8142480 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1395,7 +1395,7 @@ static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid,
BNX2X_HW_CID(bp, cid)));
type_16 = (type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
- type_16 |= (cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+ type_16 |= (bp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
SPE_HDR_FUNCTION_ID;
kwqe.hdr.type = cpu_to_le16(type_16);
@@ -1433,7 +1433,6 @@ static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type,
static void cnic_bnx2x_set_tcp_options(struct cnic_dev *dev, int time_stamps,
int en_tcp_dack)
{
- struct cnic_local *cp = dev->cnic_priv;
struct bnx2x *bp = netdev_priv(dev->netdev);
u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN;
u16 tstorm_flags = 0;
@@ -1446,10 +1445,10 @@ static void cnic_bnx2x_set_tcp_options(struct cnic_dev *dev, int time_stamps,
tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_DELAYED_ACK_EN;
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags);
+ XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(bp->pfid), xstorm_flags);
CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags);
+ TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(bp->pfid), tstorm_flags);
}
static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
@@ -1458,7 +1457,7 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
struct bnx2x *bp = netdev_priv(dev->netdev);
struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe;
int hq_bds, pages;
- u32 pfid = cp->pfid;
+ u32 pfid = bp->pfid;
cp->num_iscsi_tasks = req1->num_tasks_per_conn;
cp->num_ccells = req1->num_ccells_per_conn;
@@ -1541,9 +1540,8 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe;
- struct cnic_local *cp = dev->cnic_priv;
struct bnx2x *bp = netdev_priv(dev->netdev);
- u32 pfid = cp->pfid;
+ u32 pfid = bp->pfid;
struct iscsi_kcqe kcqe;
struct kcqe *cqes[1];
@@ -2078,9 +2076,8 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
{
- struct cnic_local *cp = dev->cnic_priv;
struct bnx2x *bp = netdev_priv(dev->netdev);
- u32 pfid = cp->pfid;
+ u32 pfid = bp->pfid;
u8 *mac = dev->mac_addr;
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
@@ -2186,7 +2183,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
cnic_init_storm_conn_bufs(dev, kwqe1, kwqe3, conn_buf);
CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->pfid), csk->vlan_id);
+ XSTORM_ISCSI_LOCAL_VLAN_OFFSET(bp->pfid), csk->vlan_id);
ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT,
kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data);
@@ -4228,9 +4225,8 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
{
- struct cnic_local *cp = dev->cnic_priv;
struct bnx2x *bp = netdev_priv(dev->netdev);
- u32 pfid = cp->pfid;
+ u32 pfid = bp->pfid;
u32 port = BP_PORT(bp);
cnic_init_bnx2x_mac(dev);
@@ -4996,7 +4992,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
data->general.activate_flg = 1;
data->general.sp_client_id = cli;
data->general.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
- data->general.func_id = cp->pfid;
+ data->general.func_id = bp->pfid;
for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
@@ -5046,7 +5042,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
struct bnx2x *bp = netdev_priv(dev->netdev);
- u32 pfid = cp->pfid;
+ u32 pfid = bp->pfid;
cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
@@ -5090,11 +5086,10 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
u32 pfid;
dev->stats_addr = ethdev->addr_drv_info_to_mcp;
- cp->pfid = bp->pfid;
cp->func = bp->pf_num;
func = CNIC_FUNC(cp);
- pfid = cp->pfid;
+ pfid = bp->pfid;
ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
cp->iscsi_start_cid, 0);
@@ -5393,7 +5388,7 @@ static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
*cp->kcq1.hw_prod_idx_ptr = 0;
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);
+ CSTORM_ISCSI_EQ_CONS_OFFSET(bp->pfid, 0), 0);
CNIC_WR16(dev, cp->kcq1.io_addr, 0);
cnic_free_resc(dev);
}
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index 10531f6..0121a5d 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -303,7 +303,6 @@ struct cnic_local {
u32 chip_id;
int func;
- u32 pfid;
u32 shmem_base;
--
1.7.1
^ permalink raw reply related
* Re: [sfc:master 79/80] drivers/net/ethernet/sfc/mcdi.c:960:1: warning: 'efx_mcdi_print_fwver' uses dynamic stack allocation
From: Ben Hutchings @ 2013-09-02 18:35 UTC (permalink / raw)
To: Fengguang Wu; +Cc: kbuild-all, netdev, linux-net-drivers
In-Reply-To: <5221261c.gkIQ84VFSaPYEYzp%fengguang.wu@intel.com>
On Sat, 2013-08-31 at 07:09 +0800, kbuild test robot wrote:
> tree: git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next master
> head: f7a6d2c4427790cc8695401576dc594fcce8fc80
> commit: 8127d661e77f5ec410093bce411f540afa34593f [79/80] sfc: Add support for Solarflare SFC9100 family
> config: make ARCH=s390 allmodconfig
>
> All warnings:
>
> drivers/net/ethernet/sfc/mcdi.c: In function 'efx_mcdi_print_fwver':
> >> drivers/net/ethernet/sfc/mcdi.c:960:1: warning: 'efx_mcdi_print_fwver' uses dynamic stack allocation [enabled by default]
[...]
What we actually do is:
MCDI_DECLARE_BUF(outbuf,
max(MC_CMD_GET_VERSION_OUT_LEN,
MC_CMD_GET_CAPABILITIES_OUT_LEN));
The dimension of the outbuf array is constant, even though max() doesn't
expand to a compile-time constant expression. It's odd that gcc would
complain about this specifically on s390 (or is it that you're using a
different compiler version there?). I don't know whether anything can
or should be done about to fix the warning.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: pull-request: can-next 2013-08-29
From: Marc Kleine-Budde @ 2013-09-02 19:06 UTC (permalink / raw)
To: Linux Netdev List
Cc: linux-can@vger.kernel.org, David Miller, kernel@pengutronix.de
In-Reply-To: <521FB992.5080002@pengutronix.de>
[-- Attachment #1: Type: text/plain, Size: 1726 bytes --]
Hello David,
On 08/29/2013 11:13 PM, Marc Kleine-Budde wrote:
> this is a pull request for net-next. There are two patches from Gerhard
> Sittig, which improves the clock handling on mpc5121. Oliver Hartkopp
> provides a patch that adds a per rule limitation of frame hops.
have you forgotten this pull request?
Marc
> The following changes since commit 7ec06da81d2b98859b558d8d551a0c4e3d9516a3:
>
> net: packet: document available fanout policies (2013-08-29 16:43:29 -0400)
>
> are available in the git repository at:
>
> git://gitorious.org/linux-can/linux-can-next.git for-davem
>
> for you to fetch changes up to 391ac1282dd7ff1cb8245cccc5262e8e4173edc4:
>
> can: gw: add a per rule limitation of frame hops (2013-08-29 22:58:24 +0200)
>
> ----------------------------------------------------------------
> Gerhard Sittig (2):
> can: mscan: add a comment on reg to idx mapping
> can: mscan: improve clock API use
>
> Oliver Hartkopp (1):
> can: gw: add a per rule limitation of frame hops
>
> drivers/net/can/mscan/mpc5xxx_can.c | 23 ++++++++++++++++-------
> drivers/net/can/mscan/mscan.c | 25 ++++++++++++++++++++++++-
> drivers/net/can/mscan/mscan.h | 3 +++
> include/uapi/linux/can/gw.h | 9 ++++++++-
> net/can/gw.c | 35 +++++++++++++++++++++++++++++++----
> 5 files changed, 82 insertions(+), 13 deletions(-)
>
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply
* Re: [PATCH v4] ipv6:introduce function to find route for redirect
From: Hannes Frederic Sowa @ 2013-09-02 19:50 UTC (permalink / raw)
To: Duan Jiong; +Cc: davem, netdev
In-Reply-To: <52242CE1.5050501@cn.fujitsu.com>
On Mon, Sep 02, 2013 at 02:14:57PM +0800, Duan Jiong wrote:
> +static struct rt6_info *__ip6_route_redirect(struct net *net,
> + struct fib6_table *table,
> + struct flowi6 *fl6,
> + int flags)
> +{
> + struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
> + struct rt6_info *rt;
> + struct fib6_node *fn;
> +
> + /* Get the "current" route for this destination and
> + * check if the redirect has come from approriate router.
> + *
> + * RFC 4861 specifies that redirects should only be
> + * accepted if they come from the nexthop to the target.
> + * Due to the way the routes are chosen, this notion
> + * is a bit fuzzy and one might need to check all possible
> + * routes.
> + */
> +
> + read_lock_bh(&table->tb6_lock);
> + fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
> +restart:
> + for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
> + if (rt6_check_expired(rt))
> + continue;
> + if (rt->dst.error)
> + continue;
Sorry, I should have been more clear what I meant with failing early:
I considered a setup like this:
ip -6 r a default nexthop via fe80::1 dev eth0
ip -6 r a prohibit 2002:1::/64
If the kernel receives a redirect for a destination e.g. 2002:1::1 we
would backtrack above the prohibit rule and return the dst of the default
route and would insert a new cached route which could circumvent the
prohibit rule. We have to try to lock down the tree below 2002:1::/64
in that case. A possible solution for that would be to do something
like this:
/* We don't accept a redirect in case a more specific route is
* installed with dst.error and stop backtracking.
*/
if (rt->dst.error)
break;
Either we have to replace the rt with net->ipv6.ip6_null_entry in that
case or check dst->error before calling rt6_do_redirect below.
> + if (!(rt->rt6i_flags & RTF_GATEWAY))
> + continue;
> + if (fl6->flowi6_oif != rt->dst.dev->ifindex)
> + continue;
> + if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
> + continue;
> + break;
> + }
> +
> + if (!rt)
> + rt = net->ipv6.ip6_null_entry;
> + BACKTRACK(net, &fl6->saddr);
> +out:
> + dst_hold(&rt->dst);
> +
> + read_unlock_bh(&table->tb6_lock);
> +
> + return rt;
> +};
>
> [...]
>
> @@ -1171,9 +1238,8 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
> fl6.saddr = iph->saddr;
> fl6.flowlabel = ip6_flowinfo(iph);
>
> - dst = ip6_route_output(net, NULL, &fl6);
> - if (!dst->error)
> - rt6_do_redirect(dst, NULL, skb);
> + dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
> + rt6_do_redirect(dst, NULL, skb);
> dst_release(dst);
> }
> EXPORT_SYMBOL_GPL(ip6_redirect);
> @@ -1193,9 +1259,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
> fl6.daddr = msg->dest;
> fl6.saddr = iph->daddr;
>
> - dst = ip6_route_output(net, NULL, &fl6);
> - if (!dst->error)
> - rt6_do_redirect(dst, NULL, skb);
> + dst = ip6_route_redirect(net, &fl6, &iph->saddr);
> + rt6_do_redirect(dst, NULL, skb);
> dst_release(dst);
> }
Btw. I still think it should be possible to eliminate
ip6_redirect_no_header:
We could always use ip6_redirect_no_header and use the data of the redirected
header option just for finding the socket to be notified. We can do the whole
verification and route updating in ndisc layer and then just call into icmpv6
layer if upper protocols need a notification of the redirect. But that should
go into another patch. ;)
Thanks,
Hannes
^ permalink raw reply
* Re: [PATCH] net: netx-eth: remove unnecessary casting when using dev_get_platdata()
From: Sergei Shtylyov @ 2013-09-02 21:01 UTC (permalink / raw)
To: Jingoo Han; +Cc: 'David S. Miller', netdev
In-Reply-To: <004b01cea774$975b48b0$c611da10$%han@samsung.com>
Hello.
On 09/02/2013 04:37 AM, Jingoo Han wrote:
> Casting from 'void *' is unnecessary when using dev_get_platdata().
dev_get_platdata() is irrelevant here. Casting from/to 'void *' to/from
any pointer type is just automatic.
> Reported-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
WBR, Sergei
^ permalink raw reply
* Re: [guv v2 04/31] net: Replace __get_cpu_var uses
From: David Howells @ 2013-09-02 21:35 UTC (permalink / raw)
To: Christoph Lameter
Cc: dhowells, Tejun Heo, akpm, David S. Miller, netdev, linux-arch,
Steven Rostedt, linux-kernel
In-Reply-To: <00000140bc5ef9df-d7f75909-a25e-4471-84b2-dfbec07117b0-000000@email.amazonses.com>
Would it be possible to use __thread annotations for per-CPU variables, I
wonder?
David
^ permalink raw reply
* [PATCH RFC net-next 01/21] net: add neighbour_dev_list to save only neighbours
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Currently, we distinguish neighbours (first-level linked devices) from
non-neighbours by the neighbour bool in the netdev_adjacent. This could be
quite time-consuming in case we would like to traverse *only* through
neighbours - cause we'd have to traverse through all devices and check for
this flag, and in a (quite common) scenario where we have lots of vlans on
top of bridge, which is on top of a bond - the bonding would have to go
through all those vlans to get its upper neighbour linked devices.
This situation is really unpleasant, cause there are already a lot of cases
when a device with slaves needs to go through them in hot path.
To fix this, introduce a new upper/lower device lists structure -
neighbour_dev_list, which contains only the neighbours. It works always in
pair with the all_device_list structure (renamed from upper/lower_dev_list),
i.e. both of them contain the same links, only that all_dev_list contains
also non-neighbour device links. It's really a small change visible,
currently, only for __netdev_adjacent_dev_insert/remove(), and doesn't
change the main linked logic at all.
Also, add some comments a fix a name collision in
netdev_for_each_upper_dev_rcu().
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
include/linux/netdevice.h | 24 ++++---
net/core/dev.c | 157 ++++++++++++++++++++++++++++++++++------------
2 files changed, 134 insertions(+), 47 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3ad49b8..df50548 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1124,8 +1124,18 @@ struct net_device {
struct list_head dev_list;
struct list_head napi_list;
struct list_head unreg_list;
- struct list_head upper_dev_list; /* List of upper devices */
- struct list_head lower_dev_list;
+
+ /* directly linked devices, like slaves for bonding */
+ struct {
+ struct list_head upper;
+ struct list_head lower;
+ } neighbour_dev_list ;
+
+ /* all linked devices, *including* neighbours */
+ struct {
+ struct list_head upper;
+ struct list_head lower;
+ } all_dev_list ;
/* currently active device features */
@@ -2772,11 +2782,11 @@ extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
struct list_head **iter);
/* iterate through upper list, must be called under RCU read lock */
-#define netdev_for_each_upper_dev_rcu(dev, upper, iter) \
- for (iter = &(dev)->upper_dev_list, \
- upper = netdev_upper_get_next_dev_rcu(dev, &(iter)); \
- upper; \
- upper = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+#define netdev_for_each_upper_dev_rcu(dev, updev, iter) \
+ for (iter = &(dev)->all_dev_list.upper, \
+ updev= netdev_upper_get_next_dev_rcu(dev, &(iter)); \
+ updev; \
+ updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 743620e..9e4eb40 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4373,9 +4373,6 @@ struct netdev_adjacent {
/* upper master flag, there can only be one master device per list */
bool master;
- /* indicates that this dev is our first-level lower/upper device */
- bool neighbour;
-
/* counter for the number of times this device was added to us */
u16 ref_nr;
@@ -4385,12 +4382,17 @@ struct netdev_adjacent {
static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
struct net_device *adj_dev,
- bool upper)
+ bool upper, bool neighbour)
{
struct netdev_adjacent *adj;
struct list_head *dev_list;
- dev_list = upper ? &dev->upper_dev_list : &dev->lower_dev_list;
+ if (neighbour)
+ dev_list = upper ? &dev->neighbour_dev_list.upper :
+ &dev->neighbour_dev_list.lower;
+ else
+ dev_list = upper ? &dev->all_dev_list.upper :
+ &dev->all_dev_list.lower;
list_for_each_entry(adj, dev_list, list) {
if (adj->dev == adj_dev)
@@ -4402,13 +4404,25 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
struct net_device *udev)
{
- return __netdev_find_adj(dev, udev, true);
+ return __netdev_find_adj(dev, udev, true, false);
}
static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
struct net_device *ldev)
{
- return __netdev_find_adj(dev, ldev, false);
+ return __netdev_find_adj(dev, ldev, false, false);
+}
+
+static inline struct netdev_adjacent *__netdev_find_upper_neighbour(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_find_adj(dev, udev, true, true);
+}
+
+static inline struct netdev_adjacent *__netdev_find_lower_neighbour(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_find_adj(dev, ldev, false, true);
}
/**
@@ -4440,7 +4454,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev)
{
ASSERT_RTNL();
- return !list_empty(&dev->upper_dev_list);
+ return !list_empty(&dev->all_dev_list.upper);
}
EXPORT_SYMBOL(netdev_has_any_upper_dev);
@@ -4457,10 +4471,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
ASSERT_RTNL();
- if (list_empty(&dev->upper_dev_list))
+ if (list_empty(&dev->neighbour_dev_list.upper))
return NULL;
- upper = list_first_entry(&dev->upper_dev_list,
+ upper = list_first_entry(&dev->neighbour_dev_list.upper,
struct netdev_adjacent, list);
if (likely(upper->master))
return upper->dev;
@@ -4484,7 +4498,7 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
- if (&upper->list == &dev->upper_dev_list)
+ if (&upper->list == &dev->all_dev_list.upper)
return NULL;
*iter = &upper->list;
@@ -4504,7 +4518,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
{
struct netdev_adjacent *upper;
- upper = list_first_or_null_rcu(&dev->upper_dev_list,
+ upper = list_first_or_null_rcu(&dev->neighbour_dev_list.upper,
struct netdev_adjacent, list);
if (upper && likely(upper->master))
return upper->dev;
@@ -4517,11 +4531,12 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
bool neighbour, bool master,
bool upper)
{
- struct netdev_adjacent *adj;
+ struct netdev_adjacent *adj, *neigh = NULL;
- adj = __netdev_find_adj(dev, adj_dev, upper);
+ adj = __netdev_find_adj(dev, adj_dev, upper, false);
if (adj) {
+ /* we cannot insert a neighbour device twice */
BUG_ON(neighbour);
adj->ref_nr++;
return 0;
@@ -4533,24 +4548,50 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->dev = adj_dev;
adj->master = master;
- adj->neighbour = neighbour;
adj->ref_nr = 1;
-
dev_hold(adj_dev);
+
+ if (neighbour) {
+ neigh = kmalloc(sizeof(*neigh), GFP_KERNEL);
+ if (!neigh) {
+ kfree(adj);
+ return -ENOMEM;
+ }
+ neigh->dev = adj_dev;
+ neigh->master = master;
+ neigh->ref_nr = 1;
+ dev_hold(adj_dev);
+ }
+
pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
adj_dev->name, upper ? "upper" : "lower", dev->name,
adj_dev->name);
+ if (neigh)
+ pr_debug("dev_hold for %s, because of %s link added from %s"
+ " to %s (neighbour)\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name);
if (!upper) {
- list_add_tail_rcu(&adj->list, &dev->lower_dev_list);
+ if (neigh)
+ list_add_tail_rcu(&neigh->list,
+ &dev->neighbour_dev_list.lower);
+ list_add_tail_rcu(&adj->list, &dev->all_dev_list.lower);
return 0;
}
/* Ensure that master upper link is always the first item in list. */
- if (master)
- list_add_rcu(&adj->list, &dev->upper_dev_list);
- else
- list_add_tail_rcu(&adj->list, &dev->upper_dev_list);
+ if (master) {
+ if (neigh)
+ list_add_rcu(&neigh->list,
+ &dev->neighbour_dev_list.upper);
+ list_add_rcu(&adj->list, &dev->all_dev_list.upper);
+ } else {
+ if (neigh)
+ list_add_tail_rcu(&neigh->list,
+ &dev->neighbour_dev_list.upper);
+ list_add_tail_rcu(&adj->list, &dev->all_dev_list.upper);
+ }
return 0;
}
@@ -4574,17 +4615,36 @@ static inline int __netdev_lower_dev_insert(struct net_device *dev,
void __netdev_adjacent_dev_remove(struct net_device *dev,
struct net_device *adj_dev, bool upper)
{
- struct netdev_adjacent *adj;
+ struct netdev_adjacent *adj, *neighbour;
- if (upper)
+ if (upper) {
adj = __netdev_find_upper(dev, adj_dev);
- else
+ neighbour = __netdev_find_upper_neighbour(dev, adj_dev);
+ } else {
adj = __netdev_find_lower(dev, adj_dev);
+ neighbour = __netdev_find_lower_neighbour(dev, adj_dev);
+ }
- if (!adj)
+ if (!adj) {
+ pr_err("tried to remove %s device %s from %s\n",
+ upper ? "upper" : "lower", dev->name, adj_dev->name);
BUG();
+ }
if (adj->ref_nr > 1) {
+ pr_debug("rec_cnt-- for link to %s, because of %s link removed"
+ " from %s to %s, remains %d\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name, adj->ref_nr-1);
+ if (neighbour) {
+ pr_debug("rec_cnt-- for link to %s, because of %s link"
+ " removed from %s to %s, remain %d (neigh)\n",
+ adj_dev->name, upper ? "upper" : "lower",
+ dev->name, adj_dev->name,
+ neighbour->ref_nr-1);
+ BUG_ON(adj->ref_nr != neighbour->ref_nr);
+ neighbour->ref_nr--;
+ }
adj->ref_nr--;
return;
}
@@ -4595,6 +4655,15 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
adj_dev->name);
dev_put(adj_dev);
kfree_rcu(adj, rcu);
+ if (neighbour) {
+ pr_debug("dev_put for %s, because of %s link removed from %s"
+ " to %s (neighbour)\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name);
+ list_del_rcu(&neighbour->list);
+ dev_put(adj_dev);
+ kfree_rcu(neighbour, rcu);
+ }
}
static inline void __netdev_upper_dev_remove(struct net_device *dev,
@@ -4675,12 +4744,14 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return ret;
/* Now that we linked these devs, make all the upper_dev's
- * upper_dev_list visible to every dev's lower_dev_list and vice
+ * all_dev_list.upper visible to every dev's all_dev_list.lower an
* versa, and don't forget the devices itself. All of these
* links are non-neighbours.
*/
- list_for_each_entry(i, &dev->lower_dev_list, list) {
- list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &dev->all_dev_list.lower, list) {
+ list_for_each_entry(j, &upper_dev->all_dev_list.upper, list) {
+ pr_debug("Interlinking %s with %s, non-neighbour\n",
+ i->dev->name, j->dev->name);
ret = __netdev_adjacent_dev_link(i->dev, j->dev);
if (ret)
goto rollback_mesh;
@@ -4688,14 +4759,18 @@ static int __netdev_upper_dev_link(struct net_device *dev,
}
/* add dev to every upper_dev's upper device */
- list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &upper_dev->all_dev_list.upper, list) {
+ pr_debug("linking %s's upper device %s with %s\n", upper_dev->name,
+ i->dev->name, dev->name);
ret = __netdev_adjacent_dev_link(dev, i->dev);
if (ret)
goto rollback_upper_mesh;
}
/* add upper_dev to every dev's lower device */
- list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(i, &dev->all_dev_list.lower, list) {
+ pr_debug("linking %s's lower device %s with %s\n", dev->name,
+ i->dev->name, upper_dev->name);
ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
if (ret)
goto rollback_lower_mesh;
@@ -4706,7 +4781,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
rollback_lower_mesh:
to_i = i;
- list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(i, &dev->all_dev_list.lower, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
@@ -4716,7 +4791,7 @@ rollback_lower_mesh:
rollback_upper_mesh:
to_i = i;
- list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &upper_dev->all_dev_list.upper, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(dev, i->dev);
@@ -4727,8 +4802,8 @@ rollback_upper_mesh:
rollback_mesh:
to_i = i;
to_j = j;
- list_for_each_entry(i, &dev->lower_dev_list, list) {
- list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &dev->all_dev_list.lower, list) {
+ list_for_each_entry(j, &upper_dev->all_dev_list.upper, list) {
if (i == to_i && j == to_j)
break;
__netdev_adjacent_dev_unlink(i->dev, j->dev);
@@ -4797,17 +4872,17 @@ void netdev_upper_dev_unlink(struct net_device *dev,
* devices from all upper_dev's upper devices and vice
* versa, to maintain the graph relationship.
*/
- list_for_each_entry(i, &dev->lower_dev_list, list)
- list_for_each_entry(j, &upper_dev->upper_dev_list, list)
+ list_for_each_entry(i, &dev->all_dev_list.lower, list)
+ list_for_each_entry(j, &upper_dev->all_dev_list.upper, list)
__netdev_adjacent_dev_unlink(i->dev, j->dev);
/* remove also the devices itself from lower/upper device
* list
*/
- list_for_each_entry(i, &dev->lower_dev_list, list)
+ list_for_each_entry(i, &dev->all_dev_list.lower, list)
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
- list_for_each_entry(i, &upper_dev->upper_dev_list, list)
+ list_for_each_entry(i, &upper_dev->all_dev_list.upper, list)
__netdev_adjacent_dev_unlink(dev, i->dev);
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
@@ -6069,8 +6144,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
- INIT_LIST_HEAD(&dev->upper_dev_list);
- INIT_LIST_HEAD(&dev->lower_dev_list);
+ INIT_LIST_HEAD(&dev->neighbour_dev_list.upper);
+ INIT_LIST_HEAD(&dev->neighbour_dev_list.lower);
+ INIT_LIST_HEAD(&dev->all_dev_list.upper);
+ INIT_LIST_HEAD(&dev->all_dev_list.lower);
dev->priv_flags = IFF_XMIT_DST_RELEASE;
setup(dev);
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 02/21] net: add RCU variant to search for netdev_adjacent link
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Currently we have only the RTNL flavour, however we can traverse it while
holding only RCU, so add the RCU search.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
net/core/dev.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9e4eb40..4e67a67 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4380,6 +4380,51 @@ struct netdev_adjacent {
struct rcu_head rcu;
};
+static struct netdev_adjacent *__netdev_find_adj_rcu(struct net_device *dev,
+ struct net_device *adj_dev,
+ bool upper, bool neighbour)
+{
+ struct netdev_adjacent *adj;
+ struct list_head *dev_list;
+
+ if (neighbour)
+ dev_list = upper ? &dev->neighbour_dev_list.upper :
+ &dev->neighbour_dev_list.lower;
+ else
+ dev_list = upper ? &dev->all_dev_list.upper :
+ &dev->all_dev_list.lower;
+
+ list_for_each_entry_rcu(adj, dev_list, list) {
+ if (adj->dev == adj_dev)
+ return adj;
+ }
+ return NULL;
+}
+
+static inline struct netdev_adjacent *__netdev_find_upper_rcu(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_find_adj_rcu(dev, udev, true, false);
+}
+
+static inline struct netdev_adjacent *__netdev_find_lower_rcu(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_find_adj_rcu(dev, ldev, false, false);
+}
+
+static inline struct netdev_adjacent *__netdev_find_upper_neighbour_rcu(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_find_adj_rcu(dev, udev, true, true);
+}
+
+static inline struct netdev_adjacent *__netdev_find_lower_neighbour_rcu(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_find_adj_rcu(dev, ldev, false, true);
+}
+
static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
struct net_device *adj_dev,
bool upper, bool neighbour)
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 03/21] net: add netdev_adjacent->private and allow to use it
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Currently, even though we can access any linked device, we can't attach
anything to it, which is vital to properly manage them.
To fix this, add a new void *private to netdev_adjacent and functions
setting/getting it (per link), so that we can save, per example, bonding's
slave structures there, per slave device.
netdev_master_upper_dev_link_private(dev, upper_dev, private) links dev to
upper dev and populates the neighbour link only with private.
netdev_lower_dev_get_private{,_rcu}() returns the private, if found.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
include/linux/netdevice.h | 7 ++++
net/core/dev.c | 83 ++++++++++++++++++++++++++++++++++++++---------
2 files changed, 75 insertions(+), 15 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index df50548..ef1ddee 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2794,8 +2794,15 @@ extern int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev);
extern int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev);
+extern int netdev_master_upper_dev_link_private(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private);
extern void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev);
+extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
+ struct net_device *lower_dev);
+extern void *netdev_lower_dev_get_private(struct net_device *dev,
+ struct net_device *lower_dev);
extern int skb_checksum_help(struct sk_buff *skb);
extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
netdev_features_t features, bool tx_path);
diff --git a/net/core/dev.c b/net/core/dev.c
index 4e67a67..fc5c5a1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4376,6 +4376,9 @@ struct netdev_adjacent {
/* counter for the number of times this device was added to us */
u16 ref_nr;
+ /* private field for the users */
+ void *private;
+
struct list_head list;
struct rcu_head rcu;
};
@@ -4574,7 +4577,7 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
bool neighbour, bool master,
- bool upper)
+ bool upper, void *private)
{
struct netdev_adjacent *adj, *neigh = NULL;
@@ -4618,9 +4621,15 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj_dev->name);
if (!upper) {
- if (neigh)
+ if (neigh) {
+ /* we're backlinging the master device to its
+ * slave, so save the private in this link.
+ */
+ if (master)
+ neigh->private = private;
list_add_tail_rcu(&neigh->list,
&dev->neighbour_dev_list.lower);
+ }
list_add_tail_rcu(&adj->list, &dev->all_dev_list.lower);
return 0;
}
@@ -4646,15 +4655,16 @@ static inline int __netdev_upper_dev_insert(struct net_device *dev,
bool master, bool neighbour)
{
return __netdev_adjacent_dev_insert(dev, udev, neighbour, master,
- true);
+ true, NULL);
}
static inline int __netdev_lower_dev_insert(struct net_device *dev,
struct net_device *ldev,
- bool neighbour)
+ bool master, bool neighbour,
+ void *private)
{
- return __netdev_adjacent_dev_insert(dev, ldev, neighbour, false,
- false);
+ return __netdev_adjacent_dev_insert(dev, ldev, neighbour, master,
+ false, private);
}
void __netdev_adjacent_dev_remove(struct net_device *dev,
@@ -4725,7 +4735,8 @@ static inline void __netdev_lower_dev_remove(struct net_device *dev,
int __netdev_adjacent_dev_insert_link(struct net_device *dev,
struct net_device *upper_dev,
- bool master, bool neighbour)
+ bool master, bool neighbour,
+ void *private)
{
int ret;
@@ -4733,7 +4744,8 @@ int __netdev_adjacent_dev_insert_link(struct net_device *dev,
if (ret)
return ret;
- ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour);
+ ret = __netdev_lower_dev_insert(upper_dev, dev, master, neighbour,
+ private);
if (ret) {
__netdev_upper_dev_remove(dev, upper_dev);
return ret;
@@ -4745,14 +4757,15 @@ int __netdev_adjacent_dev_insert_link(struct net_device *dev,
static inline int __netdev_adjacent_dev_link(struct net_device *dev,
struct net_device *udev)
{
- return __netdev_adjacent_dev_insert_link(dev, udev, false, false);
+ return __netdev_adjacent_dev_insert_link(dev, udev, false, false, NULL);
}
static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
struct net_device *udev,
- bool master)
+ bool master, void *priv)
{
- return __netdev_adjacent_dev_insert_link(dev, udev, master, true);
+ return __netdev_adjacent_dev_insert_link(dev, udev, master, true,
+ priv);
}
void __netdev_adjacent_dev_unlink(struct net_device *dev,
@@ -4764,7 +4777,8 @@ void __netdev_adjacent_dev_unlink(struct net_device *dev,
static int __netdev_upper_dev_link(struct net_device *dev,
- struct net_device *upper_dev, bool master)
+ struct net_device *upper_dev, bool master,
+ void *private)
{
struct netdev_adjacent *i, *j, *to_i, *to_j;
int ret = 0;
@@ -4784,7 +4798,8 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (master && netdev_master_upper_dev_get(dev))
return -EBUSY;
- ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master);
+ ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master,
+ private);
if (ret)
return ret;
@@ -4875,7 +4890,7 @@ rollback_mesh:
int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, false);
+ return __netdev_upper_dev_link(dev, upper_dev, false, NULL);
}
EXPORT_SYMBOL(netdev_upper_dev_link);
@@ -4893,10 +4908,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link);
int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, true);
+ return __netdev_upper_dev_link(dev, upper_dev, true, NULL);
}
EXPORT_SYMBOL(netdev_master_upper_dev_link);
+int netdev_master_upper_dev_link_private(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private)
+{
+ return __netdev_upper_dev_link(dev, upper_dev, true, private);
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_link_private);
+
/**
* netdev_upper_dev_unlink - Removes a link to upper device
* @dev: device
@@ -4934,6 +4957,36 @@ void netdev_upper_dev_unlink(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
+void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
+ struct net_device *lower_dev)
+{
+ struct netdev_adjacent *lower;
+
+ if (!lower_dev)
+ return NULL;
+ lower = __netdev_find_lower_neighbour_rcu(dev, lower_dev);
+ if (!lower)
+ return NULL;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu);
+
+void *netdev_lower_dev_get_private(struct net_device *dev,
+ struct net_device *lower_dev)
+{
+ struct netdev_adjacent *lower;
+
+ if (!lower_dev)
+ return NULL;
+ lower = __netdev_find_lower_neighbour(dev, lower_dev);
+ if (!lower)
+ return NULL;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_private);
+
static void dev_change_rx_flags(struct net_device *dev, int flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 05/21] vlan: link the upper neighbour only after registering
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Patrick McHardy, David S. Miller
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Otherwise users might access it without being fully registered, as per
sysfs - it only inits in register_netdevice(), so is unusable till it is
called.
CC: Patrick McHardy <kaber@trash.net>
CC: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
net/8021q/vlan.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 61fc573..69b4a35 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -169,13 +169,13 @@ int register_vlan_dev(struct net_device *dev)
if (err < 0)
goto out_uninit_mvrp;
- err = netdev_upper_dev_link(real_dev, dev);
- if (err)
- goto out_uninit_mvrp;
-
err = register_netdevice(dev);
if (err < 0)
- goto out_upper_dev_unlink;
+ goto out_uninit_mvrp;
+
+ err = netdev_upper_dev_link(real_dev, dev);
+ if (err)
+ goto out_unregister_netdev;
/* Account for reference in struct vlan_dev_priv */
dev_hold(real_dev);
@@ -191,8 +191,8 @@ int register_vlan_dev(struct net_device *dev)
return 0;
-out_upper_dev_unlink:
- netdev_upper_dev_unlink(real_dev, dev);
+out_unregister_netdev:
+ unregister_netdevice(dev);
out_uninit_mvrp:
if (grp->nr_vlan_devs == 0)
vlan_mvrp_uninit_applicant(real_dev);
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 04/21] net: expose the master link to sysfs, and remove it from bond
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek, David S. Miller,
Eric Dumazet, Jiri Pirko, Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Currently, we can have only one master upper neighbour, so it would be
useful to create a symlink to it in the sysfs device directory, the way
that bonding now does it, for every device. Lower devices from
bridge/team/etc will automagically get it, so we could rely on it.
Also, remove the same functionality from bonding.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_sysfs.c | 12 +-----------
net/core/dev.c | 9 +++++++++
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 0f539de..5715277 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -174,20 +174,11 @@ int bond_create_slave_symlinks(struct net_device *master,
char linkname[IFNAMSIZ+7];
int ret = 0;
- /* first, create a link from the slave back to the master */
- ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
- "master");
- if (ret)
- return ret;
- /* next, create a link from the master to the slave */
+ /* create a link from the master to the slave */
sprintf(linkname, "slave_%s", slave->name);
ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
linkname);
- /* free the master link created earlier in case of error */
- if (ret)
- sysfs_remove_link(&(slave->dev.kobj), "master");
-
return ret;
}
@@ -197,7 +188,6 @@ void bond_destroy_slave_symlinks(struct net_device *master,
{
char linkname[IFNAMSIZ+7];
- sysfs_remove_link(&(slave->dev.kobj), "master");
sprintf(linkname, "slave_%s", slave->name);
sysfs_remove_link(&(master->dev.kobj), linkname);
}
diff --git a/net/core/dev.c b/net/core/dev.c
index fc5c5a1..7eecf35 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4580,6 +4580,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
bool upper, void *private)
{
struct netdev_adjacent *adj, *neigh = NULL;
+ int ret;
adj = __netdev_find_adj(dev, adj_dev, upper, false);
@@ -4636,6 +4637,12 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
/* Ensure that master upper link is always the first item in list. */
if (master) {
+ ret = sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj), "master");
+ if (ret) {
+ kfree(neigh);
+ kfree(adj);
+ return ret;
+ }
if (neigh)
list_add_rcu(&neigh->list,
&dev->neighbour_dev_list.upper);
@@ -4716,6 +4723,8 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
adj_dev->name, upper ? "upper" : "lower", dev->name,
adj_dev->name);
list_del_rcu(&neighbour->list);
+ if (neighbour->master && upper)
+ sysfs_remove_link(&(dev->dev.kobj), "master");
dev_put(adj_dev);
kfree_rcu(neighbour, rcu);
}
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 07/21] bonding: add bond_has_slaves() and use it
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Currently we verify if we have slaves by checking if bond->slave_list is
empty. Create a define bond_has_slaves() and use it, a bit more readable
and easier to change in the future.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 2 +-
drivers/net/bonding/bond_alb.c | 8 ++++----
drivers/net/bonding/bond_main.c | 32 ++++++++++++++++----------------
drivers/net/bonding/bond_sysfs.c | 4 ++--
drivers/net/bonding/bonding.h | 2 ++
5 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 9010265..f0cca88 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2117,7 +2117,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
read_lock(&bond->lock);
//check if there are any slaves
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
// check if agg_select_timer timer after initialize is timed out
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 0182352..a277465 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1177,7 +1177,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
struct slave *tmp_slave1, *free_mac_slave = NULL;
struct slave *has_bond_addr = bond->curr_active_slave;
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
/* this is the first slave */
return 0;
}
@@ -1464,7 +1464,7 @@ void bond_alb_monitor(struct work_struct *work)
read_lock(&bond->lock);
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
bond_info->tx_rebalance_counter = 0;
bond_info->lp_counter = 0;
goto re_arm;
@@ -1601,7 +1601,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
*/
void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
{
- if (!list_empty(&bond->slave_list))
+ if (bond_has_slaves(bond))
alb_change_hw_addr_on_detach(bond, slave);
tlb_clear_slave(bond, slave, 0);
@@ -1671,7 +1671,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
swap_slave = bond->curr_active_slave;
rcu_assign_pointer(bond->curr_active_slave, new_slave);
- if (!new_slave || list_empty(&bond->slave_list))
+ if (!new_slave || !bond_has_slaves(bond))
return;
/* set the new curr_active_slave to the bonds mac address
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b0b753d..b347b3d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -384,7 +384,7 @@ static int bond_set_carrier(struct bonding *bond)
{
struct slave *slave;
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto down;
if (bond->params.mode == BOND_MODE_8023AD)
@@ -1093,7 +1093,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
read_lock(&bond->lock);
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
/* Disable adding VLANs to empty bond. But why? --mq */
features |= NETIF_F_VLAN_CHALLENGED;
goto out;
@@ -1131,7 +1131,7 @@ static void bond_compute_features(struct bonding *bond)
read_lock(&bond->lock);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto done;
bond_for_each_slave(bond, slave) {
@@ -1322,7 +1322,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* bond ether type mutual exclusion - don't allow slaves of dissimilar
* ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
*/
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
if (bond_dev->type != slave_dev->type) {
pr_debug("%s: change device type from %d to %d\n",
bond_dev->name,
@@ -1361,7 +1361,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
}
if (slave_ops->ndo_set_mac_address == NULL) {
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.",
bond_dev->name);
bond->params.fail_over_mac = BOND_FOM_ACTIVE;
@@ -1377,7 +1377,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* If this is the first slave, then we need to set the master's hardware
* address to be the same as the slave's. */
- if (list_empty(&bond->slave_list) &&
+ if (!bond_has_slaves(bond) &&
bond->dev->addr_assign_type == NET_ADDR_RANDOM)
bond_set_dev_addr(bond->dev, slave_dev);
@@ -1700,7 +1700,7 @@ err_free:
err_undo_flags:
bond_compute_features(bond);
/* Enslave of first slave has failed and we need to fix master's mac */
- if (list_empty(&bond->slave_list) &&
+ if (!bond_has_slaves(bond) &&
ether_addr_equal(bond_dev->dev_addr, slave_dev->dev_addr))
eth_hw_addr_random(bond_dev);
@@ -1778,7 +1778,7 @@ static int __bond_release_one(struct net_device *bond_dev,
if (!all && !bond->params.fail_over_mac) {
if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
- !list_empty(&bond->slave_list))
+ bond_has_slaves(bond))
pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
bond_dev->name, slave_dev->name,
slave->perm_hwaddr,
@@ -1821,7 +1821,7 @@ static int __bond_release_one(struct net_device *bond_dev,
write_lock_bh(&bond->lock);
}
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
bond_set_carrier(bond);
eth_hw_addr_random(bond_dev);
@@ -1837,7 +1837,7 @@ static int __bond_release_one(struct net_device *bond_dev,
unblock_netpoll_tx();
synchronize_rcu();
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
}
@@ -1906,7 +1906,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
int ret;
ret = bond_release(bond_dev, slave_dev);
- if (ret == 0 && list_empty(&bond->slave_list)) {
+ if (ret == 0 && !bond_has_slaves(bond)) {
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
pr_info("%s: destroying bond %s.\n",
bond_dev->name, bond_dev->name);
@@ -2218,7 +2218,7 @@ void bond_mii_monitor(struct work_struct *work)
delay = msecs_to_jiffies(bond->params.miimon);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
should_notify_peers = bond_should_notify_peers(bond);
@@ -2513,7 +2513,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
read_lock(&bond->lock);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
oldcurrent = bond->curr_active_slave;
@@ -2833,7 +2833,7 @@ void bond_activebackup_arp_mon(struct work_struct *work)
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
should_notify_peers = bond_should_notify_peers(bond);
@@ -3156,7 +3156,7 @@ static int bond_open(struct net_device *bond_dev)
/* reset slave->backup and slave->inactive */
read_lock(&bond->lock);
- if (!list_empty(&bond->slave_list)) {
+ if (bond_has_slaves(bond)) {
read_lock(&bond->curr_slave_lock);
bond_for_each_slave(bond, slave) {
if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
@@ -3873,7 +3873,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
rcu_read_lock();
- if (!list_empty(&bond->slave_list))
+ if (bond_has_slaves(bond))
ret = __bond_start_xmit(skb, dev);
else
kfree_skb(skb);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 7b962a2..8721dcb 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -291,7 +291,7 @@ static ssize_t bonding_store_mode(struct device *d,
goto out;
}
- if (!list_empty(&bond->slave_list)) {
+ if (bond_has_slaves(bond)) {
pr_err("unable to update mode of %s because it has slaves.\n",
bond->dev->name);
ret = -EPERM;
@@ -473,7 +473,7 @@ static ssize_t bonding_store_fail_over_mac(struct device *d,
if (!rtnl_trylock())
return restart_syscall();
- if (!list_empty(&bond->slave_list)) {
+ if (bond_has_slaves(bond)) {
pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
bond->dev->name);
ret = -EPERM;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index f7a167d..5645cd2 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -72,6 +72,8 @@
res; })
/* slave list primitives */
+#define bond_has_slaves(bond) !list_empty(&(bond)->slave_list)
+
#define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 08/21] bonding: convert bond_has_slaves() to use the neighbour list
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
The same way as it was used for its own slave_list.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bonding.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 5645cd2..37055cd 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -72,7 +72,7 @@
res; })
/* slave list primitives */
-#define bond_has_slaves(bond) !list_empty(&(bond)->slave_list)
+#define bond_has_slaves(bond) !list_empty(&(bond)->dev->neighbour_dev_list.lower)
#define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 09/21] bonding: populate neighbour's private on enslave
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Use the new provided function when attaching the lower slave to populate
its ->private with struct slave *new_slave. Also, move it to the end to
be able to 'find' it only after it was completely initialized, and
deinitialize in the first place on release.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_main.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b347b3d..427d943 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1242,11 +1242,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
}
static int bond_master_upper_dev_link(struct net_device *bond_dev,
- struct net_device *slave_dev)
+ struct net_device *slave_dev,
+ struct slave *slave)
{
int err;
- err = netdev_master_upper_dev_link(slave_dev, bond_dev);
+ err = netdev_master_upper_dev_link_private(slave_dev, bond_dev, slave);
if (err)
return err;
slave_dev->flags |= IFF_SLAVE;
@@ -1422,17 +1423,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
}
}
- res = bond_master_upper_dev_link(bond_dev, slave_dev);
- if (res) {
- pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
- goto err_restore_mac;
- }
-
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
pr_debug("Opening slave %s failed\n", slave_dev->name);
- goto err_unset_master;
+ goto err_restore_mac;
}
new_slave->bond = bond;
@@ -1642,6 +1637,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_detach;
}
+ res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave);
+ if (res) {
+ pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
+ goto err_unregister;
+ }
+
+
pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
bond_is_active_slave(new_slave) ? "n active" : " backup",
@@ -1651,6 +1653,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
return 0;
/* Undo stages on error */
+err_unregister:
+ netdev_rx_handler_unregister(slave_dev);
+
err_detach:
if (!USES_PRIMARY(bond->params.mode))
bond_hw_addr_flush(bond_dev, slave_dev);
@@ -1677,9 +1682,6 @@ err_close:
slave_dev->priv_flags &= ~IFF_BONDING;
dev_close(slave_dev);
-err_unset_master:
- bond_upper_dev_unlink(bond_dev, slave_dev);
-
err_restore_mac:
if (!bond->params.fail_over_mac) {
/* XXX TODO - fom follow mode needs to change master's
@@ -1750,6 +1752,8 @@ static int __bond_release_one(struct net_device *bond_dev,
}
write_unlock_bh(&bond->lock);
+
+ bond_upper_dev_unlink(bond_dev, slave_dev);
/* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore.
*/
@@ -1866,8 +1870,6 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_hw_addr_flush(bond_dev, slave_dev);
}
- bond_upper_dev_unlink(bond_dev, slave_dev);
-
slave_disable_netpoll(slave);
/* close slave before restoring its mac address */
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 06/21] net: create sysfs symlinks for neighbour devices
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek, David S. Miller,
Eric Dumazet, Jiri Pirko, Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Also, remove the same functionality from bonding - it will be already done
for any device that links to its lower/upper neighbour.
The links will be created for dev's kobject, and will look like
slave_eth0 for lower device eth0 and upper_bridge0 for upper device
bridge0.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_main.c | 11 +----------
drivers/net/bonding/bond_sysfs.c | 25 -------------------------
drivers/net/bonding/bonding.h | 2 --
net/core/dev.c | 29 +++++++++++++++++++++++++++++
4 files changed, 30 insertions(+), 37 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index c50679f..b0b753d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1635,15 +1635,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
read_unlock(&bond->lock);
- res = bond_create_slave_symlinks(bond_dev, slave_dev);
- if (res)
- goto err_detach;
-
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
new_slave);
if (res) {
pr_debug("Error %d calling netdev_rx_handler_register\n", res);
- goto err_dest_symlinks;
+ goto err_detach;
}
pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
@@ -1655,9 +1651,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
return 0;
/* Undo stages on error */
-err_dest_symlinks:
- bond_destroy_slave_symlinks(bond_dev, slave_dev);
-
err_detach:
if (!USES_PRIMARY(bond->params.mode))
bond_hw_addr_flush(bond_dev, slave_dev);
@@ -1856,8 +1849,6 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_dev->name, slave_dev->name, bond_dev->name);
/* must do this from outside any spinlocks */
- bond_destroy_slave_symlinks(bond_dev, slave_dev);
-
vlan_vids_del_by_dev(slave_dev, bond_dev);
/* If the mode USES_PRIMARY, then this cases was handled above by
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 5715277..7b962a2 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -168,31 +168,6 @@ static const struct class_attribute class_attr_bonding_masters = {
.namespace = bonding_namespace,
};
-int bond_create_slave_symlinks(struct net_device *master,
- struct net_device *slave)
-{
- char linkname[IFNAMSIZ+7];
- int ret = 0;
-
- /* create a link from the master to the slave */
- sprintf(linkname, "slave_%s", slave->name);
- ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
- linkname);
-
- return ret;
-
-}
-
-void bond_destroy_slave_symlinks(struct net_device *master,
- struct net_device *slave)
-{
- char linkname[IFNAMSIZ+7];
-
- sprintf(linkname, "slave_%s", slave->name);
- sysfs_remove_link(&(master->dev.kobj), linkname);
-}
-
-
/*
* Show the slaves in the current bond.
*/
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 4abc925..f7a167d 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -455,8 +455,6 @@ int bond_create(struct net *net, const char *name);
int bond_create_sysfs(struct bond_net *net);
void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond);
-int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
-void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_mii_monitor(struct work_struct *);
diff --git a/net/core/dev.c b/net/core/dev.c
index 7eecf35..1c3e98d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4580,6 +4580,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
bool upper, void *private)
{
struct netdev_adjacent *adj, *neigh = NULL;
+ char linkname[IFNAMSIZ+7];
int ret;
adj = __netdev_find_adj(dev, adj_dev, upper, false);
@@ -4628,6 +4629,16 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
*/
if (master)
neigh->private = private;
+
+ sprintf(linkname, "slave_%s", adj_dev->name);
+ ret = sysfs_create_link(&(dev->dev.kobj),
+ &(adj_dev->dev.kobj),
+ linkname);
+ if (ret) {
+ kfree(neigh);
+ kfree(adj);
+ return ret;
+ }
list_add_tail_rcu(&neigh->list,
&dev->neighbour_dev_list.lower);
}
@@ -4635,10 +4646,24 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
return 0;
}
+ /* it's upper neighbour, we don't care if it's master or not */
+ if (neigh) {
+ sprintf(linkname, "upper_%s", adj_dev->name);
+ ret = sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj),
+ linkname);
+ if (ret) {
+ kfree(neigh);
+ kfree(adj);
+ return ret;
+ }
+ }
+
/* Ensure that master upper link is always the first item in list. */
if (master) {
ret = sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj), "master");
if (ret) {
+ if (neigh)
+ sysfs_remove_link(&(dev->dev.kobj), linkname);
kfree(neigh);
kfree(adj);
return ret;
@@ -4678,6 +4703,7 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
struct net_device *adj_dev, bool upper)
{
struct netdev_adjacent *adj, *neighbour;
+ char linkname[IFNAMSIZ+7];
if (upper) {
adj = __netdev_find_upper(dev, adj_dev);
@@ -4725,6 +4751,9 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
list_del_rcu(&neighbour->list);
if (neighbour->master && upper)
sysfs_remove_link(&(dev->dev.kobj), "master");
+ sprintf(linkname, "%s_%s", upper ? "upper" : "slave",
+ adj_dev->name);
+ sysfs_remove_link(&(dev->dev.kobj), linkname);
dev_put(adj_dev);
kfree_rcu(neighbour, rcu);
}
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 11/21] bonding: remove bond_for_each_slave_reverse()
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
We only use it in rollback scenarios and can easily use the standart
bond_for_each_dev() instead.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_alb.c | 14 ++++++++------
drivers/net/bonding/bond_main.c | 34 ++++++++++++++++++++++------------
drivers/net/bonding/bonding.h | 10 ----------
3 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index a277465..bda976f 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1248,9 +1248,9 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
*/
static int alb_set_mac_address(struct bonding *bond, void *addr)
{
- char tmp_addr[ETH_ALEN];
- struct slave *slave;
+ struct slave *slave, *rollback_slave;
struct sockaddr sa;
+ char tmp_addr[ETH_ALEN];
int res;
if (bond->alb_info.rlb_enabled)
@@ -1276,10 +1276,12 @@ unwind:
sa.sa_family = bond->dev->type;
/* unwind from head to the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave) {
- memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
- dev_set_mac_address(slave->dev, &sa);
- memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+ bond_for_each_slave(bond, rollback_slave) {
+ if (rollback_slave == slave)
+ break;
+ memcpy(tmp_addr, rollback_slave->dev->dev_addr, ETH_ALEN);
+ dev_set_mac_address(rollback_slave->dev, &sa);
+ memcpy(rollback_slave->dev->dev_addr, tmp_addr, ETH_ALEN);
}
return res;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 427d943..0a4aa0d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -332,7 +332,7 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
__be16 proto, u16 vid)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave;
+ struct slave *slave, *rollback_slave;
int res;
bond_for_each_slave(bond, slave) {
@@ -344,9 +344,13 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
return 0;
unwind:
- /* unwind from the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave)
- vlan_vid_del(slave->dev, proto, vid);
+ /* unwind to the slave that failed */
+ bond_for_each_slave(bond, rollback_slave) {
+ if (rollback_slave == slave)
+ break;
+
+ vlan_vid_del(rollback_slave->dev, proto, vid);
+ }
return res;
}
@@ -3477,7 +3481,7 @@ static int bond_neigh_setup(struct net_device *dev,
static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave;
+ struct slave *slave, *rollback_slave;
int res = 0;
pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
@@ -3526,13 +3530,16 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
unwind:
/* unwind from head to the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave) {
+ bond_for_each_slave(bond, rollback_slave) {
int tmp_res;
- tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
+ if (rollback_slave == slave);
+ break;
+
+ tmp_res = dev_set_mtu(rollback_slave->dev, bond_dev->mtu);
if (tmp_res) {
pr_debug("unwind err %d dev %s\n",
- tmp_res, slave->dev->name);
+ tmp_res, rollback_slave->dev->name);
}
}
@@ -3549,8 +3556,8 @@ unwind:
static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave, *rollback_slave;
struct sockaddr *sa = addr, tmp_sa;
- struct slave *slave;
int res = 0;
if (bond->params.mode == BOND_MODE_ALB)
@@ -3616,13 +3623,16 @@ unwind:
tmp_sa.sa_family = bond_dev->type;
/* unwind from head to the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave) {
+ bond_for_each_slave(bond, rollback_slave) {
int tmp_res;
- tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
+ if (rollback_slave == slave)
+ break;
+
+ tmp_res = dev_set_mac_address(rollback_slave->dev, &tmp_sa);
if (tmp_res) {
pr_debug("unwind err %d dev %s\n",
- tmp_res, slave->dev->name);
+ tmp_res, rollback_slave->dev->name);
}
}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 7cb60f9..8c11f96 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -122,16 +122,6 @@
#define bond_for_each_slave_rcu(bond, pos) \
list_for_each_entry_rcu(pos, &(bond)->slave_list, list)
-/**
- * bond_for_each_slave_reverse - iterate in reverse from a given position
- * @bond: the bond holding this list
- * @pos: slave to continue from
- *
- * Caller must hold bond->lock
- */
-#define bond_for_each_slave_continue_reverse(bond, pos) \
- list_for_each_entry_continue_reverse(pos, &(bond)->slave_list, list)
-
#ifdef CONFIG_NET_POLL_CONTROLLER
extern atomic_t netpoll_block_tx;
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 12/21] net: add for_each iterators through neighbour lower link's private
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Currently we can only iterate through the devices itself, however it'd be
really costy to first get the next device and then search for the link and
get its private - which is a common method to go through slaves of a
device.
Add both RCU and RTNL/other locking variants of iterators.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
include/linux/netdevice.h | 17 ++++++++++++
net/core/dev.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ef1ddee..1a149ef 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2788,6 +2788,23 @@ extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
updev; \
updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+extern void *netdev_lower_neigh_get_next_private(struct net_device *dev,
+ struct list_head **iter);
+extern void *netdev_lower_neigh_get_next_private_rcu(struct net_device *dev,
+ struct list_head **iter);
+
+#define netdev_for_each_lower_neigh_private(dev, priv, iter) \
+ for (iter = &(dev)->neighbour_dev_list.lower, \
+ priv = netdev_lower_neigh_get_next_private(dev, &(iter)); \
+ priv; \
+ priv = netdev_lower_neigh_get_next_private(dev, &(iter)))
+
+#define netdev_for_each_lower_neigh_private_rcu(dev, priv, iter) \
+ for (iter = &(dev)->neighbour_dev_list.lower, \
+ priv = netdev_lower_neigh_get_next_private_rcu(dev, &(iter)); \
+ priv; \
+ priv = netdev_lower_neigh_get_next_private_rcu(dev, &(iter)))
+
extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
extern int netdev_upper_dev_link(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index 1c3e98d..55f8ac4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4555,6 +4555,72 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+/* netdev_lower_neigh_get_next_private - Get the next ->private from the
+ * lower neighbour list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold either hold the
+ * RTNL lock or its own locking that guarantees that the neighbour lower
+ * list will remain unchainged. If iter is NULL - return the first private.
+ */
+void *netdev_lower_neigh_get_next_private(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *lower;
+
+ if (iter)
+ lower = list_entry((*iter)->next, struct netdev_adjacent,
+ list);
+ else
+ lower = list_entry(dev->neighbour_dev_list.lower.next,
+ struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->neighbour_dev_list.lower)
+ return NULL;
+
+ if (iter)
+ *iter = &lower->list;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_neigh_get_next_private);
+
+/* netdev_lower_neigh_get_next_private_rcu - Get the next ->private from the
+ * lower neighbour list, RCU
+ * variant
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold RCU read lock.
+ * If iter is NULL - returns the first private.
+ */
+void *netdev_lower_neigh_get_next_private_rcu(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *lower;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ if (iter)
+ lower = list_entry_rcu((*iter)->next, struct netdev_adjacent,
+ list);
+ else
+ lower = list_entry_rcu(dev->neighbour_dev_list.lower.next,
+ struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->neighbour_dev_list.lower)
+ return NULL;
+
+ if (iter)
+ *iter = &lower->list;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_neigh_get_next_private_rcu);
+
/**
* netdev_master_upper_dev_get_rcu - Get master upper device
* @dev: device
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 14/21] net: add netdev_for_each_lower_neigh_private_continue()
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
This macro allows going through the neighbour lower list private's from a
specific position and till it doesn't hit the same position again.
For that, two functions are needed:
netdev_lower_neigh_set_iter_per_private(dev, iter, from_priv) - which
searches for from_priv and, if found, sets the iter to the correct
position, returning from_priv.
netdev_lower_neigh_get_next_private_to(dev, iter, from_priv) - gets the
next ->private (and skips the list head), or if the next private equals
from_priv - returns NULL. Also returns NULL if the ->private is NULL, to
catch the case if the list doesn't have any elements.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
include/linux/netdevice.h | 14 +++++++++++
net/core/dev.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 76 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1a149ef..20afdf98 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2788,6 +2788,20 @@ extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
updev; \
updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+extern void *netdev_lower_neigh_set_iter_per_private(struct net_device *dev,
+ struct list_head **iter,
+ void *private);
+extern void *netdev_lower_neigh_get_next_private_to(struct net_device *dev,
+ struct list_head **iter,
+ void *to);
+
+#define netdev_for_each_lower_neigh_private_continue(dev, priv, from_priv, iter) \
+ for (priv = netdev_lower_neigh_set_iter_per_private(dev, &(iter), \
+ from_priv); \
+ priv; \
+ priv = netdev_lower_neigh_get_next_private_to(dev, &(iter), \
+ from_priv))
+
extern void *netdev_lower_neigh_get_next_private(struct net_device *dev,
struct list_head **iter);
extern void *netdev_lower_neigh_get_next_private_rcu(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index 55f8ac4..1b9862b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4555,6 +4555,68 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+/* netdev_lower_neigh_set_iter_per_private - Set the iter to reflect the
+ * position of the ->private
+ * @dev: device
+ * @iter: iter to be set
+ * @private: private to be found
+ *
+ * Iterates through lower neighbours, searching for private. When found,
+ * sets the iter to the ->list. Returns private or NULL if not found. User
+ * must hold RTNL lock or make sure that the list isn't modified.
+ */
+void *netdev_lower_neigh_set_iter_per_private(struct net_device *dev,
+ struct list_head **iter,
+ void *private)
+{
+ struct netdev_adjacent *lower;
+
+ list_for_each_entry(lower, &dev->neighbour_dev_list.lower, list)
+ if (lower->private == private)
+ break;
+
+ if (&lower->list == &dev->neighbour_dev_list.lower)
+ return NULL;
+
+ *iter = &lower->list;
+
+ return private;
+}
+EXPORT_SYMBOL(netdev_lower_neigh_set_iter_per_private);
+
+/* netdev_lower_neigh_get_next_private_to - Get the next ->private from the
+ * lower neighbour list, stop at to
+ * @dev: device
+ * @iter: list_head ** of the current position
+ * @to: if private == to then stop
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold either hold the
+ * RTNL lock or its own locking that guarantees that the neighbour lower
+ * list will remain unchainged. Stops when private == to or when it hits a
+ * NULL private.
+ */
+void *netdev_lower_neigh_get_next_private_to(struct net_device *dev,
+ struct list_head **iter,
+ void *to)
+{
+ struct netdev_adjacent *lower;
+
+ lower = list_entry((*iter)->next, struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->neighbour_dev_list.lower)
+ lower = list_entry(lower->list.next, struct netdev_adjacent,
+ list);
+
+ if (lower->private == to || !lower->private)
+ return NULL;
+
+ *iter = &lower->list;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_neigh_get_next_private_to);
+
/* netdev_lower_neigh_get_next_private - Get the next ->private from the
* lower neighbour list
* @dev: device
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 15/21] bonding: use neighbour list for bond_for_each_slave_continue()
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
Use netdev_for_each_lower_neigh_private_continue() macro to iterate through
bonding slaves. It needs a struct list_head *, so add where needed.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 3 +--
drivers/net/bonding/bond_alb.c | 4 ++--
drivers/net/bonding/bond_main.c | 8 ++++----
drivers/net/bonding/bonding.h | 7 +++----
4 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7430cbb..325ce90 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2423,7 +2423,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
int slave_agg_no;
int slaves_in_agg;
int agg_id;
- int i;
struct ad_info ad_info;
int res = 1;
@@ -2463,7 +2462,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
start_at = slave;
- bond_for_each_slave_from(bond, slave, i, start_at) {
+ bond_for_each_slave_from(bond, slave, iter, start_at) {
int slave_agg_id = 0;
struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 738eeae..9633ca2 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -384,7 +384,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct slave *rx_slave, *slave, *start_at;
- int i = 0;
+ struct list_head *iter;
if (bond_info->next_rx_slave)
start_at = bond_info->next_rx_slave;
@@ -393,7 +393,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
rx_slave = NULL;
- bond_for_each_slave_from(bond, slave, i, start_at) {
+ bond_for_each_slave_from(bond, slave, iter, start_at) {
if (SLAVE_IS_OK(slave)) {
if (!rx_slave) {
rx_slave = slave;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 297b910..59814c9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -792,8 +792,8 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
{
struct slave *new_active, *old_active;
struct slave *bestslave = NULL;
+ struct list_head *iter;
int mintime = bond->params.updelay;
- int i;
new_active = bond->curr_active_slave;
@@ -812,7 +812,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
/* remember where to stop iterating over the slaves */
old_active = new_active;
- bond_for_each_slave_from(bond, new_active, i, old_active) {
+ bond_for_each_slave_from(bond, new_active, iter, old_active) {
if (new_active->link == BOND_LINK_UP) {
return new_active;
} else if (new_active->link == BOND_LINK_BACK &&
@@ -2783,7 +2783,7 @@ do_failover:
static void bond_ab_arp_probe(struct bonding *bond)
{
struct slave *slave, *next_slave;
- int i;
+ struct list_head *iter;
read_lock(&bond->curr_slave_lock);
@@ -2815,7 +2815,7 @@ static void bond_ab_arp_probe(struct bonding *bond)
/* search for next candidate */
next_slave = bond_next_slave(bond, bond->current_arp_slave);
- bond_for_each_slave_from(bond, slave, i, next_slave) {
+ bond_for_each_slave_from(bond, slave, iter, next_slave) {
if (IS_UP(slave->dev)) {
slave->link = BOND_LINK_BACK;
bond_set_slave_active_flags(slave);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index b6dc9db..583077d 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -99,14 +99,13 @@
* bond_for_each_slave_from - iterate the slaves list from a starting point
* @bond: the bond holding this list.
* @pos: current slave.
- * @cnt: counter for max number of moves
+ * @iter: list_head * iterator
* @start: starting point.
*
* Caller must hold bond->lock
*/
-#define bond_for_each_slave_from(bond, pos, cnt, start) \
- for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \
- cnt++, pos = bond_next_slave(bond, pos))
+#define bond_for_each_slave_from(bond, pos, iter, start) \
+ netdev_for_each_lower_neigh_private_continue((bond)->dev, pos, start, iter)
/**
* bond_for_each_slave - iterate over all slaves
--
1.8.4
^ permalink raw reply related
* [PATCH RFC net-next 16/21] net: add a possibility to get private from netdev_adjacent->list
From: Veaceslav Falico @ 2013-09-02 21:39 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck
In-Reply-To: <1378157965-17537-1-git-send-email-vfalico@redhat.com>
It will be useful to get first/last element.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
include/linux/netdevice.h | 1 +
net/core/dev.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 20afdf98..bde2244 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2819,6 +2819,7 @@ extern void *netdev_lower_neigh_get_next_private_rcu(struct net_device *dev,
priv; \
priv = netdev_lower_neigh_get_next_private_rcu(dev, &(iter)))
+extern void *netdev_adjacent_get_private(struct list_head *adj_list);
extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
extern int netdev_upper_dev_link(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index 1b9862b..6df11a0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4530,6 +4530,16 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
+void *netdev_adjacent_get_private(struct list_head *adj_list)
+{
+ struct netdev_adjacent *adj;
+
+ adj = list_entry(adj_list, struct netdev_adjacent, list);
+
+ return adj->private;
+}
+EXPORT_SYMBOL(netdev_adjacent_get_private);
+
/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list
* @dev: device
* @iter: list_head ** of the current position
--
1.8.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox