diff options
author | David S. Miller <davem@davemloft.net> | 2011-10-07 13:38:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-07 13:38:43 -0400 |
commit | 88c5100c28b02c4b2b2c6f6fafbbd76d90f698b9 (patch) | |
tree | 08c4399e0341f7eb0ccb24e15f2cab687275c2a4 /drivers/net/ethernet | |
parent | 8083f0fc969d9b5353061a7a6f963405057e26b1 (diff) | |
parent | 3ee72ca99288f1de95ec9c570e43f531c8799f06 (diff) |
Merge branch 'master' of github.com:davem330/net
Conflicts:
net/batman-adv/soft-interface.c
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb3/l2t.c | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb3/l2t.h | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/ibmveth.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 56 |
9 files changed, 100 insertions, 46 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 0b9bd551580b..51bd7485ab18 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | |||
@@ -2123,6 +2123,7 @@ static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap) | |||
2123 | break; | 2123 | break; |
2124 | case DCB_CAP_ATTR_DCBX: | 2124 | case DCB_CAP_ATTR_DCBX: |
2125 | *cap = BNX2X_DCBX_CAPS; | 2125 | *cap = BNX2X_DCBX_CAPS; |
2126 | break; | ||
2126 | default: | 2127 | default: |
2127 | rval = -EINVAL; | 2128 | rval = -EINVAL; |
2128 | break; | 2129 | break; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 28bde1610ffb..6486ab8c8fc8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -4937,7 +4937,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) | |||
4937 | int igu_seg_id; | 4937 | int igu_seg_id; |
4938 | int port = BP_PORT(bp); | 4938 | int port = BP_PORT(bp); |
4939 | int func = BP_FUNC(bp); | 4939 | int func = BP_FUNC(bp); |
4940 | int reg_offset; | 4940 | int reg_offset, reg_offset_en5; |
4941 | u64 section; | 4941 | u64 section; |
4942 | int index; | 4942 | int index; |
4943 | struct hc_sp_status_block_data sp_sb_data; | 4943 | struct hc_sp_status_block_data sp_sb_data; |
@@ -4960,6 +4960,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) | |||
4960 | 4960 | ||
4961 | reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : | 4961 | reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : |
4962 | MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); | 4962 | MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); |
4963 | reg_offset_en5 = (port ? MISC_REG_AEU_ENABLE5_FUNC_1_OUT_0 : | ||
4964 | MISC_REG_AEU_ENABLE5_FUNC_0_OUT_0); | ||
4963 | for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) { | 4965 | for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) { |
4964 | int sindex; | 4966 | int sindex; |
4965 | /* take care of sig[0]..sig[4] */ | 4967 | /* take care of sig[0]..sig[4] */ |
@@ -4974,7 +4976,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp) | |||
4974 | * and not 16 between the different groups | 4976 | * and not 16 between the different groups |
4975 | */ | 4977 | */ |
4976 | bp->attn_group[index].sig[4] = REG_RD(bp, | 4978 | bp->attn_group[index].sig[4] = REG_RD(bp, |
4977 | reg_offset + 0x10 + 0x4*index); | 4979 | reg_offset_en5 + 0x4*index); |
4978 | else | 4980 | else |
4979 | bp->attn_group[index].sig[4] = 0; | 4981 | bp->attn_group[index].sig[4] = 0; |
4980 | } | 4982 | } |
@@ -7619,8 +7621,11 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) | |||
7619 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | 7621 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; |
7620 | u8 *mac_addr = bp->dev->dev_addr; | 7622 | u8 *mac_addr = bp->dev->dev_addr; |
7621 | u32 val; | 7623 | u32 val; |
7624 | u16 pmc; | ||
7625 | |||
7622 | /* The mac address is written to entries 1-4 to | 7626 | /* The mac address is written to entries 1-4 to |
7623 | preserve entry 0 which is used by the PMF */ | 7627 | * preserve entry 0 which is used by the PMF |
7628 | */ | ||
7624 | u8 entry = (BP_VN(bp) + 1)*8; | 7629 | u8 entry = (BP_VN(bp) + 1)*8; |
7625 | 7630 | ||
7626 | val = (mac_addr[0] << 8) | mac_addr[1]; | 7631 | val = (mac_addr[0] << 8) | mac_addr[1]; |
@@ -7630,6 +7635,11 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) | |||
7630 | (mac_addr[4] << 8) | mac_addr[5]; | 7635 | (mac_addr[4] << 8) | mac_addr[5]; |
7631 | EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val); | 7636 | EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val); |
7632 | 7637 | ||
7638 | /* Enable the PME and clear the status */ | ||
7639 | pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmc); | ||
7640 | pmc |= PCI_PM_CTRL_PME_ENABLE | PCI_PM_CTRL_PME_STATUS; | ||
7641 | pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, pmc); | ||
7642 | |||
7633 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; | 7643 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; |
7634 | 7644 | ||
7635 | } else | 7645 | } else |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index 750e8445dac4..fc7bd0f23c0b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h | |||
@@ -1384,6 +1384,18 @@ | |||
1384 | Latched ump_tx_parity; [31] MCP Latched scpad_parity; */ | 1384 | Latched ump_tx_parity; [31] MCP Latched scpad_parity; */ |
1385 | #define MISC_REG_AEU_ENABLE4_PXP_0 0xa108 | 1385 | #define MISC_REG_AEU_ENABLE4_PXP_0 0xa108 |
1386 | #define MISC_REG_AEU_ENABLE4_PXP_1 0xa1a8 | 1386 | #define MISC_REG_AEU_ENABLE4_PXP_1 0xa1a8 |
1387 | /* [RW 32] fifth 32b for enabling the output for function 0 output0. Mapped | ||
1388 | * as follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC | ||
1389 | * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6] | ||
1390 | * mstat0 attention; [7] mstat0 parity; [8] mstat1 attention; [9] mstat1 | ||
1391 | * parity; [31-10] Reserved; */ | ||
1392 | #define MISC_REG_AEU_ENABLE5_FUNC_0_OUT_0 0xa688 | ||
1393 | /* [RW 32] Fifth 32b for enabling the output for function 1 output0. Mapped | ||
1394 | * as follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC | ||
1395 | * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6] | ||
1396 | * mstat0 attention; [7] mstat0 parity; [8] mstat1 attention; [9] mstat1 | ||
1397 | * parity; [31-10] Reserved; */ | ||
1398 | #define MISC_REG_AEU_ENABLE5_FUNC_1_OUT_0 0xa6b0 | ||
1387 | /* [RW 1] set/clr general attention 0; this will set/clr bit 94 in the aeu | 1399 | /* [RW 1] set/clr general attention 0; this will set/clr bit 94 in the aeu |
1388 | 128 bit vector */ | 1400 | 128 bit vector */ |
1389 | #define MISC_REG_AEU_GENERAL_ATTN_0 0xa000 | 1401 | #define MISC_REG_AEU_GENERAL_ATTN_0 0xa000 |
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c index 805076c54f1b..da5a5d9b8aff 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | |||
@@ -1146,12 +1146,14 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) | |||
1146 | if (te && te->ctx && te->client && te->client->redirect) { | 1146 | if (te && te->ctx && te->client && te->client->redirect) { |
1147 | update_tcb = te->client->redirect(te->ctx, old, new, e); | 1147 | update_tcb = te->client->redirect(te->ctx, old, new, e); |
1148 | if (update_tcb) { | 1148 | if (update_tcb) { |
1149 | rcu_read_lock(); | ||
1149 | l2t_hold(L2DATA(tdev), e); | 1150 | l2t_hold(L2DATA(tdev), e); |
1151 | rcu_read_unlock(); | ||
1150 | set_l2t_ix(tdev, tid, e); | 1152 | set_l2t_ix(tdev, tid, e); |
1151 | } | 1153 | } |
1152 | } | 1154 | } |
1153 | } | 1155 | } |
1154 | l2t_release(L2DATA(tdev), e); | 1156 | l2t_release(tdev, e); |
1155 | } | 1157 | } |
1156 | 1158 | ||
1157 | /* | 1159 | /* |
@@ -1264,7 +1266,7 @@ int cxgb3_offload_activate(struct adapter *adapter) | |||
1264 | goto out_free; | 1266 | goto out_free; |
1265 | 1267 | ||
1266 | err = -ENOMEM; | 1268 | err = -ENOMEM; |
1267 | L2DATA(dev) = t3_init_l2t(l2t_capacity); | 1269 | RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity)); |
1268 | if (!L2DATA(dev)) | 1270 | if (!L2DATA(dev)) |
1269 | goto out_free; | 1271 | goto out_free; |
1270 | 1272 | ||
@@ -1298,16 +1300,24 @@ int cxgb3_offload_activate(struct adapter *adapter) | |||
1298 | 1300 | ||
1299 | out_free_l2t: | 1301 | out_free_l2t: |
1300 | t3_free_l2t(L2DATA(dev)); | 1302 | t3_free_l2t(L2DATA(dev)); |
1301 | L2DATA(dev) = NULL; | 1303 | rcu_assign_pointer(dev->l2opt, NULL); |
1302 | out_free: | 1304 | out_free: |
1303 | kfree(t); | 1305 | kfree(t); |
1304 | return err; | 1306 | return err; |
1305 | } | 1307 | } |
1306 | 1308 | ||
1309 | static void clean_l2_data(struct rcu_head *head) | ||
1310 | { | ||
1311 | struct l2t_data *d = container_of(head, struct l2t_data, rcu_head); | ||
1312 | t3_free_l2t(d); | ||
1313 | } | ||
1314 | |||
1315 | |||
1307 | void cxgb3_offload_deactivate(struct adapter *adapter) | 1316 | void cxgb3_offload_deactivate(struct adapter *adapter) |
1308 | { | 1317 | { |
1309 | struct t3cdev *tdev = &adapter->tdev; | 1318 | struct t3cdev *tdev = &adapter->tdev; |
1310 | struct t3c_data *t = T3C_DATA(tdev); | 1319 | struct t3c_data *t = T3C_DATA(tdev); |
1320 | struct l2t_data *d; | ||
1311 | 1321 | ||
1312 | remove_adapter(adapter); | 1322 | remove_adapter(adapter); |
1313 | if (list_empty(&adapter_list)) | 1323 | if (list_empty(&adapter_list)) |
@@ -1315,8 +1325,11 @@ void cxgb3_offload_deactivate(struct adapter *adapter) | |||
1315 | 1325 | ||
1316 | free_tid_maps(&t->tid_maps); | 1326 | free_tid_maps(&t->tid_maps); |
1317 | T3C_DATA(tdev) = NULL; | 1327 | T3C_DATA(tdev) = NULL; |
1318 | t3_free_l2t(L2DATA(tdev)); | 1328 | rcu_read_lock(); |
1319 | L2DATA(tdev) = NULL; | 1329 | d = L2DATA(tdev); |
1330 | rcu_read_unlock(); | ||
1331 | rcu_assign_pointer(tdev->l2opt, NULL); | ||
1332 | call_rcu(&d->rcu_head, clean_l2_data); | ||
1320 | if (t->nofail_skb) | 1333 | if (t->nofail_skb) |
1321 | kfree_skb(t->nofail_skb); | 1334 | kfree_skb(t->nofail_skb); |
1322 | kfree(t); | 1335 | kfree(t); |
diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.c b/drivers/net/ethernet/chelsio/cxgb3/l2t.c index f452c4003253..41540978a173 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.c | |||
@@ -300,14 +300,21 @@ static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh) | |||
300 | struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, | 300 | struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, |
301 | struct net_device *dev) | 301 | struct net_device *dev) |
302 | { | 302 | { |
303 | struct l2t_entry *e; | 303 | struct l2t_entry *e = NULL; |
304 | struct l2t_data *d = L2DATA(cdev); | 304 | struct l2t_data *d; |
305 | int hash; | ||
305 | u32 addr = *(u32 *) neigh->primary_key; | 306 | u32 addr = *(u32 *) neigh->primary_key; |
306 | int ifidx = neigh->dev->ifindex; | 307 | int ifidx = neigh->dev->ifindex; |
307 | int hash = arp_hash(addr, ifidx, d); | ||
308 | struct port_info *p = netdev_priv(dev); | 308 | struct port_info *p = netdev_priv(dev); |
309 | int smt_idx = p->port_id; | 309 | int smt_idx = p->port_id; |
310 | 310 | ||
311 | rcu_read_lock(); | ||
312 | d = L2DATA(cdev); | ||
313 | if (!d) | ||
314 | goto done_rcu; | ||
315 | |||
316 | hash = arp_hash(addr, ifidx, d); | ||
317 | |||
311 | write_lock_bh(&d->lock); | 318 | write_lock_bh(&d->lock); |
312 | for (e = d->l2tab[hash].first; e; e = e->next) | 319 | for (e = d->l2tab[hash].first; e; e = e->next) |
313 | if (e->addr == addr && e->ifindex == ifidx && | 320 | if (e->addr == addr && e->ifindex == ifidx && |
@@ -338,6 +345,8 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, | |||
338 | } | 345 | } |
339 | done: | 346 | done: |
340 | write_unlock_bh(&d->lock); | 347 | write_unlock_bh(&d->lock); |
348 | done_rcu: | ||
349 | rcu_read_unlock(); | ||
341 | return e; | 350 | return e; |
342 | } | 351 | } |
343 | 352 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h index 7a12d52ed4fc..c5f54796e2cb 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h +++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h | |||
@@ -76,6 +76,7 @@ struct l2t_data { | |||
76 | atomic_t nfree; /* number of free entries */ | 76 | atomic_t nfree; /* number of free entries */ |
77 | rwlock_t lock; | 77 | rwlock_t lock; |
78 | struct l2t_entry l2tab[0]; | 78 | struct l2t_entry l2tab[0]; |
79 | struct rcu_head rcu_head; /* to handle rcu cleanup */ | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | typedef void (*arp_failure_handler_func)(struct t3cdev * dev, | 82 | typedef void (*arp_failure_handler_func)(struct t3cdev * dev, |
@@ -99,7 +100,7 @@ static inline void set_arp_failure_handler(struct sk_buff *skb, | |||
99 | /* | 100 | /* |
100 | * Getting to the L2 data from an offload device. | 101 | * Getting to the L2 data from an offload device. |
101 | */ | 102 | */ |
102 | #define L2DATA(dev) ((dev)->l2opt) | 103 | #define L2DATA(cdev) (rcu_dereference((cdev)->l2opt)) |
103 | 104 | ||
104 | #define W_TCB_L2T_IX 0 | 105 | #define W_TCB_L2T_IX 0 |
105 | #define S_TCB_L2T_IX 7 | 106 | #define S_TCB_L2T_IX 7 |
@@ -126,15 +127,22 @@ static inline int l2t_send(struct t3cdev *dev, struct sk_buff *skb, | |||
126 | return t3_l2t_send_slow(dev, skb, e); | 127 | return t3_l2t_send_slow(dev, skb, e); |
127 | } | 128 | } |
128 | 129 | ||
129 | static inline void l2t_release(struct l2t_data *d, struct l2t_entry *e) | 130 | static inline void l2t_release(struct t3cdev *t, struct l2t_entry *e) |
130 | { | 131 | { |
131 | if (atomic_dec_and_test(&e->refcnt)) | 132 | struct l2t_data *d; |
133 | |||
134 | rcu_read_lock(); | ||
135 | d = L2DATA(t); | ||
136 | |||
137 | if (atomic_dec_and_test(&e->refcnt) && d) | ||
132 | t3_l2e_free(d, e); | 138 | t3_l2e_free(d, e); |
139 | |||
140 | rcu_read_unlock(); | ||
133 | } | 141 | } |
134 | 142 | ||
135 | static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e) | 143 | static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e) |
136 | { | 144 | { |
137 | if (atomic_add_return(1, &e->refcnt) == 1) /* 0 -> 1 transition */ | 145 | if (d && atomic_add_return(1, &e->refcnt) == 1) /* 0 -> 1 transition */ |
138 | atomic_dec(&d->nfree); | 146 | atomic_dec(&d->nfree); |
139 | } | 147 | } |
140 | 148 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 40b395f932cf..4c8f42afa3c6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
@@ -3715,6 +3715,9 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
3715 | setup_debugfs(adapter); | 3715 | setup_debugfs(adapter); |
3716 | } | 3716 | } |
3717 | 3717 | ||
3718 | /* PCIe EEH recovery on powerpc platforms needs fundamental reset */ | ||
3719 | pdev->needs_freset = 1; | ||
3720 | |||
3718 | if (is_offload(adapter)) | 3721 | if (is_offload(adapter)) |
3719 | attach_ulds(adapter); | 3722 | attach_ulds(adapter); |
3720 | 3723 | ||
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 72b84de48756..4da972eaabb4 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c | |||
@@ -636,8 +636,8 @@ static int ibmveth_open(struct net_device *netdev) | |||
636 | netdev_err(netdev, "unable to request irq 0x%x, rc %d\n", | 636 | netdev_err(netdev, "unable to request irq 0x%x, rc %d\n", |
637 | netdev->irq, rc); | 637 | netdev->irq, rc); |
638 | do { | 638 | do { |
639 | rc = h_free_logical_lan(adapter->vdev->unit_address); | 639 | lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); |
640 | } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); | 640 | } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY)); |
641 | 641 | ||
642 | goto err_out; | 642 | goto err_out; |
643 | } | 643 | } |
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 5dc61b4ef3cd..b89f3a684aec 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | |||
@@ -1198,6 +1198,8 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) | |||
1198 | iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), | 1198 | iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), |
1199 | &hw->reg->INT_EN); | 1199 | &hw->reg->INT_EN); |
1200 | pch_gbe_stop_receive(adapter); | 1200 | pch_gbe_stop_receive(adapter); |
1201 | int_st |= ioread32(&hw->reg->INT_ST); | ||
1202 | int_st = int_st & ioread32(&hw->reg->INT_EN); | ||
1201 | } | 1203 | } |
1202 | if (int_st & PCH_GBE_INT_RX_DMA_ERR) | 1204 | if (int_st & PCH_GBE_INT_RX_DMA_ERR) |
1203 | adapter->stats.intr_rx_dma_err_count++; | 1205 | adapter->stats.intr_rx_dma_err_count++; |
@@ -1217,14 +1219,11 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) | |||
1217 | /* Set Pause packet */ | 1219 | /* Set Pause packet */ |
1218 | pch_gbe_mac_set_pause_packet(hw); | 1220 | pch_gbe_mac_set_pause_packet(hw); |
1219 | } | 1221 | } |
1220 | if ((int_en & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT)) | ||
1221 | == 0) { | ||
1222 | return IRQ_HANDLED; | ||
1223 | } | ||
1224 | } | 1222 | } |
1225 | 1223 | ||
1226 | /* When request status is Receive interruption */ | 1224 | /* When request status is Receive interruption */ |
1227 | if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))) { | 1225 | if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT)) || |
1226 | (adapter->rx_stop_flag == true)) { | ||
1228 | if (likely(napi_schedule_prep(&adapter->napi))) { | 1227 | if (likely(napi_schedule_prep(&adapter->napi))) { |
1229 | /* Enable only Rx Descriptor empty */ | 1228 | /* Enable only Rx Descriptor empty */ |
1230 | atomic_inc(&adapter->irq_sem); | 1229 | atomic_inc(&adapter->irq_sem); |
@@ -1384,7 +1383,7 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, | |||
1384 | struct sk_buff *skb; | 1383 | struct sk_buff *skb; |
1385 | unsigned int i; | 1384 | unsigned int i; |
1386 | unsigned int cleaned_count = 0; | 1385 | unsigned int cleaned_count = 0; |
1387 | bool cleaned = false; | 1386 | bool cleaned = true; |
1388 | 1387 | ||
1389 | pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); | 1388 | pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); |
1390 | 1389 | ||
@@ -1395,7 +1394,6 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, | |||
1395 | 1394 | ||
1396 | while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) { | 1395 | while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) { |
1397 | pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status); | 1396 | pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status); |
1398 | cleaned = true; | ||
1399 | buffer_info = &tx_ring->buffer_info[i]; | 1397 | buffer_info = &tx_ring->buffer_info[i]; |
1400 | skb = buffer_info->skb; | 1398 | skb = buffer_info->skb; |
1401 | 1399 | ||
@@ -1438,8 +1436,10 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, | |||
1438 | tx_desc = PCH_GBE_TX_DESC(*tx_ring, i); | 1436 | tx_desc = PCH_GBE_TX_DESC(*tx_ring, i); |
1439 | 1437 | ||
1440 | /* weight of a sort for tx, to avoid endless transmit cleanup */ | 1438 | /* weight of a sort for tx, to avoid endless transmit cleanup */ |
1441 | if (cleaned_count++ == PCH_GBE_TX_WEIGHT) | 1439 | if (cleaned_count++ == PCH_GBE_TX_WEIGHT) { |
1440 | cleaned = false; | ||
1442 | break; | 1441 | break; |
1442 | } | ||
1443 | } | 1443 | } |
1444 | pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n", | 1444 | pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n", |
1445 | cleaned_count); | 1445 | cleaned_count); |
@@ -2167,7 +2167,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) | |||
2167 | { | 2167 | { |
2168 | struct pch_gbe_adapter *adapter = | 2168 | struct pch_gbe_adapter *adapter = |
2169 | container_of(napi, struct pch_gbe_adapter, napi); | 2169 | container_of(napi, struct pch_gbe_adapter, napi); |
2170 | struct net_device *netdev = adapter->netdev; | ||
2171 | int work_done = 0; | 2170 | int work_done = 0; |
2172 | bool poll_end_flag = false; | 2171 | bool poll_end_flag = false; |
2173 | bool cleaned = false; | 2172 | bool cleaned = false; |
@@ -2175,33 +2174,32 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) | |||
2175 | 2174 | ||
2176 | pr_debug("budget : %d\n", budget); | 2175 | pr_debug("budget : %d\n", budget); |
2177 | 2176 | ||
2178 | /* Keep link state information with original netdev */ | 2177 | pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget); |
2179 | if (!netif_carrier_ok(netdev)) { | 2178 | cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); |
2179 | |||
2180 | if (!cleaned) | ||
2181 | work_done = budget; | ||
2182 | /* If no Tx and not enough Rx work done, | ||
2183 | * exit the polling mode | ||
2184 | */ | ||
2185 | if (work_done < budget) | ||
2180 | poll_end_flag = true; | 2186 | poll_end_flag = true; |
2181 | } else { | 2187 | |
2182 | pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget); | 2188 | if (poll_end_flag) { |
2189 | napi_complete(napi); | ||
2190 | if (adapter->rx_stop_flag) { | ||
2191 | adapter->rx_stop_flag = false; | ||
2192 | pch_gbe_start_receive(&adapter->hw); | ||
2193 | } | ||
2194 | pch_gbe_irq_enable(adapter); | ||
2195 | } else | ||
2183 | if (adapter->rx_stop_flag) { | 2196 | if (adapter->rx_stop_flag) { |
2184 | adapter->rx_stop_flag = false; | 2197 | adapter->rx_stop_flag = false; |
2185 | pch_gbe_start_receive(&adapter->hw); | 2198 | pch_gbe_start_receive(&adapter->hw); |
2186 | int_en = ioread32(&adapter->hw.reg->INT_EN); | 2199 | int_en = ioread32(&adapter->hw.reg->INT_EN); |
2187 | iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), | 2200 | iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), |
2188 | &adapter->hw.reg->INT_EN); | 2201 | &adapter->hw.reg->INT_EN); |
2189 | } | 2202 | } |
2190 | cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); | ||
2191 | |||
2192 | if (cleaned) | ||
2193 | work_done = budget; | ||
2194 | /* If no Tx and not enough Rx work done, | ||
2195 | * exit the polling mode | ||
2196 | */ | ||
2197 | if ((work_done < budget) || !netif_running(netdev)) | ||
2198 | poll_end_flag = true; | ||
2199 | } | ||
2200 | |||
2201 | if (poll_end_flag) { | ||
2202 | napi_complete(napi); | ||
2203 | pch_gbe_irq_enable(adapter); | ||
2204 | } | ||
2205 | 2203 | ||
2206 | pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", | 2204 | pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", |
2207 | poll_end_flag, work_done, budget); | 2205 | poll_end_flag, work_done, budget); |