14d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2a02d44a02bd2b3f3848f30e335adc3c076b3f905Divy Le Ray * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. 34d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 44d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * This software is available to you under a choice of one of two 54d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * licenses. You may choose to be licensed under the terms of the GNU 64d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * General Public License (GPL) Version 2, available from the file 74d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * COPYING in the main directory of this source tree, or the 84d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * OpenIB.org BSD license below: 94d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Redistribution and use in source and binary forms, with or 114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * without modification, are permitted provided that the following 124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * conditions are met: 134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * - Redistributions of source code must retain the above 154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * copyright notice, this list of conditions and the following 164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * disclaimer. 174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * - Redistributions in binary form must reproduce the above 194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * copyright notice, this list of conditions and the following 204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * disclaimer in the documentation and/or other materials 214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * provided with the distribution. 224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * SOFTWARE. 314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/skbuff.h> 334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/netdevice.h> 344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/if.h> 354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/if_vlan.h> 364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/jhash.h> 375a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 38ee40fa0656a730491765545ff7550f3c1ceb0fbcPaul Gortmaker#include <linux/export.h> 394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <net/neighbour.h> 404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "common.h" 414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "t3cdev.h" 424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "cxgb3_defs.h" 434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "l2t.h" 444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "t3_cpl.h" 454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "firmware_exports.h" 464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#define VLAN_NONE 0xfff 484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Module locking notes: There is a RW lock protecting the L2 table as a 514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * whole plus a spinlock per L2T entry. Entry lookups and allocations happen 524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * under the protection of the table lock, individual entry changes happen 534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * while holding that entry's spinlock. The table lock nests outside the 544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * entry locks. Allocations of new entries take the table lock as writers so 554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * no other lookups can happen while allocating new entries. Entry updates 564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * take the table lock as readers so multiple entries can be updated in 574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * parallel. An L2T entry can be dropped by decrementing its reference count 584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * and therefore can happen in parallel with entry allocation but no entry 594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * can change state or increment its ref count during allocation as both of 604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * these perform lookups. 614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline unsigned int vlan_prio(const struct l2t_entry *e) 644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return e->vlan >> 13; 664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline unsigned int arp_hash(u32 key, int ifindex, 694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray const struct l2t_data *d) 704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return jhash_2words(key, ifindex, 0) & (d->nentries - 1); 724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void neigh_replace(struct l2t_entry *e, struct neighbour *n) 754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_hold(n); 774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->neigh) 784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_release(e->neigh); 794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->neigh = n; 804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Set up an L2T entry and send any packets waiting in the arp queue. The 844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * supplied skb is used for the CPL_L2T_WRITE_REQ. Must be called with the 854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * entry locked. 864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, 884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_entry *e) 894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct cpl_l2t_write_req *req; 91147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller struct sk_buff *tmp; 924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (!skb) { 944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray skb = alloc_skb(sizeof(*req), GFP_ATOMIC); 954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (!skb) 964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -ENOMEM; 974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req)); 1004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); 1014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx)); 1024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray req->params = htonl(V_L2T_W_IDX(e->idx) | V_L2T_W_IFF(e->smt_idx) | 1034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray V_L2T_W_VLAN(e->vlan & VLAN_VID_MASK) | 1044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray V_L2T_W_PRIO(vlan_prio(e))); 1054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac)); 1064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); 1074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray skb->priority = CPL_PRIORITY_CONTROL; 1084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray cxgb3_ofld_send(dev, skb); 109147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller 110147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller skb_queue_walk_safe(&e->arpq, skb, tmp) { 111147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller __skb_unlink(skb, &e->arpq); 1124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray cxgb3_ofld_send(dev, skb); 1134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_VALID; 1154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 1174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 1184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 1204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Add a packet to the an L2T entry's queue of packets awaiting resolution. 1214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Must be called with the entry's lock held. 1224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 1234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb) 1244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 125147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller __skb_queue_tail(&e->arpq, skb); 1264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 1274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, 1294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_entry *e) 1304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 1314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayagain: 1324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray switch (e->state) { 1334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ 1344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_event_send(e->neigh, NULL); 1354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_bh(&e->lock); 1364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->state == L2T_STATE_STALE) 1374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_VALID; 1384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 1394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray case L2T_STATE_VALID: /* fast-path, send the packet on */ 1404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return cxgb3_ofld_send(dev, skb); 1414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray case L2T_STATE_RESOLVING: 1424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_bh(&e->lock); 1434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->state != L2T_STATE_RESOLVING) { 1444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* ARP already completed */ 1454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 1464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray goto again; 1474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray arpq_enqueue(e, skb); 1494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 1504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* 1524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Only the first packet added to the arpq should kick off 1534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * resolution. However, because the alloc_skb below can fail, 1544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * we allow each packet added to the arpq to retry resolution 1554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * as a way of recovering from transient memory exhaustion. 1564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * A better way would be to use a work request to retry L2T 1574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * entries when there's no memory. 1584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 1594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (!neigh_event_send(e->neigh, NULL)) { 1604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray skb = alloc_skb(sizeof(struct cpl_l2t_write_req), 1614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray GFP_ATOMIC); 1624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (!skb) 1634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray break; 1644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_bh(&e->lock); 166147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller if (!skb_queue_empty(&e->arpq)) 1674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray setup_l2e_send_pending(dev, skb, e); 1684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else /* we lost the race */ 1694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray __kfree_skb(skb); 1704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 1714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 1744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 1754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(t3_l2t_send_slow); 1774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e) 1794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 1804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayagain: 1814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray switch (e->state) { 1824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ 1834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_event_send(e->neigh, NULL); 1844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_bh(&e->lock); 1854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->state == L2T_STATE_STALE) { 1864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_VALID; 1874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 1894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return; 1904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray case L2T_STATE_VALID: /* fast-path, send the packet on */ 1914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return; 1924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray case L2T_STATE_RESOLVING: 1934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_bh(&e->lock); 1944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->state != L2T_STATE_RESOLVING) { 1954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* ARP already completed */ 1964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 1974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray goto again; 1984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 2004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* 2024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Only the first packet added to the arpq should kick off 2034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * resolution. However, because the alloc_skb below can fail, 2044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * we allow each packet added to the arpq to retry resolution 2054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * as a way of recovering from transient memory exhaustion. 2064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * A better way would be to use a work request to retry L2T 2074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * entries when there's no memory. 2084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_event_send(e->neigh, NULL); 2104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 2114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(t3_l2t_send_event); 2144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Allocate a free L2T entry. Must be called with l2t_data.lock held. 2174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic struct l2t_entry *alloc_l2e(struct l2t_data *d) 2194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_entry *end, *e, **p; 2214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (!atomic_read(&d->nfree)) 2234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return NULL; 2244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* there's definitely a free entry */ 2264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (e = d->rover, end = &d->l2tab[d->nentries]; e != end; ++e) 2274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (atomic_read(&e->refcnt) == 0) 2284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray goto found; 2294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (e = &d->l2tab[1]; atomic_read(&e->refcnt); ++e) ; 2314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayfound: 2324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d->rover = e + 1; 2334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray atomic_dec(&d->nfree); 2344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* 2364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * The entry we found may be an inactive entry that is 2374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * presently in the hash table. We need to remove it. 2384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->state != L2T_STATE_UNUSED) { 2404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int hash = arp_hash(e->addr, e->ifindex, d); 2414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (p = &d->l2tab[hash].first; *p; p = &(*p)->next) 2434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (*p == e) { 2444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *p = e->next; 2454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray break; 2464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 2474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_UNUSED; 2484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 2494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return e; 2504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Called when an L2T entry has no more users. The entry is left in the hash 2544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * table since it is likely to be reused but we also bump nfree to indicate 2554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * that the entry can be reallocated for a different neighbor. We also drop 2564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * the existing neighbor reference in case the neighbor is going away and is 2574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * waiting on our reference. 2584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 2594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Because entries can be reallocated to other neighbors once their ref count 2604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * drops to 0 we need to take the entry's lock to avoid races with a new 2614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * incarnation. 2624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid t3_l2e_free(struct l2t_data *d, struct l2t_entry *e) 2644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_bh(&e->lock); 2664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (atomic_read(&e->refcnt) == 0) { /* hasn't been recycled */ 2674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->neigh) { 2684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_release(e->neigh); 2694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->neigh = NULL; 2704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 2714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 2724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 2734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray atomic_inc(&d->nfree); 2744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(t3_l2e_free); 2774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Update an L2T entry that was previously used for the same next hop as neigh. 2804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Must be called with softirqs disabled. 2814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh) 2834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray unsigned int nud_state; 2854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock(&e->lock); /* avoid race with t3_l2t_free */ 2874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (neigh != e->neigh) 2894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_replace(e, neigh); 2904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray nud_state = neigh->nud_state; 2914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)) || 2924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray !(nud_state & NUD_VALID)) 2934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_RESOLVING; 2944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else if (nud_state & NUD_CONNECTED) 2954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_VALID; 2964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else 2974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_STALE; 2984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock(&e->lock); 2994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 3004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 301a4757123aeadf450b5b3c5f51f214660e20477f3David Millerstruct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst, 3024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct net_device *dev) 3034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 304e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman struct l2t_entry *e = NULL; 305a4757123aeadf450b5b3c5f51f214660e20477f3David Miller struct neighbour *neigh; 306a4757123aeadf450b5b3c5f51f214660e20477f3David Miller struct port_info *p; 307e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman struct l2t_data *d; 308e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman int hash; 309a4757123aeadf450b5b3c5f51f214660e20477f3David Miller u32 addr; 310a4757123aeadf450b5b3c5f51f214660e20477f3David Miller int ifidx; 311a4757123aeadf450b5b3c5f51f214660e20477f3David Miller int smt_idx; 3124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 313e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman rcu_read_lock(); 314a4757123aeadf450b5b3c5f51f214660e20477f3David Miller neigh = dst_get_neighbour_noref(dst); 315a4757123aeadf450b5b3c5f51f214660e20477f3David Miller if (!neigh) 316a4757123aeadf450b5b3c5f51f214660e20477f3David Miller goto done_rcu; 317a4757123aeadf450b5b3c5f51f214660e20477f3David Miller 318a4757123aeadf450b5b3c5f51f214660e20477f3David Miller addr = *(u32 *) neigh->primary_key; 319a4757123aeadf450b5b3c5f51f214660e20477f3David Miller ifidx = neigh->dev->ifindex; 320a4757123aeadf450b5b3c5f51f214660e20477f3David Miller 321a4757123aeadf450b5b3c5f51f214660e20477f3David Miller if (!dev) 322a4757123aeadf450b5b3c5f51f214660e20477f3David Miller dev = neigh->dev; 323a4757123aeadf450b5b3c5f51f214660e20477f3David Miller p = netdev_priv(dev); 324a4757123aeadf450b5b3c5f51f214660e20477f3David Miller smt_idx = p->port_id; 325a4757123aeadf450b5b3c5f51f214660e20477f3David Miller 326e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman d = L2DATA(cdev); 327e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman if (!d) 328e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman goto done_rcu; 329e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman 330e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman hash = arp_hash(addr, ifidx, d); 331e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman 3324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray write_lock_bh(&d->lock); 3334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (e = d->l2tab[hash].first; e; e = e->next) 3344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->addr == addr && e->ifindex == ifidx && 3354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->smt_idx == smt_idx) { 3364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray l2t_hold(d, e); 3374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (atomic_read(&e->refcnt) == 1) 3384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray reuse_entry(e, neigh); 339a4757123aeadf450b5b3c5f51f214660e20477f3David Miller goto done_unlock; 3404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 3414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* Need to allocate a new entry */ 3434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e = alloc_l2e(d); 3444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e) { 3454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock(&e->lock); /* avoid race with t3_l2t_free */ 3464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->next = d->l2tab[hash].first; 3474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d->l2tab[hash].first = e; 3484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->state = L2T_STATE_RESOLVING; 3494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->addr = addr; 3504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->ifindex = ifidx; 3514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->smt_idx = smt_idx; 3524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray atomic_set(&e->refcnt, 1); 3534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_replace(e, neigh); 3544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (neigh->dev->priv_flags & IFF_802_1Q_VLAN) 35522d1ba74bbafa96d3f425cc12714d3fe8675183fPatrick McHardy e->vlan = vlan_dev_vlan_id(neigh->dev); 3564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else 3574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray e->vlan = VLAN_NONE; 3584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock(&e->lock); 3594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 360a4757123aeadf450b5b3c5f51f214660e20477f3David Millerdone_unlock: 3614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray write_unlock_bh(&d->lock); 362e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Hormandone_rcu: 363e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman rcu_read_unlock(); 3644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return e; 3654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 3664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(t3_l2t_get); 3684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 3704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Called when address resolution fails for an L2T entry to handle packets 3714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * on the arpq head. If a packet specifies a failure handler it is invoked, 3724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * otherwise the packets is sent to the offload device. 3734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 3744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * XXX: maybe we should abandon the latter behavior and just require a failure 3754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * handler. 3764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 377147e70e62fdd5af6263106ad634b03c5154c1e56David S. Millerstatic void handle_failed_resolution(struct t3cdev *dev, struct sk_buff_head *arpq) 3784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 379147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller struct sk_buff *skb, *tmp; 380147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller 381147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller skb_queue_walk_safe(arpq, skb, tmp) { 3824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_skb_cb *cb = L2T_SKB_CB(skb); 3834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 384147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller __skb_unlink(skb, arpq); 3854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (cb->arp_failure_handler) 3864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray cb->arp_failure_handler(dev, skb); 3874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else 3884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray cxgb3_ofld_send(dev, skb); 3894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 3904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 3914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 3934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Called when the host's ARP layer makes a change to some entry that is 3944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * loaded into the HW L2 table. 3954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 3964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) 3974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 398147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller struct sk_buff_head arpq; 3994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_entry *e; 4004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_data *d = L2DATA(dev); 4014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 addr = *(u32 *) neigh->primary_key; 4024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int ifidx = neigh->dev->ifindex; 4034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int hash = arp_hash(addr, ifidx, d); 4044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray read_lock_bh(&d->lock); 4064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (e = d->l2tab[hash].first; e; e = e->next) 4074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->addr == addr && e->ifindex == ifidx) { 4084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock(&e->lock); 4094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray goto found; 4104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 4114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray read_unlock_bh(&d->lock); 4124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return; 4134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayfound: 415147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller __skb_queue_head_init(&arpq); 416147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller 4174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray read_unlock(&d->lock); 4184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (atomic_read(&e->refcnt)) { 4194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (neigh != e->neigh) 4204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray neigh_replace(e, neigh); 4214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (e->state == L2T_STATE_RESOLVING) { 4234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (neigh->nud_state & NUD_FAILED) { 424147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller skb_queue_splice_init(&e->arpq, &arpq); 4254eb61e0231be536d8116457b67b3e447bbd510dcSteve Wise } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE)) 4264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray setup_l2e_send_pending(dev, NULL, e); 4274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } else { 4288082c37cdc31fb0ed178d9d706bf7568ada0edd9YOSHIFUJI Hideaki e->state = neigh->nud_state & NUD_CONNECTED ? 4294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray L2T_STATE_VALID : L2T_STATE_STALE; 4304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (memcmp(e->dmac, neigh->ha, 6)) 4314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray setup_l2e_send_pending(dev, NULL, e); 4324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 4334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 4344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_unlock_bh(&e->lock); 4354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 436147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller if (!skb_queue_empty(&arpq)) 437147e70e62fdd5af6263106ad634b03c5154c1e56David S. Miller handle_failed_resolution(dev, &arpq); 4384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 4394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystruct l2t_data *t3_init_l2t(unsigned int l2t_capacity) 4414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 4424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct l2t_data *d; 4434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int i, size = sizeof(*d) + l2t_capacity * sizeof(struct l2t_entry); 4444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d = cxgb_alloc_mem(size); 4464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (!d) 4474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return NULL; 4484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d->nentries = l2t_capacity; 4504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d->rover = &d->l2tab[1]; /* entry 0 is not used */ 4514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray atomic_set(&d->nfree, l2t_capacity - 1); 4524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray rwlock_init(&d->lock); 4534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (i = 0; i < l2t_capacity; ++i) { 4554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d->l2tab[i].idx = i; 4564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray d->l2tab[i].state = L2T_STATE_UNUSED; 4576d329af9967e7ab3f4a3d7f1e8ef87539c3a069fRoland Dreier __skb_queue_head_init(&d->l2tab[i].arpq); 4584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray spin_lock_init(&d->l2tab[i].lock); 4594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray atomic_set(&d->l2tab[i].refcnt, 0); 4604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 4614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return d; 4624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 4634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid t3_free_l2t(struct l2t_data *d) 4654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 4664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray cxgb_free_mem(d); 4674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 4684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 469