be2net: Support for version 1 of stats for BE3
[linux-2.6-microblaze.git] / drivers / net / benet / be_cmds.c
index 1e2d825..08e0938 100644 (file)
@@ -78,11 +78,22 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
        }
 
        if (compl_status == MCC_STATUS_SUCCESS) {
-               if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) {
-                       struct be_cmd_resp_get_stats *resp =
-                                               adapter->stats_cmd.va;
-                       be_dws_le_to_cpu(&resp->hw_stats,
-                                               sizeof(resp->hw_stats));
+               if ((compl->tag0 == OPCODE_ETH_GET_STATISTICS) &&
+                       (compl->tag1 == CMD_SUBSYSTEM_ETH)) {
+                       if (adapter->generation == BE_GEN3) {
+                               struct be_cmd_resp_get_stats_v1 *resp =
+                                                       adapter->stats_cmd.va;
+
+                               be_dws_le_to_cpu(&resp->hw_stats,
+                                                       sizeof(resp->hw_stats));
+                       } else {
+                               struct be_cmd_resp_get_stats_v0 *resp =
+                                                       adapter->stats_cmd.va;
+
+                               be_dws_le_to_cpu(&resp->hw_stats,
+                                                       sizeof(resp->hw_stats));
+                       }
+                       be_parse_stats(adapter);
                        netdev_stats_update(adapter);
                        adapter->stats_cmd_sent = false;
                }
@@ -132,7 +143,7 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
                struct be_async_event_grp5_pvid_state *evt)
 {
        if (evt->enabled)
-               adapter->pvid = evt->tag;
+               adapter->pvid = le16_to_cpu(evt->tag);
        else
                adapter->pvid = 0;
 }
@@ -292,12 +303,12 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
 
                if (msecs > 4000) {
                        dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
-                       be_detect_dump_ue(adapter);
+                       if (!lancer_chip(adapter))
+                               be_detect_dump_ue(adapter);
                        return -1;
                }
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(msecs_to_jiffies(1));
+               msleep(1);
                msecs++;
        } while (true);
 
@@ -374,23 +385,25 @@ int be_cmd_POST(struct be_adapter *adapter)
 {
        u16 stage;
        int status, timeout = 0;
+       struct device *dev = &adapter->pdev->dev;
 
        do {
                status = be_POST_stage_get(adapter, &stage);
                if (status) {
-                       dev_err(&adapter->pdev->dev, "POST error; stage=0x%x\n",
-                               stage);
+                       dev_err(dev, "POST error; stage=0x%x\n", stage);
                        return -1;
                } else if (stage != POST_STAGE_ARMFW_RDY) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(2 * HZ);
+                       if (msleep_interruptible(2000)) {
+                               dev_err(dev, "Waiting for POST aborted\n");
+                               return -EINTR;
+                       }
                        timeout += 2;
                } else {
                        return 0;
                }
        } while (timeout < 40);
 
-       dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage);
+       dev_err(dev, "POST timeout; stage=0x%x\n", stage);
        return -1;
 }
 
@@ -728,8 +741,6 @@ int be_cmd_cq_create(struct be_adapter *adapter,
        if (lancer_chip(adapter)) {
                req->hdr.version = 2;
                req->page_size = 1; /* 1 for 4K */
-               AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt,
-                                                               coalesce_wm);
                AMAP_SET_BITS(struct amap_cq_context_lancer, nodelay, ctxt,
                                                                no_delay);
                AMAP_SET_BITS(struct amap_cq_context_lancer, count, ctxt,
@@ -1074,7 +1085,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
 int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 {
        struct be_mcc_wrb *wrb;
-       struct be_cmd_req_get_stats *req;
+       struct be_cmd_req_hdr *hdr;
        struct be_sge *sge;
        int status = 0;
 
@@ -1088,14 +1099,19 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
                status = -EBUSY;
                goto err;
        }
-       req = nonemb_cmd->va;
+       hdr = nonemb_cmd->va;
        sge = nonembedded_sgl(wrb);
 
-       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+       be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1,
                        OPCODE_ETH_GET_STATISTICS);
 
-       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
-               OPCODE_ETH_GET_STATISTICS, sizeof(*req));
+       be_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
+               OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size);
+
+       if (adapter->generation == BE_GEN3)
+               hdr->version = 1;
+
+       wrb->tag1 = CMD_SUBSYSTEM_ETH;
        sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
        sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
        sge->len = cpu_to_le32(nonemb_cmd->size);
@@ -1110,7 +1126,7 @@ err:
 
 /* Uses synchronous mcc */
 int be_cmd_link_status_query(struct be_adapter *adapter,
-                       bool *link_up, u8 *mac_speed, u16 *link_speed)
+                       bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_link_status *req;
@@ -1186,6 +1202,116 @@ err:
        return status;
 }
 
