aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c167
1 files changed, 81 insertions, 86 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index ad1531ae3aa..30874cda847 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -124,41 +124,16 @@
#define qlcnic_83xx_is_ip_align(sts) (((sts) >> 46) & 1)
#define qlcnic_83xx_has_vlan_tag(sts) (((sts) >> 47) & 1)
-struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *,
- struct qlcnic_host_rds_ring *, u16, u16);
+static int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring,
+ int max);
-inline void qlcnic_enable_tx_intr(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring)
-{
- if (qlcnic_check_multi_tx(adapter) &&
- !adapter->ahw->diag_test)
- writel(0x0, tx_ring->crb_intr_mask);
-}
-
-
-static inline void qlcnic_disable_tx_int(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring)
-{
- if (qlcnic_check_multi_tx(adapter) &&
- !adapter->ahw->diag_test)
- writel(1, tx_ring->crb_intr_mask);
-}
+static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *,
+ struct qlcnic_host_rds_ring *,
+ u16, u16);
-inline void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring)
+static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
{
- writel(0, tx_ring->crb_intr_mask);
-}
-
-inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
- struct qlcnic_host_tx_ring *tx_ring)
-{
- writel(1, tx_ring->crb_intr_mask);
-}
-
-static inline u8 qlcnic_mac_hash(u64 mac)
-{
- return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff));
+ return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
}
static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
@@ -202,7 +177,7 @@ static struct qlcnic_filter *qlcnic_find_mac_filter(struct hlist_head *head,
struct hlist_node *n;
hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
- if (!memcmp(tmp_fil->faddr, addr, ETH_ALEN) &&
+ if (ether_addr_equal(tmp_fil->faddr, addr) &&
tmp_fil->vlan_id == vlan_id)
return tmp_fil;
}
@@ -210,8 +185,8 @@ static struct qlcnic_filter *qlcnic_find_mac_filter(struct hlist_head *head,
return NULL;
}
-void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
- int loopback_pkt, u16 vlan_id)
+static void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter,
+ struct sk_buff *skb, int loopback_pkt, u16 vlan_id)
{
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
struct qlcnic_filter *fil, *tmp_fil;
@@ -221,8 +196,11 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
u8 hindex, op;
int ret;
+ if (!qlcnic_sriov_pf_check(adapter) || (vlan_id == 0xffff))
+ vlan_id = 0;
+
memcpy(&src_addr, phdr->h_source, ETH_ALEN);
- hindex = qlcnic_mac_hash(src_addr) &
+ hindex = qlcnic_mac_hash(src_addr, vlan_id) &
(adapter->fhash.fbucket_size - 1);
if (loopback_pkt) {
@@ -322,31 +300,47 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
struct cmd_desc_type0 *first_desc,
struct sk_buff *skb)
{
+ struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
+ struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+ struct net_device *netdev = adapter->netdev;
+ u16 protocol = ntohs(skb->protocol);
struct qlcnic_filter *fil, *tmp_fil;
- struct hlist_node *n;
struct hlist_head *head;
- struct net_device *netdev = adapter->netdev;
- struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+ struct hlist_node *n;
u64 src_addr = 0;
u16 vlan_id = 0;
- u8 hindex;
+ u8 hindex, hval;
- if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
- return;
+ if (!qlcnic_sriov_pf_check(adapter)) {
+ if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
+ return;
+ } else {
+ if (protocol == ETH_P_8021Q) {
+ vh = (struct vlan_ethhdr *)skb->data;
+ vlan_id = ntohs(vh->h_vlan_TCI);
+ } else if (vlan_tx_tag_present(skb)) {
+ vlan_id = vlan_tx_tag_get(skb);
+ }
+
+ if (ether_addr_equal(phdr->h_source, adapter->mac_addr) &&
+ !vlan_id)
+ return;
+ }
if (adapter->fhash.fnum >= adapter->fhash.fmax) {
adapter->stats.mac_filter_limit_overrun++;
- netdev_info(netdev, "Can not add more than %d mac addresses\n",
- adapter->fhash.fmax);
+ netdev_info(netdev, "Can not add more than %d mac-vlan filters, configured %d\n",
+ adapter->fhash.fmax, adapter->fhash.fnum);
return;
}
memcpy(&src_addr, phdr->h_source, ETH_ALEN);
- hindex = qlcnic_mac_hash(src_addr) & (adapter->fhash.fbucket_size - 1);
+ hval = qlcnic_mac_hash(src_addr, vlan_id);
+ hindex = hval & (adapter->fhash.fbucket_size - 1);
head = &(adapter->fhash.fhead[hindex]);
hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
- if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+ if (ether_addr_equal(tmp_fil->faddr, (u8 *)&src_addr) &&
tmp_fil->vlan_id == vlan_id) {
if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
qlcnic_change_filter(adapter, &src_addr,
@@ -862,7 +856,7 @@ static int qlcnic_poll(struct napi_struct *napi, int budget)
if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi);
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
- qlcnic_enable_int(sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
qlcnic_enable_tx_intr(adapter, tx_ring);
}
}
@@ -903,7 +897,7 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(&sds_ring->napi);
if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_enable_int(sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
}
return work_done;
@@ -1015,9 +1009,9 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index,
}
}
-struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
- struct qlcnic_host_rds_ring *ring,
- u16 index, u16 cksum)
+static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_rds_ring *ring,
+ u16 index, u16 cksum)
{
struct qlcnic_rx_buffer *buffer;
struct sk_buff *skb;
@@ -1236,7 +1230,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
return buffer;
}
-int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+static int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
{
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_adapter *adapter = sds_ring->adapter;
@@ -1466,8 +1460,7 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
if (qlcnic_check_multi_tx(adapter) &&
- !adapter->ahw->diag_test &&
- (adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
+ !adapter->ahw->diag_test) {
netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
NAPI_POLL_WEIGHT);
} else {
@@ -1535,13 +1528,12 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
napi_enable(&sds_ring->napi);
- qlcnic_enable_int(sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
}
if (qlcnic_check_multi_tx(adapter) &&
(adapter->flags & QLCNIC_MSIX_ENABLED) &&
- !adapter->ahw->diag_test &&
- (adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
+ !adapter->ahw->diag_test) {
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
napi_enable(&tx_ring->napi);
@@ -1562,7 +1554,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
- qlcnic_disable_int(sds_ring);
+ qlcnic_disable_sds_intr(adapter, sds_ring);
napi_synchronize(&sds_ring->napi);
napi_disable(&sds_ring->napi);
}
@@ -1572,7 +1564,7 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
qlcnic_check_multi_tx(adapter)) {
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
- qlcnic_disable_tx_int(adapter, tx_ring);
+ qlcnic_disable_tx_intr(adapter, tx_ring);
napi_synchronize(&tx_ring->napi);
napi_disable(&tx_ring->napi);
}
@@ -1601,7 +1593,8 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
struct sk_buff *skb;
struct qlcnic_host_rds_ring *rds_ring;
int index, length, cksum, is_lb_pkt;
- u16 vid = 0xffff, t_vid;
+ u16 vid = 0xffff;
+ int err;
if (unlikely(ring >= adapter->max_rds_rings))
return NULL;
@@ -1619,19 +1612,19 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
if (!skb)
return buffer;
- if (adapter->drv_mac_learn &&
- (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
- t_vid = 0;
- is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
- qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
- }
-
if (length > rds_ring->skb_size)
skb_put(skb, rds_ring->skb_size);
else
skb_put(skb, length);
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ err = qlcnic_check_rx_tagging(adapter, skb, &vid);
+
+ if (adapter->rx_mac_learn) {
+ is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
+ qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
+ }
+
+ if (unlikely(err)) {
adapter->stats.rxdropped++;
dev_kfree_skb(skb);
return buffer;
@@ -1666,7 +1659,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
int l2_hdr_offset, l4_hdr_offset;
int index, is_lb_pkt;
u16 lro_length, length, data_offset, gso_size;
- u16 vid = 0xffff, t_vid;
+ u16 vid = 0xffff;
+ int err;
if (unlikely(ring > adapter->max_rds_rings))
return NULL;
@@ -1688,12 +1682,6 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
if (!skb)
return buffer;
- if (adapter->drv_mac_learn &&
- (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
- t_vid = 0;
- is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
- qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
- }
if (qlcnic_83xx_is_tstamp(sts_data[1]))
data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE;
else
@@ -1702,7 +1690,14 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
skb_put(skb, lro_length + data_offset);
skb_pull(skb, l2_hdr_offset);
- if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ err = qlcnic_check_rx_tagging(adapter, skb, &vid);
+
+ if (adapter->rx_mac_learn) {
+ is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
+ qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
+ }
+
+ if (unlikely(err)) {
adapter->stats.rxdropped++;
dev_kfree_skb(skb);
return buffer;
@@ -1832,7 +1827,7 @@ static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget)
work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi);
- qlcnic_83xx_enable_intr(adapter, sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
}
return work_done;
@@ -1855,7 +1850,7 @@ static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi);
- qlcnic_83xx_enable_intr(adapter, sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
}
return work_done;
@@ -1874,7 +1869,7 @@ static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
if (work_done) {
napi_complete(&tx_ring->napi);
if (test_bit(__QLCNIC_DEV_UP , &adapter->state))
- qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+ qlcnic_enable_tx_intr(adapter, tx_ring);
}
return work_done;
@@ -1892,7 +1887,7 @@ static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(&sds_ring->napi);
if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
- qlcnic_83xx_enable_intr(adapter, sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
}
return work_done;
@@ -1912,7 +1907,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
sds_ring = &recv_ctx->sds_rings[ring];
napi_enable(&sds_ring->napi);
if (adapter->flags & QLCNIC_MSIX_ENABLED)
- qlcnic_83xx_enable_intr(adapter, sds_ring);
+ qlcnic_enable_sds_intr(adapter, sds_ring);
}
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
@@ -1920,7 +1915,7 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
napi_enable(&tx_ring->napi);
- qlcnic_83xx_enable_tx_intr(adapter, tx_ring);
+ qlcnic_enable_tx_intr(adapter, tx_ring);
}
}
}
@@ -1938,7 +1933,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
if (adapter->flags & QLCNIC_MSIX_ENABLED)
- qlcnic_83xx_disable_intr(adapter, sds_ring);
+ qlcnic_disable_sds_intr(adapter, sds_ring);
napi_synchronize(&sds_ring->napi);
napi_disable(&sds_ring->napi);
}
@@ -1947,7 +1942,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
- qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
+ qlcnic_disable_tx_intr(adapter, tx_ring);
napi_synchronize(&tx_ring->napi);
napi_disable(&tx_ring->napi);
}
@@ -2027,8 +2022,8 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
qlcnic_free_tx_rings(adapter);
}
-void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
- int ring, u64 sts_data[])
+static void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter,
+ int ring, u64 sts_data[])
{
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
struct sk_buff *skb;