aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/benet/be.h6
-rw-r--r--drivers/net/benet/be_cmds.c34
-rw-r--r--drivers/net/benet/be_cmds.h36
-rw-r--r--drivers/net/benet/be_main.c37
4 files changed, 80 insertions, 33 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 94b75cb072f7..f703758f0a6e 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -163,6 +163,10 @@ struct be_ctrl_info {
163 struct be_mcc_obj mcc_obj; 163 struct be_mcc_obj mcc_obj;
164 spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ 164 spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
165 spinlock_t mcc_cq_lock; 165 spinlock_t mcc_cq_lock;
166
167 /* MCC Async callback */
168 void (*async_cb)(void *adapter, bool link_up);
169 void *adapter_ctxt;
166}; 170};
167 171
168#include "be_cmds.h" 172#include "be_cmds.h"
@@ -272,7 +276,7 @@ struct be_adapter {
272 u32 if_handle; /* Used to configure filtering */ 276 u32 if_handle; /* Used to configure filtering */
273 u32 pmac_id; /* MAC addr handle used by BE card */ 277 u32 pmac_id; /* MAC addr handle used by BE card */
274 278
275 struct be_link_info link; 279 bool link_up;
276 u32 port_num; 280 u32 port_num;
277 bool promiscuous; 281 bool promiscuous;
278}; 282};
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 4a2e1f518f78..583517ed56f0 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -69,6 +69,20 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
69 return 0; 69 return 0;
70} 70}
71 71
72/* Link state evt is a string of bytes; no need for endian swapping */
73static void be_async_link_state_process(struct be_ctrl_info *ctrl,
74 struct be_async_event_link_state *evt)
75{
76 ctrl->async_cb(ctrl->adapter_ctxt,
77 evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false);
78}
79
80static inline bool is_link_state_evt(u32 trailer)
81{
82 return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
83 ASYNC_TRAILER_EVENT_CODE_MASK) ==
84 ASYNC_EVENT_CODE_LINK_STATE);
85}
72 86
73static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl) 87static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl)
74{ 88{
@@ -89,7 +103,14 @@ void be_process_mcc(struct be_ctrl_info *ctrl)
89 103
90 spin_lock_bh(&ctrl->mcc_cq_lock); 104 spin_lock_bh(&ctrl->mcc_cq_lock);
91 while ((compl = be_mcc_compl_get(ctrl))) { 105 while ((compl = be_mcc_compl_get(ctrl))) {
92 if (!(compl->flags & CQE_FLAGS_ASYNC_MASK)) { 106 if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
107 /* Interpret flags as an async trailer */
108 BUG_ON(!is_link_state_evt(compl->flags));
109
110 /* Interpret compl as a async link evt */
111 be_async_link_state_process(ctrl,
112 (struct be_async_event_link_state *) compl);
113 } else {
93 be_mcc_compl_process(ctrl, compl); 114 be_mcc_compl_process(ctrl, compl);
94 atomic_dec(&ctrl->mcc_obj.q.used); 115 atomic_dec(&ctrl->mcc_obj.q.used);
95 } 116 }
@@ -786,13 +807,15 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd)
786} 807}
787 808
788int be_cmd_link_status_query(struct be_ctrl_info *ctrl, 809int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
789 struct be_link_info *link) 810 bool *link_up)
790{ 811{
791 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 812 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
792 struct be_cmd_req_link_status *req = embedded_payload(wrb); 813 struct be_cmd_req_link_status *req = embedded_payload(wrb);
793 int status; 814 int status;
794 815
795 spin_lock(&ctrl->mbox_lock); 816 spin_lock(&ctrl->mbox_lock);
817
818 *link_up = false;
796 memset(wrb, 0, sizeof(*wrb)); 819 memset(wrb, 0, sizeof(*wrb));
797 820
798 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 821 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -803,11 +826,8 @@ int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
803 status = be_mbox_db_ring(ctrl); 826 status = be_mbox_db_ring(ctrl);
804 if (!status) { 827 if (!status) {
805 struct be_cmd_resp_link_status *resp = embedded_payload(wrb); 828 struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
806 link->speed = resp->mac_speed; 829 if (resp->mac_speed != PHY_LINK_SPEED_ZERO)
807 link->duplex = resp->mac_duplex; 830 *link_up = true;
808 link->fault = resp->mac_fault;
809 } else {
810 link->speed = PHY_LINK_SPEED_ZERO;
811 } 831 }
812 832
813 spin_unlock(&ctrl->mbox_lock); 833 spin_unlock(&ctrl->mbox_lock);
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index a567aa437ec9..747626da7b4e 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -76,6 +76,34 @@ struct be_mcc_cq_entry {
76 u32 flags; /* dword 3 */ 76 u32 flags; /* dword 3 */
77}; 77};
78 78
79/* When the async bit of mcc_compl is set, the last 4 bytes of
80 * mcc_compl is interpreted as follows:
81 */
82#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
83#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF
84#define ASYNC_EVENT_CODE_LINK_STATE 0x1
85struct be_async_event_trailer {
86 u32 code;
87};
88
89enum {
90 ASYNC_EVENT_LINK_DOWN = 0x0,
91 ASYNC_EVENT_LINK_UP = 0x1
92};
93
94/* When the event code of an async trailer is link-state, the mcc_compl
95 * must be interpreted as follows
96 */
97struct be_async_event_link_state {
98 u8 physical_port;
99 u8 port_link_status;
100 u8 port_duplex;
101 u8 port_speed;
102 u8 port_fault;
103 u8 rsvd0[7];
104 struct be_async_event_trailer trailer;
105} __packed;
106
79struct be_mcc_mailbox { 107struct be_mcc_mailbox {
80 struct be_mcc_wrb wrb; 108 struct be_mcc_wrb wrb;
81 struct be_mcc_cq_entry cqe; 109 struct be_mcc_cq_entry cqe;
@@ -580,12 +608,6 @@ struct be_cmd_req_link_status {
580 u32 rsvd; 608 u32 rsvd;
581}; 609};
582 610
583struct be_link_info {
584 u8 duplex;
585 u8 speed;
586 u8 fault;
587};
588
589enum { 611enum {
590 PHY_LINK_DUPLEX_NONE = 0x0, 612 PHY_LINK_DUPLEX_NONE = 0x0,
591 PHY_LINK_DUPLEX_HALF = 0x1, 613 PHY_LINK_DUPLEX_HALF = 0x1,
@@ -704,7 +726,7 @@ extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
704extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, 726extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
705 int type); 727 int type);
706extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, 728extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
707 struct be_link_info *link); 729 bool *link_up);
708extern int be_cmd_reset(struct be_ctrl_info *ctrl); 730extern int be_cmd_reset(struct be_ctrl_info *ctrl);
709extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, 731extern int be_cmd_get_stats(struct be_ctrl_info *ctrl,
710 struct be_dma_mem *nonemb_cmd); 732 struct be_dma_mem *nonemb_cmd);
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 3dc68034c21d..66c10c87f517 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -214,28 +214,24 @@ static void netdev_stats_update(struct be_adapter *adapter)
214 dev_stats->tx_window_errors = 0; 214 dev_stats->tx_window_errors = 0;
215} 215}
216 216
217static void be_link_status_update(struct be_adapter *adapter) 217void be_link_status_update(void *ctxt, bool link_up)
218{ 218{
219 struct be_link_info *prev = &adapter->link; 219 struct be_adapter *adapter = ctxt;
220 struct be_link_info now = { 0 };
221 struct net_device *netdev = adapter->netdev; 220 struct net_device *netdev = adapter->netdev;
222 221
223 be_cmd_link_status_query(&adapter->ctrl, &now);
224
225 /* If link came up or went down */ 222 /* If link came up or went down */
226 if (now.speed != prev->speed && (now.speed == PHY_LINK_SPEED_ZERO || 223 if (adapter->link_up != link_up) {
227 prev->speed == PHY_LINK_SPEED_ZERO)) { 224 if (link_up) {
228 if (now.speed == PHY_LINK_SPEED_ZERO) {
229 netif_stop_queue(netdev);
230 netif_carrier_off(netdev);
231 printk(KERN_INFO "%s: Link down\n", netdev->name);
232 } else {
233 netif_start_queue(netdev); 225 netif_start_queue(netdev);
234 netif_carrier_on(netdev); 226 netif_carrier_on(netdev);
235 printk(KERN_INFO "%s: Link up\n", netdev->name); 227 printk(KERN_INFO "%s: Link up\n", netdev->name);
228 } else {
229 netif_stop_queue(netdev);
230 netif_carrier_off(netdev);
231 printk(KERN_INFO "%s: Link down\n", netdev->name);
236 } 232 }
233 adapter->link_up = link_up;
237 } 234 }
238 *prev = now;
239} 235}
240 236
241/* Update the EQ delay n BE based on the RX frags consumed / sec */ 237/* Update the EQ delay n BE based on the RX frags consumed / sec */
@@ -1395,9 +1391,6 @@ static void be_worker(struct work_struct *work)
1395 container_of(work, struct be_adapter, work.work); 1391 container_of(work, struct be_adapter, work.work);
1396 int status; 1392 int status;
1397 1393
1398 /* Check link */
1399 be_link_status_update(adapter);
1400
1401 /* Get Stats */ 1394 /* Get Stats */
1402 status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); 1395 status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd);
1403 if (!status) 1396 if (!status)
@@ -1522,6 +1515,8 @@ static int be_open(struct net_device *netdev)
1522 struct be_ctrl_info *ctrl = &adapter->ctrl; 1515 struct be_ctrl_info *ctrl = &adapter->ctrl;
1523 struct be_eq_obj *rx_eq = &adapter->rx_eq; 1516 struct be_eq_obj *rx_eq = &adapter->rx_eq;
1524 struct be_eq_obj *tx_eq = &adapter->tx_eq; 1517 struct be_eq_obj *tx_eq = &adapter->tx_eq;
1518 bool link_up;
1519 int status;
1525 1520
1526 /* First time posting */ 1521 /* First time posting */
1527 be_post_rx_frags(adapter); 1522 be_post_rx_frags(adapter);
@@ -1540,7 +1535,10 @@ static int be_open(struct net_device *netdev)
1540 /* Rx compl queue may be in unarmed state; rearm it */ 1535 /* Rx compl queue may be in unarmed state; rearm it */
1541 be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); 1536 be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
1542 1537
1543 be_link_status_update(adapter); 1538 status = be_cmd_link_status_query(ctrl, &link_up);
1539 if (status)
1540 return status;
1541 be_link_status_update(adapter, link_up);
1544 1542
1545 schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); 1543 schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
1546 return 0; 1544 return 0;
@@ -1617,7 +1615,7 @@ static int be_close(struct net_device *netdev)
1617 1615
1618 netif_stop_queue(netdev); 1616 netif_stop_queue(netdev);
1619 netif_carrier_off(netdev); 1617 netif_carrier_off(netdev);
1620 adapter->link.speed = PHY_LINK_SPEED_ZERO; 1618 adapter->link_up = false;
1621 1619
1622 be_intr_set(ctrl, false); 1620 be_intr_set(ctrl, false);
1623 1621
@@ -1808,6 +1806,9 @@ static int be_ctrl_init(struct be_adapter *adapter)
1808 spin_lock_init(&ctrl->mcc_lock); 1806 spin_lock_init(&ctrl->mcc_lock);
1809 spin_lock_init(&ctrl->mcc_cq_lock); 1807 spin_lock_init(&ctrl->mcc_cq_lock);
1810 1808
1809 ctrl->async_cb = be_link_status_update;
1810 ctrl->adapter_ctxt = adapter;
1811
1811 val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); 1812 val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
1812 ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & 1813 ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) &
1813 MEMBAR_CTRL_INT_CTRL_PFUNC_MASK; 1814 MEMBAR_CTRL_INT_CTRL_PFUNC_MASK;