diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/benet | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/benet/be.h | 47 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.c | 649 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.h | 196 | ||||
-rw-r--r-- | drivers/net/benet/be_ethtool.c | 294 | ||||
-rw-r--r-- | drivers/net/benet/be_hw.h | 121 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 828 |
7 files changed, 1772 insertions, 367 deletions
diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig index fdb6e81a4374..1a41a49bb619 100644 --- a/drivers/net/benet/Kconfig +++ b/drivers/net/benet/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config BE2NET | 1 | config BE2NET |
2 | tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" | 2 | tristate "ServerEngines' 10Gbps NIC - BladeEngine" |
3 | depends on PCI && INET | 3 | depends on PCI && INET |
4 | help | 4 | help |
5 | This driver implements the NIC functionality for ServerEngines' | 5 | This driver implements the NIC functionality for ServerEngines' |
6 | 10Gbps network adapter - BladeEngine 2. | 6 | 10Gbps network adapter - BladeEngine. |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 3b79a225628a..56387b191c96 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -29,26 +29,36 @@ | |||
29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/firmware.h> | 31 | #include <linux/firmware.h> |
32 | #include <linux/slab.h> | ||
32 | 33 | ||
33 | #include "be_hw.h" | 34 | #include "be_hw.h" |
34 | 35 | ||
35 | #define DRV_VER "2.101.205" | 36 | #define DRV_VER "2.102.147u" |
36 | #define DRV_NAME "be2net" | 37 | #define DRV_NAME "be2net" |
37 | #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" | 38 | #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" |
39 | #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" | ||
38 | #define OC_NAME "Emulex OneConnect 10Gbps NIC" | 40 | #define OC_NAME "Emulex OneConnect 10Gbps NIC" |
39 | #define DRV_DESC BE_NAME "Driver" | 41 | #define OC_NAME1 "Emulex OneConnect 10Gbps NIC (be3)" |
42 | #define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver" | ||
40 | 43 | ||
41 | #define BE_VENDOR_ID 0x19a2 | 44 | #define BE_VENDOR_ID 0x19a2 |
42 | #define BE_DEVICE_ID1 0x211 | 45 | #define BE_DEVICE_ID1 0x211 |
46 | #define BE_DEVICE_ID2 0x221 | ||
43 | #define OC_DEVICE_ID1 0x700 | 47 | #define OC_DEVICE_ID1 0x700 |
44 | #define OC_DEVICE_ID2 0x701 | 48 | #define OC_DEVICE_ID2 0x710 |
45 | 49 | ||
46 | static inline char *nic_name(struct pci_dev *pdev) | 50 | static inline char *nic_name(struct pci_dev *pdev) |
47 | { | 51 | { |
48 | if (pdev->device == OC_DEVICE_ID1 || pdev->device == OC_DEVICE_ID2) | 52 | switch (pdev->device) { |
53 | case OC_DEVICE_ID1: | ||
49 | return OC_NAME; | 54 | return OC_NAME; |
50 | else | 55 | case OC_DEVICE_ID2: |
56 | return OC_NAME1; | ||
57 | case BE_DEVICE_ID2: | ||
58 | return BE3_NAME; | ||
59 | default: | ||
51 | return BE_NAME; | 60 | return BE_NAME; |
61 | } | ||
52 | } | 62 | } |
53 | 63 | ||
54 | /* Number of bytes of an RX frame that are copied to skb->data */ | 64 | /* Number of bytes of an RX frame that are copied to skb->data */ |
@@ -142,6 +152,7 @@ struct be_eq_obj { | |||
142 | struct be_mcc_obj { | 152 | struct be_mcc_obj { |
143 | struct be_queue_info q; | 153 | struct be_queue_info q; |
144 | struct be_queue_info cq; | 154 | struct be_queue_info cq; |
155 | bool rearm_cq; | ||
145 | }; | 156 | }; |
146 | 157 | ||
147 | struct be_drvr_stats { | 158 | struct be_drvr_stats { |
@@ -154,17 +165,19 @@ struct be_drvr_stats { | |||
154 | ulong be_tx_jiffies; | 165 | ulong be_tx_jiffies; |
155 | u64 be_tx_bytes; | 166 | u64 be_tx_bytes; |
156 | u64 be_tx_bytes_prev; | 167 | u64 be_tx_bytes_prev; |
168 | u64 be_tx_pkts; | ||
157 | u32 be_tx_rate; | 169 | u32 be_tx_rate; |
158 | 170 | ||
159 | u32 cache_barrier[16]; | 171 | u32 cache_barrier[16]; |
160 | 172 | ||
161 | u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */ | 173 | u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */ |
162 | u32 be_polls; /* number of times NAPI called poll function */ | 174 | u32 be_rx_polls; /* number of times NAPI called poll function */ |
163 | u32 be_rx_events; /* number of ucast rx completion events */ | 175 | u32 be_rx_events; /* number of ucast rx completion events */ |
164 | u32 be_rx_compl; /* number of rx completion entries processed */ | 176 | u32 be_rx_compl; /* number of rx completion entries processed */ |
165 | ulong be_rx_jiffies; | 177 | ulong be_rx_jiffies; |
166 | u64 be_rx_bytes; | 178 | u64 be_rx_bytes; |
167 | u64 be_rx_bytes_prev; | 179 | u64 be_rx_bytes_prev; |
180 | u64 be_rx_pkts; | ||
168 | u32 be_rx_rate; | 181 | u32 be_rx_rate; |
169 | /* number of non ether type II frames dropped where | 182 | /* number of non ether type II frames dropped where |
170 | * frame len > length field of Mac Hdr */ | 183 | * frame len > length field of Mac Hdr */ |
@@ -181,7 +194,6 @@ struct be_drvr_stats { | |||
181 | 194 | ||
182 | struct be_stats_obj { | 195 | struct be_stats_obj { |
183 | struct be_drvr_stats drvr_stats; | 196 | struct be_drvr_stats drvr_stats; |
184 | struct net_device_stats net_stats; | ||
185 | struct be_dma_mem cmd; | 197 | struct be_dma_mem cmd; |
186 | }; | 198 | }; |
187 | 199 | ||
@@ -242,8 +254,10 @@ struct be_adapter { | |||
242 | bool rx_post_starved; /* Zero rx frags have been posted to BE */ | 254 | bool rx_post_starved; /* Zero rx frags have been posted to BE */ |
243 | 255 | ||
244 | struct vlan_group *vlan_grp; | 256 | struct vlan_group *vlan_grp; |
245 | u16 num_vlans; | 257 | u16 vlans_added; |
258 | u16 max_vlans; /* Number of vlans supported */ | ||
246 | u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; | 259 | u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; |
260 | struct be_dma_mem mc_cmd_mem; | ||
247 | 261 | ||
248 | struct be_stats_obj stats; | 262 | struct be_stats_obj stats; |
249 | /* Work queue used to perform periodic tasks like getting statistics */ | 263 | /* Work queue used to perform periodic tasks like getting statistics */ |
@@ -255,23 +269,28 @@ struct be_adapter { | |||
255 | u32 if_handle; /* Used to configure filtering */ | 269 | u32 if_handle; /* Used to configure filtering */ |
256 | u32 pmac_id; /* MAC addr handle used by BE card */ | 270 | u32 pmac_id; /* MAC addr handle used by BE card */ |
257 | 271 | ||
272 | bool eeh_err; | ||
258 | bool link_up; | 273 | bool link_up; |
259 | u32 port_num; | 274 | u32 port_num; |
260 | bool promiscuous; | 275 | bool promiscuous; |
276 | bool wol; | ||
261 | u32 cap; | 277 | u32 cap; |
262 | u32 rx_fc; /* Rx flow control */ | 278 | u32 rx_fc; /* Rx flow control */ |
263 | u32 tx_fc; /* Tx flow control */ | 279 | u32 tx_fc; /* Tx flow control */ |
280 | int link_speed; | ||
281 | u8 port_type; | ||
282 | u8 transceiver; | ||
283 | u8 generation; /* BladeEngine ASIC generation */ | ||
264 | }; | 284 | }; |
265 | 285 | ||
286 | /* BladeEngine Generation numbers */ | ||
287 | #define BE_GEN2 2 | ||
288 | #define BE_GEN3 3 | ||
289 | |||
266 | extern const struct ethtool_ops be_ethtool_ops; | 290 | extern const struct ethtool_ops be_ethtool_ops; |
267 | 291 | ||
268 | #define drvr_stats(adapter) (&adapter->stats.drvr_stats) | 292 | #define drvr_stats(adapter) (&adapter->stats.drvr_stats) |
269 | 293 | ||
270 | static inline unsigned int be_pci_func(struct be_adapter *adapter) | ||
271 | { | ||
272 | return PCI_FUNC(adapter->pdev->devfn); | ||
273 | } | ||
274 | |||
275 | #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) | 294 | #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) |
276 | 295 | ||
277 | #define PAGE_SHIFT_4K 12 | 296 | #define PAGE_SHIFT_4K 12 |
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 28a0eda92680..d0ef4ac987cd 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -71,8 +71,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, | |||
71 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | 71 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & |
72 | CQE_STATUS_EXTD_MASK; | 72 | CQE_STATUS_EXTD_MASK; |
73 | dev_warn(&adapter->pdev->dev, | 73 | dev_warn(&adapter->pdev->dev, |
74 | "Error in cmd completion: status(compl/extd)=%d/%d\n", | 74 | "Error in cmd completion - opcode %d, compl %d, extd %d\n", |
75 | compl_status, extd_status); | 75 | compl->tag0, compl_status, extd_status); |
76 | } | 76 | } |
77 | return compl_status; | 77 | return compl_status; |
78 | } | 78 | } |
@@ -104,10 +104,26 @@ static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) | |||
104 | return NULL; | 104 | return NULL; |
105 | } | 105 | } |
106 | 106 | ||
107 | int be_process_mcc(struct be_adapter *adapter) | 107 | void be_async_mcc_enable(struct be_adapter *adapter) |
108 | { | ||
109 | spin_lock_bh(&adapter->mcc_cq_lock); | ||
110 | |||
111 | be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0); | ||
112 | adapter->mcc_obj.rearm_cq = true; | ||
113 | |||
114 | spin_unlock_bh(&adapter->mcc_cq_lock); | ||
115 | } | ||
116 | |||
117 | void be_async_mcc_disable(struct be_adapter *adapter) | ||
118 | { | ||
119 | adapter->mcc_obj.rearm_cq = false; | ||
120 | } | ||
121 | |||
122 | int be_process_mcc(struct be_adapter *adapter, int *status) | ||
108 | { | 123 | { |
109 | struct be_mcc_compl *compl; | 124 | struct be_mcc_compl *compl; |
110 | int num = 0, status = 0; | 125 | int num = 0; |
126 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; | ||
111 | 127 | ||
112 | spin_lock_bh(&adapter->mcc_cq_lock); | 128 | spin_lock_bh(&adapter->mcc_cq_lock); |
113 | while ((compl = be_mcc_compl_get(adapter))) { | 129 | while ((compl = be_mcc_compl_get(adapter))) { |
@@ -119,31 +135,31 @@ int be_process_mcc(struct be_adapter *adapter) | |||
119 | be_async_link_state_process(adapter, | 135 | be_async_link_state_process(adapter, |
120 | (struct be_async_event_link_state *) compl); | 136 | (struct be_async_event_link_state *) compl); |
121 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { | 137 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { |
122 | status = be_mcc_compl_process(adapter, compl); | 138 | *status = be_mcc_compl_process(adapter, compl); |
123 | atomic_dec(&adapter->mcc_obj.q.used); | 139 | atomic_dec(&mcc_obj->q.used); |
124 | } | 140 | } |
125 | be_mcc_compl_use(compl); | 141 | be_mcc_compl_use(compl); |
126 | num++; | 142 | num++; |
127 | } | 143 | } |
128 | 144 | ||
129 | if (num) | ||
130 | be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, num); | ||
131 | |||
132 | spin_unlock_bh(&adapter->mcc_cq_lock); | 145 | spin_unlock_bh(&adapter->mcc_cq_lock); |
133 | return status; | 146 | return num; |
134 | } | 147 | } |
135 | 148 | ||
136 | /* Wait till no more pending mcc requests are present */ | 149 | /* Wait till no more pending mcc requests are present */ |
137 | static int be_mcc_wait_compl(struct be_adapter *adapter) | 150 | static int be_mcc_wait_compl(struct be_adapter *adapter) |
138 | { | 151 | { |
139 | #define mcc_timeout 120000 /* 12s timeout */ | 152 | #define mcc_timeout 120000 /* 12s timeout */ |
140 | int i, status; | 153 | int i, num, status = 0; |
154 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; | ||
155 | |||
141 | for (i = 0; i < mcc_timeout; i++) { | 156 | for (i = 0; i < mcc_timeout; i++) { |
142 | status = be_process_mcc(adapter); | 157 | num = be_process_mcc(adapter, &status); |
143 | if (status) | 158 | if (num) |
144 | return status; | 159 | be_cq_notify(adapter, mcc_obj->cq.id, |
160 | mcc_obj->rearm_cq, num); | ||
145 | 161 | ||
146 | if (atomic_read(&adapter->mcc_obj.q.used) == 0) | 162 | if (atomic_read(&mcc_obj->q.used) == 0) |
147 | break; | 163 | break; |
148 | udelay(100); | 164 | udelay(100); |
149 | } | 165 | } |
@@ -151,7 +167,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) | |||
151 | dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); | 167 | dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); |
152 | return -1; | 168 | return -1; |
153 | } | 169 | } |
154 | return 0; | 170 | return status; |
155 | } | 171 | } |
156 | 172 | ||
157 | /* Notify MCC requests and wait for completion */ | 173 | /* Notify MCC requests and wait for completion */ |
@@ -167,7 +183,14 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) | |||
167 | u32 ready; | 183 | u32 ready; |
168 | 184 | ||
169 | do { | 185 | do { |
170 | ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; | 186 | ready = ioread32(db); |
187 | if (ready == 0xffffffff) { | ||
188 | dev_err(&adapter->pdev->dev, | ||
189 | "pci slot disconnected\n"); | ||
190 | return -1; | ||
191 | } | ||
192 | |||
193 | ready &= MPU_MAILBOX_DB_RDY_MASK; | ||
171 | if (ready) | 194 | if (ready) |
172 | break; | 195 | break; |
173 | 196 | ||
@@ -198,6 +221,11 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) | |||
198 | struct be_mcc_mailbox *mbox = mbox_mem->va; | 221 | struct be_mcc_mailbox *mbox = mbox_mem->va; |
199 | struct be_mcc_compl *compl = &mbox->compl; | 222 | struct be_mcc_compl *compl = &mbox->compl; |
200 | 223 | ||
224 | /* wait for ready to be set */ | ||
225 | status = be_mbox_db_ready_wait(adapter, db); | ||
226 | if (status != 0) | ||
227 | return status; | ||
228 | |||
201 | val |= MPU_MAILBOX_DB_HI_MASK; | 229 | val |= MPU_MAILBOX_DB_HI_MASK; |
202 | /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ | 230 | /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ |
203 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | 231 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; |
@@ -277,7 +305,7 @@ static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) | |||
277 | 305 | ||
278 | /* Don't touch the hdr after it's prepared */ | 306 | /* Don't touch the hdr after it's prepared */ |
279 | static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | 307 | static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, |
280 | bool embedded, u8 sge_cnt) | 308 | bool embedded, u8 sge_cnt, u32 opcode) |
281 | { | 309 | { |
282 | if (embedded) | 310 | if (embedded) |
283 | wrb->embedded |= MCC_WRB_EMBEDDED_MASK; | 311 | wrb->embedded |= MCC_WRB_EMBEDDED_MASK; |
@@ -285,7 +313,8 @@ static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | |||
285 | wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << | 313 | wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << |
286 | MCC_WRB_SGE_CNT_SHIFT; | 314 | MCC_WRB_SGE_CNT_SHIFT; |
287 | wrb->payload_length = payload_len; | 315 | wrb->payload_length = payload_len; |
288 | be_dws_cpu_to_le(wrb, 20); | 316 | wrb->tag0 = opcode; |
317 | be_dws_cpu_to_le(wrb, 8); | ||
289 | } | 318 | } |
290 | 319 | ||
291 | /* Don't touch the hdr after it's prepared */ | 320 | /* Don't touch the hdr after it's prepared */ |
@@ -295,6 +324,7 @@ static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, | |||
295 | req_hdr->opcode = opcode; | 324 | req_hdr->opcode = opcode; |
296 | req_hdr->subsystem = subsystem; | 325 | req_hdr->subsystem = subsystem; |
297 | req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); | 326 | req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); |
327 | req_hdr->version = 0; | ||
298 | } | 328 | } |
299 | 329 | ||
300 | static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, | 330 | static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, |
@@ -349,7 +379,11 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) | |||
349 | struct be_queue_info *mccq = &adapter->mcc_obj.q; | 379 | struct be_queue_info *mccq = &adapter->mcc_obj.q; |
350 | struct be_mcc_wrb *wrb; | 380 | struct be_mcc_wrb *wrb; |
351 | 381 | ||
352 | BUG_ON(atomic_read(&mccq->used) >= mccq->len); | 382 | if (atomic_read(&mccq->used) >= mccq->len) { |
383 | dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n"); | ||
384 | return NULL; | ||
385 | } | ||
386 | |||
353 | wrb = queue_head_node(mccq); | 387 | wrb = queue_head_node(mccq); |
354 | queue_head_inc(mccq); | 388 | queue_head_inc(mccq); |
355 | atomic_inc(&mccq->used); | 389 | atomic_inc(&mccq->used); |
@@ -357,6 +391,60 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) | |||
357 | return wrb; | 391 | return wrb; |
358 | } | 392 | } |
359 | 393 | ||
394 | /* Tell fw we're about to start firing cmds by writing a | ||
395 | * special pattern across the wrb hdr; uses mbox | ||
396 | */ | ||
397 | int be_cmd_fw_init(struct be_adapter *adapter) | ||
398 | { | ||
399 | u8 *wrb; | ||
400 | int status; | ||
401 | |||
402 | spin_lock(&adapter->mbox_lock); | ||
403 | |||
404 | wrb = (u8 *)wrb_from_mbox(adapter); | ||
405 | *wrb++ = 0xFF; | ||
406 | *wrb++ = 0x12; | ||
407 | *wrb++ = 0x34; | ||
408 | *wrb++ = 0xFF; | ||
409 | *wrb++ = 0xFF; | ||
410 | *wrb++ = 0x56; | ||
411 | *wrb++ = 0x78; | ||
412 | *wrb = 0xFF; | ||
413 | |||
414 | status = be_mbox_notify_wait(adapter); | ||
415 | |||
416 | spin_unlock(&adapter->mbox_lock); | ||
417 | return status; | ||
418 | } | ||
419 | |||
420 | /* Tell fw we're done with firing cmds by writing a | ||
421 | * special pattern across the wrb hdr; uses mbox | ||
422 | */ | ||
423 | int be_cmd_fw_clean(struct be_adapter *adapter) | ||
424 | { | ||
425 | u8 *wrb; | ||
426 | int status; | ||
427 | |||
428 | if (adapter->eeh_err) | ||
429 | return -EIO; | ||
430 | |||
431 | spin_lock(&adapter->mbox_lock); | ||
432 | |||
433 | wrb = (u8 *)wrb_from_mbox(adapter); | ||
434 | *wrb++ = 0xFF; | ||
435 | *wrb++ = 0xAA; | ||
436 | *wrb++ = 0xBB; | ||
437 | *wrb++ = 0xFF; | ||
438 | *wrb++ = 0xFF; | ||
439 | *wrb++ = 0xCC; | ||
440 | *wrb++ = 0xDD; | ||
441 | *wrb = 0xFF; | ||
442 | |||
443 | status = be_mbox_notify_wait(adapter); | ||
444 | |||
445 | spin_unlock(&adapter->mbox_lock); | ||
446 | return status; | ||
447 | } | ||
360 | int be_cmd_eq_create(struct be_adapter *adapter, | 448 | int be_cmd_eq_create(struct be_adapter *adapter, |
361 | struct be_queue_info *eq, int eq_delay) | 449 | struct be_queue_info *eq, int eq_delay) |
362 | { | 450 | { |
@@ -370,15 +458,13 @@ int be_cmd_eq_create(struct be_adapter *adapter, | |||
370 | wrb = wrb_from_mbox(adapter); | 458 | wrb = wrb_from_mbox(adapter); |
371 | req = embedded_payload(wrb); | 459 | req = embedded_payload(wrb); |
372 | 460 | ||
373 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 461 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_COMMON_EQ_CREATE); |
374 | 462 | ||
375 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 463 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
376 | OPCODE_COMMON_EQ_CREATE, sizeof(*req)); | 464 | OPCODE_COMMON_EQ_CREATE, sizeof(*req)); |
377 | 465 | ||
378 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); | 466 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); |
379 | 467 | ||
380 | AMAP_SET_BITS(struct amap_eq_context, func, req->context, | ||
381 | be_pci_func(adapter)); | ||
382 | AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); | 468 | AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); |
383 | /* 4byte eqe*/ | 469 | /* 4byte eqe*/ |
384 | AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); | 470 | AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); |
@@ -414,7 +500,8 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, | |||
414 | wrb = wrb_from_mbox(adapter); | 500 | wrb = wrb_from_mbox(adapter); |
415 | req = embedded_payload(wrb); | 501 | req = embedded_payload(wrb); |
416 | 502 | ||
417 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 503 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
504 | OPCODE_COMMON_NTWK_MAC_QUERY); | ||
418 | 505 | ||
419 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 506 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
420 | OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req)); | 507 | OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req)); |
@@ -448,9 +535,14 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, | |||
448 | spin_lock_bh(&adapter->mcc_lock); | 535 | spin_lock_bh(&adapter->mcc_lock); |
449 | 536 | ||
450 | wrb = wrb_from_mccq(adapter); | 537 | wrb = wrb_from_mccq(adapter); |
538 | if (!wrb) { | ||
539 | status = -EBUSY; | ||
540 | goto err; | ||
541 | } | ||
451 | req = embedded_payload(wrb); | 542 | req = embedded_payload(wrb); |
452 | 543 | ||
453 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 544 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
545 | OPCODE_COMMON_NTWK_PMAC_ADD); | ||
454 | 546 | ||
455 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 547 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
456 | OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req)); | 548 | OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req)); |
@@ -464,6 +556,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, | |||
464 | *pmac_id = le32_to_cpu(resp->pmac_id); | 556 | *pmac_id = le32_to_cpu(resp->pmac_id); |
465 | } | 557 | } |
466 | 558 | ||
559 | err: | ||
467 | spin_unlock_bh(&adapter->mcc_lock); | 560 | spin_unlock_bh(&adapter->mcc_lock); |
468 | return status; | 561 | return status; |
469 | } | 562 | } |
@@ -478,9 +571,14 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) | |||
478 | spin_lock_bh(&adapter->mcc_lock); | 571 | spin_lock_bh(&adapter->mcc_lock); |
479 | 572 | ||
480 | wrb = wrb_from_mccq(adapter); | 573 | wrb = wrb_from_mccq(adapter); |
574 | if (!wrb) { | ||
575 | status = -EBUSY; | ||
576 | goto err; | ||
577 | } | ||
481 | req = embedded_payload(wrb); | 578 | req = embedded_payload(wrb); |
482 | 579 | ||
483 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 580 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
581 | OPCODE_COMMON_NTWK_PMAC_DEL); | ||
484 | 582 | ||
485 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 583 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
486 | OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req)); | 584 | OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req)); |
@@ -490,8 +588,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) | |||
490 | 588 | ||
491 | status = be_mcc_notify_wait(adapter); | 589 | status = be_mcc_notify_wait(adapter); |
492 | 590 | ||
591 | err: | ||
493 | spin_unlock_bh(&adapter->mcc_lock); | 592 | spin_unlock_bh(&adapter->mcc_lock); |
494 | |||
495 | return status; | 593 | return status; |
496 | } | 594 | } |
497 | 595 | ||
@@ -512,7 +610,8 @@ int be_cmd_cq_create(struct be_adapter *adapter, | |||
512 | req = embedded_payload(wrb); | 610 | req = embedded_payload(wrb); |
513 | ctxt = &req->context; | 611 | ctxt = &req->context; |
514 | 612 | ||
515 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 613 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
614 | OPCODE_COMMON_CQ_CREATE); | ||
516 | 615 | ||
517 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 616 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
518 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); | 617 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); |
@@ -528,7 +627,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, | |||
528 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); | 627 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); |
529 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); | 628 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); |
530 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); | 629 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); |
531 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, be_pci_func(adapter)); | ||
532 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 630 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); |
533 | 631 | ||
534 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 632 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); |
@@ -569,14 +667,14 @@ int be_cmd_mccq_create(struct be_adapter *adapter, | |||
569 | req = embedded_payload(wrb); | 667 | req = embedded_payload(wrb); |
570 | ctxt = &req->context; | 668 | ctxt = &req->context; |
571 | 669 | ||
572 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 670 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
671 | OPCODE_COMMON_MCC_CREATE); | ||
573 | 672 | ||
574 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 673 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
575 | OPCODE_COMMON_MCC_CREATE, sizeof(*req)); | 674 | OPCODE_COMMON_MCC_CREATE, sizeof(*req)); |
576 | 675 | ||
577 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 676 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); |
578 | 677 | ||
579 | AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, be_pci_func(adapter)); | ||
580 | AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); | 678 | AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); |
581 | AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, | 679 | AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, |
582 | be_encoded_q_len(mccq->len)); | 680 | be_encoded_q_len(mccq->len)); |
@@ -613,7 +711,8 @@ int be_cmd_txq_create(struct be_adapter *adapter, | |||
613 | req = embedded_payload(wrb); | 711 | req = embedded_payload(wrb); |
614 | ctxt = &req->context; | 712 | ctxt = &req->context; |
615 | 713 | ||
616 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 714 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
715 | OPCODE_ETH_TX_CREATE); | ||
617 | 716 | ||
618 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE, | 717 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE, |
619 | sizeof(*req)); | 718 | sizeof(*req)); |
@@ -624,8 +723,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, | |||
624 | 723 | ||
625 | AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, | 724 | AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, |
626 | be_encoded_q_len(txq->len)); | 725 | be_encoded_q_len(txq->len)); |
627 | AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, | ||
628 | be_pci_func(adapter)); | ||
629 | AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); | 726 | AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); |
630 | AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); | 727 | AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); |
631 | 728 | ||
@@ -660,7 +757,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter, | |||
660 | wrb = wrb_from_mbox(adapter); | 757 | wrb = wrb_from_mbox(adapter); |
661 | req = embedded_payload(wrb); | 758 | req = embedded_payload(wrb); |
662 | 759 | ||
663 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 760 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
761 | OPCODE_ETH_RX_CREATE); | ||
664 | 762 | ||
665 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE, | 763 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE, |
666 | sizeof(*req)); | 764 | sizeof(*req)); |
@@ -696,13 +794,14 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, | |||
696 | u8 subsys = 0, opcode = 0; | 794 | u8 subsys = 0, opcode = 0; |
697 | int status; | 795 | int status; |
698 | 796 | ||
797 | if (adapter->eeh_err) | ||
798 | return -EIO; | ||
799 | |||
699 | spin_lock(&adapter->mbox_lock); | 800 | spin_lock(&adapter->mbox_lock); |
700 | 801 | ||
701 | wrb = wrb_from_mbox(adapter); | 802 | wrb = wrb_from_mbox(adapter); |
702 | req = embedded_payload(wrb); | 803 | req = embedded_payload(wrb); |
703 | 804 | ||
704 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
705 | |||
706 | switch (queue_type) { | 805 | switch (queue_type) { |
707 | case QTYPE_EQ: | 806 | case QTYPE_EQ: |
708 | subsys = CMD_SUBSYSTEM_COMMON; | 807 | subsys = CMD_SUBSYSTEM_COMMON; |
@@ -727,6 +826,9 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, | |||
727 | default: | 826 | default: |
728 | BUG(); | 827 | BUG(); |
729 | } | 828 | } |
829 | |||
830 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, opcode); | ||
831 | |||
730 | be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); | 832 | be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); |
731 | req->id = cpu_to_le16(q->id); | 833 | req->id = cpu_to_le16(q->id); |
732 | 834 | ||
@@ -752,7 +854,8 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, | |||
752 | wrb = wrb_from_mbox(adapter); | 854 | wrb = wrb_from_mbox(adapter); |
753 | req = embedded_payload(wrb); | 855 | req = embedded_payload(wrb); |
754 | 856 | ||
755 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 857 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
858 | OPCODE_COMMON_NTWK_INTERFACE_CREATE); | ||
756 | 859 | ||
757 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 860 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
758 | OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req)); | 861 | OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req)); |
@@ -782,12 +885,16 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id) | |||
782 | struct be_cmd_req_if_destroy *req; | 885 | struct be_cmd_req_if_destroy *req; |
783 | int status; | 886 | int status; |
784 | 887 | ||
888 | if (adapter->eeh_err) | ||
889 | return -EIO; | ||
890 | |||
785 | spin_lock(&adapter->mbox_lock); | 891 | spin_lock(&adapter->mbox_lock); |
786 | 892 | ||
787 | wrb = wrb_from_mbox(adapter); | 893 | wrb = wrb_from_mbox(adapter); |
788 | req = embedded_payload(wrb); | 894 | req = embedded_payload(wrb); |
789 | 895 | ||
790 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 896 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
897 | OPCODE_COMMON_NTWK_INTERFACE_DESTROY); | ||
791 | 898 | ||
792 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 899 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
793 | OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); | 900 | OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); |
@@ -810,15 +917,20 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) | |||
810 | struct be_mcc_wrb *wrb; | 917 | struct be_mcc_wrb *wrb; |
811 | struct be_cmd_req_get_stats *req; | 918 | struct be_cmd_req_get_stats *req; |
812 | struct be_sge *sge; | 919 | struct be_sge *sge; |
920 | int status = 0; | ||
813 | 921 | ||
814 | spin_lock_bh(&adapter->mcc_lock); | 922 | spin_lock_bh(&adapter->mcc_lock); |
815 | 923 | ||
816 | wrb = wrb_from_mccq(adapter); | 924 | wrb = wrb_from_mccq(adapter); |
925 | if (!wrb) { | ||
926 | status = -EBUSY; | ||
927 | goto err; | ||
928 | } | ||
817 | req = nonemb_cmd->va; | 929 | req = nonemb_cmd->va; |
818 | sge = nonembedded_sgl(wrb); | 930 | sge = nonembedded_sgl(wrb); |
819 | 931 | ||
820 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | 932 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, |
821 | wrb->tag0 = OPCODE_ETH_GET_STATISTICS; | 933 | OPCODE_ETH_GET_STATISTICS); |
822 | 934 | ||
823 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, | 935 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, |
824 | OPCODE_ETH_GET_STATISTICS, sizeof(*req)); | 936 | OPCODE_ETH_GET_STATISTICS, sizeof(*req)); |
@@ -828,13 +940,14 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) | |||
828 | 940 | ||
829 | be_mcc_notify(adapter); | 941 | be_mcc_notify(adapter); |
830 | 942 | ||
943 | err: | ||
831 | spin_unlock_bh(&adapter->mcc_lock); | 944 | spin_unlock_bh(&adapter->mcc_lock); |
832 | return 0; | 945 | return status; |
833 | } | 946 | } |
834 | 947 | ||
835 | /* Uses synchronous mcc */ | 948 | /* Uses synchronous mcc */ |
836 | int be_cmd_link_status_query(struct be_adapter *adapter, | 949 | int be_cmd_link_status_query(struct be_adapter *adapter, |
837 | bool *link_up) | 950 | bool *link_up, u8 *mac_speed, u16 *link_speed) |
838 | { | 951 | { |
839 | struct be_mcc_wrb *wrb; | 952 | struct be_mcc_wrb *wrb; |
840 | struct be_cmd_req_link_status *req; | 953 | struct be_cmd_req_link_status *req; |
@@ -843,11 +956,16 @@ int be_cmd_link_status_query(struct be_adapter *adapter, | |||
843 | spin_lock_bh(&adapter->mcc_lock); | 956 | spin_lock_bh(&adapter->mcc_lock); |
844 | 957 | ||
845 | wrb = wrb_from_mccq(adapter); | 958 | wrb = wrb_from_mccq(adapter); |
959 | if (!wrb) { | ||
960 | status = -EBUSY; | ||
961 | goto err; | ||
962 | } | ||
846 | req = embedded_payload(wrb); | 963 | req = embedded_payload(wrb); |
847 | 964 | ||
848 | *link_up = false; | 965 | *link_up = false; |
849 | 966 | ||
850 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 967 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
968 | OPCODE_COMMON_NTWK_LINK_STATUS_QUERY); | ||
851 | 969 | ||
852 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 970 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
853 | OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); | 971 | OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); |
@@ -855,10 +973,14 @@ int be_cmd_link_status_query(struct be_adapter *adapter, | |||
855 | status = be_mcc_notify_wait(adapter); | 973 | status = be_mcc_notify_wait(adapter); |
856 | if (!status) { | 974 | if (!status) { |
857 | struct be_cmd_resp_link_status *resp = embedded_payload(wrb); | 975 | struct be_cmd_resp_link_status *resp = embedded_payload(wrb); |
858 | if (resp->mac_speed != PHY_LINK_SPEED_ZERO) | 976 | if (resp->mac_speed != PHY_LINK_SPEED_ZERO) { |
859 | *link_up = true; | 977 | *link_up = true; |
978 | *link_speed = le16_to_cpu(resp->link_speed); | ||
979 | *mac_speed = resp->mac_speed; | ||
980 | } | ||
860 | } | 981 | } |
861 | 982 | ||
983 | err: | ||
862 | spin_unlock_bh(&adapter->mcc_lock); | 984 | spin_unlock_bh(&adapter->mcc_lock); |
863 | return status; | 985 | return status; |
864 | } | 986 | } |
@@ -875,7 +997,8 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver) | |||
875 | wrb = wrb_from_mbox(adapter); | 997 | wrb = wrb_from_mbox(adapter); |
876 | req = embedded_payload(wrb); | 998 | req = embedded_payload(wrb); |
877 | 999 | ||
878 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1000 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1001 | OPCODE_COMMON_GET_FW_VERSION); | ||
879 | 1002 | ||
880 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1003 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
881 | OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); | 1004 | OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); |
@@ -897,13 +1020,19 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) | |||
897 | { | 1020 | { |
898 | struct be_mcc_wrb *wrb; | 1021 | struct be_mcc_wrb *wrb; |
899 | struct be_cmd_req_modify_eq_delay *req; | 1022 | struct be_cmd_req_modify_eq_delay *req; |
1023 | int status = 0; | ||
900 | 1024 | ||
901 | spin_lock_bh(&adapter->mcc_lock); | 1025 | spin_lock_bh(&adapter->mcc_lock); |
902 | 1026 | ||
903 | wrb = wrb_from_mccq(adapter); | 1027 | wrb = wrb_from_mccq(adapter); |
1028 | if (!wrb) { | ||
1029 | status = -EBUSY; | ||
1030 | goto err; | ||
1031 | } | ||
904 | req = embedded_payload(wrb); | 1032 | req = embedded_payload(wrb); |
905 | 1033 | ||
906 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1034 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1035 | OPCODE_COMMON_MODIFY_EQ_DELAY); | ||
907 | 1036 | ||
908 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1037 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
909 | OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); | 1038 | OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); |
@@ -915,8 +1044,9 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) | |||
915 | 1044 | ||
916 | be_mcc_notify(adapter); | 1045 | be_mcc_notify(adapter); |
917 | 1046 | ||
1047 | err: | ||
918 | spin_unlock_bh(&adapter->mcc_lock); | 1048 | spin_unlock_bh(&adapter->mcc_lock); |
919 | return 0; | 1049 | return status; |
920 | } | 1050 | } |
921 | 1051 | ||
922 | /* Uses sycnhronous mcc */ | 1052 | /* Uses sycnhronous mcc */ |
@@ -930,9 +1060,14 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, | |||
930 | spin_lock_bh(&adapter->mcc_lock); | 1060 | spin_lock_bh(&adapter->mcc_lock); |
931 | 1061 | ||
932 | wrb = wrb_from_mccq(adapter); | 1062 | wrb = wrb_from_mccq(adapter); |
1063 | if (!wrb) { | ||
1064 | status = -EBUSY; | ||
1065 | goto err; | ||
1066 | } | ||
933 | req = embedded_payload(wrb); | 1067 | req = embedded_payload(wrb); |
934 | 1068 | ||
935 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1069 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1070 | OPCODE_COMMON_NTWK_VLAN_CONFIG); | ||
936 | 1071 | ||
937 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1072 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
938 | OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req)); | 1073 | OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req)); |
@@ -948,6 +1083,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, | |||
948 | 1083 | ||
949 | status = be_mcc_notify_wait(adapter); | 1084 | status = be_mcc_notify_wait(adapter); |
950 | 1085 | ||
1086 | err: | ||
951 | spin_unlock_bh(&adapter->mcc_lock); | 1087 | spin_unlock_bh(&adapter->mcc_lock); |
952 | return status; | 1088 | return status; |
953 | } | 1089 | } |
@@ -964,9 +1100,13 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) | |||
964 | spin_lock_bh(&adapter->mcc_lock); | 1100 | spin_lock_bh(&adapter->mcc_lock); |
965 | 1101 | ||
966 | wrb = wrb_from_mccq(adapter); | 1102 | wrb = wrb_from_mccq(adapter); |
1103 | if (!wrb) { | ||
1104 | status = -EBUSY; | ||
1105 | goto err; | ||
1106 | } | ||
967 | req = embedded_payload(wrb); | 1107 | req = embedded_payload(wrb); |
968 | 1108 | ||
969 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1109 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_PROMISCUOUS); |
970 | 1110 | ||
971 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, | 1111 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, |
972 | OPCODE_ETH_PROMISCUOUS, sizeof(*req)); | 1112 | OPCODE_ETH_PROMISCUOUS, sizeof(*req)); |
@@ -978,6 +1118,7 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) | |||
978 | 1118 | ||
979 | status = be_mcc_notify_wait(adapter); | 1119 | status = be_mcc_notify_wait(adapter); |
980 | 1120 | ||
1121 | err: | ||
981 | spin_unlock_bh(&adapter->mcc_lock); | 1122 | spin_unlock_bh(&adapter->mcc_lock); |
982 | return status; | 1123 | return status; |
983 | } | 1124 | } |
@@ -987,40 +1128,51 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) | |||
987 | * (mc == NULL) => multicast promiscous | 1128 | * (mc == NULL) => multicast promiscous |
988 | */ | 1129 | */ |
989 | int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, | 1130 | int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, |
990 | struct dev_mc_list *mc_list, u32 mc_count) | 1131 | struct net_device *netdev, struct be_dma_mem *mem) |
991 | { | 1132 | { |
992 | #define BE_MAX_MC 32 /* set mcast promisc if > 32 */ | ||
993 | struct be_mcc_wrb *wrb; | 1133 | struct be_mcc_wrb *wrb; |
994 | struct be_cmd_req_mcast_mac_config *req; | 1134 | struct be_cmd_req_mcast_mac_config *req = mem->va; |
1135 | struct be_sge *sge; | ||
1136 | int status; | ||
995 | 1137 | ||
996 | spin_lock_bh(&adapter->mcc_lock); | 1138 | spin_lock_bh(&adapter->mcc_lock); |
997 | 1139 | ||
998 | wrb = wrb_from_mccq(adapter); | 1140 | wrb = wrb_from_mccq(adapter); |
999 | req = embedded_payload(wrb); | 1141 | if (!wrb) { |
1142 | status = -EBUSY; | ||
1143 | goto err; | ||
1144 | } | ||
1145 | sge = nonembedded_sgl(wrb); | ||
1146 | memset(req, 0, sizeof(*req)); | ||
1000 | 1147 | ||
1001 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1148 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, |
1149 | OPCODE_COMMON_NTWK_MULTICAST_SET); | ||
1150 | sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma)); | ||
1151 | sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF); | ||
1152 | sge->len = cpu_to_le32(mem->size); | ||
1002 | 1153 | ||
1003 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1154 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1004 | OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); | 1155 | OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); |
1005 | 1156 | ||
1006 | req->interface_id = if_id; | 1157 | req->interface_id = if_id; |
1007 | if (mc_list && mc_count <= BE_MAX_MC) { | 1158 | if (netdev) { |
1008 | int i; | 1159 | int i; |
1009 | struct dev_mc_list *mc; | 1160 | struct dev_mc_list *mc; |
1010 | 1161 | ||
1011 | req->num_mac = cpu_to_le16(mc_count); | 1162 | req->num_mac = cpu_to_le16(netdev_mc_count(netdev)); |
1012 | 1163 | ||
1013 | for (mc = mc_list, i = 0; mc; mc = mc->next, i++) | 1164 | i = 0; |
1165 | netdev_for_each_mc_addr(mc, netdev) | ||
1014 | memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN); | 1166 | memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN); |
1015 | } else { | 1167 | } else { |
1016 | req->promiscuous = 1; | 1168 | req->promiscuous = 1; |
1017 | } | 1169 | } |
1018 | 1170 | ||
1019 | be_mcc_notify_wait(adapter); | 1171 | status = be_mcc_notify_wait(adapter); |
1020 | 1172 | ||
1173 | err: | ||
1021 | spin_unlock_bh(&adapter->mcc_lock); | 1174 | spin_unlock_bh(&adapter->mcc_lock); |
1022 | 1175 | return status; | |
1023 | return 0; | ||
1024 | } | 1176 | } |
1025 | 1177 | ||
1026 | /* Uses synchrounous mcc */ | 1178 | /* Uses synchrounous mcc */ |
@@ -1033,9 +1185,14 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) | |||
1033 | spin_lock_bh(&adapter->mcc_lock); | 1185 | spin_lock_bh(&adapter->mcc_lock); |
1034 | 1186 | ||
1035 | wrb = wrb_from_mccq(adapter); | 1187 | wrb = wrb_from_mccq(adapter); |
1188 | if (!wrb) { | ||
1189 | status = -EBUSY; | ||
1190 | goto err; | ||
1191 | } | ||
1036 | req = embedded_payload(wrb); | 1192 | req = embedded_payload(wrb); |
1037 | 1193 | ||
1038 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1194 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1195 | OPCODE_COMMON_SET_FLOW_CONTROL); | ||
1039 | 1196 | ||
1040 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1197 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1041 | OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req)); | 1198 | OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req)); |
@@ -1045,6 +1202,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) | |||
1045 | 1202 | ||
1046 | status = be_mcc_notify_wait(adapter); | 1203 | status = be_mcc_notify_wait(adapter); |
1047 | 1204 | ||
1205 | err: | ||
1048 | spin_unlock_bh(&adapter->mcc_lock); | 1206 | spin_unlock_bh(&adapter->mcc_lock); |
1049 | return status; | 1207 | return status; |
1050 | } | 1208 | } |
@@ -1059,9 +1217,14 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) | |||
1059 | spin_lock_bh(&adapter->mcc_lock); | 1217 | spin_lock_bh(&adapter->mcc_lock); |
1060 | 1218 | ||
1061 | wrb = wrb_from_mccq(adapter); | 1219 | wrb = wrb_from_mccq(adapter); |
1220 | if (!wrb) { | ||
1221 | status = -EBUSY; | ||
1222 | goto err; | ||
1223 | } | ||
1062 | req = embedded_payload(wrb); | 1224 | req = embedded_payload(wrb); |
1063 | 1225 | ||
1064 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1226 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1227 | OPCODE_COMMON_GET_FLOW_CONTROL); | ||
1065 | 1228 | ||
1066 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1229 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1067 | OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); | 1230 | OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); |
@@ -1074,6 +1237,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) | |||
1074 | *rx_fc = le16_to_cpu(resp->rx_flow_control); | 1237 | *rx_fc = le16_to_cpu(resp->rx_flow_control); |
1075 | } | 1238 | } |
1076 | 1239 | ||
1240 | err: | ||
1077 | spin_unlock_bh(&adapter->mcc_lock); | 1241 | spin_unlock_bh(&adapter->mcc_lock); |
1078 | return status; | 1242 | return status; |
1079 | } | 1243 | } |
@@ -1090,7 +1254,8 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *cap) | |||
1090 | wrb = wrb_from_mbox(adapter); | 1254 | wrb = wrb_from_mbox(adapter); |
1091 | req = embedded_payload(wrb); | 1255 | req = embedded_payload(wrb); |
1092 | 1256 | ||
1093 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1257 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1258 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG); | ||
1094 | 1259 | ||
1095 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1260 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1096 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); | 1261 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); |
@@ -1118,7 +1283,8 @@ int be_cmd_reset_function(struct be_adapter *adapter) | |||
1118 | wrb = wrb_from_mbox(adapter); | 1283 | wrb = wrb_from_mbox(adapter); |
1119 | req = embedded_payload(wrb); | 1284 | req = embedded_payload(wrb); |
1120 | 1285 | ||
1121 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 1286 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, |
1287 | OPCODE_COMMON_FUNCTION_RESET); | ||
1122 | 1288 | ||
1123 | be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, | 1289 | be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, |
1124 | OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); | 1290 | OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); |
@@ -1129,20 +1295,133 @@ int be_cmd_reset_function(struct be_adapter *adapter) | |||
1129 | return status; | 1295 | return status; |
1130 | } | 1296 | } |
1131 | 1297 | ||
1298 | /* Uses sync mcc */ | ||
1299 | int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, | ||
1300 | u8 bcn, u8 sts, u8 state) | ||
1301 | { | ||
1302 | struct be_mcc_wrb *wrb; | ||
1303 | struct be_cmd_req_enable_disable_beacon *req; | ||
1304 | int status; | ||
1305 | |||
1306 | spin_lock_bh(&adapter->mcc_lock); | ||
1307 | |||
1308 | wrb = wrb_from_mccq(adapter); | ||
1309 | if (!wrb) { | ||
1310 | status = -EBUSY; | ||
1311 | goto err; | ||
1312 | } | ||
1313 | req = embedded_payload(wrb); | ||
1314 | |||
1315 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, | ||
1316 | OPCODE_COMMON_ENABLE_DISABLE_BEACON); | ||
1317 | |||
1318 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1319 | OPCODE_COMMON_ENABLE_DISABLE_BEACON, sizeof(*req)); | ||
1320 | |||
1321 | req->port_num = port_num; | ||
1322 | req->beacon_state = state; | ||
1323 | req->beacon_duration = bcn; | ||
1324 | req->status_duration = sts; | ||
1325 | |||
1326 | status = be_mcc_notify_wait(adapter); | ||
1327 | |||
1328 | err: | ||
1329 | spin_unlock_bh(&adapter->mcc_lock); | ||
1330 | return status; | ||
1331 | } | ||
1332 | |||
1333 | /* Uses sync mcc */ | ||
1334 | int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) | ||
1335 | { | ||
1336 | struct be_mcc_wrb *wrb; | ||
1337 | struct be_cmd_req_get_beacon_state *req; | ||
1338 | int status; | ||
1339 | |||
1340 | spin_lock_bh(&adapter->mcc_lock); | ||
1341 | |||
1342 | wrb = wrb_from_mccq(adapter); | ||
1343 | if (!wrb) { | ||
1344 | status = -EBUSY; | ||
1345 | goto err; | ||
1346 | } | ||
1347 | req = embedded_payload(wrb); | ||
1348 | |||
1349 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, | ||
1350 | OPCODE_COMMON_GET_BEACON_STATE); | ||
1351 | |||
1352 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1353 | OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req)); | ||
1354 | |||
1355 | req->port_num = port_num; | ||
1356 | |||
1357 | status = be_mcc_notify_wait(adapter); | ||
1358 | if (!status) { | ||
1359 | struct be_cmd_resp_get_beacon_state *resp = | ||
1360 | embedded_payload(wrb); | ||
1361 | *state = resp->beacon_state; | ||
1362 | } | ||
1363 | |||
1364 | err: | ||
1365 | spin_unlock_bh(&adapter->mcc_lock); | ||
1366 | return status; | ||
1367 | } | ||
1368 | |||
1369 | /* Uses sync mcc */ | ||
1370 | int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, | ||
1371 | u8 *connector) | ||
1372 | { | ||
1373 | struct be_mcc_wrb *wrb; | ||
1374 | struct be_cmd_req_port_type *req; | ||
1375 | int status; | ||
1376 | |||
1377 | spin_lock_bh(&adapter->mcc_lock); | ||
1378 | |||
1379 | wrb = wrb_from_mccq(adapter); | ||
1380 | if (!wrb) { | ||
1381 | status = -EBUSY; | ||
1382 | goto err; | ||
1383 | } | ||
1384 | req = embedded_payload(wrb); | ||
1385 | |||
1386 | be_wrb_hdr_prepare(wrb, sizeof(struct be_cmd_resp_port_type), true, 0, | ||
1387 | OPCODE_COMMON_READ_TRANSRECV_DATA); | ||
1388 | |||
1389 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1390 | OPCODE_COMMON_READ_TRANSRECV_DATA, sizeof(*req)); | ||
1391 | |||
1392 | req->port = cpu_to_le32(port); | ||
1393 | req->page_num = cpu_to_le32(TR_PAGE_A0); | ||
1394 | status = be_mcc_notify_wait(adapter); | ||
1395 | if (!status) { | ||
1396 | struct be_cmd_resp_port_type *resp = embedded_payload(wrb); | ||
1397 | *connector = resp->data.connector; | ||
1398 | } | ||
1399 | |||
1400 | err: | ||
1401 | spin_unlock_bh(&adapter->mcc_lock); | ||
1402 | return status; | ||
1403 | } | ||
1404 | |||
1132 | int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, | 1405 | int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, |
1133 | u32 flash_type, u32 flash_opcode, u32 buf_size) | 1406 | u32 flash_type, u32 flash_opcode, u32 buf_size) |
1134 | { | 1407 | { |
1135 | struct be_mcc_wrb *wrb; | 1408 | struct be_mcc_wrb *wrb; |
1136 | struct be_cmd_write_flashrom *req = cmd->va; | 1409 | struct be_cmd_write_flashrom *req; |
1137 | struct be_sge *sge; | 1410 | struct be_sge *sge; |
1138 | int status; | 1411 | int status; |
1139 | 1412 | ||
1140 | spin_lock_bh(&adapter->mcc_lock); | 1413 | spin_lock_bh(&adapter->mcc_lock); |
1141 | 1414 | ||
1142 | wrb = wrb_from_mccq(adapter); | 1415 | wrb = wrb_from_mccq(adapter); |
1416 | if (!wrb) { | ||
1417 | status = -EBUSY; | ||
1418 | goto err; | ||
1419 | } | ||
1420 | req = cmd->va; | ||
1143 | sge = nonembedded_sgl(wrb); | 1421 | sge = nonembedded_sgl(wrb); |
1144 | 1422 | ||
1145 | be_wrb_hdr_prepare(wrb, cmd->size, false, 1); | 1423 | be_wrb_hdr_prepare(wrb, cmd->size, false, 1, |
1424 | OPCODE_COMMON_WRITE_FLASHROM); | ||
1146 | 1425 | ||
1147 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1426 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1148 | OPCODE_COMMON_WRITE_FLASHROM, cmd->size); | 1427 | OPCODE_COMMON_WRITE_FLASHROM, cmd->size); |
@@ -1156,6 +1435,238 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, | |||
1156 | 1435 | ||
1157 | status = be_mcc_notify_wait(adapter); | 1436 | status = be_mcc_notify_wait(adapter); |
1158 | 1437 | ||
1438 | err: | ||
1439 | spin_unlock_bh(&adapter->mcc_lock); | ||
1440 | return status; | ||
1441 | } | ||
1442 | |||
1443 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, | ||
1444 | int offset) | ||
1445 | { | ||
1446 | struct be_mcc_wrb *wrb; | ||
1447 | struct be_cmd_write_flashrom *req; | ||
1448 | int status; | ||
1449 | |||
1450 | spin_lock_bh(&adapter->mcc_lock); | ||
1451 | |||
1452 | wrb = wrb_from_mccq(adapter); | ||
1453 | if (!wrb) { | ||
1454 | status = -EBUSY; | ||
1455 | goto err; | ||
1456 | } | ||
1457 | req = embedded_payload(wrb); | ||
1458 | |||
1459 | be_wrb_hdr_prepare(wrb, sizeof(*req)+4, true, 0, | ||
1460 | OPCODE_COMMON_READ_FLASHROM); | ||
1461 | |||
1462 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1463 | OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4); | ||
1464 | |||
1465 | req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT); | ||
1466 | req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); | ||
1467 | req->params.offset = cpu_to_le32(offset); | ||
1468 | req->params.data_buf_size = cpu_to_le32(0x4); | ||
1469 | |||
1470 | status = be_mcc_notify_wait(adapter); | ||
1471 | if (!status) | ||
1472 | memcpy(flashed_crc, req->params.data_buf, 4); | ||
1473 | |||
1474 | err: | ||
1475 | spin_unlock_bh(&adapter->mcc_lock); | ||
1476 | return status; | ||
1477 | } | ||
1478 | |||
1479 | extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, | ||
1480 | struct be_dma_mem *nonemb_cmd) | ||
1481 | { | ||
1482 | struct be_mcc_wrb *wrb; | ||
1483 | struct be_cmd_req_acpi_wol_magic_config *req; | ||
1484 | struct be_sge *sge; | ||
1485 | int status; | ||
1486 | |||
1487 | spin_lock_bh(&adapter->mcc_lock); | ||
1488 | |||
1489 | wrb = wrb_from_mccq(adapter); | ||
1490 | if (!wrb) { | ||
1491 | status = -EBUSY; | ||
1492 | goto err; | ||
1493 | } | ||
1494 | req = nonemb_cmd->va; | ||
1495 | sge = nonembedded_sgl(wrb); | ||
1496 | |||
1497 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, | ||
1498 | OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG); | ||
1499 | |||
1500 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, | ||
1501 | OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req)); | ||
1502 | memcpy(req->magic_mac, mac, ETH_ALEN); | ||
1503 | |||
1504 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
1505 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
1506 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
1507 | |||
1508 | status = be_mcc_notify_wait(adapter); | ||
1509 | |||
1510 | err: | ||
1511 | spin_unlock_bh(&adapter->mcc_lock); | ||
1512 | return status; | ||
1513 | } | ||
1514 | |||
1515 | int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, | ||
1516 | u8 loopback_type, u8 enable) | ||
1517 | { | ||
1518 | struct be_mcc_wrb *wrb; | ||
1519 | struct be_cmd_req_set_lmode *req; | ||
1520 | int status; | ||
1521 | |||
1522 | spin_lock_bh(&adapter->mcc_lock); | ||
1523 | |||
1524 | wrb = wrb_from_mccq(adapter); | ||
1525 | if (!wrb) { | ||
1526 | status = -EBUSY; | ||
1527 | goto err; | ||
1528 | } | ||
1529 | |||
1530 | req = embedded_payload(wrb); | ||
1531 | |||
1532 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, | ||
1533 | OPCODE_LOWLEVEL_SET_LOOPBACK_MODE); | ||
1534 | |||
1535 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, | ||
1536 | OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, | ||
1537 | sizeof(*req)); | ||
1538 | |||
1539 | req->src_port = port_num; | ||
1540 | req->dest_port = port_num; | ||
1541 | req->loopback_type = loopback_type; | ||
1542 | req->loopback_state = enable; | ||
1543 | |||
1544 | status = be_mcc_notify_wait(adapter); | ||
1545 | err: | ||
1546 | spin_unlock_bh(&adapter->mcc_lock); | ||
1547 | return status; | ||
1548 | } | ||
1549 | |||
1550 | int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, | ||
1551 | u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern) | ||
1552 | { | ||
1553 | struct be_mcc_wrb *wrb; | ||
1554 | struct be_cmd_req_loopback_test *req; | ||
1555 | int status; | ||
1556 | |||
1557 | spin_lock_bh(&adapter->mcc_lock); | ||
1558 | |||
1559 | wrb = wrb_from_mccq(adapter); | ||
1560 | if (!wrb) { | ||
1561 | status = -EBUSY; | ||
1562 | goto err; | ||
1563 | } | ||
1564 | |||
1565 | req = embedded_payload(wrb); | ||
1566 | |||
1567 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, | ||
1568 | OPCODE_LOWLEVEL_LOOPBACK_TEST); | ||
1569 | |||
1570 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, | ||
1571 | OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req)); | ||
1572 | req->hdr.timeout = 4; | ||
1573 | |||
1574 | req->pattern = cpu_to_le64(pattern); | ||
1575 | req->src_port = cpu_to_le32(port_num); | ||
1576 | req->dest_port = cpu_to_le32(port_num); | ||
1577 | req->pkt_size = cpu_to_le32(pkt_size); | ||
1578 | req->num_pkts = cpu_to_le32(num_pkts); | ||
1579 | req->loopback_type = cpu_to_le32(loopback_type); | ||
1580 | |||
1581 | status = be_mcc_notify_wait(adapter); | ||
1582 | if (!status) { | ||
1583 | struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb); | ||
1584 | status = le32_to_cpu(resp->status); | ||
1585 | } | ||
1586 | |||
1587 | err: | ||
1588 | spin_unlock_bh(&adapter->mcc_lock); | ||
1589 | return status; | ||
1590 | } | ||
1591 | |||
1592 | int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, | ||
1593 | u32 byte_cnt, struct be_dma_mem *cmd) | ||
1594 | { | ||
1595 | struct be_mcc_wrb *wrb; | ||
1596 | struct be_cmd_req_ddrdma_test *req; | ||
1597 | struct be_sge *sge; | ||
1598 | int status; | ||
1599 | int i, j = 0; | ||
1600 | |||
1601 | spin_lock_bh(&adapter->mcc_lock); | ||
1602 | |||
1603 | wrb = wrb_from_mccq(adapter); | ||
1604 | if (!wrb) { | ||
1605 | status = -EBUSY; | ||
1606 | goto err; | ||
1607 | } | ||
1608 | req = cmd->va; | ||
1609 | sge = nonembedded_sgl(wrb); | ||
1610 | be_wrb_hdr_prepare(wrb, cmd->size, false, 1, | ||
1611 | OPCODE_LOWLEVEL_HOST_DDR_DMA); | ||
1612 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, | ||
1613 | OPCODE_LOWLEVEL_HOST_DDR_DMA, cmd->size); | ||
1614 | |||
1615 | sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma)); | ||
1616 | sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF); | ||
1617 | sge->len = cpu_to_le32(cmd->size); | ||
1618 | |||
1619 | req->pattern = cpu_to_le64(pattern); | ||
1620 | req->byte_count = cpu_to_le32(byte_cnt); | ||
1621 | for (i = 0; i < byte_cnt; i++) { | ||
1622 | req->snd_buff[i] = (u8)(pattern >> (j*8)); | ||
1623 | j++; | ||
1624 | if (j > 7) | ||
1625 | j = 0; | ||
1626 | } | ||
1627 | |||
1628 | status = be_mcc_notify_wait(adapter); | ||
1629 | |||
1630 | if (!status) { | ||
1631 | struct be_cmd_resp_ddrdma_test *resp; | ||
1632 | resp = cmd->va; | ||
1633 | if ((memcmp(resp->rcv_buff, req->snd_buff, byte_cnt) != 0) || | ||
1634 | resp->snd_err) { | ||
1635 | status = -1; | ||
1636 | } | ||
1637 | } | ||
1638 | |||
1639 | err: | ||
1640 | spin_unlock_bh(&adapter->mcc_lock); | ||
1641 | return status; | ||
1642 | } | ||
1643 | |||
1644 | extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, | ||
1645 | struct be_dma_mem *nonemb_cmd) | ||
1646 | { | ||
1647 | struct be_mcc_wrb *wrb; | ||
1648 | struct be_cmd_req_seeprom_read *req; | ||
1649 | struct be_sge *sge; | ||
1650 | int status; | ||
1651 | |||
1652 | spin_lock_bh(&adapter->mcc_lock); | ||
1653 | |||
1654 | wrb = wrb_from_mccq(adapter); | ||
1655 | req = nonemb_cmd->va; | ||
1656 | sge = nonembedded_sgl(wrb); | ||
1657 | |||
1658 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, | ||
1659 | OPCODE_COMMON_SEEPROM_READ); | ||
1660 | |||
1661 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1662 | OPCODE_COMMON_SEEPROM_READ, sizeof(*req)); | ||
1663 | |||
1664 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
1665 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
1666 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
1667 | |||
1668 | status = be_mcc_notify_wait(adapter); | ||
1669 | |||
1159 | spin_unlock_bh(&adapter->mcc_lock); | 1670 | spin_unlock_bh(&adapter->mcc_lock); |
1160 | return status; | 1671 | return status; |
1161 | } | 1672 | } |
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index e5f9676cf1bc..cce61f9a3714 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -112,16 +112,19 @@ struct be_mcc_mailbox { | |||
112 | 112 | ||
113 | #define CMD_SUBSYSTEM_COMMON 0x1 | 113 | #define CMD_SUBSYSTEM_COMMON 0x1 |
114 | #define CMD_SUBSYSTEM_ETH 0x3 | 114 | #define CMD_SUBSYSTEM_ETH 0x3 |
115 | #define CMD_SUBSYSTEM_LOWLEVEL 0xb | ||
115 | 116 | ||
116 | #define OPCODE_COMMON_NTWK_MAC_QUERY 1 | 117 | #define OPCODE_COMMON_NTWK_MAC_QUERY 1 |
117 | #define OPCODE_COMMON_NTWK_MAC_SET 2 | 118 | #define OPCODE_COMMON_NTWK_MAC_SET 2 |
118 | #define OPCODE_COMMON_NTWK_MULTICAST_SET 3 | 119 | #define OPCODE_COMMON_NTWK_MULTICAST_SET 3 |
119 | #define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 | 120 | #define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 |
120 | #define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 | 121 | #define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 |
122 | #define OPCODE_COMMON_READ_FLASHROM 6 | ||
121 | #define OPCODE_COMMON_WRITE_FLASHROM 7 | 123 | #define OPCODE_COMMON_WRITE_FLASHROM 7 |
122 | #define OPCODE_COMMON_CQ_CREATE 12 | 124 | #define OPCODE_COMMON_CQ_CREATE 12 |
123 | #define OPCODE_COMMON_EQ_CREATE 13 | 125 | #define OPCODE_COMMON_EQ_CREATE 13 |
124 | #define OPCODE_COMMON_MCC_CREATE 21 | 126 | #define OPCODE_COMMON_MCC_CREATE 21 |
127 | #define OPCODE_COMMON_SEEPROM_READ 30 | ||
125 | #define OPCODE_COMMON_NTWK_RX_FILTER 34 | 128 | #define OPCODE_COMMON_NTWK_RX_FILTER 34 |
126 | #define OPCODE_COMMON_GET_FW_VERSION 35 | 129 | #define OPCODE_COMMON_GET_FW_VERSION 35 |
127 | #define OPCODE_COMMON_SET_FLOW_CONTROL 36 | 130 | #define OPCODE_COMMON_SET_FLOW_CONTROL 36 |
@@ -138,6 +141,9 @@ struct be_mcc_mailbox { | |||
138 | #define OPCODE_COMMON_NTWK_PMAC_ADD 59 | 141 | #define OPCODE_COMMON_NTWK_PMAC_ADD 59 |
139 | #define OPCODE_COMMON_NTWK_PMAC_DEL 60 | 142 | #define OPCODE_COMMON_NTWK_PMAC_DEL 60 |
140 | #define OPCODE_COMMON_FUNCTION_RESET 61 | 143 | #define OPCODE_COMMON_FUNCTION_RESET 61 |
144 | #define OPCODE_COMMON_ENABLE_DISABLE_BEACON 69 | ||
145 | #define OPCODE_COMMON_GET_BEACON_STATE 70 | ||
146 | #define OPCODE_COMMON_READ_TRANSRECV_DATA 73 | ||
141 | 147 | ||
142 | #define OPCODE_ETH_ACPI_CONFIG 2 | 148 | #define OPCODE_ETH_ACPI_CONFIG 2 |
143 | #define OPCODE_ETH_PROMISCUOUS 3 | 149 | #define OPCODE_ETH_PROMISCUOUS 3 |
@@ -146,6 +152,11 @@ struct be_mcc_mailbox { | |||
146 | #define OPCODE_ETH_RX_CREATE 8 | 152 | #define OPCODE_ETH_RX_CREATE 8 |
147 | #define OPCODE_ETH_TX_DESTROY 9 | 153 | #define OPCODE_ETH_TX_DESTROY 9 |
148 | #define OPCODE_ETH_RX_DESTROY 10 | 154 | #define OPCODE_ETH_RX_DESTROY 10 |
155 | #define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG 12 | ||
156 | |||
157 | #define OPCODE_LOWLEVEL_HOST_DDR_DMA 17 | ||
158 | #define OPCODE_LOWLEVEL_LOOPBACK_TEST 18 | ||
159 | #define OPCODE_LOWLEVEL_SET_LOOPBACK_MODE 19 | ||
149 | 160 | ||
150 | struct be_cmd_req_hdr { | 161 | struct be_cmd_req_hdr { |
151 | u8 opcode; /* dword 0 */ | 162 | u8 opcode; /* dword 0 */ |
@@ -154,7 +165,8 @@ struct be_cmd_req_hdr { | |||
154 | u8 domain; /* dword 0 */ | 165 | u8 domain; /* dword 0 */ |
155 | u32 timeout; /* dword 1 */ | 166 | u32 timeout; /* dword 1 */ |
156 | u32 request_length; /* dword 2 */ | 167 | u32 request_length; /* dword 2 */ |
157 | u32 rsvd; /* dword 3 */ | 168 | u8 version; /* dword 3 */ |
169 | u8 rsvd[3]; /* dword 3 */ | ||
158 | }; | 170 | }; |
159 | 171 | ||
160 | #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ | 172 | #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ |
@@ -435,7 +447,7 @@ enum be_if_flags { | |||
435 | * filtering capabilities. */ | 447 | * filtering capabilities. */ |
436 | struct be_cmd_req_if_create { | 448 | struct be_cmd_req_if_create { |
437 | struct be_cmd_req_hdr hdr; | 449 | struct be_cmd_req_hdr hdr; |
438 | u32 version; /* ignore currntly */ | 450 | u32 version; /* ignore currently */ |
439 | u32 capability_flags; | 451 | u32 capability_flags; |
440 | u32 enable_flags; | 452 | u32 enable_flags; |
441 | u8 mac_addr[ETH_ALEN]; | 453 | u8 mac_addr[ETH_ALEN]; |
@@ -587,6 +599,8 @@ struct be_cmd_req_promiscuous_config { | |||
587 | u16 rsvd0; | 599 | u16 rsvd0; |
588 | } __packed; | 600 | } __packed; |
589 | 601 | ||
602 | /******************** Multicast MAC Config *******************/ | ||
603 | #define BE_MAX_MC 64 /* set mcast promisc if > 64 */ | ||
590 | struct macaddr { | 604 | struct macaddr { |
591 | u8 byte[ETH_ALEN]; | 605 | u8 byte[ETH_ALEN]; |
592 | }; | 606 | }; |
@@ -596,7 +610,7 @@ struct be_cmd_req_mcast_mac_config { | |||
596 | u16 num_mac; | 610 | u16 num_mac; |
597 | u8 promiscuous; | 611 | u8 promiscuous; |
598 | u8 interface_id; | 612 | u8 interface_id; |
599 | struct macaddr mac[32]; | 613 | struct macaddr mac[BE_MAX_MC]; |
600 | } __packed; | 614 | } __packed; |
601 | 615 | ||
602 | static inline struct be_hw_stats * | 616 | static inline struct be_hw_stats * |
@@ -633,9 +647,47 @@ struct be_cmd_resp_link_status { | |||
633 | u8 mac_fault; | 647 | u8 mac_fault; |
634 | u8 mgmt_mac_duplex; | 648 | u8 mgmt_mac_duplex; |
635 | u8 mgmt_mac_speed; | 649 | u8 mgmt_mac_speed; |
636 | u16 rsvd0; | 650 | u16 link_speed; |
651 | u32 rsvd0; | ||
637 | } __packed; | 652 | } __packed; |
638 | 653 | ||
654 | /******************** Port Identification ***************************/ | ||
655 | /* Identifies the type of port attached to NIC */ | ||
656 | struct be_cmd_req_port_type { | ||
657 | struct be_cmd_req_hdr hdr; | ||
658 | u32 page_num; | ||
659 | u32 port; | ||
660 | }; | ||
661 | |||
662 | enum { | ||
663 | TR_PAGE_A0 = 0xa0, | ||
664 | TR_PAGE_A2 = 0xa2 | ||
665 | }; | ||
666 | |||
667 | struct be_cmd_resp_port_type { | ||
668 | struct be_cmd_resp_hdr hdr; | ||
669 | u32 page_num; | ||
670 | u32 port; | ||
671 | struct data { | ||
672 | u8 identifier; | ||
673 | u8 identifier_ext; | ||
674 | u8 connector; | ||
675 | u8 transceiver[8]; | ||
676 | u8 rsvd0[3]; | ||
677 | u8 length_km; | ||
678 | u8 length_hm; | ||
679 | u8 length_om1; | ||
680 | u8 length_om2; | ||
681 | u8 length_cu; | ||
682 | u8 length_cu_m; | ||
683 | u8 vendor_name[16]; | ||
684 | u8 rsvd; | ||
685 | u8 vendor_oui[3]; | ||
686 | u8 vendor_pn[16]; | ||
687 | u8 vendor_rev[4]; | ||
688 | } data; | ||
689 | }; | ||
690 | |||
639 | /******************** Get FW Version *******************/ | 691 | /******************** Get FW Version *******************/ |
640 | struct be_cmd_req_get_fw_version { | 692 | struct be_cmd_req_get_fw_version { |
641 | struct be_cmd_req_hdr hdr; | 693 | struct be_cmd_req_hdr hdr; |
@@ -699,6 +751,37 @@ struct be_cmd_resp_query_fw_cfg { | |||
699 | u32 rsvd[26]; | 751 | u32 rsvd[26]; |
700 | }; | 752 | }; |
701 | 753 | ||
754 | /******************** Port Beacon ***************************/ | ||
755 | |||
756 | #define BEACON_STATE_ENABLED 0x1 | ||
757 | #define BEACON_STATE_DISABLED 0x0 | ||
758 | |||
759 | struct be_cmd_req_enable_disable_beacon { | ||
760 | struct be_cmd_req_hdr hdr; | ||
761 | u8 port_num; | ||
762 | u8 beacon_state; | ||
763 | u8 beacon_duration; | ||
764 | u8 status_duration; | ||
765 | } __packed; | ||
766 | |||
767 | struct be_cmd_resp_enable_disable_beacon { | ||
768 | struct be_cmd_resp_hdr resp_hdr; | ||
769 | u32 rsvd0; | ||
770 | } __packed; | ||
771 | |||
772 | struct be_cmd_req_get_beacon_state { | ||
773 | struct be_cmd_req_hdr hdr; | ||
774 | u8 port_num; | ||
775 | u8 rsvd0; | ||
776 | u16 rsvd1; | ||
777 | } __packed; | ||
778 | |||
779 | struct be_cmd_resp_get_beacon_state { | ||
780 | struct be_cmd_resp_hdr resp_hdr; | ||
781 | u8 beacon_state; | ||
782 | u8 rsvd0[3]; | ||
783 | } __packed; | ||
784 | |||
702 | /****************** Firmware Flash ******************/ | 785 | /****************** Firmware Flash ******************/ |
703 | struct flashrom_params { | 786 | struct flashrom_params { |
704 | u32 op_code; | 787 | u32 op_code; |
@@ -713,6 +796,79 @@ struct be_cmd_write_flashrom { | |||
713 | struct flashrom_params params; | 796 | struct flashrom_params params; |
714 | }; | 797 | }; |
715 | 798 | ||
799 | /************************ WOL *******************************/ | ||
800 | struct be_cmd_req_acpi_wol_magic_config{ | ||
801 | struct be_cmd_req_hdr hdr; | ||
802 | u32 rsvd0[145]; | ||
803 | u8 magic_mac[6]; | ||
804 | u8 rsvd2[2]; | ||
805 | } __packed; | ||
806 | |||
807 | /********************** LoopBack test *********************/ | ||
808 | struct be_cmd_req_loopback_test { | ||
809 | struct be_cmd_req_hdr hdr; | ||
810 | u32 loopback_type; | ||
811 | u32 num_pkts; | ||
812 | u64 pattern; | ||
813 | u32 src_port; | ||
814 | u32 dest_port; | ||
815 | u32 pkt_size; | ||
816 | }; | ||
817 | |||
818 | struct be_cmd_resp_loopback_test { | ||
819 | struct be_cmd_resp_hdr resp_hdr; | ||
820 | u32 status; | ||
821 | u32 num_txfer; | ||
822 | u32 num_rx; | ||
823 | u32 miscomp_off; | ||
824 | u32 ticks_compl; | ||
825 | }; | ||
826 | |||
827 | struct be_cmd_req_set_lmode { | ||
828 | struct be_cmd_req_hdr hdr; | ||
829 | u8 src_port; | ||
830 | u8 dest_port; | ||
831 | u8 loopback_type; | ||
832 | u8 loopback_state; | ||
833 | }; | ||
834 | |||
835 | struct be_cmd_resp_set_lmode { | ||
836 | struct be_cmd_resp_hdr resp_hdr; | ||
837 | u8 rsvd0[4]; | ||
838 | }; | ||
839 | |||
840 | /********************** DDR DMA test *********************/ | ||
841 | struct be_cmd_req_ddrdma_test { | ||
842 | struct be_cmd_req_hdr hdr; | ||
843 | u64 pattern; | ||
844 | u32 byte_count; | ||
845 | u32 rsvd0; | ||
846 | u8 snd_buff[4096]; | ||
847 | u8 rsvd1[4096]; | ||
848 | }; | ||
849 | |||
850 | struct be_cmd_resp_ddrdma_test { | ||
851 | struct be_cmd_resp_hdr hdr; | ||
852 | u64 pattern; | ||
853 | u32 byte_cnt; | ||
854 | u32 snd_err; | ||
855 | u8 rsvd0[4096]; | ||
856 | u8 rcv_buff[4096]; | ||
857 | }; | ||
858 | |||
859 | /*********************** SEEPROM Read ***********************/ | ||
860 | |||
861 | #define BE_READ_SEEPROM_LEN 1024 | ||
862 | struct be_cmd_req_seeprom_read { | ||
863 | struct be_cmd_req_hdr hdr; | ||
864 | u8 rsvd0[BE_READ_SEEPROM_LEN]; | ||
865 | }; | ||
866 | |||
867 | struct be_cmd_resp_seeprom_read { | ||
868 | struct be_cmd_req_hdr hdr; | ||
869 | u8 seeprom_data[BE_READ_SEEPROM_LEN]; | ||
870 | }; | ||
871 | |||
716 | extern int be_pci_fnum_get(struct be_adapter *adapter); | 872 | extern int be_pci_fnum_get(struct be_adapter *adapter); |
717 | extern int be_cmd_POST(struct be_adapter *adapter); | 873 | extern int be_cmd_POST(struct be_adapter *adapter); |
718 | extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, | 874 | extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, |
@@ -743,7 +899,7 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter, | |||
743 | extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, | 899 | extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, |
744 | int type); | 900 | int type); |
745 | extern int be_cmd_link_status_query(struct be_adapter *adapter, | 901 | extern int be_cmd_link_status_query(struct be_adapter *adapter, |
746 | bool *link_up); | 902 | bool *link_up, u8 *mac_speed, u16 *link_speed); |
747 | extern int be_cmd_reset(struct be_adapter *adapter); | 903 | extern int be_cmd_reset(struct be_adapter *adapter); |
748 | extern int be_cmd_get_stats(struct be_adapter *adapter, | 904 | extern int be_cmd_get_stats(struct be_adapter *adapter, |
749 | struct be_dma_mem *nonemb_cmd); | 905 | struct be_dma_mem *nonemb_cmd); |
@@ -756,7 +912,7 @@ extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, | |||
756 | extern int be_cmd_promiscuous_config(struct be_adapter *adapter, | 912 | extern int be_cmd_promiscuous_config(struct be_adapter *adapter, |
757 | u8 port_num, bool en); | 913 | u8 port_num, bool en); |
758 | extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, | 914 | extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, |
759 | struct dev_mc_list *mc_list, u32 mc_count); | 915 | struct net_device *netdev, struct be_dma_mem *mem); |
760 | extern int be_cmd_set_flow_control(struct be_adapter *adapter, | 916 | extern int be_cmd_set_flow_control(struct be_adapter *adapter, |
761 | u32 tx_fc, u32 rx_fc); | 917 | u32 tx_fc, u32 rx_fc); |
762 | extern int be_cmd_get_flow_control(struct be_adapter *adapter, | 918 | extern int be_cmd_get_flow_control(struct be_adapter *adapter, |
@@ -764,7 +920,31 @@ extern int be_cmd_get_flow_control(struct be_adapter *adapter, | |||
764 | extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, | 920 | extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, |
765 | u32 *port_num, u32 *cap); | 921 | u32 *port_num, u32 *cap); |
766 | extern int be_cmd_reset_function(struct be_adapter *adapter); | 922 | extern int be_cmd_reset_function(struct be_adapter *adapter); |
767 | extern int be_process_mcc(struct be_adapter *adapter); | 923 | extern int be_process_mcc(struct be_adapter *adapter, int *status); |
924 | extern int be_cmd_set_beacon_state(struct be_adapter *adapter, | ||
925 | u8 port_num, u8 beacon, u8 status, u8 state); | ||
926 | extern int be_cmd_get_beacon_state(struct be_adapter *adapter, | ||
927 | u8 port_num, u32 *state); | ||
928 | extern int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, | ||
929 | u8 *connector); | ||
768 | extern int be_cmd_write_flashrom(struct be_adapter *adapter, | 930 | extern int be_cmd_write_flashrom(struct be_adapter *adapter, |
769 | struct be_dma_mem *cmd, u32 flash_oper, | 931 | struct be_dma_mem *cmd, u32 flash_oper, |
770 | u32 flash_opcode, u32 buf_size); | 932 | u32 flash_opcode, u32 buf_size); |
933 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, | ||
934 | int offset); | ||
935 | extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, | ||
936 | struct be_dma_mem *nonemb_cmd); | ||
937 | extern int be_cmd_fw_init(struct be_adapter *adapter); | ||
938 | extern int be_cmd_fw_clean(struct be_adapter *adapter); | ||
939 | extern void be_async_mcc_enable(struct be_adapter *adapter); | ||
940 | extern void be_async_mcc_disable(struct be_adapter *adapter); | ||
941 | extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, | ||
942 | u32 loopback_type, u32 pkt_size, | ||
943 | u32 num_pkts, u64 pattern); | ||
944 | extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, | ||
945 | u32 byte_cnt, struct be_dma_mem *cmd); | ||
946 | extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, | ||
947 | struct be_dma_mem *nonemb_cmd); | ||
948 | extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, | ||
949 | u8 loopback_type, u8 enable); | ||
950 | |||
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index f0fd95b43c07..51e1065e7897 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -55,7 +55,7 @@ static const struct be_ethtool_stat et_stats[] = { | |||
55 | {DRVSTAT_INFO(be_tx_stops)}, | 55 | {DRVSTAT_INFO(be_tx_stops)}, |
56 | {DRVSTAT_INFO(be_fwd_reqs)}, | 56 | {DRVSTAT_INFO(be_fwd_reqs)}, |
57 | {DRVSTAT_INFO(be_tx_wrbs)}, | 57 | {DRVSTAT_INFO(be_tx_wrbs)}, |
58 | {DRVSTAT_INFO(be_polls)}, | 58 | {DRVSTAT_INFO(be_rx_polls)}, |
59 | {DRVSTAT_INFO(be_tx_events)}, | 59 | {DRVSTAT_INFO(be_tx_events)}, |
60 | {DRVSTAT_INFO(be_rx_events)}, | 60 | {DRVSTAT_INFO(be_rx_events)}, |
61 | {DRVSTAT_INFO(be_tx_compl)}, | 61 | {DRVSTAT_INFO(be_tx_compl)}, |
@@ -107,6 +107,20 @@ static const struct be_ethtool_stat et_stats[] = { | |||
107 | }; | 107 | }; |
108 | #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) | 108 | #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) |
109 | 109 | ||
110 | static const char et_self_tests[][ETH_GSTRING_LEN] = { | ||
111 | "MAC Loopback test", | ||
112 | "PHY Loopback test", | ||
113 | "External Loopback test", | ||
114 | "DDR DMA test" | ||
115 | "Link test" | ||
116 | }; | ||
117 | |||
118 | #define ETHTOOL_TESTS_NUM ARRAY_SIZE(et_self_tests) | ||
119 | #define BE_MAC_LOOPBACK 0x0 | ||
120 | #define BE_PHY_LOOPBACK 0x1 | ||
121 | #define BE_ONE_PORT_EXT_LOOPBACK 0x2 | ||
122 | #define BE_NO_LOOPBACK 0xff | ||
123 | |||
110 | static void | 124 | static void |
111 | be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) | 125 | be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) |
112 | { | 126 | { |
@@ -234,7 +248,7 @@ be_get_ethtool_stats(struct net_device *netdev, | |||
234 | struct be_rxf_stats *rxf_stats = &hw_stats->rxf; | 248 | struct be_rxf_stats *rxf_stats = &hw_stats->rxf; |
235 | struct be_port_rxf_stats *port_stats = | 249 | struct be_port_rxf_stats *port_stats = |
236 | &rxf_stats->port[adapter->port_num]; | 250 | &rxf_stats->port[adapter->port_num]; |
237 | struct net_device_stats *net_stats = &adapter->stats.net_stats; | 251 | struct net_device_stats *net_stats = &netdev->stats; |
238 | struct be_erx_stats *erx_stats = &hw_stats->erx; | 252 | struct be_erx_stats *erx_stats = &hw_stats->erx; |
239 | void *p = NULL; | 253 | void *p = NULL; |
240 | int i; | 254 | int i; |
@@ -278,19 +292,100 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset, | |||
278 | data += ETH_GSTRING_LEN; | 292 | data += ETH_GSTRING_LEN; |
279 | } | 293 | } |
280 | break; | 294 | break; |
295 | case ETH_SS_TEST: | ||
296 | for (i = 0; i < ETHTOOL_TESTS_NUM; i++) { | ||
297 | memcpy(data, et_self_tests[i], ETH_GSTRING_LEN); | ||
298 | data += ETH_GSTRING_LEN; | ||
299 | } | ||
300 | break; | ||
281 | } | 301 | } |
282 | } | 302 | } |
283 | 303 | ||
284 | static int be_get_stats_count(struct net_device *netdev) | 304 | static int be_get_sset_count(struct net_device *netdev, int stringset) |
285 | { | 305 | { |
286 | return ETHTOOL_STATS_NUM; | 306 | switch (stringset) { |
307 | case ETH_SS_TEST: | ||
308 | return ETHTOOL_TESTS_NUM; | ||
309 | case ETH_SS_STATS: | ||
310 | return ETHTOOL_STATS_NUM; | ||
311 | default: | ||
312 | return -EINVAL; | ||
313 | } | ||
287 | } | 314 | } |
288 | 315 | ||
289 | static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | 316 | static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) |
290 | { | 317 | { |
291 | ecmd->speed = SPEED_10000; | 318 | struct be_adapter *adapter = netdev_priv(netdev); |
319 | u8 mac_speed = 0, connector = 0; | ||
320 | u16 link_speed = 0; | ||
321 | bool link_up = false; | ||
322 | int status; | ||
323 | |||
324 | if (adapter->link_speed < 0) { | ||
325 | status = be_cmd_link_status_query(adapter, &link_up, | ||
326 | &mac_speed, &link_speed); | ||
327 | |||
328 | /* link_speed is in units of 10 Mbps */ | ||
329 | if (link_speed) { | ||
330 | ecmd->speed = link_speed*10; | ||
331 | } else { | ||
332 | switch (mac_speed) { | ||
333 | case PHY_LINK_SPEED_1GBPS: | ||
334 | ecmd->speed = SPEED_1000; | ||
335 | break; | ||
336 | case PHY_LINK_SPEED_10GBPS: | ||
337 | ecmd->speed = SPEED_10000; | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | status = be_cmd_read_port_type(adapter, adapter->port_num, | ||
343 | &connector); | ||
344 | if (!status) { | ||
345 | switch (connector) { | ||
346 | case 7: | ||
347 | ecmd->port = PORT_FIBRE; | ||
348 | ecmd->transceiver = XCVR_EXTERNAL; | ||
349 | break; | ||
350 | case 0: | ||
351 | ecmd->port = PORT_TP; | ||
352 | ecmd->transceiver = XCVR_EXTERNAL; | ||
353 | break; | ||
354 | default: | ||
355 | ecmd->port = PORT_TP; | ||
356 | ecmd->transceiver = XCVR_INTERNAL; | ||
357 | break; | ||
358 | } | ||
359 | } else { | ||
360 | ecmd->port = PORT_AUI; | ||
361 | ecmd->transceiver = XCVR_INTERNAL; | ||
362 | } | ||
363 | |||
364 | /* Save for future use */ | ||
365 | adapter->link_speed = ecmd->speed; | ||
366 | adapter->port_type = ecmd->port; | ||
367 | adapter->transceiver = ecmd->transceiver; | ||
368 | } else { | ||
369 | ecmd->speed = adapter->link_speed; | ||
370 | ecmd->port = adapter->port_type; | ||
371 | ecmd->transceiver = adapter->transceiver; | ||
372 | } | ||
373 | |||
292 | ecmd->duplex = DUPLEX_FULL; | 374 | ecmd->duplex = DUPLEX_FULL; |
293 | ecmd->autoneg = AUTONEG_DISABLE; | 375 | ecmd->autoneg = AUTONEG_DISABLE; |
376 | ecmd->phy_address = adapter->port_num; | ||
377 | switch (ecmd->port) { | ||
378 | case PORT_FIBRE: | ||
379 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); | ||
380 | break; | ||
381 | case PORT_TP: | ||
382 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP); | ||
383 | break; | ||
384 | case PORT_AUI: | ||
385 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI); | ||
386 | break; | ||
387 | } | ||
388 | |||
294 | return 0; | 389 | return 0; |
295 | } | 390 | } |
296 | 391 | ||
@@ -335,6 +430,142 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) | |||
335 | } | 430 | } |
336 | 431 | ||
337 | static int | 432 | static int |
433 | be_phys_id(struct net_device *netdev, u32 data) | ||
434 | { | ||
435 | struct be_adapter *adapter = netdev_priv(netdev); | ||
436 | int status; | ||
437 | u32 cur; | ||
438 | |||
439 | be_cmd_get_beacon_state(adapter, adapter->port_num, &cur); | ||
440 | |||
441 | if (cur == BEACON_STATE_ENABLED) | ||
442 | return 0; | ||
443 | |||
444 | if (data < 2) | ||
445 | data = 2; | ||
446 | |||
447 | status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0, | ||
448 | BEACON_STATE_ENABLED); | ||
449 | set_current_state(TASK_INTERRUPTIBLE); | ||
450 | schedule_timeout(data*HZ); | ||
451 | |||
452 | status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0, | ||
453 | BEACON_STATE_DISABLED); | ||
454 | |||
455 | return status; | ||
456 | } | ||
457 | |||
458 | static void | ||
459 | be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||
460 | { | ||
461 | struct be_adapter *adapter = netdev_priv(netdev); | ||
462 | |||
463 | wol->supported = WAKE_MAGIC; | ||
464 | if (adapter->wol) | ||
465 | wol->wolopts = WAKE_MAGIC; | ||
466 | else | ||
467 | wol->wolopts = 0; | ||
468 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | static int | ||
473 | be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||
474 | { | ||
475 | struct be_adapter *adapter = netdev_priv(netdev); | ||
476 | |||
477 | if (wol->wolopts & ~WAKE_MAGIC) | ||
478 | return -EINVAL; | ||
479 | |||
480 | if (wol->wolopts & WAKE_MAGIC) | ||
481 | adapter->wol = true; | ||
482 | else | ||
483 | adapter->wol = false; | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int | ||
489 | be_test_ddr_dma(struct be_adapter *adapter) | ||
490 | { | ||
491 | int ret, i; | ||
492 | struct be_dma_mem ddrdma_cmd; | ||
493 | u64 pattern[2] = {0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL}; | ||
494 | |||
495 | ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test); | ||
496 | ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size, | ||
497 | &ddrdma_cmd.dma); | ||
498 | if (!ddrdma_cmd.va) { | ||
499 | dev_err(&adapter->pdev->dev, "Memory allocation failure \n"); | ||
500 | return -ENOMEM; | ||
501 | } | ||
502 | |||
503 | for (i = 0; i < 2; i++) { | ||
504 | ret = be_cmd_ddr_dma_test(adapter, pattern[i], | ||
505 | 4096, &ddrdma_cmd); | ||
506 | if (ret != 0) | ||
507 | goto err; | ||
508 | } | ||
509 | |||
510 | err: | ||
511 | pci_free_consistent(adapter->pdev, ddrdma_cmd.size, | ||
512 | ddrdma_cmd.va, ddrdma_cmd.dma); | ||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type, | ||
517 | u64 *status) | ||
518 | { | ||
519 | be_cmd_set_loopback(adapter, adapter->port_num, | ||
520 | loopback_type, 1); | ||
521 | *status = be_cmd_loopback_test(adapter, adapter->port_num, | ||
522 | loopback_type, 1500, | ||
523 | 2, 0xabc); | ||
524 | be_cmd_set_loopback(adapter, adapter->port_num, | ||
525 | BE_NO_LOOPBACK, 1); | ||
526 | return *status; | ||
527 | } | ||
528 | |||
529 | static void | ||
530 | be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) | ||
531 | { | ||
532 | struct be_adapter *adapter = netdev_priv(netdev); | ||
533 | bool link_up; | ||
534 | u8 mac_speed = 0; | ||
535 | u16 qos_link_speed = 0; | ||
536 | |||
537 | memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM); | ||
538 | |||
539 | if (test->flags & ETH_TEST_FL_OFFLINE) { | ||
540 | if (be_loopback_test(adapter, BE_MAC_LOOPBACK, | ||
541 | &data[0]) != 0) { | ||
542 | test->flags |= ETH_TEST_FL_FAILED; | ||
543 | } | ||
544 | if (be_loopback_test(adapter, BE_PHY_LOOPBACK, | ||
545 | &data[1]) != 0) { | ||
546 | test->flags |= ETH_TEST_FL_FAILED; | ||
547 | } | ||
548 | if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK, | ||
549 | &data[2]) != 0) { | ||
550 | test->flags |= ETH_TEST_FL_FAILED; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | if (be_test_ddr_dma(adapter) != 0) { | ||
555 | data[3] = 1; | ||
556 | test->flags |= ETH_TEST_FL_FAILED; | ||
557 | } | ||
558 | |||
559 | if (be_cmd_link_status_query(adapter, &link_up, &mac_speed, | ||
560 | &qos_link_speed) != 0) { | ||
561 | test->flags |= ETH_TEST_FL_FAILED; | ||
562 | data[4] = -1; | ||
563 | } else if (mac_speed) { | ||
564 | data[4] = 1; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | static int | ||
338 | be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) | 569 | be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) |
339 | { | 570 | { |
340 | struct be_adapter *adapter = netdev_priv(netdev); | 571 | struct be_adapter *adapter = netdev_priv(netdev); |
@@ -348,10 +579,57 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) | |||
348 | return be_load_fw(adapter, file_name); | 579 | return be_load_fw(adapter, file_name); |
349 | } | 580 | } |
350 | 581 | ||
582 | static int | ||
583 | be_get_eeprom_len(struct net_device *netdev) | ||
584 | { | ||
585 | return BE_READ_SEEPROM_LEN; | ||
586 | } | ||
587 | |||
588 | static int | ||
589 | be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, | ||
590 | uint8_t *data) | ||
591 | { | ||
592 | struct be_adapter *adapter = netdev_priv(netdev); | ||
593 | struct be_dma_mem eeprom_cmd; | ||
594 | struct be_cmd_resp_seeprom_read *resp; | ||
595 | int status; | ||
596 | |||
597 | if (!eeprom->len) | ||
598 | return -EINVAL; | ||
599 | |||
600 | eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16); | ||
601 | |||
602 | memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem)); | ||
603 | eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read); | ||
604 | eeprom_cmd.va = pci_alloc_consistent(adapter->pdev, eeprom_cmd.size, | ||
605 | &eeprom_cmd.dma); | ||
606 | |||
607 | if (!eeprom_cmd.va) { | ||
608 | dev_err(&adapter->pdev->dev, | ||
609 | "Memory allocation failure. Could not read eeprom\n"); | ||
610 | return -ENOMEM; | ||
611 | } | ||
612 | |||
613 | status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd); | ||
614 | |||
615 | if (!status) { | ||
616 | resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va; | ||
617 | memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len); | ||
618 | } | ||
619 | pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va, | ||
620 | eeprom_cmd.dma); | ||
621 | |||
622 | return status; | ||
623 | } | ||
624 | |||
351 | const struct ethtool_ops be_ethtool_ops = { | 625 | const struct ethtool_ops be_ethtool_ops = { |
352 | .get_settings = be_get_settings, | 626 | .get_settings = be_get_settings, |
353 | .get_drvinfo = be_get_drvinfo, | 627 | .get_drvinfo = be_get_drvinfo, |
628 | .get_wol = be_get_wol, | ||
629 | .set_wol = be_set_wol, | ||
354 | .get_link = ethtool_op_get_link, | 630 | .get_link = ethtool_op_get_link, |
631 | .get_eeprom_len = be_get_eeprom_len, | ||
632 | .get_eeprom = be_read_eeprom, | ||
355 | .get_coalesce = be_get_coalesce, | 633 | .get_coalesce = be_get_coalesce, |
356 | .set_coalesce = be_set_coalesce, | 634 | .set_coalesce = be_set_coalesce, |
357 | .get_ringparam = be_get_ringparam, | 635 | .get_ringparam = be_get_ringparam, |
@@ -366,7 +644,9 @@ const struct ethtool_ops be_ethtool_ops = { | |||
366 | .get_tso = ethtool_op_get_tso, | 644 | .get_tso = ethtool_op_get_tso, |
367 | .set_tso = ethtool_op_set_tso, | 645 | .set_tso = ethtool_op_set_tso, |
368 | .get_strings = be_get_stat_strings, | 646 | .get_strings = be_get_stat_strings, |
369 | .get_stats_count = be_get_stats_count, | 647 | .phys_id = be_phys_id, |
648 | .get_sset_count = be_get_sset_count, | ||
370 | .get_ethtool_stats = be_get_ethtool_stats, | 649 | .get_ethtool_stats = be_get_ethtool_stats, |
371 | .flash_device = be_do_flash, | 650 | .flash_device = be_do_flash, |
651 | .self_test = be_self_test, | ||
372 | }; | 652 | }; |
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index a3394b4aa14a..2d4a4b827637 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -52,6 +52,10 @@ | |||
52 | */ | 52 | */ |
53 | #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ | 53 | #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ |
54 | 54 | ||
55 | /********* Power managment (WOL) **********/ | ||
56 | #define PCICFG_PM_CONTROL_OFFSET 0x44 | ||
57 | #define PCICFG_PM_CONTROL_MASK 0x108 /* bits 3 & 8 */ | ||
58 | |||
55 | /********* ISR0 Register offset **********/ | 59 | /********* ISR0 Register offset **********/ |
56 | #define CEV_ISR0_OFFSET 0xC18 | 60 | #define CEV_ISR0_OFFSET 0xC18 |
57 | #define CEV_ISR_SIZE 4 | 61 | #define CEV_ISR_SIZE 4 |
@@ -95,6 +99,64 @@ | |||
95 | /* Number of entries posted */ | 99 | /* Number of entries posted */ |
96 | #define DB_MCCQ_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ | 100 | #define DB_MCCQ_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ |
97 | 101 | ||
102 | /* Flashrom related descriptors */ | ||
103 | #define IMAGE_TYPE_FIRMWARE 160 | ||
104 | #define IMAGE_TYPE_BOOTCODE 224 | ||
105 | #define IMAGE_TYPE_OPTIONROM 32 | ||
106 | |||
107 | #define NUM_FLASHDIR_ENTRIES 32 | ||
108 | |||
109 | #define IMG_TYPE_ISCSI_ACTIVE 0 | ||
110 | #define IMG_TYPE_REDBOOT 1 | ||
111 | #define IMG_TYPE_BIOS 2 | ||
112 | #define IMG_TYPE_PXE_BIOS 3 | ||
113 | #define IMG_TYPE_FCOE_BIOS 8 | ||
114 | #define IMG_TYPE_ISCSI_BACKUP 9 | ||
115 | #define IMG_TYPE_FCOE_FW_ACTIVE 10 | ||
116 | #define IMG_TYPE_FCOE_FW_BACKUP 11 | ||
117 | #define IMG_TYPE_NCSI_FW 13 | ||
118 | |||
119 | #define FLASHROM_OPER_FLASH 1 | ||
120 | #define FLASHROM_OPER_SAVE 2 | ||
121 | #define FLASHROM_OPER_REPORT 4 | ||
122 | |||
123 | #define FLASH_IMAGE_MAX_SIZE_g2 (1310720) /* Max firmware image sz */ | ||
124 | #define FLASH_BIOS_IMAGE_MAX_SIZE_g2 (262144) /* Max OPTION ROM img sz */ | ||
125 | #define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2 (262144) /* Max Redboot image sz */ | ||
126 | #define FLASH_IMAGE_MAX_SIZE_g3 (2097152) /* Max fw image size */ | ||
127 | #define FLASH_BIOS_IMAGE_MAX_SIZE_g3 (524288) /* Max OPTION ROM img sz */ | ||
128 | #define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 (1048576) /* Max Redboot image sz */ | ||
129 | #define FLASH_NCSI_IMAGE_MAX_SIZE_g3 (262144) /* Max NSCI image sz */ | ||
130 | |||
131 | #define FLASH_NCSI_MAGIC (0x16032009) | ||
132 | #define FLASH_NCSI_DISABLED (0) | ||
133 | #define FLASH_NCSI_ENABLED (1) | ||
134 | |||
135 | #define FLASH_NCSI_BITFILE_HDR_OFFSET (0x600000) | ||
136 | |||
137 | /* Offsets for components on Flash. */ | ||
138 | #define FLASH_iSCSI_PRIMARY_IMAGE_START_g2 (1048576) | ||
139 | #define FLASH_iSCSI_BACKUP_IMAGE_START_g2 (2359296) | ||
140 | #define FLASH_FCoE_PRIMARY_IMAGE_START_g2 (3670016) | ||
141 | #define FLASH_FCoE_BACKUP_IMAGE_START_g2 (4980736) | ||
142 | #define FLASH_iSCSI_BIOS_START_g2 (7340032) | ||
143 | #define FLASH_PXE_BIOS_START_g2 (7864320) | ||
144 | #define FLASH_FCoE_BIOS_START_g2 (524288) | ||
145 | #define FLASH_REDBOOT_START_g2 (0) | ||
146 | |||
147 | #define FLASH_NCSI_START_g3 (15990784) | ||
148 | #define FLASH_iSCSI_PRIMARY_IMAGE_START_g3 (2097152) | ||
149 | #define FLASH_iSCSI_BACKUP_IMAGE_START_g3 (4194304) | ||
150 | #define FLASH_FCoE_PRIMARY_IMAGE_START_g3 (6291456) | ||
151 | #define FLASH_FCoE_BACKUP_IMAGE_START_g3 (8388608) | ||
152 | #define FLASH_iSCSI_BIOS_START_g3 (12582912) | ||
153 | #define FLASH_PXE_BIOS_START_g3 (13107200) | ||
154 | #define FLASH_FCoE_BIOS_START_g3 (13631488) | ||
155 | #define FLASH_REDBOOT_START_g3 (262144) | ||
156 | |||
157 | |||
158 | |||
159 | |||
98 | /* | 160 | /* |
99 | * BE descriptors: host memory data structures whose formats | 161 | * BE descriptors: host memory data structures whose formats |
100 | * are hardwired in BE silicon. | 162 | * are hardwired in BE silicon. |
@@ -103,6 +165,7 @@ | |||
103 | #define EQ_ENTRY_VALID_MASK 0x1 /* bit 0 */ | 165 | #define EQ_ENTRY_VALID_MASK 0x1 /* bit 0 */ |
104 | #define EQ_ENTRY_RES_ID_MASK 0xFFFF /* bits 16 - 31 */ | 166 | #define EQ_ENTRY_RES_ID_MASK 0xFFFF /* bits 16 - 31 */ |
105 | #define EQ_ENTRY_RES_ID_SHIFT 16 | 167 | #define EQ_ENTRY_RES_ID_SHIFT 16 |
168 | |||
106 | struct be_eq_entry { | 169 | struct be_eq_entry { |
107 | u32 evt; | 170 | u32 evt; |
108 | }; | 171 | }; |
@@ -217,36 +280,6 @@ struct be_eth_rx_compl { | |||
217 | u32 dw[4]; | 280 | u32 dw[4]; |
218 | }; | 281 | }; |
219 | 282 | ||
220 | /* Flashrom related descriptors */ | ||
221 | #define IMAGE_TYPE_FIRMWARE 160 | ||
222 | #define IMAGE_TYPE_BOOTCODE 224 | ||
223 | #define IMAGE_TYPE_OPTIONROM 32 | ||
224 | |||
225 | #define NUM_FLASHDIR_ENTRIES 32 | ||
226 | |||
227 | #define FLASHROM_TYPE_ISCSI_ACTIVE 0 | ||
228 | #define FLASHROM_TYPE_BIOS 2 | ||
229 | #define FLASHROM_TYPE_PXE_BIOS 3 | ||
230 | #define FLASHROM_TYPE_FCOE_BIOS 8 | ||
231 | #define FLASHROM_TYPE_ISCSI_BACKUP 9 | ||
232 | #define FLASHROM_TYPE_FCOE_FW_ACTIVE 10 | ||
233 | #define FLASHROM_TYPE_FCOE_FW_BACKUP 11 | ||
234 | |||
235 | #define FLASHROM_OPER_FLASH 1 | ||
236 | #define FLASHROM_OPER_SAVE 2 | ||
237 | |||
238 | #define FLASH_IMAGE_MAX_SIZE (1310720) /* Max firmware image size */ | ||
239 | #define FLASH_BIOS_IMAGE_MAX_SIZE (262144) /* Max OPTION ROM image sz */ | ||
240 | |||
241 | /* Offsets for components on Flash. */ | ||
242 | #define FLASH_iSCSI_PRIMARY_IMAGE_START (1048576) | ||
243 | #define FLASH_iSCSI_BACKUP_IMAGE_START (2359296) | ||
244 | #define FLASH_FCoE_PRIMARY_IMAGE_START (3670016) | ||
245 | #define FLASH_FCoE_BACKUP_IMAGE_START (4980736) | ||
246 | #define FLASH_iSCSI_BIOS_START (7340032) | ||
247 | #define FLASH_PXE_BIOS_START (7864320) | ||
248 | #define FLASH_FCoE_BIOS_START (524288) | ||
249 | |||
250 | struct controller_id { | 283 | struct controller_id { |
251 | u32 vendor; | 284 | u32 vendor; |
252 | u32 device; | 285 | u32 device; |
@@ -254,7 +287,20 @@ struct controller_id { | |||
254 | u32 subdevice; | 287 | u32 subdevice; |
255 | }; | 288 | }; |
256 | 289 | ||
257 | struct flash_file_hdr { | 290 | struct flash_comp { |
291 | unsigned long offset; | ||
292 | int optype; | ||
293 | int size; | ||
294 | }; | ||
295 | |||
296 | struct image_hdr { | ||
297 | u32 imageid; | ||
298 | u32 imageoffset; | ||
299 | u32 imagelength; | ||
300 | u32 image_checksum; | ||
301 | u8 image_version[32]; | ||
302 | }; | ||
303 | struct flash_file_hdr_g2 { | ||
258 | u8 sign[32]; | 304 | u8 sign[32]; |
259 | u32 cksum; | 305 | u32 cksum; |
260 | u32 antidote; | 306 | u32 antidote; |
@@ -266,6 +312,17 @@ struct flash_file_hdr { | |||
266 | u8 build[24]; | 312 | u8 build[24]; |
267 | }; | 313 | }; |
268 | 314 | ||
315 | struct flash_file_hdr_g3 { | ||
316 | u8 sign[52]; | ||
317 | u8 ufi_version[4]; | ||
318 | u32 file_len; | ||
319 | u32 cksum; | ||
320 | u32 antidote; | ||
321 | u32 num_imgs; | ||
322 | u8 build[24]; | ||
323 | u8 rsvd[32]; | ||
324 | }; | ||
325 | |||
269 | struct flash_section_hdr { | 326 | struct flash_section_hdr { |
270 | u32 format_rev; | 327 | u32 format_rev; |
271 | u32 cksum; | 328 | u32 cksum; |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 876b357101fa..ec6ace802256 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -31,6 +31,7 @@ MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); | |||
31 | 31 | ||
32 | static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { | 32 | static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { |
33 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 33 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
34 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, | ||
34 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, | 35 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, |
35 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, | 36 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, |
36 | { 0 } | 37 | { 0 } |
@@ -67,6 +68,9 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) | |||
67 | u32 reg = ioread32(addr); | 68 | u32 reg = ioread32(addr); |
68 | u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | 69 | u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; |
69 | 70 | ||
71 | if (adapter->eeh_err) | ||
72 | return; | ||
73 | |||
70 | if (!enabled && enable) | 74 | if (!enabled && enable) |
71 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | 75 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; |
72 | else if (enabled && !enable) | 76 | else if (enabled && !enable) |
@@ -98,6 +102,10 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, | |||
98 | { | 102 | { |
99 | u32 val = 0; | 103 | u32 val = 0; |
100 | val |= qid & DB_EQ_RING_ID_MASK; | 104 | val |= qid & DB_EQ_RING_ID_MASK; |
105 | |||
106 | if (adapter->eeh_err) | ||
107 | return; | ||
108 | |||
101 | if (arm) | 109 | if (arm) |
102 | val |= 1 << DB_EQ_REARM_SHIFT; | 110 | val |= 1 << DB_EQ_REARM_SHIFT; |
103 | if (clear_int) | 111 | if (clear_int) |
@@ -111,6 +119,10 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) | |||
111 | { | 119 | { |
112 | u32 val = 0; | 120 | u32 val = 0; |
113 | val |= qid & DB_CQ_RING_ID_MASK; | 121 | val |= qid & DB_CQ_RING_ID_MASK; |
122 | |||
123 | if (adapter->eeh_err) | ||
124 | return; | ||
125 | |||
114 | if (arm) | 126 | if (arm) |
115 | val |= 1 << DB_CQ_REARM_SHIFT; | 127 | val |= 1 << DB_CQ_REARM_SHIFT; |
116 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; | 128 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; |
@@ -123,6 +135,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) | |||
123 | struct sockaddr *addr = p; | 135 | struct sockaddr *addr = p; |
124 | int status = 0; | 136 | int status = 0; |
125 | 137 | ||
138 | if (!is_valid_ether_addr(addr->sa_data)) | ||
139 | return -EADDRNOTAVAIL; | ||
140 | |||
126 | status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id); | 141 | status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id); |
127 | if (status) | 142 | if (status) |
128 | return status; | 143 | return status; |
@@ -141,16 +156,13 @@ void netdev_stats_update(struct be_adapter *adapter) | |||
141 | struct be_rxf_stats *rxf_stats = &hw_stats->rxf; | 156 | struct be_rxf_stats *rxf_stats = &hw_stats->rxf; |
142 | struct be_port_rxf_stats *port_stats = | 157 | struct be_port_rxf_stats *port_stats = |
143 | &rxf_stats->port[adapter->port_num]; | 158 | &rxf_stats->port[adapter->port_num]; |
144 | struct net_device_stats *dev_stats = &adapter->stats.net_stats; | 159 | struct net_device_stats *dev_stats = &adapter->netdev->stats; |
145 | struct be_erx_stats *erx_stats = &hw_stats->erx; | 160 | struct be_erx_stats *erx_stats = &hw_stats->erx; |
146 | 161 | ||
147 | dev_stats->rx_packets = port_stats->rx_total_frames; | 162 | dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts; |
148 | dev_stats->tx_packets = port_stats->tx_unicastframes + | 163 | dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; |
149 | port_stats->tx_multicastframes + port_stats->tx_broadcastframes; | 164 | dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; |
150 | dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 | | 165 | dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; |
151 | (u64) port_stats->rx_bytes_lsd; | ||
152 | dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 | | ||
153 | (u64) port_stats->tx_bytes_lsd; | ||
154 | 166 | ||
155 | /* bad pkts received */ | 167 | /* bad pkts received */ |
156 | dev_stats->rx_errors = port_stats->rx_crc_errors + | 168 | dev_stats->rx_errors = port_stats->rx_crc_errors + |
@@ -168,7 +180,8 @@ void netdev_stats_update(struct be_adapter *adapter) | |||
168 | port_stats->rx_udp_checksum_errs; | 180 | port_stats->rx_udp_checksum_errs; |
169 | 181 | ||
170 | /* no space in linux buffers: best possible approximation */ | 182 | /* no space in linux buffers: best possible approximation */ |
171 | dev_stats->rx_dropped = erx_stats->rx_drops_no_fragments[0]; | 183 | dev_stats->rx_dropped = |
184 | erx_stats->rx_drops_no_fragments[adapter->rx_obj.q.id]; | ||
172 | 185 | ||
173 | /* detailed rx errors */ | 186 | /* detailed rx errors */ |
174 | dev_stats->rx_length_errors = port_stats->rx_in_range_errors + | 187 | dev_stats->rx_length_errors = port_stats->rx_in_range_errors + |
@@ -214,6 +227,7 @@ void be_link_status_update(struct be_adapter *adapter, bool link_up) | |||
214 | 227 | ||
215 | /* If link came up or went down */ | 228 | /* If link came up or went down */ |
216 | if (adapter->link_up != link_up) { | 229 | if (adapter->link_up != link_up) { |
230 | adapter->link_speed = -1; | ||
217 | if (link_up) { | 231 | if (link_up) { |
218 | netif_start_queue(netdev); | 232 | netif_start_queue(netdev); |
219 | netif_carrier_on(netdev); | 233 | netif_carrier_on(netdev); |
@@ -269,9 +283,7 @@ static void be_rx_eqd_update(struct be_adapter *adapter) | |||
269 | 283 | ||
270 | static struct net_device_stats *be_get_stats(struct net_device *dev) | 284 | static struct net_device_stats *be_get_stats(struct net_device *dev) |
271 | { | 285 | { |
272 | struct be_adapter *adapter = netdev_priv(dev); | 286 | return &dev->stats; |
273 | |||
274 | return &adapter->stats.net_stats; | ||
275 | } | 287 | } |
276 | 288 | ||
277 | static u32 be_calc_rate(u64 bytes, unsigned long ticks) | 289 | static u32 be_calc_rate(u64 bytes, unsigned long ticks) |
@@ -307,12 +319,13 @@ static void be_tx_rate_update(struct be_adapter *adapter) | |||
307 | } | 319 | } |
308 | 320 | ||
309 | static void be_tx_stats_update(struct be_adapter *adapter, | 321 | static void be_tx_stats_update(struct be_adapter *adapter, |
310 | u32 wrb_cnt, u32 copied, bool stopped) | 322 | u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped) |
311 | { | 323 | { |
312 | struct be_drvr_stats *stats = drvr_stats(adapter); | 324 | struct be_drvr_stats *stats = drvr_stats(adapter); |
313 | stats->be_tx_reqs++; | 325 | stats->be_tx_reqs++; |
314 | stats->be_tx_wrbs += wrb_cnt; | 326 | stats->be_tx_wrbs += wrb_cnt; |
315 | stats->be_tx_bytes += copied; | 327 | stats->be_tx_bytes += copied; |
328 | stats->be_tx_pkts += (gso_segs ? gso_segs : 1); | ||
316 | if (stopped) | 329 | if (stopped) |
317 | stats->be_tx_stops++; | 330 | stats->be_tx_stops++; |
318 | } | 331 | } |
@@ -389,15 +402,11 @@ static int make_tx_wrbs(struct be_adapter *adapter, | |||
389 | atomic_add(wrb_cnt, &txq->used); | 402 | atomic_add(wrb_cnt, &txq->used); |
390 | queue_head_inc(txq); | 403 | queue_head_inc(txq); |
391 | 404 | ||
392 | if (skb_dma_map(&pdev->dev, skb, DMA_TO_DEVICE)) { | ||
393 | dev_err(&pdev->dev, "TX DMA mapping failed\n"); | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | if (skb->len > skb->data_len) { | 405 | if (skb->len > skb->data_len) { |
398 | int len = skb->len - skb->data_len; | 406 | int len = skb->len - skb->data_len; |
407 | busaddr = pci_map_single(pdev, skb->data, len, | ||
408 | PCI_DMA_TODEVICE); | ||
399 | wrb = queue_head_node(txq); | 409 | wrb = queue_head_node(txq); |
400 | busaddr = skb_shinfo(skb)->dma_head; | ||
401 | wrb_fill(wrb, busaddr, len); | 410 | wrb_fill(wrb, busaddr, len); |
402 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | 411 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); |
403 | queue_head_inc(txq); | 412 | queue_head_inc(txq); |
@@ -407,8 +416,9 @@ static int make_tx_wrbs(struct be_adapter *adapter, | |||
407 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 416 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
408 | struct skb_frag_struct *frag = | 417 | struct skb_frag_struct *frag = |
409 | &skb_shinfo(skb)->frags[i]; | 418 | &skb_shinfo(skb)->frags[i]; |
410 | 419 | busaddr = pci_map_page(pdev, frag->page, | |
411 | busaddr = skb_shinfo(skb)->dma_maps[i]; | 420 | frag->page_offset, |
421 | frag->size, PCI_DMA_TODEVICE); | ||
412 | wrb = queue_head_node(txq); | 422 | wrb = queue_head_node(txq); |
413 | wrb_fill(wrb, busaddr, frag->size); | 423 | wrb_fill(wrb, busaddr, frag->size); |
414 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | 424 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); |
@@ -460,7 +470,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
460 | 470 | ||
461 | be_txq_notify(adapter, txq->id, wrb_cnt); | 471 | be_txq_notify(adapter, txq->id, wrb_cnt); |
462 | 472 | ||
463 | be_tx_stats_update(adapter, wrb_cnt, copied, stopped); | 473 | be_tx_stats_update(adapter, wrb_cnt, copied, |
474 | skb_shinfo(skb)->gso_segs, stopped); | ||
464 | } else { | 475 | } else { |
465 | txq->head = start; | 476 | txq->head = start; |
466 | dev_kfree_skb_any(skb); | 477 | dev_kfree_skb_any(skb); |
@@ -472,10 +483,12 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) | |||
472 | { | 483 | { |
473 | struct be_adapter *adapter = netdev_priv(netdev); | 484 | struct be_adapter *adapter = netdev_priv(netdev); |
474 | if (new_mtu < BE_MIN_MTU || | 485 | if (new_mtu < BE_MIN_MTU || |
475 | new_mtu > BE_MAX_JUMBO_FRAME_SIZE) { | 486 | new_mtu > (BE_MAX_JUMBO_FRAME_SIZE - |
487 | (ETH_HLEN + ETH_FCS_LEN))) { | ||
476 | dev_info(&adapter->pdev->dev, | 488 | dev_info(&adapter->pdev->dev, |
477 | "MTU must be between %d and %d bytes\n", | 489 | "MTU must be between %d and %d bytes\n", |
478 | BE_MIN_MTU, BE_MAX_JUMBO_FRAME_SIZE); | 490 | BE_MIN_MTU, |
491 | (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))); | ||
479 | return -EINVAL; | 492 | return -EINVAL; |
480 | } | 493 | } |
481 | dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", | 494 | dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", |
@@ -485,17 +498,16 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) | |||
485 | } | 498 | } |
486 | 499 | ||
487 | /* | 500 | /* |
488 | * if there are BE_NUM_VLANS_SUPPORTED or lesser number of VLANS configured, | 501 | * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE. |
489 | * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, | 502 | * If the user configures more, place BE in vlan promiscuous mode. |
490 | * set the BE in promiscuous VLAN mode. | ||
491 | */ | 503 | */ |
492 | static int be_vid_config(struct be_adapter *adapter) | 504 | static int be_vid_config(struct be_adapter *adapter) |
493 | { | 505 | { |
494 | u16 vtag[BE_NUM_VLANS_SUPPORTED]; | 506 | u16 vtag[BE_NUM_VLANS_SUPPORTED]; |
495 | u16 ntags = 0, i; | 507 | u16 ntags = 0, i; |
496 | int status; | 508 | int status = 0; |
497 | 509 | ||
498 | if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { | 510 | if (adapter->vlans_added <= adapter->max_vlans) { |
499 | /* Construct VLAN Table to give to HW */ | 511 | /* Construct VLAN Table to give to HW */ |
500 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 512 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { |
501 | if (adapter->vlan_tag[i]) { | 513 | if (adapter->vlan_tag[i]) { |
@@ -529,21 +541,21 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) | |||
529 | { | 541 | { |
530 | struct be_adapter *adapter = netdev_priv(netdev); | 542 | struct be_adapter *adapter = netdev_priv(netdev); |
531 | 543 | ||
532 | adapter->num_vlans++; | ||
533 | adapter->vlan_tag[vid] = 1; | 544 | adapter->vlan_tag[vid] = 1; |
534 | 545 | adapter->vlans_added++; | |
535 | be_vid_config(adapter); | 546 | if (adapter->vlans_added <= (adapter->max_vlans + 1)) |
547 | be_vid_config(adapter); | ||
536 | } | 548 | } |
537 | 549 | ||
538 | static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) | 550 | static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) |
539 | { | 551 | { |
540 | struct be_adapter *adapter = netdev_priv(netdev); | 552 | struct be_adapter *adapter = netdev_priv(netdev); |
541 | 553 | ||
542 | adapter->num_vlans--; | ||
543 | adapter->vlan_tag[vid] = 0; | 554 | adapter->vlan_tag[vid] = 0; |
544 | |||
545 | vlan_group_set_device(adapter->vlan_grp, vid, NULL); | 555 | vlan_group_set_device(adapter->vlan_grp, vid, NULL); |
546 | be_vid_config(adapter); | 556 | adapter->vlans_added--; |
557 | if (adapter->vlans_added <= adapter->max_vlans) | ||
558 | be_vid_config(adapter); | ||
547 | } | 559 | } |
548 | 560 | ||
549 | static void be_set_multicast_list(struct net_device *netdev) | 561 | static void be_set_multicast_list(struct net_device *netdev) |
@@ -562,13 +574,16 @@ static void be_set_multicast_list(struct net_device *netdev) | |||
562 | be_cmd_promiscuous_config(adapter, adapter->port_num, 0); | 574 | be_cmd_promiscuous_config(adapter, adapter->port_num, 0); |
563 | } | 575 | } |
564 | 576 | ||
565 | if (netdev->flags & IFF_ALLMULTI) { | 577 | /* Enable multicast promisc if num configured exceeds what we support */ |
566 | be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0); | 578 | if (netdev->flags & IFF_ALLMULTI || |
579 | netdev_mc_count(netdev) > BE_MAX_MC) { | ||
580 | be_cmd_multicast_set(adapter, adapter->if_handle, NULL, | ||
581 | &adapter->mc_cmd_mem); | ||
567 | goto done; | 582 | goto done; |
568 | } | 583 | } |
569 | 584 | ||
570 | be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, | 585 | be_cmd_multicast_set(adapter, adapter->if_handle, netdev, |
571 | netdev->mc_count); | 586 | &adapter->mc_cmd_mem); |
572 | done: | 587 | done: |
573 | return; | 588 | return; |
574 | } | 589 | } |
@@ -603,6 +618,7 @@ static void be_rx_stats_update(struct be_adapter *adapter, | |||
603 | stats->be_rx_compl++; | 618 | stats->be_rx_compl++; |
604 | stats->be_rx_frags += numfrags; | 619 | stats->be_rx_frags += numfrags; |
605 | stats->be_rx_bytes += pktsize; | 620 | stats->be_rx_bytes += pktsize; |
621 | stats->be_rx_pkts++; | ||
606 | } | 622 | } |
607 | 623 | ||
608 | static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) | 624 | static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) |
@@ -630,9 +646,11 @@ get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) | |||
630 | rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; | 646 | rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; |
631 | BUG_ON(!rx_page_info->page); | 647 | BUG_ON(!rx_page_info->page); |
632 | 648 | ||
633 | if (rx_page_info->last_page_user) | 649 | if (rx_page_info->last_page_user) { |
634 | pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), | 650 | pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), |
635 | adapter->big_page_size, PCI_DMA_FROMDEVICE); | 651 | adapter->big_page_size, PCI_DMA_FROMDEVICE); |
652 | rx_page_info->last_page_user = false; | ||
653 | } | ||
636 | 654 | ||
637 | atomic_dec(&rxq->used); | 655 | atomic_dec(&rxq->used); |
638 | return rx_page_info; | 656 | return rx_page_info; |
@@ -662,17 +680,17 @@ static void be_rx_compl_discard(struct be_adapter *adapter, | |||
662 | * indicated by rxcp. | 680 | * indicated by rxcp. |
663 | */ | 681 | */ |
664 | static void skb_fill_rx_data(struct be_adapter *adapter, | 682 | static void skb_fill_rx_data(struct be_adapter *adapter, |
665 | struct sk_buff *skb, struct be_eth_rx_compl *rxcp) | 683 | struct sk_buff *skb, struct be_eth_rx_compl *rxcp, |
684 | u16 num_rcvd) | ||
666 | { | 685 | { |
667 | struct be_queue_info *rxq = &adapter->rx_obj.q; | 686 | struct be_queue_info *rxq = &adapter->rx_obj.q; |
668 | struct be_rx_page_info *page_info; | 687 | struct be_rx_page_info *page_info; |
669 | u16 rxq_idx, i, num_rcvd, j; | 688 | u16 rxq_idx, i, j; |
670 | u32 pktsize, hdr_len, curr_frag_len, size; | 689 | u32 pktsize, hdr_len, curr_frag_len, size; |
671 | u8 *start; | 690 | u8 *start; |
672 | 691 | ||
673 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 692 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
674 | pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 693 | pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
675 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | ||
676 | 694 | ||
677 | page_info = get_rx_page_info(adapter, rxq_idx); | 695 | page_info = get_rx_page_info(adapter, rxq_idx); |
678 | 696 | ||
@@ -700,7 +718,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, | |||
700 | skb->data_len = curr_frag_len - hdr_len; | 718 | skb->data_len = curr_frag_len - hdr_len; |
701 | skb->tail += hdr_len; | 719 | skb->tail += hdr_len; |
702 | } | 720 | } |
703 | memset(page_info, 0, sizeof(*page_info)); | 721 | page_info->page = NULL; |
704 | 722 | ||
705 | if (pktsize <= rx_frag_size) { | 723 | if (pktsize <= rx_frag_size) { |
706 | BUG_ON(num_rcvd != 1); | 724 | BUG_ON(num_rcvd != 1); |
@@ -733,7 +751,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, | |||
733 | skb->len += curr_frag_len; | 751 | skb->len += curr_frag_len; |
734 | skb->data_len += curr_frag_len; | 752 | skb->data_len += curr_frag_len; |
735 | 753 | ||
736 | memset(page_info, 0, sizeof(*page_info)); | 754 | page_info->page = NULL; |
737 | } | 755 | } |
738 | BUG_ON(j > MAX_SKB_FRAGS); | 756 | BUG_ON(j > MAX_SKB_FRAGS); |
739 | 757 | ||
@@ -748,27 +766,23 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
748 | { | 766 | { |
749 | struct sk_buff *skb; | 767 | struct sk_buff *skb; |
750 | u32 vlanf, vid; | 768 | u32 vlanf, vid; |
769 | u16 num_rcvd; | ||
751 | u8 vtm; | 770 | u8 vtm; |
752 | 771 | ||
753 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); | 772 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
754 | vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); | 773 | /* Is it a flush compl that has no data */ |
755 | 774 | if (unlikely(num_rcvd == 0)) | |
756 | /* vlanf could be wrongly set in some cards. | 775 | return; |
757 | * ignore if vtm is not set */ | ||
758 | if ((adapter->cap == 0x400) && !vtm) | ||
759 | vlanf = 0; | ||
760 | 776 | ||
761 | skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN); | 777 | skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); |
762 | if (!skb) { | 778 | if (unlikely(!skb)) { |
763 | if (net_ratelimit()) | 779 | if (net_ratelimit()) |
764 | dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); | 780 | dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); |
765 | be_rx_compl_discard(adapter, rxcp); | 781 | be_rx_compl_discard(adapter, rxcp); |
766 | return; | 782 | return; |
767 | } | 783 | } |
768 | 784 | ||
769 | skb_reserve(skb, NET_IP_ALIGN); | 785 | skb_fill_rx_data(adapter, skb, rxcp, num_rcvd); |
770 | |||
771 | skb_fill_rx_data(adapter, skb, rxcp); | ||
772 | 786 | ||
773 | if (do_pkt_csum(rxcp, adapter->rx_csum)) | 787 | if (do_pkt_csum(rxcp, adapter->rx_csum)) |
774 | skb->ip_summed = CHECKSUM_NONE; | 788 | skb->ip_summed = CHECKSUM_NONE; |
@@ -779,13 +793,21 @@ static void be_rx_compl_process(struct be_adapter *adapter, | |||
779 | skb->protocol = eth_type_trans(skb, adapter->netdev); | 793 | skb->protocol = eth_type_trans(skb, adapter->netdev); |
780 | skb->dev = adapter->netdev; | 794 | skb->dev = adapter->netdev; |
781 | 795 | ||
782 | if (vlanf) { | 796 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); |
783 | if (!adapter->vlan_grp || adapter->num_vlans == 0) { | 797 | vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); |
798 | |||
799 | /* vlanf could be wrongly set in some cards. | ||
800 | * ignore if vtm is not set */ | ||
801 | if ((adapter->cap & 0x400) && !vtm) | ||
802 | vlanf = 0; | ||
803 | |||
804 | if (unlikely(vlanf)) { | ||
805 | if (!adapter->vlan_grp || adapter->vlans_added == 0) { | ||
784 | kfree_skb(skb); | 806 | kfree_skb(skb); |
785 | return; | 807 | return; |
786 | } | 808 | } |
787 | vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); | 809 | vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); |
788 | vid = be16_to_cpu(vid); | 810 | vid = swab16(vid); |
789 | vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid); | 811 | vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid); |
790 | } else { | 812 | } else { |
791 | netif_receive_skb(skb); | 813 | netif_receive_skb(skb); |
@@ -807,6 +829,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
807 | u8 vtm; | 829 | u8 vtm; |
808 | 830 | ||
809 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 831 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
832 | /* Is it a flush compl that has no data */ | ||
833 | if (unlikely(num_rcvd == 0)) | ||
834 | return; | ||
835 | |||
810 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 836 | pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
811 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); | 837 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); |
812 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 838 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
@@ -814,7 +840,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
814 | 840 | ||
815 | /* vlanf could be wrongly set in some cards. | 841 | /* vlanf could be wrongly set in some cards. |
816 | * ignore if vtm is not set */ | 842 | * ignore if vtm is not set */ |
817 | if ((adapter->cap == 0x400) && !vtm) | 843 | if ((adapter->cap & 0x400) && !vtm) |
818 | vlanf = 0; | 844 | vlanf = 0; |
819 | 845 | ||
820 | skb = napi_get_frags(&eq_obj->napi); | 846 | skb = napi_get_frags(&eq_obj->napi); |
@@ -858,9 +884,9 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
858 | napi_gro_frags(&eq_obj->napi); | 884 | napi_gro_frags(&eq_obj->napi); |
859 | } else { | 885 | } else { |
860 | vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); | 886 | vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); |
861 | vid = be16_to_cpu(vid); | 887 | vid = swab16(vid); |
862 | 888 | ||
863 | if (!adapter->vlan_grp || adapter->num_vlans == 0) | 889 | if (!adapter->vlan_grp || adapter->vlans_added == 0) |
864 | return; | 890 | return; |
865 | 891 | ||
866 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); | 892 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); |
@@ -908,7 +934,7 @@ static inline struct page *be_alloc_pages(u32 size) | |||
908 | static void be_post_rx_frags(struct be_adapter *adapter) | 934 | static void be_post_rx_frags(struct be_adapter *adapter) |
909 | { | 935 | { |
910 | struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; | 936 | struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; |
911 | struct be_rx_page_info *page_info = NULL; | 937 | struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; |
912 | struct be_queue_info *rxq = &adapter->rx_obj.q; | 938 | struct be_queue_info *rxq = &adapter->rx_obj.q; |
913 | struct page *pagep = NULL; | 939 | struct page *pagep = NULL; |
914 | struct be_eth_rx_d *rxd; | 940 | struct be_eth_rx_d *rxd; |
@@ -939,7 +965,6 @@ static void be_post_rx_frags(struct be_adapter *adapter) | |||
939 | rxd = queue_head_node(rxq); | 965 | rxd = queue_head_node(rxq); |
940 | rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); | 966 | rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); |
941 | rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); | 967 | rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); |
942 | queue_head_inc(rxq); | ||
943 | 968 | ||
944 | /* Any space left in the current big page for another frag? */ | 969 | /* Any space left in the current big page for another frag? */ |
945 | if ((page_offset + rx_frag_size + rx_frag_size) > | 970 | if ((page_offset + rx_frag_size + rx_frag_size) > |
@@ -947,10 +972,13 @@ static void be_post_rx_frags(struct be_adapter *adapter) | |||
947 | pagep = NULL; | 972 | pagep = NULL; |
948 | page_info->last_page_user = true; | 973 | page_info->last_page_user = true; |
949 | } | 974 | } |
975 | |||
976 | prev_page_info = page_info; | ||
977 | queue_head_inc(rxq); | ||
950 | page_info = &page_info_tbl[rxq->head]; | 978 | page_info = &page_info_tbl[rxq->head]; |
951 | } | 979 | } |
952 | if (pagep) | 980 | if (pagep) |
953 | page_info->last_page_user = true; | 981 | prev_page_info->last_page_user = true; |
954 | 982 | ||
955 | if (posted) { | 983 | if (posted) { |
956 | atomic_add(posted, &rxq->used); | 984 | atomic_add(posted, &rxq->used); |
@@ -981,23 +1009,41 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) | |||
981 | static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) | 1009 | static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) |
982 | { | 1010 | { |
983 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1011 | struct be_queue_info *txq = &adapter->tx_obj.q; |
1012 | struct be_eth_wrb *wrb; | ||
984 | struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; | 1013 | struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; |
985 | struct sk_buff *sent_skb; | 1014 | struct sk_buff *sent_skb; |
1015 | u64 busaddr; | ||
986 | u16 cur_index, num_wrbs = 0; | 1016 | u16 cur_index, num_wrbs = 0; |
987 | 1017 | ||
988 | cur_index = txq->tail; | 1018 | cur_index = txq->tail; |
989 | sent_skb = sent_skbs[cur_index]; | 1019 | sent_skb = sent_skbs[cur_index]; |
990 | BUG_ON(!sent_skb); | 1020 | BUG_ON(!sent_skb); |
991 | sent_skbs[cur_index] = NULL; | 1021 | sent_skbs[cur_index] = NULL; |
1022 | wrb = queue_tail_node(txq); | ||
1023 | be_dws_le_to_cpu(wrb, sizeof(*wrb)); | ||
1024 | busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo; | ||
1025 | if (busaddr != 0) { | ||
1026 | pci_unmap_single(adapter->pdev, busaddr, | ||
1027 | wrb->frag_len, PCI_DMA_TODEVICE); | ||
1028 | } | ||
1029 | num_wrbs++; | ||
1030 | queue_tail_inc(txq); | ||
992 | 1031 | ||
993 | do { | 1032 | while (cur_index != last_index) { |
994 | cur_index = txq->tail; | 1033 | cur_index = txq->tail; |
1034 | wrb = queue_tail_node(txq); | ||
1035 | be_dws_le_to_cpu(wrb, sizeof(*wrb)); | ||
1036 | busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo; | ||
1037 | if (busaddr != 0) { | ||
1038 | pci_unmap_page(adapter->pdev, busaddr, | ||
1039 | wrb->frag_len, PCI_DMA_TODEVICE); | ||
1040 | } | ||
995 | num_wrbs++; | 1041 | num_wrbs++; |
996 | queue_tail_inc(txq); | 1042 | queue_tail_inc(txq); |
997 | } while (cur_index != last_index); | 1043 | } |
998 | 1044 | ||
999 | atomic_sub(num_wrbs, &txq->used); | 1045 | atomic_sub(num_wrbs, &txq->used); |
1000 | skb_dma_unmap(&adapter->pdev->dev, sent_skb, DMA_TO_DEVICE); | 1046 | |
1001 | kfree_skb(sent_skb); | 1047 | kfree_skb(sent_skb); |
1002 | } | 1048 | } |
1003 | 1049 | ||
@@ -1082,6 +1128,9 @@ static void be_tx_compl_clean(struct be_adapter *adapter) | |||
1082 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1128 | struct be_queue_info *txq = &adapter->tx_obj.q; |
1083 | struct be_eth_tx_compl *txcp; | 1129 | struct be_eth_tx_compl *txcp; |
1084 | u16 end_idx, cmpl = 0, timeo = 0; | 1130 | u16 end_idx, cmpl = 0, timeo = 0; |
1131 | struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; | ||
1132 | struct sk_buff *sent_skb; | ||
1133 | bool dummy_wrb; | ||
1085 | 1134 | ||
1086 | /* Wait for a max of 200ms for all the tx-completions to arrive. */ | 1135 | /* Wait for a max of 200ms for all the tx-completions to arrive. */ |
1087 | do { | 1136 | do { |
@@ -1105,6 +1154,15 @@ static void be_tx_compl_clean(struct be_adapter *adapter) | |||
1105 | if (atomic_read(&txq->used)) | 1154 | if (atomic_read(&txq->used)) |
1106 | dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", | 1155 | dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", |
1107 | atomic_read(&txq->used)); | 1156 | atomic_read(&txq->used)); |
1157 | |||
1158 | /* free posted tx for which compls will never arrive */ | ||
1159 | while (atomic_read(&txq->used)) { | ||
1160 | sent_skb = sent_skbs[txq->tail]; | ||
1161 | end_idx = txq->tail; | ||
1162 | index_adv(&end_idx, | ||
1163 | wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); | ||
1164 | be_tx_compl_process(adapter, end_idx); | ||
1165 | } | ||
1108 | } | 1166 | } |
1109 | 1167 | ||
1110 | static void be_mcc_queues_destroy(struct be_adapter *adapter) | 1168 | static void be_mcc_queues_destroy(struct be_adapter *adapter) |
@@ -1237,6 +1295,11 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) | |||
1237 | q = &adapter->rx_obj.q; | 1295 | q = &adapter->rx_obj.q; |
1238 | if (q->created) { | 1296 | if (q->created) { |
1239 | be_cmd_q_destroy(adapter, q, QTYPE_RXQ); | 1297 | be_cmd_q_destroy(adapter, q, QTYPE_RXQ); |
1298 | |||
1299 | /* After the rxq is invalidated, wait for a grace time | ||
1300 | * of 1ms for all dma to end and the flush compl to arrive | ||
1301 | */ | ||
1302 | mdelay(1); | ||
1240 | be_rx_q_clean(adapter); | 1303 | be_rx_q_clean(adapter); |
1241 | } | 1304 | } |
1242 | be_queue_free(adapter, q); | 1305 | be_queue_free(adapter, q); |
@@ -1319,7 +1382,7 @@ rx_eq_free: | |||
1319 | /* There are 8 evt ids per func. Retruns the evt id's bit number */ | 1382 | /* There are 8 evt ids per func. Retruns the evt id's bit number */ |
1320 | static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) | 1383 | static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) |
1321 | { | 1384 | { |
1322 | return eq_id - 8 * be_pci_func(adapter); | 1385 | return eq_id % 8; |
1323 | } | 1386 | } |
1324 | 1387 | ||
1325 | static irqreturn_t be_intx(int irq, void *dev) | 1388 | static irqreturn_t be_intx(int irq, void *dev) |
@@ -1328,7 +1391,7 @@ static irqreturn_t be_intx(int irq, void *dev) | |||
1328 | int isr; | 1391 | int isr; |
1329 | 1392 | ||
1330 | isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + | 1393 | isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + |
1331 | be_pci_func(adapter) * CEV_ISR_SIZE); | 1394 | (adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE); |
1332 | if (!isr) | 1395 | if (!isr) |
1333 | return IRQ_NONE; | 1396 | return IRQ_NONE; |
1334 | 1397 | ||
@@ -1377,6 +1440,7 @@ int be_poll_rx(struct napi_struct *napi, int budget) | |||
1377 | struct be_eth_rx_compl *rxcp; | 1440 | struct be_eth_rx_compl *rxcp; |
1378 | u32 work_done; | 1441 | u32 work_done; |
1379 | 1442 | ||
1443 | adapter->stats.drvr_stats.be_rx_polls++; | ||
1380 | for (work_done = 0; work_done < budget; work_done++) { | 1444 | for (work_done = 0; work_done < budget; work_done++) { |
1381 | rxcp = be_rx_compl_get(adapter); | 1445 | rxcp = be_rx_compl_get(adapter); |
1382 | if (!rxcp) | 1446 | if (!rxcp) |
@@ -1405,23 +1469,38 @@ int be_poll_rx(struct napi_struct *napi, int budget) | |||
1405 | return work_done; | 1469 | return work_done; |
1406 | } | 1470 | } |
1407 | 1471 | ||
1408 | void be_process_tx(struct be_adapter *adapter) | 1472 | /* As TX and MCC share the same EQ check for both TX and MCC completions. |
1473 | * For TX/MCC we don't honour budget; consume everything | ||
1474 | */ | ||
1475 | static int be_poll_tx_mcc(struct napi_struct *napi, int budget) | ||
1409 | { | 1476 | { |
1477 | struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); | ||
1478 | struct be_adapter *adapter = | ||
1479 | container_of(tx_eq, struct be_adapter, tx_eq); | ||
1410 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1480 | struct be_queue_info *txq = &adapter->tx_obj.q; |
1411 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; | 1481 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; |
1412 | struct be_eth_tx_compl *txcp; | 1482 | struct be_eth_tx_compl *txcp; |
1413 | u32 num_cmpl = 0; | 1483 | int tx_compl = 0, mcc_compl, status = 0; |
1414 | u16 end_idx; | 1484 | u16 end_idx; |
1415 | 1485 | ||
1416 | while ((txcp = be_tx_compl_get(tx_cq))) { | 1486 | while ((txcp = be_tx_compl_get(tx_cq))) { |
1417 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, | 1487 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, |
1418 | wrb_index, txcp); | 1488 | wrb_index, txcp); |
1419 | be_tx_compl_process(adapter, end_idx); | 1489 | be_tx_compl_process(adapter, end_idx); |
1420 | num_cmpl++; | 1490 | tx_compl++; |
1491 | } | ||
1492 | |||
1493 | mcc_compl = be_process_mcc(adapter, &status); | ||
1494 | |||
1495 | napi_complete(napi); | ||
1496 | |||
1497 | if (mcc_compl) { | ||
1498 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; | ||
1499 | be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); | ||
1421 | } | 1500 | } |
1422 | 1501 | ||
1423 | if (num_cmpl) { | 1502 | if (tx_compl) { |
1424 | be_cq_notify(adapter, tx_cq->id, true, num_cmpl); | 1503 | be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl); |
1425 | 1504 | ||
1426 | /* As Tx wrbs have been freed up, wake up netdev queue if | 1505 | /* As Tx wrbs have been freed up, wake up netdev queue if |
1427 | * it was stopped due to lack of tx wrbs. | 1506 | * it was stopped due to lack of tx wrbs. |
@@ -1432,24 +1511,8 @@ void be_process_tx(struct be_adapter *adapter) | |||
1432 | } | 1511 | } |
1433 | 1512 | ||
1434 | drvr_stats(adapter)->be_tx_events++; | 1513 | drvr_stats(adapter)->be_tx_events++; |
1435 | drvr_stats(adapter)->be_tx_compl += num_cmpl; | 1514 | drvr_stats(adapter)->be_tx_compl += tx_compl; |
1436 | } | 1515 | } |
1437 | } | ||
1438 | |||
1439 | /* As TX and MCC share the same EQ check for both TX and MCC completions. | ||
1440 | * For TX/MCC we don't honour budget; consume everything | ||
1441 | */ | ||
1442 | static int be_poll_tx_mcc(struct napi_struct *napi, int budget) | ||
1443 | { | ||
1444 | struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); | ||
1445 | struct be_adapter *adapter = | ||
1446 | container_of(tx_eq, struct be_adapter, tx_eq); | ||
1447 | |||
1448 | napi_complete(napi); | ||
1449 | |||
1450 | be_process_tx(adapter); | ||
1451 | |||
1452 | be_process_mcc(adapter); | ||
1453 | 1516 | ||
1454 | return 1; | 1517 | return 1; |
1455 | } | 1518 | } |
@@ -1475,6 +1538,14 @@ static void be_worker(struct work_struct *work) | |||
1475 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); | 1538 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); |
1476 | } | 1539 | } |
1477 | 1540 | ||
1541 | static void be_msix_disable(struct be_adapter *adapter) | ||
1542 | { | ||
1543 | if (adapter->msix_enabled) { | ||
1544 | pci_disable_msix(adapter->pdev); | ||
1545 | adapter->msix_enabled = false; | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1478 | static void be_msix_enable(struct be_adapter *adapter) | 1549 | static void be_msix_enable(struct be_adapter *adapter) |
1479 | { | 1550 | { |
1480 | int i, status; | 1551 | int i, status; |
@@ -1590,6 +1661,8 @@ static int be_open(struct net_device *netdev) | |||
1590 | struct be_eq_obj *tx_eq = &adapter->tx_eq; | 1661 | struct be_eq_obj *tx_eq = &adapter->tx_eq; |
1591 | bool link_up; | 1662 | bool link_up; |
1592 | int status; | 1663 | int status; |
1664 | u8 mac_speed; | ||
1665 | u16 link_speed; | ||
1593 | 1666 | ||
1594 | /* First time posting */ | 1667 | /* First time posting */ |
1595 | be_post_rx_frags(adapter); | 1668 | be_post_rx_frags(adapter); |
@@ -1608,7 +1681,11 @@ static int be_open(struct net_device *netdev) | |||
1608 | /* Rx compl queue may be in unarmed state; rearm it */ | 1681 | /* Rx compl queue may be in unarmed state; rearm it */ |
1609 | be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0); | 1682 | be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0); |
1610 | 1683 | ||
1611 | status = be_cmd_link_status_query(adapter, &link_up); | 1684 | /* Now that interrupts are on we can process async mcc */ |
1685 | be_async_mcc_enable(adapter); | ||
1686 | |||
1687 | status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, | ||
1688 | &link_speed); | ||
1612 | if (status) | 1689 | if (status) |
1613 | goto ret_sts; | 1690 | goto ret_sts; |
1614 | be_link_status_update(adapter, link_up); | 1691 | be_link_status_update(adapter, link_up); |
@@ -1627,6 +1704,44 @@ ret_sts: | |||
1627 | return status; | 1704 | return status; |
1628 | } | 1705 | } |
1629 | 1706 | ||
1707 | static int be_setup_wol(struct be_adapter *adapter, bool enable) | ||
1708 | { | ||
1709 | struct be_dma_mem cmd; | ||
1710 | int status = 0; | ||
1711 | u8 mac[ETH_ALEN]; | ||
1712 | |||
1713 | memset(mac, 0, ETH_ALEN); | ||
1714 | |||
1715 | cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config); | ||
1716 | cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma); | ||
1717 | if (cmd.va == NULL) | ||
1718 | return -1; | ||
1719 | memset(cmd.va, 0, cmd.size); | ||
1720 | |||
1721 | if (enable) { | ||
1722 | status = pci_write_config_dword(adapter->pdev, | ||
1723 | PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK); | ||
1724 | if (status) { | ||
1725 | dev_err(&adapter->pdev->dev, | ||
1726 | "Could not enable Wake-on-lan \n"); | ||
1727 | pci_free_consistent(adapter->pdev, cmd.size, cmd.va, | ||
1728 | cmd.dma); | ||
1729 | return status; | ||
1730 | } | ||
1731 | status = be_cmd_enable_magic_wol(adapter, | ||
1732 | adapter->netdev->dev_addr, &cmd); | ||
1733 | pci_enable_wake(adapter->pdev, PCI_D3hot, 1); | ||
1734 | pci_enable_wake(adapter->pdev, PCI_D3cold, 1); | ||
1735 | } else { | ||
1736 | status = be_cmd_enable_magic_wol(adapter, mac, &cmd); | ||
1737 | pci_enable_wake(adapter->pdev, PCI_D3hot, 0); | ||
1738 | pci_enable_wake(adapter->pdev, PCI_D3cold, 0); | ||
1739 | } | ||
1740 | |||
1741 | pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma); | ||
1742 | return status; | ||
1743 | } | ||
1744 | |||
1630 | static int be_setup(struct be_adapter *adapter) | 1745 | static int be_setup(struct be_adapter *adapter) |
1631 | { | 1746 | { |
1632 | struct net_device *netdev = adapter->netdev; | 1747 | struct net_device *netdev = adapter->netdev; |
@@ -1658,6 +1773,8 @@ static int be_setup(struct be_adapter *adapter) | |||
1658 | if (status != 0) | 1773 | if (status != 0) |
1659 | goto rx_qs_destroy; | 1774 | goto rx_qs_destroy; |
1660 | 1775 | ||
1776 | adapter->link_speed = -1; | ||
1777 | |||
1661 | return 0; | 1778 | return 0; |
1662 | 1779 | ||
1663 | rx_qs_destroy: | 1780 | rx_qs_destroy: |
@@ -1678,6 +1795,8 @@ static int be_clear(struct be_adapter *adapter) | |||
1678 | 1795 | ||
1679 | be_cmd_if_destroy(adapter, adapter->if_handle); | 1796 | be_cmd_if_destroy(adapter, adapter->if_handle); |
1680 | 1797 | ||
1798 | /* tell fw we're done with firing cmds */ | ||
1799 | be_cmd_fw_clean(adapter); | ||
1681 | return 0; | 1800 | return 0; |
1682 | } | 1801 | } |
1683 | 1802 | ||
@@ -1690,6 +1809,8 @@ static int be_close(struct net_device *netdev) | |||
1690 | 1809 | ||
1691 | cancel_delayed_work_sync(&adapter->work); | 1810 | cancel_delayed_work_sync(&adapter->work); |
1692 | 1811 | ||
1812 | be_async_mcc_disable(adapter); | ||
1813 | |||
1693 | netif_stop_queue(netdev); | 1814 | netif_stop_queue(netdev); |
1694 | netif_carrier_off(netdev); | 1815 | netif_carrier_off(netdev); |
1695 | adapter->link_up = false; | 1816 | adapter->link_up = false; |
@@ -1720,103 +1841,159 @@ static int be_close(struct net_device *netdev) | |||
1720 | #define FW_FILE_HDR_SIGN "ServerEngines Corp. " | 1841 | #define FW_FILE_HDR_SIGN "ServerEngines Corp. " |
1721 | char flash_cookie[2][16] = {"*** SE FLAS", | 1842 | char flash_cookie[2][16] = {"*** SE FLAS", |
1722 | "H DIRECTORY *** "}; | 1843 | "H DIRECTORY *** "}; |
1723 | static int be_flash_image(struct be_adapter *adapter, | 1844 | |
1724 | const struct firmware *fw, | 1845 | static bool be_flash_redboot(struct be_adapter *adapter, |
1725 | struct be_dma_mem *flash_cmd, u32 flash_type) | 1846 | const u8 *p, u32 img_start, int image_size, |
1847 | int hdr_size) | ||
1726 | { | 1848 | { |
1849 | u32 crc_offset; | ||
1850 | u8 flashed_crc[4]; | ||
1727 | int status; | 1851 | int status; |
1728 | u32 flash_op, image_offset = 0, total_bytes, image_size = 0; | ||
1729 | int num_bytes; | ||
1730 | const u8 *p = fw->data; | ||
1731 | struct be_cmd_write_flashrom *req = flash_cmd->va; | ||
1732 | 1852 | ||
1733 | switch (flash_type) { | 1853 | crc_offset = hdr_size + img_start + image_size - 4; |
1734 | case FLASHROM_TYPE_ISCSI_ACTIVE: | ||
1735 | image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START; | ||
1736 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1737 | break; | ||
1738 | case FLASHROM_TYPE_ISCSI_BACKUP: | ||
1739 | image_offset = FLASH_iSCSI_BACKUP_IMAGE_START; | ||
1740 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1741 | break; | ||
1742 | case FLASHROM_TYPE_FCOE_FW_ACTIVE: | ||
1743 | image_offset = FLASH_FCoE_PRIMARY_IMAGE_START; | ||
1744 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1745 | break; | ||
1746 | case FLASHROM_TYPE_FCOE_FW_BACKUP: | ||
1747 | image_offset = FLASH_FCoE_BACKUP_IMAGE_START; | ||
1748 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1749 | break; | ||
1750 | case FLASHROM_TYPE_BIOS: | ||
1751 | image_offset = FLASH_iSCSI_BIOS_START; | ||
1752 | image_size = FLASH_BIOS_IMAGE_MAX_SIZE; | ||
1753 | break; | ||
1754 | case FLASHROM_TYPE_FCOE_BIOS: | ||
1755 | image_offset = FLASH_FCoE_BIOS_START; | ||
1756 | image_size = FLASH_BIOS_IMAGE_MAX_SIZE; | ||
1757 | break; | ||
1758 | case FLASHROM_TYPE_PXE_BIOS: | ||
1759 | image_offset = FLASH_PXE_BIOS_START; | ||
1760 | image_size = FLASH_BIOS_IMAGE_MAX_SIZE; | ||
1761 | break; | ||
1762 | default: | ||
1763 | return 0; | ||
1764 | } | ||
1765 | 1854 | ||
1766 | p += sizeof(struct flash_file_hdr) + image_offset; | 1855 | p += crc_offset; |
1767 | if (p + image_size > fw->data + fw->size) | ||
1768 | return -1; | ||
1769 | 1856 | ||
1770 | total_bytes = image_size; | 1857 | status = be_cmd_get_flash_crc(adapter, flashed_crc, |
1858 | (image_size - 4)); | ||
1859 | if (status) { | ||
1860 | dev_err(&adapter->pdev->dev, | ||
1861 | "could not get crc from flash, not flashing redboot\n"); | ||
1862 | return false; | ||
1863 | } | ||
1771 | 1864 | ||
1772 | while (total_bytes) { | 1865 | /*update redboot only if crc does not match*/ |
1773 | if (total_bytes > 32*1024) | 1866 | if (!memcmp(flashed_crc, p, 4)) |
1774 | num_bytes = 32*1024; | 1867 | return false; |
1775 | else | 1868 | else |
1776 | num_bytes = total_bytes; | 1869 | return true; |
1777 | total_bytes -= num_bytes; | 1870 | } |
1778 | 1871 | ||
1779 | if (!total_bytes) | 1872 | static int be_flash_data(struct be_adapter *adapter, |
1780 | flash_op = FLASHROM_OPER_FLASH; | 1873 | const struct firmware *fw, |
1781 | else | 1874 | struct be_dma_mem *flash_cmd, int num_of_images) |
1782 | flash_op = FLASHROM_OPER_SAVE; | 1875 | |
1783 | memcpy(req->params.data_buf, p, num_bytes); | 1876 | { |
1784 | p += num_bytes; | 1877 | int status = 0, i, filehdr_size = 0; |
1785 | status = be_cmd_write_flashrom(adapter, flash_cmd, | 1878 | u32 total_bytes = 0, flash_op; |
1786 | flash_type, flash_op, num_bytes); | 1879 | int num_bytes; |
1787 | if (status) { | 1880 | const u8 *p = fw->data; |
1788 | dev_err(&adapter->pdev->dev, | 1881 | struct be_cmd_write_flashrom *req = flash_cmd->va; |
1789 | "cmd to write to flash rom failed. type/op %d/%d\n", | 1882 | struct flash_comp *pflashcomp; |
1790 | flash_type, flash_op); | 1883 | int num_comp; |
1791 | return -1; | 1884 | |
1885 | struct flash_comp gen3_flash_types[9] = { | ||
1886 | { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, | ||
1887 | FLASH_IMAGE_MAX_SIZE_g3}, | ||
1888 | { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, | ||
1889 | FLASH_REDBOOT_IMAGE_MAX_SIZE_g3}, | ||
1890 | { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS, | ||
1891 | FLASH_BIOS_IMAGE_MAX_SIZE_g3}, | ||
1892 | { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS, | ||
1893 | FLASH_BIOS_IMAGE_MAX_SIZE_g3}, | ||
1894 | { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS, | ||
1895 | FLASH_BIOS_IMAGE_MAX_SIZE_g3}, | ||
1896 | { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP, | ||
1897 | FLASH_IMAGE_MAX_SIZE_g3}, | ||
1898 | { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, | ||
1899 | FLASH_IMAGE_MAX_SIZE_g3}, | ||
1900 | { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, | ||
1901 | FLASH_IMAGE_MAX_SIZE_g3}, | ||
1902 | { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW, | ||
1903 | FLASH_NCSI_IMAGE_MAX_SIZE_g3} | ||
1904 | }; | ||
1905 | struct flash_comp gen2_flash_types[8] = { | ||
1906 | { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, | ||
1907 | FLASH_IMAGE_MAX_SIZE_g2}, | ||
1908 | { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT, | ||
1909 | FLASH_REDBOOT_IMAGE_MAX_SIZE_g2}, | ||
1910 | { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS, | ||
1911 | FLASH_BIOS_IMAGE_MAX_SIZE_g2}, | ||
1912 | { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS, | ||
1913 | FLASH_BIOS_IMAGE_MAX_SIZE_g2}, | ||
1914 | { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS, | ||
1915 | FLASH_BIOS_IMAGE_MAX_SIZE_g2}, | ||
1916 | { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP, | ||
1917 | FLASH_IMAGE_MAX_SIZE_g2}, | ||
1918 | { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE, | ||
1919 | FLASH_IMAGE_MAX_SIZE_g2}, | ||
1920 | { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP, | ||
1921 | FLASH_IMAGE_MAX_SIZE_g2} | ||
1922 | }; | ||
1923 | |||
1924 | if (adapter->generation == BE_GEN3) { | ||
1925 | pflashcomp = gen3_flash_types; | ||
1926 | filehdr_size = sizeof(struct flash_file_hdr_g3); | ||
1927 | num_comp = 9; | ||
1928 | } else { | ||
1929 | pflashcomp = gen2_flash_types; | ||
1930 | filehdr_size = sizeof(struct flash_file_hdr_g2); | ||
1931 | num_comp = 8; | ||
1932 | } | ||
1933 | for (i = 0; i < num_comp; i++) { | ||
1934 | if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) && | ||
1935 | memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) | ||
1936 | continue; | ||
1937 | if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && | ||
1938 | (!be_flash_redboot(adapter, fw->data, | ||
1939 | pflashcomp[i].offset, pflashcomp[i].size, | ||
1940 | filehdr_size))) | ||
1941 | continue; | ||
1942 | p = fw->data; | ||
1943 | p += filehdr_size + pflashcomp[i].offset | ||
1944 | + (num_of_images * sizeof(struct image_hdr)); | ||
1945 | if (p + pflashcomp[i].size > fw->data + fw->size) | ||
1946 | return -1; | ||
1947 | total_bytes = pflashcomp[i].size; | ||
1948 | while (total_bytes) { | ||
1949 | if (total_bytes > 32*1024) | ||
1950 | num_bytes = 32*1024; | ||
1951 | else | ||
1952 | num_bytes = total_bytes; | ||
1953 | total_bytes -= num_bytes; | ||
1954 | |||
1955 | if (!total_bytes) | ||
1956 | flash_op = FLASHROM_OPER_FLASH; | ||
1957 | else | ||
1958 | flash_op = FLASHROM_OPER_SAVE; | ||
1959 | memcpy(req->params.data_buf, p, num_bytes); | ||
1960 | p += num_bytes; | ||
1961 | status = be_cmd_write_flashrom(adapter, flash_cmd, | ||
1962 | pflashcomp[i].optype, flash_op, num_bytes); | ||
1963 | if (status) { | ||
1964 | dev_err(&adapter->pdev->dev, | ||
1965 | "cmd to write to flash rom failed.\n"); | ||
1966 | return -1; | ||
1967 | } | ||
1968 | yield(); | ||
1792 | } | 1969 | } |
1793 | yield(); | ||
1794 | } | 1970 | } |
1795 | |||
1796 | return 0; | 1971 | return 0; |
1797 | } | 1972 | } |
1798 | 1973 | ||
1974 | static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) | ||
1975 | { | ||
1976 | if (fhdr == NULL) | ||
1977 | return 0; | ||
1978 | if (fhdr->build[0] == '3') | ||
1979 | return BE_GEN3; | ||
1980 | else if (fhdr->build[0] == '2') | ||
1981 | return BE_GEN2; | ||
1982 | else | ||
1983 | return 0; | ||
1984 | } | ||
1985 | |||
1799 | int be_load_fw(struct be_adapter *adapter, u8 *func) | 1986 | int be_load_fw(struct be_adapter *adapter, u8 *func) |
1800 | { | 1987 | { |
1801 | char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; | 1988 | char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; |
1802 | const struct firmware *fw; | 1989 | const struct firmware *fw; |
1803 | struct flash_file_hdr *fhdr; | 1990 | struct flash_file_hdr_g2 *fhdr; |
1804 | struct flash_section_info *fsec = NULL; | 1991 | struct flash_file_hdr_g3 *fhdr3; |
1992 | struct image_hdr *img_hdr_ptr = NULL; | ||
1805 | struct be_dma_mem flash_cmd; | 1993 | struct be_dma_mem flash_cmd; |
1806 | int status; | 1994 | int status, i = 0, num_imgs = 0; |
1807 | const u8 *p; | 1995 | const u8 *p; |
1808 | bool entry_found = false; | ||
1809 | int flash_type; | ||
1810 | char fw_ver[FW_VER_LEN]; | ||
1811 | char fw_cfg; | ||
1812 | 1996 | ||
1813 | status = be_cmd_get_fw_ver(adapter, fw_ver); | ||
1814 | if (status) | ||
1815 | return status; | ||
1816 | |||
1817 | fw_cfg = *(fw_ver + 2); | ||
1818 | if (fw_cfg == '0') | ||
1819 | fw_cfg = '1'; | ||
1820 | strcpy(fw_file, func); | 1997 | strcpy(fw_file, func); |
1821 | 1998 | ||
1822 | status = request_firmware(&fw, fw_file, &adapter->pdev->dev); | 1999 | status = request_firmware(&fw, fw_file, &adapter->pdev->dev); |
@@ -1824,34 +2001,9 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) | |||
1824 | goto fw_exit; | 2001 | goto fw_exit; |
1825 | 2002 | ||
1826 | p = fw->data; | 2003 | p = fw->data; |
1827 | fhdr = (struct flash_file_hdr *) p; | 2004 | fhdr = (struct flash_file_hdr_g2 *) p; |
1828 | if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) { | ||
1829 | dev_err(&adapter->pdev->dev, | ||
1830 | "Firmware(%s) load error (signature did not match)\n", | ||
1831 | fw_file); | ||
1832 | status = -1; | ||
1833 | goto fw_exit; | ||
1834 | } | ||
1835 | |||
1836 | dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); | 2005 | dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); |
1837 | 2006 | ||
1838 | p += sizeof(struct flash_file_hdr); | ||
1839 | while (p < (fw->data + fw->size)) { | ||
1840 | fsec = (struct flash_section_info *)p; | ||
1841 | if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) { | ||
1842 | entry_found = true; | ||
1843 | break; | ||
1844 | } | ||
1845 | p += 32; | ||
1846 | } | ||
1847 | |||
1848 | if (!entry_found) { | ||
1849 | status = -1; | ||
1850 | dev_err(&adapter->pdev->dev, | ||
1851 | "Flash cookie not found in firmware image\n"); | ||
1852 | goto fw_exit; | ||
1853 | } | ||
1854 | |||
1855 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; | 2007 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; |
1856 | flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size, | 2008 | flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size, |
1857 | &flash_cmd.dma); | 2009 | &flash_cmd.dma); |
@@ -1862,12 +2014,25 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) | |||
1862 | goto fw_exit; | 2014 | goto fw_exit; |
1863 | } | 2015 | } |
1864 | 2016 | ||
1865 | for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE; | 2017 | if ((adapter->generation == BE_GEN3) && |
1866 | flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) { | 2018 | (get_ufigen_type(fhdr) == BE_GEN3)) { |
1867 | status = be_flash_image(adapter, fw, &flash_cmd, | 2019 | fhdr3 = (struct flash_file_hdr_g3 *) fw->data; |
1868 | flash_type); | 2020 | num_imgs = le32_to_cpu(fhdr3->num_imgs); |
1869 | if (status) | 2021 | for (i = 0; i < num_imgs; i++) { |
1870 | break; | 2022 | img_hdr_ptr = (struct image_hdr *) (fw->data + |
2023 | (sizeof(struct flash_file_hdr_g3) + | ||
2024 | i * sizeof(struct image_hdr))); | ||
2025 | if (le32_to_cpu(img_hdr_ptr->imageid) == 1) | ||
2026 | status = be_flash_data(adapter, fw, &flash_cmd, | ||
2027 | num_imgs); | ||
2028 | } | ||
2029 | } else if ((adapter->generation == BE_GEN2) && | ||
2030 | (get_ufigen_type(fhdr) == BE_GEN2)) { | ||
2031 | status = be_flash_data(adapter, fw, &flash_cmd, 0); | ||
2032 | } else { | ||
2033 | dev_err(&adapter->pdev->dev, | ||
2034 | "UFI and Interface are not compatible for flashing\n"); | ||
2035 | status = -1; | ||
1871 | } | 2036 | } |
1872 | 2037 | ||
1873 | pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va, | 2038 | pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va, |
@@ -1877,7 +2042,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) | |||
1877 | goto fw_exit; | 2042 | goto fw_exit; |
1878 | } | 2043 | } |
1879 | 2044 | ||
1880 | dev_info(&adapter->pdev->dev, "Firmware flashed succesfully\n"); | 2045 | dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); |
1881 | 2046 | ||
1882 | fw_exit: | 2047 | fw_exit: |
1883 | release_firmware(fw); | 2048 | release_firmware(fw); |
@@ -1906,6 +2071,8 @@ static void be_netdev_init(struct net_device *netdev) | |||
1906 | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM | | 2071 | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM | |
1907 | NETIF_F_GRO; | 2072 | NETIF_F_GRO; |
1908 | 2073 | ||
2074 | netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM; | ||
2075 | |||
1909 | netdev->flags |= IFF_MULTICAST; | 2076 | netdev->flags |= IFF_MULTICAST; |
1910 | 2077 | ||
1911 | adapter->rx_csum = true; | 2078 | adapter->rx_csum = true; |
@@ -1942,6 +2109,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) | |||
1942 | static int be_map_pci_bars(struct be_adapter *adapter) | 2109 | static int be_map_pci_bars(struct be_adapter *adapter) |
1943 | { | 2110 | { |
1944 | u8 __iomem *addr; | 2111 | u8 __iomem *addr; |
2112 | int pcicfg_reg; | ||
1945 | 2113 | ||
1946 | addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), | 2114 | addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), |
1947 | pci_resource_len(adapter->pdev, 2)); | 2115 | pci_resource_len(adapter->pdev, 2)); |
@@ -1955,8 +2123,13 @@ static int be_map_pci_bars(struct be_adapter *adapter) | |||
1955 | goto pci_map_err; | 2123 | goto pci_map_err; |
1956 | adapter->db = addr; | 2124 | adapter->db = addr; |
1957 | 2125 | ||
1958 | addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), | 2126 | if (adapter->generation == BE_GEN2) |
1959 | pci_resource_len(adapter->pdev, 1)); | 2127 | pcicfg_reg = 1; |
2128 | else | ||
2129 | pcicfg_reg = 0; | ||
2130 | |||
2131 | addr = ioremap_nocache(pci_resource_start(adapter->pdev, pcicfg_reg), | ||
2132 | pci_resource_len(adapter->pdev, pcicfg_reg)); | ||
1960 | if (addr == NULL) | 2133 | if (addr == NULL) |
1961 | goto pci_map_err; | 2134 | goto pci_map_err; |
1962 | adapter->pcicfg = addr; | 2135 | adapter->pcicfg = addr; |
@@ -1977,34 +2150,62 @@ static void be_ctrl_cleanup(struct be_adapter *adapter) | |||
1977 | if (mem->va) | 2150 | if (mem->va) |
1978 | pci_free_consistent(adapter->pdev, mem->size, | 2151 | pci_free_consistent(adapter->pdev, mem->size, |
1979 | mem->va, mem->dma); | 2152 | mem->va, mem->dma); |
2153 | |||
2154 | mem = &adapter->mc_cmd_mem; | ||
2155 | if (mem->va) | ||
2156 | pci_free_consistent(adapter->pdev, mem->size, | ||
2157 | mem->va, mem->dma); | ||
1980 | } | 2158 | } |
1981 | 2159 | ||
1982 | static int be_ctrl_init(struct be_adapter *adapter) | 2160 | static int be_ctrl_init(struct be_adapter *adapter) |
1983 | { | 2161 | { |
1984 | struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; | 2162 | struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; |
1985 | struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; | 2163 | struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; |
2164 | struct be_dma_mem *mc_cmd_mem = &adapter->mc_cmd_mem; | ||
1986 | int status; | 2165 | int status; |
1987 | 2166 | ||
1988 | status = be_map_pci_bars(adapter); | 2167 | status = be_map_pci_bars(adapter); |
1989 | if (status) | 2168 | if (status) |
1990 | return status; | 2169 | goto done; |
1991 | 2170 | ||
1992 | mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; | 2171 | mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; |
1993 | mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev, | 2172 | mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev, |
1994 | mbox_mem_alloc->size, &mbox_mem_alloc->dma); | 2173 | mbox_mem_alloc->size, &mbox_mem_alloc->dma); |
1995 | if (!mbox_mem_alloc->va) { | 2174 | if (!mbox_mem_alloc->va) { |
1996 | be_unmap_pci_bars(adapter); | 2175 | status = -ENOMEM; |
1997 | return -1; | 2176 | goto unmap_pci_bars; |
1998 | } | 2177 | } |
2178 | |||
1999 | mbox_mem_align->size = sizeof(struct be_mcc_mailbox); | 2179 | mbox_mem_align->size = sizeof(struct be_mcc_mailbox); |
2000 | mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); | 2180 | mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); |
2001 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); | 2181 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); |
2002 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); | 2182 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); |
2183 | |||
2184 | mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config); | ||
2185 | mc_cmd_mem->va = pci_alloc_consistent(adapter->pdev, mc_cmd_mem->size, | ||
2186 | &mc_cmd_mem->dma); | ||
2187 | if (mc_cmd_mem->va == NULL) { | ||
2188 | status = -ENOMEM; | ||
2189 | goto free_mbox; | ||
2190 | } | ||
2191 | memset(mc_cmd_mem->va, 0, mc_cmd_mem->size); | ||
2192 | |||
2003 | spin_lock_init(&adapter->mbox_lock); | 2193 | spin_lock_init(&adapter->mbox_lock); |
2004 | spin_lock_init(&adapter->mcc_lock); | 2194 | spin_lock_init(&adapter->mcc_lock); |
2005 | spin_lock_init(&adapter->mcc_cq_lock); | 2195 | spin_lock_init(&adapter->mcc_cq_lock); |
2006 | 2196 | ||
2197 | pci_save_state(adapter->pdev); | ||
2007 | return 0; | 2198 | return 0; |
2199 | |||
2200 | free_mbox: | ||
2201 | pci_free_consistent(adapter->pdev, mbox_mem_alloc->size, | ||
2202 | mbox_mem_alloc->va, mbox_mem_alloc->dma); | ||
2203 | |||
2204 | unmap_pci_bars: | ||
2205 | be_unmap_pci_bars(adapter); | ||
2206 | |||
2207 | done: | ||
2208 | return status; | ||
2008 | } | 2209 | } |
2009 | 2210 | ||
2010 | static void be_stats_cleanup(struct be_adapter *adapter) | 2211 | static void be_stats_cleanup(struct be_adapter *adapter) |
@@ -2026,12 +2227,14 @@ static int be_stats_init(struct be_adapter *adapter) | |||
2026 | cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); | 2227 | cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); |
2027 | if (cmd->va == NULL) | 2228 | if (cmd->va == NULL) |
2028 | return -1; | 2229 | return -1; |
2230 | memset(cmd->va, 0, cmd->size); | ||
2029 | return 0; | 2231 | return 0; |
2030 | } | 2232 | } |
2031 | 2233 | ||
2032 | static void __devexit be_remove(struct pci_dev *pdev) | 2234 | static void __devexit be_remove(struct pci_dev *pdev) |
2033 | { | 2235 | { |
2034 | struct be_adapter *adapter = pci_get_drvdata(pdev); | 2236 | struct be_adapter *adapter = pci_get_drvdata(pdev); |
2237 | |||
2035 | if (!adapter) | 2238 | if (!adapter) |
2036 | return; | 2239 | return; |
2037 | 2240 | ||
@@ -2043,10 +2246,7 @@ static void __devexit be_remove(struct pci_dev *pdev) | |||
2043 | 2246 | ||
2044 | be_ctrl_cleanup(adapter); | 2247 | be_ctrl_cleanup(adapter); |
2045 | 2248 | ||
2046 | if (adapter->msix_enabled) { | 2249 | be_msix_disable(adapter); |
2047 | pci_disable_msix(adapter->pdev); | ||
2048 | adapter->msix_enabled = false; | ||
2049 | } | ||
2050 | 2250 | ||
2051 | pci_set_drvdata(pdev, NULL); | 2251 | pci_set_drvdata(pdev, NULL); |
2052 | pci_release_regions(pdev); | 2252 | pci_release_regions(pdev); |
@@ -2055,25 +2255,38 @@ static void __devexit be_remove(struct pci_dev *pdev) | |||
2055 | free_netdev(adapter->netdev); | 2255 | free_netdev(adapter->netdev); |
2056 | } | 2256 | } |
2057 | 2257 | ||
2058 | static int be_hw_up(struct be_adapter *adapter) | 2258 | static int be_get_config(struct be_adapter *adapter) |
2059 | { | 2259 | { |
2060 | int status; | 2260 | int status; |
2261 | u8 mac[ETH_ALEN]; | ||
2061 | 2262 | ||
2062 | status = be_cmd_POST(adapter); | 2263 | status = be_cmd_get_fw_ver(adapter, adapter->fw_ver); |
2063 | if (status) | 2264 | if (status) |
2064 | return status; | 2265 | return status; |
2065 | 2266 | ||
2066 | status = be_cmd_reset_function(adapter); | 2267 | status = be_cmd_query_fw_cfg(adapter, |
2268 | &adapter->port_num, &adapter->cap); | ||
2067 | if (status) | 2269 | if (status) |
2068 | return status; | 2270 | return status; |
2069 | 2271 | ||
2070 | status = be_cmd_get_fw_ver(adapter, adapter->fw_ver); | 2272 | memset(mac, 0, ETH_ALEN); |
2273 | status = be_cmd_mac_addr_query(adapter, mac, | ||
2274 | MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0); | ||
2071 | if (status) | 2275 | if (status) |
2072 | return status; | 2276 | return status; |
2073 | 2277 | ||
2074 | status = be_cmd_query_fw_cfg(adapter, | 2278 | if (!is_valid_ether_addr(mac)) |
2075 | &adapter->port_num, &adapter->cap); | 2279 | return -EADDRNOTAVAIL; |
2076 | return status; | 2280 | |
2281 | memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); | ||
2282 | memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); | ||
2283 | |||
2284 | if (adapter->cap & 0x400) | ||
2285 | adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; | ||
2286 | else | ||
2287 | adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; | ||
2288 | |||
2289 | return 0; | ||
2077 | } | 2290 | } |
2078 | 2291 | ||
2079 | static int __devinit be_probe(struct pci_dev *pdev, | 2292 | static int __devinit be_probe(struct pci_dev *pdev, |
@@ -2082,7 +2295,6 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
2082 | int status = 0; | 2295 | int status = 0; |
2083 | struct be_adapter *adapter; | 2296 | struct be_adapter *adapter; |
2084 | struct net_device *netdev; | 2297 | struct net_device *netdev; |
2085 | u8 mac[ETH_ALEN]; | ||
2086 | 2298 | ||
2087 | status = pci_enable_device(pdev); | 2299 | status = pci_enable_device(pdev); |
2088 | if (status) | 2300 | if (status) |
@@ -2099,9 +2311,25 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
2099 | goto rel_reg; | 2311 | goto rel_reg; |
2100 | } | 2312 | } |
2101 | adapter = netdev_priv(netdev); | 2313 | adapter = netdev_priv(netdev); |
2314 | |||
2315 | switch (pdev->device) { | ||
2316 | case BE_DEVICE_ID1: | ||
2317 | case OC_DEVICE_ID1: | ||
2318 | adapter->generation = BE_GEN2; | ||
2319 | break; | ||
2320 | case BE_DEVICE_ID2: | ||
2321 | case OC_DEVICE_ID2: | ||
2322 | adapter->generation = BE_GEN3; | ||
2323 | break; | ||
2324 | default: | ||
2325 | adapter->generation = 0; | ||
2326 | } | ||
2327 | |||
2102 | adapter->pdev = pdev; | 2328 | adapter->pdev = pdev; |
2103 | pci_set_drvdata(pdev, adapter); | 2329 | pci_set_drvdata(pdev, adapter); |
2104 | adapter->netdev = netdev; | 2330 | adapter->netdev = netdev; |
2331 | be_netdev_init(netdev); | ||
2332 | SET_NETDEV_DEV(netdev, &pdev->dev); | ||
2105 | 2333 | ||
2106 | be_msix_enable(adapter); | 2334 | be_msix_enable(adapter); |
2107 | 2335 | ||
@@ -2120,27 +2348,34 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
2120 | if (status) | 2348 | if (status) |
2121 | goto free_netdev; | 2349 | goto free_netdev; |
2122 | 2350 | ||
2123 | status = be_stats_init(adapter); | 2351 | /* sync up with fw's ready state */ |
2352 | status = be_cmd_POST(adapter); | ||
2124 | if (status) | 2353 | if (status) |
2125 | goto ctrl_clean; | 2354 | goto ctrl_clean; |
2126 | 2355 | ||
2127 | status = be_hw_up(adapter); | 2356 | /* tell fw we're ready to fire cmds */ |
2357 | status = be_cmd_fw_init(adapter); | ||
2128 | if (status) | 2358 | if (status) |
2129 | goto stats_clean; | 2359 | goto ctrl_clean; |
2360 | |||
2361 | status = be_cmd_reset_function(adapter); | ||
2362 | if (status) | ||
2363 | goto ctrl_clean; | ||
2364 | |||
2365 | status = be_stats_init(adapter); | ||
2366 | if (status) | ||
2367 | goto ctrl_clean; | ||
2130 | 2368 | ||
2131 | status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, | 2369 | status = be_get_config(adapter); |
2132 | true /* permanent */, 0); | ||
2133 | if (status) | 2370 | if (status) |
2134 | goto stats_clean; | 2371 | goto stats_clean; |
2135 | memcpy(netdev->dev_addr, mac, ETH_ALEN); | ||
2136 | 2372 | ||
2137 | INIT_DELAYED_WORK(&adapter->work, be_worker); | 2373 | INIT_DELAYED_WORK(&adapter->work, be_worker); |
2138 | be_netdev_init(netdev); | ||
2139 | SET_NETDEV_DEV(netdev, &adapter->pdev->dev); | ||
2140 | 2374 | ||
2141 | status = be_setup(adapter); | 2375 | status = be_setup(adapter); |
2142 | if (status) | 2376 | if (status) |
2143 | goto stats_clean; | 2377 | goto stats_clean; |
2378 | |||
2144 | status = register_netdev(netdev); | 2379 | status = register_netdev(netdev); |
2145 | if (status != 0) | 2380 | if (status != 0) |
2146 | goto unsetup; | 2381 | goto unsetup; |
@@ -2155,7 +2390,9 @@ stats_clean: | |||
2155 | ctrl_clean: | 2390 | ctrl_clean: |
2156 | be_ctrl_cleanup(adapter); | 2391 | be_ctrl_cleanup(adapter); |
2157 | free_netdev: | 2392 | free_netdev: |
2393 | be_msix_disable(adapter); | ||
2158 | free_netdev(adapter->netdev); | 2394 | free_netdev(adapter->netdev); |
2395 | pci_set_drvdata(pdev, NULL); | ||
2159 | rel_reg: | 2396 | rel_reg: |
2160 | pci_release_regions(pdev); | 2397 | pci_release_regions(pdev); |
2161 | disable_dev: | 2398 | disable_dev: |
@@ -2170,6 +2407,9 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2170 | struct be_adapter *adapter = pci_get_drvdata(pdev); | 2407 | struct be_adapter *adapter = pci_get_drvdata(pdev); |
2171 | struct net_device *netdev = adapter->netdev; | 2408 | struct net_device *netdev = adapter->netdev; |
2172 | 2409 | ||
2410 | if (adapter->wol) | ||
2411 | be_setup_wol(adapter, true); | ||
2412 | |||
2173 | netif_device_detach(netdev); | 2413 | netif_device_detach(netdev); |
2174 | if (netif_running(netdev)) { | 2414 | if (netif_running(netdev)) { |
2175 | rtnl_lock(); | 2415 | rtnl_lock(); |
@@ -2200,6 +2440,11 @@ static int be_resume(struct pci_dev *pdev) | |||
2200 | pci_set_power_state(pdev, 0); | 2440 | pci_set_power_state(pdev, 0); |
2201 | pci_restore_state(pdev); | 2441 | pci_restore_state(pdev); |
2202 | 2442 | ||
2443 | /* tell fw we're ready to fire cmds */ | ||
2444 | status = be_cmd_fw_init(adapter); | ||
2445 | if (status) | ||
2446 | return status; | ||
2447 | |||
2203 | be_setup(adapter); | 2448 | be_setup(adapter); |
2204 | if (netif_running(netdev)) { | 2449 | if (netif_running(netdev)) { |
2205 | rtnl_lock(); | 2450 | rtnl_lock(); |
@@ -2207,22 +2452,135 @@ static int be_resume(struct pci_dev *pdev) | |||
2207 | rtnl_unlock(); | 2452 | rtnl_unlock(); |
2208 | } | 2453 | } |
2209 | netif_device_attach(netdev); | 2454 | netif_device_attach(netdev); |
2455 | |||
2456 | if (adapter->wol) | ||
2457 | be_setup_wol(adapter, false); | ||
2210 | return 0; | 2458 | return 0; |
2211 | } | 2459 | } |
2212 | 2460 | ||
2461 | /* | ||
2462 | * An FLR will stop BE from DMAing any data. | ||
2463 | */ | ||
2464 | static void be_shutdown(struct pci_dev *pdev) | ||
2465 | { | ||
2466 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2467 | struct net_device *netdev = adapter->netdev; | ||
2468 | |||
2469 | netif_device_detach(netdev); | ||
2470 | |||
2471 | be_cmd_reset_function(adapter); | ||
2472 | |||
2473 | if (adapter->wol) | ||
2474 | be_setup_wol(adapter, true); | ||
2475 | |||
2476 | pci_disable_device(pdev); | ||
2477 | |||
2478 | return; | ||
2479 | } | ||
2480 | |||
2481 | static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, | ||
2482 | pci_channel_state_t state) | ||
2483 | { | ||
2484 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2485 | struct net_device *netdev = adapter->netdev; | ||
2486 | |||
2487 | dev_err(&adapter->pdev->dev, "EEH error detected\n"); | ||
2488 | |||
2489 | adapter->eeh_err = true; | ||
2490 | |||
2491 | netif_device_detach(netdev); | ||
2492 | |||
2493 | if (netif_running(netdev)) { | ||
2494 | rtnl_lock(); | ||
2495 | be_close(netdev); | ||
2496 | rtnl_unlock(); | ||
2497 | } | ||
2498 | be_clear(adapter); | ||
2499 | |||
2500 | if (state == pci_channel_io_perm_failure) | ||
2501 | return PCI_ERS_RESULT_DISCONNECT; | ||
2502 | |||
2503 | pci_disable_device(pdev); | ||
2504 | |||
2505 | return PCI_ERS_RESULT_NEED_RESET; | ||
2506 | } | ||
2507 | |||
2508 | static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) | ||
2509 | { | ||
2510 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2511 | int status; | ||
2512 | |||
2513 | dev_info(&adapter->pdev->dev, "EEH reset\n"); | ||
2514 | adapter->eeh_err = false; | ||
2515 | |||
2516 | status = pci_enable_device(pdev); | ||
2517 | if (status) | ||
2518 | return PCI_ERS_RESULT_DISCONNECT; | ||
2519 | |||
2520 | pci_set_master(pdev); | ||
2521 | pci_set_power_state(pdev, 0); | ||
2522 | pci_restore_state(pdev); | ||
2523 | |||
2524 | /* Check if card is ok and fw is ready */ | ||
2525 | status = be_cmd_POST(adapter); | ||
2526 | if (status) | ||
2527 | return PCI_ERS_RESULT_DISCONNECT; | ||
2528 | |||
2529 | return PCI_ERS_RESULT_RECOVERED; | ||
2530 | } | ||
2531 | |||
2532 | static void be_eeh_resume(struct pci_dev *pdev) | ||
2533 | { | ||
2534 | int status = 0; | ||
2535 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2536 | struct net_device *netdev = adapter->netdev; | ||
2537 | |||
2538 | dev_info(&adapter->pdev->dev, "EEH resume\n"); | ||
2539 | |||
2540 | pci_save_state(pdev); | ||
2541 | |||
2542 | /* tell fw we're ready to fire cmds */ | ||
2543 | status = be_cmd_fw_init(adapter); | ||
2544 | if (status) | ||
2545 | goto err; | ||
2546 | |||
2547 | status = be_setup(adapter); | ||
2548 | if (status) | ||
2549 | goto err; | ||
2550 | |||
2551 | if (netif_running(netdev)) { | ||
2552 | status = be_open(netdev); | ||
2553 | if (status) | ||
2554 | goto err; | ||
2555 | } | ||
2556 | netif_device_attach(netdev); | ||
2557 | return; | ||
2558 | err: | ||
2559 | dev_err(&adapter->pdev->dev, "EEH resume failed\n"); | ||
2560 | return; | ||
2561 | } | ||
2562 | |||
2563 | static struct pci_error_handlers be_eeh_handlers = { | ||
2564 | .error_detected = be_eeh_err_detected, | ||
2565 | .slot_reset = be_eeh_reset, | ||
2566 | .resume = be_eeh_resume, | ||
2567 | }; | ||
2568 | |||
2213 | static struct pci_driver be_driver = { | 2569 | static struct pci_driver be_driver = { |
2214 | .name = DRV_NAME, | 2570 | .name = DRV_NAME, |
2215 | .id_table = be_dev_ids, | 2571 | .id_table = be_dev_ids, |
2216 | .probe = be_probe, | 2572 | .probe = be_probe, |
2217 | .remove = be_remove, | 2573 | .remove = be_remove, |
2218 | .suspend = be_suspend, | 2574 | .suspend = be_suspend, |
2219 | .resume = be_resume | 2575 | .resume = be_resume, |
2576 | .shutdown = be_shutdown, | ||
2577 | .err_handler = &be_eeh_handlers | ||
2220 | }; | 2578 | }; |
2221 | 2579 | ||
2222 | static int __init be_init_module(void) | 2580 | static int __init be_init_module(void) |
2223 | { | 2581 | { |
2224 | if (rx_frag_size != 8192 && rx_frag_size != 4096 | 2582 | if (rx_frag_size != 8192 && rx_frag_size != 4096 && |
2225 | && rx_frag_size != 2048) { | 2583 | rx_frag_size != 2048) { |
2226 | printk(KERN_WARNING DRV_NAME | 2584 | printk(KERN_WARNING DRV_NAME |
2227 | " : Module param rx_frag_size must be 2048/4096/8192." | 2585 | " : Module param rx_frag_size must be 2048/4096/8192." |
2228 | " Using 2048\n"); | 2586 | " Using 2048\n"); |