diff options
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 109 |
1 files changed, 85 insertions, 24 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 5458a4357ae0..70d5db043f1e 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -633,6 +633,12 @@ static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) | |||
633 | return &wrb->payload.sgl[0]; | 633 | return &wrb->payload.sgl[0]; |
634 | } | 634 | } |
635 | 635 | ||
636 | static inline void fill_wrb_tags(struct be_mcc_wrb *wrb, | ||
637 | unsigned long addr) | ||
638 | { | ||
639 | wrb->tag0 = addr & 0xFFFFFFFF; | ||
640 | wrb->tag1 = upper_32_bits(addr); | ||
641 | } | ||
636 | 642 | ||
637 | /* Don't touch the hdr after it's prepared */ | 643 | /* Don't touch the hdr after it's prepared */ |
638 | /* mem will be NULL for embedded commands */ | 644 | /* mem will be NULL for embedded commands */ |
@@ -641,17 +647,12 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, | |||
641 | struct be_mcc_wrb *wrb, struct be_dma_mem *mem) | 647 | struct be_mcc_wrb *wrb, struct be_dma_mem *mem) |
642 | { | 648 | { |
643 | struct be_sge *sge; | 649 | struct be_sge *sge; |
644 | unsigned long addr = (unsigned long)req_hdr; | ||
645 | u64 req_addr = addr; | ||
646 | 650 | ||
647 | req_hdr->opcode = opcode; | 651 | req_hdr->opcode = opcode; |
648 | req_hdr->subsystem = subsystem; | 652 | req_hdr->subsystem = subsystem; |
649 | req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); | 653 | req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); |
650 | req_hdr->version = 0; | 654 | req_hdr->version = 0; |
651 | 655 | fill_wrb_tags(wrb, (ulong) req_hdr); | |
652 | wrb->tag0 = req_addr & 0xFFFFFFFF; | ||
653 | wrb->tag1 = upper_32_bits(req_addr); | ||
654 | |||
655 | wrb->payload_length = cmd_len; | 656 | wrb->payload_length = cmd_len; |
656 | if (mem) { | 657 | if (mem) { |
657 | wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << | 658 | wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << |
@@ -705,6 +706,78 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) | |||
705 | return wrb; | 706 | return wrb; |
706 | } | 707 | } |
707 | 708 | ||
709 | static bool use_mcc(struct be_adapter *adapter) | ||
710 | { | ||
711 | return adapter->mcc_obj.q.created; | ||
712 | } | ||
713 | |||
714 | /* Must be used only in process context */ | ||
715 | static int be_cmd_lock(struct be_adapter *adapter) | ||
716 | { | ||
717 | if (use_mcc(adapter)) { | ||
718 | spin_lock_bh(&adapter->mcc_lock); | ||
719 | return 0; | ||
720 | } else { | ||
721 | return mutex_lock_interruptible(&adapter->mbox_lock); | ||
722 | } | ||
723 | } | ||
724 | |||
725 | /* Must be used only in process context */ | ||
726 | static void be_cmd_unlock(struct be_adapter *adapter) | ||
727 | { | ||
728 | if (use_mcc(adapter)) | ||
729 | spin_unlock_bh(&adapter->mcc_lock); | ||
730 | else | ||
731 | return mutex_unlock(&adapter->mbox_lock); | ||
732 | } | ||
733 | |||
734 | static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter, | ||
735 | struct be_mcc_wrb *wrb) | ||
736 | { | ||
737 | struct be_mcc_wrb *dest_wrb; | ||
738 | |||
739 | if (use_mcc(adapter)) { | ||
740 | dest_wrb = wrb_from_mccq(adapter); | ||
741 | if (!dest_wrb) | ||
742 | return NULL; | ||
743 | } else { | ||
744 | dest_wrb = wrb_from_mbox(adapter); | ||
745 | } | ||
746 | |||
747 | memcpy(dest_wrb, wrb, sizeof(*wrb)); | ||
748 | if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK)) | ||
749 | fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb)); | ||
750 | |||
751 | return dest_wrb; | ||
752 | } | ||
753 | |||
754 | /* Must be used only in process context */ | ||
755 | static int be_cmd_notify_wait(struct be_adapter *adapter, | ||
756 | struct be_mcc_wrb *wrb) | ||
757 | { | ||
758 | struct be_mcc_wrb *dest_wrb; | ||
759 | int status; | ||
760 | |||
761 | status = be_cmd_lock(adapter); | ||
762 | if (status) | ||
763 | return status; | ||
764 | |||
765 | dest_wrb = be_cmd_copy(adapter, wrb); | ||
766 | if (!dest_wrb) | ||
767 | return -EBUSY; | ||
768 | |||
769 | if (use_mcc(adapter)) | ||
770 | status = be_mcc_notify_wait(adapter); | ||
771 | else | ||
772 | status = be_mbox_notify_wait(adapter); | ||
773 | |||
774 | if (!status) | ||
775 | memcpy(wrb, dest_wrb, sizeof(*wrb)); | ||
776 | |||
777 | be_cmd_unlock(adapter); | ||
778 | return status; | ||
779 | } | ||
780 | |||
708 | /* Tell fw we're about to start firing cmds by writing a | 781 | /* Tell fw we're about to start firing cmds by writing a |
709 | * special pattern across the wrb hdr; uses mbox | 782 | * special pattern across the wrb hdr; uses mbox |
710 | */ | 783 | */ |
@@ -1290,44 +1363,32 @@ err: | |||
1290 | } | 1363 | } |
1291 | 1364 | ||
1292 | /* Create an rx filtering policy configuration on an i/f | 1365 | /* Create an rx filtering policy configuration on an i/f |
1293 | * Uses MCCQ | 1366 | * Will use MBOX only if MCCQ has not been created. |
1294 | */ | 1367 | */ |
1295 | int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, | 1368 | int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, |
1296 | u32 *if_handle, u32 domain) | 1369 | u32 *if_handle, u32 domain) |
1297 | { | 1370 | { |
1298 | struct be_mcc_wrb *wrb; | 1371 | struct be_mcc_wrb wrb = {0}; |
1299 | struct be_cmd_req_if_create *req; | 1372 | struct be_cmd_req_if_create *req; |
1300 | int status; | 1373 | int status; |
1301 | 1374 | ||
1302 | spin_lock_bh(&adapter->mcc_lock); | 1375 | req = embedded_payload(&wrb); |
1303 | |||
1304 | wrb = wrb_from_mccq(adapter); | ||
1305 | if (!wrb) { | ||
1306 | status = -EBUSY; | ||
1307 | goto err; | ||
1308 | } | ||
1309 | req = embedded_payload(wrb); | ||
1310 | |||
1311 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1376 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1312 | OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req), wrb, NULL); | 1377 | OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req), &wrb, NULL); |
1313 | req->hdr.domain = domain; | 1378 | req->hdr.domain = domain; |
1314 | req->capability_flags = cpu_to_le32(cap_flags); | 1379 | req->capability_flags = cpu_to_le32(cap_flags); |
1315 | req->enable_flags = cpu_to_le32(en_flags); | 1380 | req->enable_flags = cpu_to_le32(en_flags); |
1316 | |||
1317 | req->pmac_invalid = true; | 1381 | req->pmac_invalid = true; |
1318 | 1382 | ||
1319 | status = be_mcc_notify_wait(adapter); | 1383 | status = be_cmd_notify_wait(adapter, &wrb); |
1320 | if (!status) { | 1384 | if (!status) { |
1321 | struct be_cmd_resp_if_create *resp = embedded_payload(wrb); | 1385 | struct be_cmd_resp_if_create *resp = embedded_payload(&wrb); |
1322 | *if_handle = le32_to_cpu(resp->interface_id); | 1386 | *if_handle = le32_to_cpu(resp->interface_id); |
1323 | 1387 | ||
1324 | /* Hack to retrieve VF's pmac-id on BE3 */ | 1388 | /* Hack to retrieve VF's pmac-id on BE3 */ |
1325 | if (BE3_chip(adapter) && !be_physfn(adapter)) | 1389 | if (BE3_chip(adapter) && !be_physfn(adapter)) |
1326 | adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); | 1390 | adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); |
1327 | } | 1391 | } |
1328 | |||
1329 | err: | ||
1330 | spin_unlock_bh(&adapter->mcc_lock); | ||
1331 | return status; | 1392 | return status; |
1332 | } | 1393 | } |
1333 | 1394 | ||