]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/rocker/rocker.c
Merge remote-tracking branch 'sound-current/for-linus'
[karo-tx-linux.git] / drivers / net / ethernet / rocker / rocker.c
index 102b37d95d85a575e4ca7fc5ee91704ac7545570..32a80d2df7ffc161e86feab52ee850c2660afcf9 100644 (file)
@@ -228,7 +228,6 @@ struct rocker_port {
        struct napi_struct napi_rx;
        struct rocker_dma_ring_info tx_ring;
        struct rocker_dma_ring_info rx_ring;
-       struct list_head trans_mem;
 };
 
 struct rocker {
@@ -346,13 +345,13 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
                                     struct switchdev_trans *trans, int flags,
                                     size_t size)
 {
-       struct list_head *elem = NULL;
+       struct switchdev_trans_item *elem = NULL;
        gfp_t gfp_flags = (flags & ROCKER_OP_FLAG_NOWAIT) ?
                          GFP_ATOMIC : GFP_KERNEL;
 
        /* If in transaction prepare phase, allocate the memory
-        * and enqueue it on a per-port list.  If in transaction
-        * commit phase, dequeue the memory from the per-port list
+        * and enqueue it on a transaction.  If in transaction
+        * commit phase, dequeue the memory from the transaction
         * rather than re-allocating the memory.  The idea is the
         * driver code paths for prepare and commit are identical
         * so the memory allocated in the prepare phase is the
@@ -361,17 +360,13 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
 
        if (!trans) {
                elem = kzalloc(size + sizeof(*elem), gfp_flags);
-               if (elem)
-                       INIT_LIST_HEAD(elem);
        } else if (switchdev_trans_ph_prepare(trans)) {
                elem = kzalloc(size + sizeof(*elem), gfp_flags);
                if (!elem)
                        return NULL;
-               list_add_tail(elem, &rocker_port->trans_mem);
+               switchdev_trans_item_enqueue(trans, elem, kfree, elem);
        } else {
-               BUG_ON(list_empty(&rocker_port->trans_mem));
-               elem = rocker_port->trans_mem.next;
-               list_del_init(elem);
+               elem = switchdev_trans_item_dequeue(trans);
        }
 
        return elem ? elem + 1 : NULL;
@@ -393,7 +388,7 @@ static void *rocker_port_kcalloc(struct rocker_port *rocker_port,
 
 static void rocker_port_kfree(struct switchdev_trans *trans, const void *mem)
 {
-       struct list_head *elem;
+       struct switchdev_trans_item *elem;
 
        /* Frees are ignored if in transaction prepare phase.  The
         * memory remains on the per-port list until freed in the
@@ -403,8 +398,7 @@ static void rocker_port_kfree(struct switchdev_trans *trans, const void *mem)
        if (switchdev_trans_ph_prepare(trans))
                return;
 
-       elem = (struct list_head *)mem - 1;
-       BUG_ON(!list_empty(elem));
+       elem = (struct switchdev_trans_item *) mem - 1;
        kfree(elem);
 }
 
@@ -3678,7 +3672,7 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
            rocker_port->stp_state == BR_STATE_FORWARDING)
                return 0;
 
-       flags |= ROCKER_OP_FLAG_REMOVE;
+       flags |= ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE;
 
        spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags);
 
@@ -4335,11 +4329,11 @@ static int rocker_port_attr_get(struct net_device *dev,
        const struct rocker *rocker = rocker_port->rocker;
 
        switch (attr->id) {
-       case SWITCHDEV_ATTR_PORT_PARENT_ID:
+       case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
                attr->u.ppid.id_len = sizeof(rocker->hw.id);
                memcpy(&attr->u.ppid.id, &rocker->hw.id, attr->u.ppid.id_len);
                break;
-       case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS:
+       case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
                attr->u.brport_flags = rocker_port->brport_flags;
                break;
        default:
@@ -4349,16 +4343,6 @@ static int rocker_port_attr_get(struct net_device *dev,
        return 0;
 }
 
-static void rocker_port_trans_abort(const struct rocker_port *rocker_port)
-{
-       struct list_head *mem, *tmp;
-
-       list_for_each_safe(mem, tmp, &rocker_port->trans_mem) {
-               list_del(mem);
-               kfree(mem);
-       }
-}
-
 static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
                                        struct switchdev_trans *trans,
                                        unsigned long brport_flags)
@@ -4377,34 +4361,38 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
        return err;
 }
 
+static int rocker_port_bridge_ageing_time(struct rocker_port *rocker_port,
+                                         struct switchdev_trans *trans,
+                                         u32 ageing_time)
+{
+       if (!switchdev_trans_ph_prepare(trans)) {
+               rocker_port->ageing_time = clock_t_to_jiffies(ageing_time);
+               mod_timer(&rocker_port->rocker->fdb_cleanup_timer, jiffies);
+       }
+
+       return 0;
+}
+
 static int rocker_port_attr_set(struct net_device *dev,
-                               struct switchdev_attr *attr,
+                               const struct switchdev_attr *attr,
                                struct switchdev_trans *trans)
 {
        struct rocker_port *rocker_port = netdev_priv(dev);
        int err = 0;
 
-       switch (trans->ph) {
-       case SWITCHDEV_TRANS_PREPARE:
-               BUG_ON(!list_empty(&rocker_port->trans_mem));
-               break;
-       case SWITCHDEV_TRANS_ABORT:
-               rocker_port_trans_abort(rocker_port);
-               return 0;
-       default:
-               break;
-       }
-
        switch (attr->id) {
-       case SWITCHDEV_ATTR_PORT_STP_STATE:
-               err = rocker_port_stp_update(rocker_port, trans,
-                                            ROCKER_OP_FLAG_NOWAIT,
+       case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
+               err = rocker_port_stp_update(rocker_port, trans, 0,
                                             attr->u.stp_state);
                break;
-       case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS:
+       case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
                err = rocker_port_brport_flags_set(rocker_port, trans,
                                                   attr->u.brport_flags);
                break;
+       case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
+               err = rocker_port_bridge_ageing_time(rocker_port, trans,
+                                                    attr->u.ageing_time);
+               break;
        default:
                err = -EOPNOTSUPP;
                break;
@@ -4435,7 +4423,7 @@ static int rocker_port_vlan_add(struct rocker_port *rocker_port,
 
 static int rocker_port_vlans_add(struct rocker_port *rocker_port,
                                 struct switchdev_trans *trans,
-                                const struct switchdev_obj_vlan *vlan)
+                                const struct switchdev_obj_port_vlan *vlan)
 {
        u16 vid;
        int err;
@@ -4452,7 +4440,7 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port,
 
 static int rocker_port_fdb_add(struct rocker_port *rocker_port,
                               struct switchdev_trans *trans,
-                              const struct switchdev_obj_fdb *fdb)
+                              const struct switchdev_obj_port_fdb *fdb)
 {
        __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
        int flags = 0;
@@ -4464,37 +4452,27 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port,
 }
 
 static int rocker_port_obj_add(struct net_device *dev,
-                              struct switchdev_obj *obj,
+                              const struct switchdev_obj *obj,
                               struct switchdev_trans *trans)
 {
        struct rocker_port *rocker_port = netdev_priv(dev);
        const struct switchdev_obj_ipv4_fib *fib4;
        int err = 0;
 
-       switch (trans->ph) {
-       case SWITCHDEV_TRANS_PREPARE:
-               BUG_ON(!list_empty(&rocker_port->trans_mem));
-               break;
-       case SWITCHDEV_TRANS_ABORT:
-               rocker_port_trans_abort(rocker_port);
-               return 0;
-       default:
-               break;
-       }
-
        switch (obj->id) {
-       case SWITCHDEV_OBJ_PORT_VLAN:
+       case SWITCHDEV_OBJ_ID_PORT_VLAN:
                err = rocker_port_vlans_add(rocker_port, trans,
-                                           &obj->u.vlan);
+                                           SWITCHDEV_OBJ_PORT_VLAN(obj));
                break;
-       case SWITCHDEV_OBJ_IPV4_FIB:
-               fib4 = &obj->u.ipv4_fib;
+       case SWITCHDEV_OBJ_ID_IPV4_FIB:
+               fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
                err = rocker_port_fib_ipv4(rocker_port, trans,
                                           htonl(fib4->dst), fib4->dst_len,
-                                          fib4->fi, fib4->tb_id, 0);
+                                          &fib4->fi, fib4->tb_id, 0);
                break;
-       case SWITCHDEV_OBJ_PORT_FDB:
-               err = rocker_port_fdb_add(rocker_port, trans, &obj->u.fdb);
+       case SWITCHDEV_OBJ_ID_PORT_FDB:
+               err = rocker_port_fdb_add(rocker_port, trans,
+                                         SWITCHDEV_OBJ_PORT_FDB(obj));
                break;
        default:
                err = -EOPNOTSUPP;
@@ -4519,7 +4497,7 @@ static int rocker_port_vlan_del(struct rocker_port *rocker_port,
 }
 
 static int rocker_port_vlans_del(struct rocker_port *rocker_port,
-                                const struct switchdev_obj_vlan *vlan)
+                                const struct switchdev_obj_port_vlan *vlan)
 {
        u16 vid;
        int err;
@@ -4535,10 +4513,10 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port,
 
 static int rocker_port_fdb_del(struct rocker_port *rocker_port,
                               struct switchdev_trans *trans,
-                              const struct switchdev_obj_fdb *fdb)
+                              const struct switchdev_obj_port_fdb *fdb)
 {
        __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
-       int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE;
+       int flags = ROCKER_OP_FLAG_REMOVE;
 
        if (!rocker_port_is_bridged(rocker_port))
                return -EINVAL;
@@ -4547,25 +4525,27 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port,
 }
 
 static int rocker_port_obj_del(struct net_device *dev,
-                              struct switchdev_obj *obj)
+                              const struct switchdev_obj *obj)
 {
        struct rocker_port *rocker_port = netdev_priv(dev);
        const struct switchdev_obj_ipv4_fib *fib4;
        int err = 0;
 
        switch (obj->id) {
-       case SWITCHDEV_OBJ_PORT_VLAN:
-               err = rocker_port_vlans_del(rocker_port, &obj->u.vlan);
+       case SWITCHDEV_OBJ_ID_PORT_VLAN:
+               err = rocker_port_vlans_del(rocker_port,
+                                           SWITCHDEV_OBJ_PORT_VLAN(obj));
                break;
-       case SWITCHDEV_OBJ_IPV4_FIB:
-               fib4 = &obj->u.ipv4_fib;
+       case SWITCHDEV_OBJ_ID_IPV4_FIB:
+               fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
                err = rocker_port_fib_ipv4(rocker_port, NULL,
                                           htonl(fib4->dst), fib4->dst_len,
-                                          fib4->fi, fib4->tb_id,
+                                          &fib4->fi, fib4->tb_id,
                                           ROCKER_OP_FLAG_REMOVE);
                break;
-       case SWITCHDEV_OBJ_PORT_FDB:
-               err = rocker_port_fdb_del(rocker_port, NULL, &obj->u.fdb);
+       case SWITCHDEV_OBJ_ID_PORT_FDB:
+               err = rocker_port_fdb_del(rocker_port, NULL,
+                                         SWITCHDEV_OBJ_PORT_FDB(obj));
                break;
        default:
                err = -EOPNOTSUPP;
@@ -4576,10 +4556,10 @@ static int rocker_port_obj_del(struct net_device *dev,
 }
 
 static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
-                               struct switchdev_obj *obj)
+                               struct switchdev_obj_port_fdb *fdb,
+                               switchdev_obj_dump_cb_t *cb)
 {
        struct rocker *rocker = rocker_port->rocker;
-       struct switchdev_obj_fdb *fdb = &obj->u.fdb;
        struct rocker_fdb_tbl_entry *found;
        struct hlist_node *tmp;
        unsigned long lock_flags;
@@ -4590,11 +4570,11 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
        hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) {
                if (found->key.rocker_port != rocker_port)
                        continue;
-               fdb->addr = found->key.addr;
+               ether_addr_copy(fdb->addr, found->key.addr);
                fdb->ndm_state = NUD_REACHABLE;
                fdb->vid = rocker_port_vlan_to_vid(rocker_port,
                                                   found->key.vlan_id);
-               err = obj->cb(rocker_port->dev, obj);
+               err = cb(&fdb->obj);
                if (err)
                        break;
        }
@@ -4604,9 +4584,9 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
 }
 
 static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
-                                struct switchdev_obj *obj)
+                                struct switchdev_obj_port_vlan *vlan,
+                                switchdev_obj_dump_cb_t *cb)
 {
-       struct switchdev_obj_vlan *vlan = &obj->u.vlan;
        u16 vid;
        int err = 0;
 
@@ -4617,7 +4597,7 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
                if (rocker_vlan_id_is_internal(htons(vid)))
                        vlan->flags |= BRIDGE_VLAN_INFO_PVID;
                vlan->vid_begin = vlan->vid_end = vid;
-               err = obj->cb(rocker_port->dev, obj);
+               err = cb(&vlan->obj);
                if (err)
                        break;
        }
@@ -4626,17 +4606,20 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port,
 }
 
 static int rocker_port_obj_dump(struct net_device *dev,
-                               struct switchdev_obj *obj)
+                               struct switchdev_obj *obj,
+                               switchdev_obj_dump_cb_t *cb)
 {
        const struct rocker_port *rocker_port = netdev_priv(dev);
        int err = 0;
 
        switch (obj->id) {
-       case SWITCHDEV_OBJ_PORT_FDB:
-               err = rocker_port_fdb_dump(rocker_port, obj);
+       case SWITCHDEV_OBJ_ID_PORT_FDB:
+               err = rocker_port_fdb_dump(rocker_port,
+                                          SWITCHDEV_OBJ_PORT_FDB(obj), cb);
                break;
-       case SWITCHDEV_OBJ_PORT_VLAN:
-               err = rocker_port_vlan_dump(rocker_port, obj);
+       case SWITCHDEV_OBJ_ID_PORT_VLAN:
+               err = rocker_port_vlan_dump(rocker_port,
+                                           SWITCHDEV_OBJ_PORT_VLAN(obj), cb);
                break;
        default:
                err = -EOPNOTSUPP;
@@ -5010,7 +4993,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
        rocker_port->pport = port_number + 1;
        rocker_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC;
        rocker_port->ageing_time = BR_DEFAULT_AGEING_TIME;
-       INIT_LIST_HEAD(&rocker_port->trans_mem);
 
        rocker_port_dev_addr_init(rocker_port);
        dev->netdev_ops = &rocker_port_netdev_ops;