+/* Uses synchronous mcc */
+int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fat *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+       req = embedded_payload(wrb);
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+                       OPCODE_COMMON_MANAGE_FAT);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+               OPCODE_COMMON_MANAGE_FAT, sizeof(*req));
+       req->fat_operation = cpu_to_le32(QUERY_FAT);
+       status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_fat *resp = embedded_payload(wrb);
+               if (log_size && resp->log_size)
+                       *log_size = le32_to_cpu(resp->log_size) -
+                                       sizeof(u32);
+       }
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
+void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
+{
+       struct be_dma_mem get_fat_cmd;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fat *req;
+       struct be_sge *sge;
+       u32 offset = 0, total_size, buf_size,
+                               log_offset = sizeof(u32), payload_len;
+       int status;
+
+       if (buf_len == 0)
+               return;
+
+       total_size = buf_len;
+
+       get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
+       get_fat_cmd.va = pci_alloc_consistent(adapter->pdev,
+                       get_fat_cmd.size,
+                       &get_fat_cmd.dma);
+       if (!get_fat_cmd.va) {
+               status = -ENOMEM;
+               dev_err(&adapter->pdev->dev,
+               "Memory allocation failure while retrieving FAT data\n");
+               return;
+       }
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       while (total_size) {
+               buf_size = min(total_size, (u32)60*1024);
+               total_size -= buf_size;
+
+               wrb = wrb_from_mccq(adapter);
+               if (!wrb) {
+                       status = -EBUSY;
+                       goto err;
+               }
+               req = get_fat_cmd.va;
+               sge = nonembedded_sgl(wrb);
+
+               payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size;
+               be_wrb_hdr_prepare(wrb, payload_len, false, 1,
+                               OPCODE_COMMON_MANAGE_FAT);
+
+               be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                               OPCODE_COMMON_MANAGE_FAT, payload_len);
+
+               sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.dma));
+               sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF);
+               sge->len = cpu_to_le32(get_fat_cmd.size);
+
+               req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
+               req->read_log_offset = cpu_to_le32(log_offset);
+               req->read_log_length = cpu_to_le32(buf_size);
+               req->data_buffer_size = cpu_to_le32(buf_size);
+
+               status = be_mcc_notify_wait(adapter);
+               if (!status) {
+                       struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
+                       memcpy(buf + offset,
+                               resp->data_buffer,
+                               resp->read_log_length);
+               } else {
+                       dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
+                       goto err;
+               }
+               offset += buf_size;
+               log_offset += buf_size;
+       }
+err:
+       pci_free_consistent(adapter->pdev, get_fat_cmd.size,
+                       get_fat_cmd.va,
+                       get_fat_cmd.dma);
+       spin_unlock_bh(&adapter->mcc_lock);
+}
+
 /* Uses Mbox */
 int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
 {
@@ -1293,12 +1419,24 @@ err:
 /* Uses MCC for this command as it may be called in BH context
  * Uses synchronous mcc
  */
-int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
+int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en)
 {
        struct be_mcc_wrb *wrb;
-       struct be_cmd_req_promiscuous_config *req;
+       struct be_cmd_req_rx_filter *req;
+       struct be_dma_mem promiscous_cmd;
+       struct be_sge *sge;
        int status;
 
+       memset(&promiscous_cmd, 0, sizeof(struct be_dma_mem));
+       promiscous_cmd.size = sizeof(struct be_cmd_req_rx_filter);
+       promiscous_cmd.va = pci_alloc_consistent(adapter->pdev,
+                               promiscous_cmd.size, &promiscous_cmd.dma);
+       if (!promiscous_cmd.va) {
+               dev_err(&adapter->pdev->dev,
+                               "Memory allocation failure\n");
+               return -ENOMEM;
+       }
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -1306,26 +1444,30 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
                status = -EBUSY;
                goto err;
        }
-       req = embedded_payload(wrb);
 
-       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_PROMISCUOUS);
+       req = promiscous_cmd.va;
+       sge = nonembedded_sgl(wrb);
 
-       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
-               OPCODE_ETH_PROMISCUOUS, sizeof(*req));
-
-       /* In FW versions X.102.149/X.101.487 and later,
-        * the port setting associated only with the
-        * issuing pci function will take effect
-        */
-       if (port_num)
-               req->port1_promiscuous = en;
-       else
-               req->port0_promiscuous = en;
+       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+                                       OPCODE_COMMON_NTWK_RX_FILTER);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                       OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req));
+
+       req->if_id = cpu_to_le32(adapter->if_handle);
+       req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
+       if (en)
+               req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS);
+
+       sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma));
+       sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF);
+       sge->len = cpu_to_le32(promiscous_cmd.size);
 
        status = be_mcc_notify_wait(adapter);
 
 err:
        spin_unlock_bh(&adapter->mcc_lock);
+       pci_free_consistent(adapter->pdev, promiscous_cmd.size,
+                       promiscous_cmd.va, promiscous_cmd.dma);
        return status;
 }