diff options
Diffstat (limited to 'drivers/net/benet/be_cmds.c')
-rw-r--r-- | drivers/net/benet/be_cmds.c | 368 |
1 files changed, 285 insertions, 83 deletions
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index d444aed962bc..583517ed56f0 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
@@ -17,6 +17,133 @@ | |||
17 | 17 | ||
18 | #include "be.h" | 18 | #include "be.h" |
19 | 19 | ||
20 | static void be_mcc_notify(struct be_ctrl_info *ctrl) | ||
21 | { | ||
22 | struct be_queue_info *mccq = &ctrl->mcc_obj.q; | ||
23 | u32 val = 0; | ||
24 | |||
25 | val |= mccq->id & DB_MCCQ_RING_ID_MASK; | ||
26 | val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; | ||
27 | iowrite32(val, ctrl->db + DB_MCCQ_OFFSET); | ||
28 | } | ||
29 | |||
30 | /* To check if valid bit is set, check the entire word as we don't know | ||
31 | * the endianness of the data (old entry is host endian while a new entry is | ||
32 | * little endian) */ | ||
33 | static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl) | ||
34 | { | ||
35 | if (compl->flags != 0) { | ||
36 | compl->flags = le32_to_cpu(compl->flags); | ||
37 | BUG_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); | ||
38 | return true; | ||
39 | } else { | ||
40 | return false; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | /* Need to reset the entire word that houses the valid bit */ | ||
45 | static inline void be_mcc_compl_use(struct be_mcc_cq_entry *compl) | ||
46 | { | ||
47 | compl->flags = 0; | ||
48 | } | ||
49 | |||
50 | static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | ||
51 | struct be_mcc_cq_entry *compl) | ||
52 | { | ||
53 | u16 compl_status, extd_status; | ||
54 | |||
55 | /* Just swap the status to host endian; mcc tag is opaquely copied | ||
56 | * from mcc_wrb */ | ||
57 | be_dws_le_to_cpu(compl, 4); | ||
58 | |||
59 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | ||
60 | CQE_STATUS_COMPL_MASK; | ||
61 | if (compl_status != MCC_STATUS_SUCCESS) { | ||
62 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | ||
63 | CQE_STATUS_EXTD_MASK; | ||
64 | printk(KERN_WARNING DRV_NAME | ||
65 | " error in cmd completion: status(compl/extd)=%d/%d\n", | ||
66 | compl_status, extd_status); | ||
67 | return -1; | ||
68 | } | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /* Link state evt is a string of bytes; no need for endian swapping */ | ||
73 | static void be_async_link_state_process(struct be_ctrl_info *ctrl, | ||
74 | struct be_async_event_link_state *evt) | ||
75 | { | ||
76 | ctrl->async_cb(ctrl->adapter_ctxt, | ||
77 | evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false); | ||
78 | } | ||
79 | |||
80 | static inline bool is_link_state_evt(u32 trailer) | ||
81 | { | ||
82 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | ||
83 | ASYNC_TRAILER_EVENT_CODE_MASK) == | ||
84 | ASYNC_EVENT_CODE_LINK_STATE); | ||
85 | } | ||
86 | |||
87 | static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl) | ||
88 | { | ||
89 | struct be_queue_info *mcc_cq = &ctrl->mcc_obj.cq; | ||
90 | struct be_mcc_cq_entry *compl = queue_tail_node(mcc_cq); | ||
91 | |||
92 | if (be_mcc_compl_is_new(compl)) { | ||
93 | queue_tail_inc(mcc_cq); | ||
94 | return compl; | ||
95 | } | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | void be_process_mcc(struct be_ctrl_info *ctrl) | ||
100 | { | ||
101 | struct be_mcc_cq_entry *compl; | ||
102 | int num = 0; | ||
103 | |||
104 | spin_lock_bh(&ctrl->mcc_cq_lock); | ||
105 | while ((compl = be_mcc_compl_get(ctrl))) { | ||
106 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { | ||
107 | /* Interpret flags as an async trailer */ | ||
108 | BUG_ON(!is_link_state_evt(compl->flags)); | ||
109 | |||
110 | /* Interpret compl as a async link evt */ | ||
111 | be_async_link_state_process(ctrl, | ||
112 | (struct be_async_event_link_state *) compl); | ||
113 | } else { | ||
114 | be_mcc_compl_process(ctrl, compl); | ||
115 | atomic_dec(&ctrl->mcc_obj.q.used); | ||
116 | } | ||
117 | be_mcc_compl_use(compl); | ||
118 | num++; | ||
119 | } | ||
120 | if (num) | ||
121 | be_cq_notify(ctrl, ctrl->mcc_obj.cq.id, true, num); | ||
122 | spin_unlock_bh(&ctrl->mcc_cq_lock); | ||
123 | } | ||
124 | |||
125 | /* Wait till no more pending mcc requests are present */ | ||
126 | static void be_mcc_wait_compl(struct be_ctrl_info *ctrl) | ||
127 | { | ||
128 | #define mcc_timeout 50000 /* 5s timeout */ | ||
129 | int i; | ||
130 | for (i = 0; i < mcc_timeout; i++) { | ||
131 | be_process_mcc(ctrl); | ||
132 | if (atomic_read(&ctrl->mcc_obj.q.used) == 0) | ||
133 | break; | ||
134 | udelay(100); | ||
135 | } | ||
136 | if (i == mcc_timeout) | ||
137 | printk(KERN_WARNING DRV_NAME "mcc poll timed out\n"); | ||
138 | } | ||
139 | |||
140 | /* Notify MCC requests and wait for completion */ | ||
141 | static void be_mcc_notify_wait(struct be_ctrl_info *ctrl) | ||
142 | { | ||
143 | be_mcc_notify(ctrl); | ||
144 | be_mcc_wait_compl(ctrl); | ||
145 | } | ||
146 | |||
20 | static int be_mbox_db_ready_wait(void __iomem *db) | 147 | static int be_mbox_db_ready_wait(void __iomem *db) |
21 | { | 148 | { |
22 | int cnt = 0, wait = 5; | 149 | int cnt = 0, wait = 5; |
@@ -44,11 +171,11 @@ static int be_mbox_db_ready_wait(void __iomem *db) | |||
44 | 171 | ||
45 | /* | 172 | /* |
46 | * Insert the mailbox address into the doorbell in two steps | 173 | * Insert the mailbox address into the doorbell in two steps |
174 | * Polls on the mbox doorbell till a command completion (or a timeout) occurs | ||
47 | */ | 175 | */ |
48 | static int be_mbox_db_ring(struct be_ctrl_info *ctrl) | 176 | static int be_mbox_db_ring(struct be_ctrl_info *ctrl) |
49 | { | 177 | { |
50 | int status; | 178 | int status; |
51 | u16 compl_status, extd_status; | ||
52 | u32 val = 0; | 179 | u32 val = 0; |
53 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | 180 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; |
54 | struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; | 181 | struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; |
@@ -79,24 +206,17 @@ static int be_mbox_db_ring(struct be_ctrl_info *ctrl) | |||
79 | if (status != 0) | 206 | if (status != 0) |
80 | return status; | 207 | return status; |
81 | 208 | ||
82 | /* compl entry has been made now */ | 209 | /* A cq entry has been made now */ |
83 | be_dws_le_to_cpu(cqe, sizeof(*cqe)); | 210 | if (be_mcc_compl_is_new(cqe)) { |
84 | if (!(cqe->flags & CQE_FLAGS_VALID_MASK)) { | 211 | status = be_mcc_compl_process(ctrl, &mbox->cqe); |
85 | printk(KERN_WARNING DRV_NAME ": ERROR invalid mbox compl\n"); | 212 | be_mcc_compl_use(cqe); |
213 | if (status) | ||
214 | return status; | ||
215 | } else { | ||
216 | printk(KERN_WARNING DRV_NAME "invalid mailbox completion\n"); | ||
86 | return -1; | 217 | return -1; |
87 | } | 218 | } |
88 | 219 | return 0; | |
89 | compl_status = (cqe->status >> CQE_STATUS_COMPL_SHIFT) & | ||
90 | CQE_STATUS_COMPL_MASK; | ||
91 | if (compl_status != MCC_STATUS_SUCCESS) { | ||
92 | extd_status = (cqe->status >> CQE_STATUS_EXTD_SHIFT) & | ||
93 | CQE_STATUS_EXTD_MASK; | ||
94 | printk(KERN_WARNING DRV_NAME | ||
95 | ": ERROR in cmd compl. status(compl/extd)=%d/%d\n", | ||
96 | compl_status, extd_status); | ||
97 | } | ||
98 | |||
99 | return compl_status; | ||
100 | } | 220 | } |
101 | 221 | ||
102 | static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) | 222 | static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) |
@@ -235,6 +355,18 @@ static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) | |||
235 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; | 355 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; |
236 | } | 356 | } |
237 | 357 | ||
358 | static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq) | ||
359 | { | ||
360 | struct be_mcc_wrb *wrb = NULL; | ||
361 | if (atomic_read(&mccq->used) < mccq->len) { | ||
362 | wrb = queue_head_node(mccq); | ||
363 | queue_head_inc(mccq); | ||
364 | atomic_inc(&mccq->used); | ||
365 | memset(wrb, 0, sizeof(*wrb)); | ||
366 | } | ||
367 | return wrb; | ||
368 | } | ||
369 | |||
238 | int be_cmd_eq_create(struct be_ctrl_info *ctrl, | 370 | int be_cmd_eq_create(struct be_ctrl_info *ctrl, |
239 | struct be_queue_info *eq, int eq_delay) | 371 | struct be_queue_info *eq, int eq_delay) |
240 | { | 372 | { |
@@ -244,7 +376,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl, | |||
244 | struct be_dma_mem *q_mem = &eq->dma_mem; | 376 | struct be_dma_mem *q_mem = &eq->dma_mem; |
245 | int status; | 377 | int status; |
246 | 378 | ||
247 | spin_lock(&ctrl->cmd_lock); | 379 | spin_lock(&ctrl->mbox_lock); |
248 | memset(wrb, 0, sizeof(*wrb)); | 380 | memset(wrb, 0, sizeof(*wrb)); |
249 | 381 | ||
250 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 382 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -272,7 +404,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl, | |||
272 | eq->id = le16_to_cpu(resp->eq_id); | 404 | eq->id = le16_to_cpu(resp->eq_id); |
273 | eq->created = true; | 405 | eq->created = true; |
274 | } | 406 | } |
275 | spin_unlock(&ctrl->cmd_lock); | 407 | spin_unlock(&ctrl->mbox_lock); |
276 | return status; | 408 | return status; |
277 | } | 409 | } |
278 | 410 | ||
@@ -284,7 +416,7 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
284 | struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); | 416 | struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); |
285 | int status; | 417 | int status; |
286 | 418 | ||
287 | spin_lock(&ctrl->cmd_lock); | 419 | spin_lock(&ctrl->mbox_lock); |
288 | memset(wrb, 0, sizeof(*wrb)); | 420 | memset(wrb, 0, sizeof(*wrb)); |
289 | 421 | ||
290 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 422 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -304,7 +436,7 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
304 | if (!status) | 436 | if (!status) |
305 | memcpy(mac_addr, resp->mac.addr, ETH_ALEN); | 437 | memcpy(mac_addr, resp->mac.addr, ETH_ALEN); |
306 | 438 | ||
307 | spin_unlock(&ctrl->cmd_lock); | 439 | spin_unlock(&ctrl->mbox_lock); |
308 | return status; | 440 | return status; |
309 | } | 441 | } |
310 | 442 | ||
@@ -315,7 +447,7 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
315 | struct be_cmd_req_pmac_add *req = embedded_payload(wrb); | 447 | struct be_cmd_req_pmac_add *req = embedded_payload(wrb); |
316 | int status; | 448 | int status; |
317 | 449 | ||
318 | spin_lock(&ctrl->cmd_lock); | 450 | spin_lock(&ctrl->mbox_lock); |
319 | memset(wrb, 0, sizeof(*wrb)); | 451 | memset(wrb, 0, sizeof(*wrb)); |
320 | 452 | ||
321 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 453 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -332,7 +464,7 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, | |||
332 | *pmac_id = le32_to_cpu(resp->pmac_id); | 464 | *pmac_id = le32_to_cpu(resp->pmac_id); |
333 | } | 465 | } |
334 | 466 | ||
335 | spin_unlock(&ctrl->cmd_lock); | 467 | spin_unlock(&ctrl->mbox_lock); |
336 | return status; | 468 | return status; |
337 | } | 469 | } |
338 | 470 | ||
@@ -342,7 +474,7 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) | |||
342 | struct be_cmd_req_pmac_del *req = embedded_payload(wrb); | 474 | struct be_cmd_req_pmac_del *req = embedded_payload(wrb); |
343 | int status; | 475 | int status; |
344 | 476 | ||
345 | spin_lock(&ctrl->cmd_lock); | 477 | spin_lock(&ctrl->mbox_lock); |
346 | memset(wrb, 0, sizeof(*wrb)); | 478 | memset(wrb, 0, sizeof(*wrb)); |
347 | 479 | ||
348 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 480 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -354,7 +486,7 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) | |||
354 | req->pmac_id = cpu_to_le32(pmac_id); | 486 | req->pmac_id = cpu_to_le32(pmac_id); |
355 | 487 | ||
356 | status = be_mbox_db_ring(ctrl); | 488 | status = be_mbox_db_ring(ctrl); |
357 | spin_unlock(&ctrl->cmd_lock); | 489 | spin_unlock(&ctrl->mbox_lock); |
358 | 490 | ||
359 | return status; | 491 | return status; |
360 | } | 492 | } |
@@ -370,7 +502,7 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
370 | void *ctxt = &req->context; | 502 | void *ctxt = &req->context; |
371 | int status; | 503 | int status; |
372 | 504 | ||
373 | spin_lock(&ctrl->cmd_lock); | 505 | spin_lock(&ctrl->mbox_lock); |
374 | memset(wrb, 0, sizeof(*wrb)); | 506 | memset(wrb, 0, sizeof(*wrb)); |
375 | 507 | ||
376 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 508 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -388,7 +520,7 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
388 | AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); | 520 | AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); |
389 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); | 521 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); |
390 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); | 522 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); |
391 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 0); | 523 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); |
392 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); | 524 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); |
393 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 525 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); |
394 | 526 | ||
@@ -399,7 +531,56 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
399 | cq->id = le16_to_cpu(resp->cq_id); | 531 | cq->id = le16_to_cpu(resp->cq_id); |
400 | cq->created = true; | 532 | cq->created = true; |
401 | } | 533 | } |
402 | spin_unlock(&ctrl->cmd_lock); | 534 | spin_unlock(&ctrl->mbox_lock); |
535 | |||
536 | return status; | ||
537 | } | ||
538 | |||
539 | static u32 be_encoded_q_len(int q_len) | ||
540 | { | ||
541 | u32 len_encoded = fls(q_len); /* log2(len) + 1 */ | ||
542 | if (len_encoded == 16) | ||
543 | len_encoded = 0; | ||
544 | return len_encoded; | ||
545 | } | ||
546 | |||
547 | int be_cmd_mccq_create(struct be_ctrl_info *ctrl, | ||
548 | struct be_queue_info *mccq, | ||
549 | struct be_queue_info *cq) | ||
550 | { | ||
551 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
552 | struct be_cmd_req_mcc_create *req = embedded_payload(wrb); | ||
553 | struct be_dma_mem *q_mem = &mccq->dma_mem; | ||
554 | void *ctxt = &req->context; | ||
555 | int status; | ||
556 | |||
557 | spin_lock(&ctrl->mbox_lock); | ||
558 | memset(wrb, 0, sizeof(*wrb)); | ||
559 | |||
560 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
561 | |||
562 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
563 | OPCODE_COMMON_MCC_CREATE, sizeof(*req)); | ||
564 | |||
565 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | ||
566 | |||
567 | AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, ctrl->pci_func); | ||
568 | AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); | ||
569 | AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, | ||
570 | be_encoded_q_len(mccq->len)); | ||
571 | AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id); | ||
572 | |||
573 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | ||
574 | |||
575 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
576 | |||
577 | status = be_mbox_db_ring(ctrl); | ||
578 | if (!status) { | ||
579 | struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); | ||
580 | mccq->id = le16_to_cpu(resp->id); | ||
581 | mccq->created = true; | ||
582 | } | ||
583 | spin_unlock(&ctrl->mbox_lock); | ||
403 | 584 | ||
404 | return status; | 585 | return status; |
405 | } | 586 | } |
@@ -415,7 +596,7 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl, | |||
415 | int status; | 596 | int status; |
416 | u32 len_encoded; | 597 | u32 len_encoded; |
417 | 598 | ||
418 | spin_lock(&ctrl->cmd_lock); | 599 | spin_lock(&ctrl->mbox_lock); |
419 | memset(wrb, 0, sizeof(*wrb)); | 600 | memset(wrb, 0, sizeof(*wrb)); |
420 | 601 | ||
421 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 602 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -446,7 +627,7 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl, | |||
446 | txq->id = le16_to_cpu(resp->cid); | 627 | txq->id = le16_to_cpu(resp->cid); |
447 | txq->created = true; | 628 | txq->created = true; |
448 | } | 629 | } |
449 | spin_unlock(&ctrl->cmd_lock); | 630 | spin_unlock(&ctrl->mbox_lock); |
450 | 631 | ||
451 | return status; | 632 | return status; |
452 | } | 633 | } |
@@ -460,7 +641,7 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl, | |||
460 | struct be_dma_mem *q_mem = &rxq->dma_mem; | 641 | struct be_dma_mem *q_mem = &rxq->dma_mem; |
461 | int status; | 642 | int status; |
462 | 643 | ||
463 | spin_lock(&ctrl->cmd_lock); | 644 | spin_lock(&ctrl->mbox_lock); |
464 | memset(wrb, 0, sizeof(*wrb)); | 645 | memset(wrb, 0, sizeof(*wrb)); |
465 | 646 | ||
466 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 647 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -482,7 +663,7 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl, | |||
482 | rxq->id = le16_to_cpu(resp->id); | 663 | rxq->id = le16_to_cpu(resp->id); |
483 | rxq->created = true; | 664 | rxq->created = true; |
484 | } | 665 | } |
485 | spin_unlock(&ctrl->cmd_lock); | 666 | spin_unlock(&ctrl->mbox_lock); |
486 | 667 | ||
487 | return status; | 668 | return status; |
488 | } | 669 | } |
@@ -496,7 +677,7 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
496 | u8 subsys = 0, opcode = 0; | 677 | u8 subsys = 0, opcode = 0; |
497 | int status; | 678 | int status; |
498 | 679 | ||
499 | spin_lock(&ctrl->cmd_lock); | 680 | spin_lock(&ctrl->mbox_lock); |
500 | 681 | ||
501 | memset(wrb, 0, sizeof(*wrb)); | 682 | memset(wrb, 0, sizeof(*wrb)); |
502 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 683 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -518,6 +699,10 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
518 | subsys = CMD_SUBSYSTEM_ETH; | 699 | subsys = CMD_SUBSYSTEM_ETH; |
519 | opcode = OPCODE_ETH_RX_DESTROY; | 700 | opcode = OPCODE_ETH_RX_DESTROY; |
520 | break; | 701 | break; |
702 | case QTYPE_MCCQ: | ||
703 | subsys = CMD_SUBSYSTEM_COMMON; | ||
704 | opcode = OPCODE_COMMON_MCC_DESTROY; | ||
705 | break; | ||
521 | default: | 706 | default: |
522 | printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); | 707 | printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); |
523 | status = -1; | 708 | status = -1; |
@@ -528,7 +713,7 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
528 | 713 | ||
529 | status = be_mbox_db_ring(ctrl); | 714 | status = be_mbox_db_ring(ctrl); |
530 | err: | 715 | err: |
531 | spin_unlock(&ctrl->cmd_lock); | 716 | spin_unlock(&ctrl->mbox_lock); |
532 | 717 | ||
533 | return status; | 718 | return status; |
534 | } | 719 | } |
@@ -541,7 +726,7 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, | |||
541 | struct be_cmd_req_if_create *req = embedded_payload(wrb); | 726 | struct be_cmd_req_if_create *req = embedded_payload(wrb); |
542 | int status; | 727 | int status; |
543 | 728 | ||
544 | spin_lock(&ctrl->cmd_lock); | 729 | spin_lock(&ctrl->mbox_lock); |
545 | memset(wrb, 0, sizeof(*wrb)); | 730 | memset(wrb, 0, sizeof(*wrb)); |
546 | 731 | ||
547 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 732 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -562,7 +747,7 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, | |||
562 | *pmac_id = le32_to_cpu(resp->pmac_id); | 747 | *pmac_id = le32_to_cpu(resp->pmac_id); |
563 | } | 748 | } |
564 | 749 | ||
565 | spin_unlock(&ctrl->cmd_lock); | 750 | spin_unlock(&ctrl->mbox_lock); |
566 | return status; | 751 | return status; |
567 | } | 752 | } |
568 | 753 | ||
@@ -572,7 +757,7 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) | |||
572 | struct be_cmd_req_if_destroy *req = embedded_payload(wrb); | 757 | struct be_cmd_req_if_destroy *req = embedded_payload(wrb); |
573 | int status; | 758 | int status; |
574 | 759 | ||
575 | spin_lock(&ctrl->cmd_lock); | 760 | spin_lock(&ctrl->mbox_lock); |
576 | memset(wrb, 0, sizeof(*wrb)); | 761 | memset(wrb, 0, sizeof(*wrb)); |
577 | 762 | ||
578 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 763 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -583,7 +768,7 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) | |||
583 | req->interface_id = cpu_to_le32(interface_id); | 768 | req->interface_id = cpu_to_le32(interface_id); |
584 | status = be_mbox_db_ring(ctrl); | 769 | status = be_mbox_db_ring(ctrl); |
585 | 770 | ||
586 | spin_unlock(&ctrl->cmd_lock); | 771 | spin_unlock(&ctrl->mbox_lock); |
587 | 772 | ||
588 | return status; | 773 | return status; |
589 | } | 774 | } |
@@ -598,7 +783,7 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) | |||
598 | struct be_sge *sge = nonembedded_sgl(wrb); | 783 | struct be_sge *sge = nonembedded_sgl(wrb); |
599 | int status; | 784 | int status; |
600 | 785 | ||
601 | spin_lock(&ctrl->cmd_lock); | 786 | spin_lock(&ctrl->mbox_lock); |
602 | memset(wrb, 0, sizeof(*wrb)); | 787 | memset(wrb, 0, sizeof(*wrb)); |
603 | 788 | ||
604 | memset(req, 0, sizeof(*req)); | 789 | memset(req, 0, sizeof(*req)); |
@@ -617,18 +802,20 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) | |||
617 | be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); | 802 | be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); |
618 | } | 803 | } |
619 | 804 | ||
620 | spin_unlock(&ctrl->cmd_lock); | 805 | spin_unlock(&ctrl->mbox_lock); |
621 | return status; | 806 | return status; |
622 | } | 807 | } |
623 | 808 | ||
624 | int be_cmd_link_status_query(struct be_ctrl_info *ctrl, | 809 | int be_cmd_link_status_query(struct be_ctrl_info *ctrl, |
625 | struct be_link_info *link) | 810 | bool *link_up) |
626 | { | 811 | { |
627 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 812 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
628 | struct be_cmd_req_link_status *req = embedded_payload(wrb); | 813 | struct be_cmd_req_link_status *req = embedded_payload(wrb); |
629 | int status; | 814 | int status; |
630 | 815 | ||
631 | spin_lock(&ctrl->cmd_lock); | 816 | spin_lock(&ctrl->mbox_lock); |
817 | |||
818 | *link_up = false; | ||
632 | memset(wrb, 0, sizeof(*wrb)); | 819 | memset(wrb, 0, sizeof(*wrb)); |
633 | 820 | ||
634 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 821 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -639,14 +826,11 @@ int be_cmd_link_status_query(struct be_ctrl_info *ctrl, | |||
639 | status = be_mbox_db_ring(ctrl); | 826 | status = be_mbox_db_ring(ctrl); |
640 | if (!status) { | 827 | if (!status) { |
641 | struct be_cmd_resp_link_status *resp = embedded_payload(wrb); | 828 | struct be_cmd_resp_link_status *resp = embedded_payload(wrb); |
642 | link->speed = resp->mac_speed; | 829 | if (resp->mac_speed != PHY_LINK_SPEED_ZERO) |
643 | link->duplex = resp->mac_duplex; | 830 | *link_up = true; |
644 | link->fault = resp->mac_fault; | ||
645 | } else { | ||
646 | link->speed = PHY_LINK_SPEED_ZERO; | ||
647 | } | 831 | } |
648 | 832 | ||
649 | spin_unlock(&ctrl->cmd_lock); | 833 | spin_unlock(&ctrl->mbox_lock); |
650 | return status; | 834 | return status; |
651 | } | 835 | } |
652 | 836 | ||
@@ -656,7 +840,7 @@ int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) | |||
656 | struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); | 840 | struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); |
657 | int status; | 841 | int status; |
658 | 842 | ||
659 | spin_lock(&ctrl->cmd_lock); | 843 | spin_lock(&ctrl->mbox_lock); |
660 | memset(wrb, 0, sizeof(*wrb)); | 844 | memset(wrb, 0, sizeof(*wrb)); |
661 | 845 | ||
662 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 846 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -670,7 +854,7 @@ int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) | |||
670 | strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); | 854 | strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); |
671 | } | 855 | } |
672 | 856 | ||
673 | spin_unlock(&ctrl->cmd_lock); | 857 | spin_unlock(&ctrl->mbox_lock); |
674 | return status; | 858 | return status; |
675 | } | 859 | } |
676 | 860 | ||
@@ -681,7 +865,7 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) | |||
681 | struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); | 865 | struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); |
682 | int status; | 866 | int status; |
683 | 867 | ||
684 | spin_lock(&ctrl->cmd_lock); | 868 | spin_lock(&ctrl->mbox_lock); |
685 | memset(wrb, 0, sizeof(*wrb)); | 869 | memset(wrb, 0, sizeof(*wrb)); |
686 | 870 | ||
687 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 871 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -696,7 +880,7 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) | |||
696 | 880 | ||
697 | status = be_mbox_db_ring(ctrl); | 881 | status = be_mbox_db_ring(ctrl); |
698 | 882 | ||
699 | spin_unlock(&ctrl->cmd_lock); | 883 | spin_unlock(&ctrl->mbox_lock); |
700 | return status; | 884 | return status; |
701 | } | 885 | } |
702 | 886 | ||
@@ -707,7 +891,7 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, | |||
707 | struct be_cmd_req_vlan_config *req = embedded_payload(wrb); | 891 | struct be_cmd_req_vlan_config *req = embedded_payload(wrb); |
708 | int status; | 892 | int status; |
709 | 893 | ||
710 | spin_lock(&ctrl->cmd_lock); | 894 | spin_lock(&ctrl->mbox_lock); |
711 | memset(wrb, 0, sizeof(*wrb)); | 895 | memset(wrb, 0, sizeof(*wrb)); |
712 | 896 | ||
713 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 897 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -726,18 +910,22 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, | |||
726 | 910 | ||
727 | status = be_mbox_db_ring(ctrl); | 911 | status = be_mbox_db_ring(ctrl); |
728 | 912 | ||
729 | spin_unlock(&ctrl->cmd_lock); | 913 | spin_unlock(&ctrl->mbox_lock); |
730 | return status; | 914 | return status; |
731 | } | 915 | } |
732 | 916 | ||
917 | /* Use MCC for this command as it may be called in BH context */ | ||
733 | int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) | 918 | int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) |
734 | { | 919 | { |
735 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 920 | struct be_mcc_wrb *wrb; |
736 | struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb); | 921 | struct be_cmd_req_promiscuous_config *req; |
737 | int status; | ||
738 | 922 | ||
739 | spin_lock(&ctrl->cmd_lock); | 923 | spin_lock_bh(&ctrl->mcc_lock); |
740 | memset(wrb, 0, sizeof(*wrb)); | 924 | |
925 | wrb = wrb_from_mcc(&ctrl->mcc_obj.q); | ||
926 | BUG_ON(!wrb); | ||
927 | |||
928 | req = embedded_payload(wrb); | ||
741 | 929 | ||
742 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 930 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
743 | 931 | ||
@@ -749,21 +937,29 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) | |||
749 | else | 937 | else |
750 | req->port0_promiscuous = en; | 938 | req->port0_promiscuous = en; |
751 | 939 | ||
752 | status = be_mbox_db_ring(ctrl); | 940 | be_mcc_notify_wait(ctrl); |
753 | 941 | ||
754 | spin_unlock(&ctrl->cmd_lock); | 942 | spin_unlock_bh(&ctrl->mcc_lock); |
755 | return status; | 943 | return 0; |
756 | } | 944 | } |
757 | 945 | ||
758 | int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, | 946 | /* |
759 | u32 num, bool promiscuous) | 947 | * Use MCC for this command as it may be called in BH context |
948 | * (mc == NULL) => multicast promiscous | ||
949 | */ | ||
950 | int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id, | ||
951 | struct dev_mc_list *mc_list, u32 mc_count) | ||
760 | { | 952 | { |
761 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 953 | #define BE_MAX_MC 32 /* set mcast promisc if > 32 */ |
762 | struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb); | 954 | struct be_mcc_wrb *wrb; |
763 | int status; | 955 | struct be_cmd_req_mcast_mac_config *req; |
764 | 956 | ||
765 | spin_lock(&ctrl->cmd_lock); | 957 | spin_lock_bh(&ctrl->mcc_lock); |
766 | memset(wrb, 0, sizeof(*wrb)); | 958 | |
959 | wrb = wrb_from_mcc(&ctrl->mcc_obj.q); | ||
960 | BUG_ON(!wrb); | ||
961 | |||
962 | req = embedded_payload(wrb); | ||
767 | 963 | ||
768 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 964 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
769 | 965 | ||
@@ -771,17 +967,23 @@ int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, | |||
771 | OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); | 967 | OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); |
772 | 968 | ||
773 | req->interface_id = if_id; | 969 | req->interface_id = if_id; |
774 | req->promiscuous = promiscuous; | 970 | if (mc_list && mc_count <= BE_MAX_MC) { |
775 | if (!promiscuous) { | 971 | int i; |
776 | req->num_mac = cpu_to_le16(num); | 972 | struct dev_mc_list *mc; |
777 | if (num) | 973 | |
778 | memcpy(req->mac, mac_table, ETH_ALEN * num); | 974 | req->num_mac = cpu_to_le16(mc_count); |
975 | |||
976 | for (mc = mc_list, i = 0; mc; mc = mc->next, i++) | ||
977 | memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN); | ||
978 | } else { | ||
979 | req->promiscuous = 1; | ||
779 | } | 980 | } |
780 | 981 | ||
781 | status = be_mbox_db_ring(ctrl); | 982 | be_mcc_notify_wait(ctrl); |
782 | 983 | ||
783 | spin_unlock(&ctrl->cmd_lock); | 984 | spin_unlock_bh(&ctrl->mcc_lock); |
784 | return status; | 985 | |
986 | return 0; | ||
785 | } | 987 | } |
786 | 988 | ||
787 | int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) | 989 | int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) |
@@ -790,7 +992,7 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) | |||
790 | struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); | 992 | struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); |
791 | int status; | 993 | int status; |
792 | 994 | ||
793 | spin_lock(&ctrl->cmd_lock); | 995 | spin_lock(&ctrl->mbox_lock); |
794 | 996 | ||
795 | memset(wrb, 0, sizeof(*wrb)); | 997 | memset(wrb, 0, sizeof(*wrb)); |
796 | 998 | ||
@@ -804,7 +1006,7 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) | |||
804 | 1006 | ||
805 | status = be_mbox_db_ring(ctrl); | 1007 | status = be_mbox_db_ring(ctrl); |
806 | 1008 | ||
807 | spin_unlock(&ctrl->cmd_lock); | 1009 | spin_unlock(&ctrl->mbox_lock); |
808 | return status; | 1010 | return status; |
809 | } | 1011 | } |
810 | 1012 | ||
@@ -814,7 +1016,7 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) | |||
814 | struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); | 1016 | struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); |
815 | int status; | 1017 | int status; |
816 | 1018 | ||
817 | spin_lock(&ctrl->cmd_lock); | 1019 | spin_lock(&ctrl->mbox_lock); |
818 | 1020 | ||
819 | memset(wrb, 0, sizeof(*wrb)); | 1021 | memset(wrb, 0, sizeof(*wrb)); |
820 | 1022 | ||
@@ -831,7 +1033,7 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) | |||
831 | *rx_fc = le16_to_cpu(resp->rx_flow_control); | 1033 | *rx_fc = le16_to_cpu(resp->rx_flow_control); |
832 | } | 1034 | } |
833 | 1035 | ||
834 | spin_unlock(&ctrl->cmd_lock); | 1036 | spin_unlock(&ctrl->mbox_lock); |
835 | return status; | 1037 | return status; |
836 | } | 1038 | } |
837 | 1039 | ||
@@ -841,7 +1043,7 @@ int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) | |||
841 | struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); | 1043 | struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); |
842 | int status; | 1044 | int status; |
843 | 1045 | ||
844 | spin_lock(&ctrl->cmd_lock); | 1046 | spin_lock(&ctrl->mbox_lock); |
845 | 1047 | ||
846 | memset(wrb, 0, sizeof(*wrb)); | 1048 | memset(wrb, 0, sizeof(*wrb)); |
847 | 1049 | ||
@@ -856,6 +1058,6 @@ int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) | |||
856 | *port_num = le32_to_cpu(resp->phys_port); | 1058 | *port_num = le32_to_cpu(resp->phys_port); |
857 | } | 1059 | } |
858 | 1060 | ||
859 | spin_unlock(&ctrl->cmd_lock); | 1061 | spin_unlock(&ctrl->mbox_lock); |
860 | return status; | 1062 | return status; |
861 | } | 1063 | } |