]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/net/ethernet/amazon/ena/ena_com.c
UBUNTU: Ubuntu-4.10.0-37.41
[mirror_ubuntu-zesty-kernel.git] / drivers / net / ethernet / amazon / ena / ena_com.c
index 3066d9c999841033d1f02b85480fb19f0cb112f6..52beba8c7a39990d3a9d6fb5910c689905a3a6a9 100644 (file)
@@ -36,9 +36,9 @@
 /*****************************************************************************/
 
 /* Timeout in micro-sec */
-#define ADMIN_CMD_TIMEOUT_US (1000000)
+#define ADMIN_CMD_TIMEOUT_US (3000000)
 
-#define ENA_ASYNC_QUEUE_DEPTH 4
+#define ENA_ASYNC_QUEUE_DEPTH 16
 #define ENA_ADMIN_QUEUE_DEPTH 32
 
 #define MIN_ENA_VER (((ENA_COMMON_SPEC_VERSION_MAJOR) << \
@@ -61,6 +61,8 @@
 
 #define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF
 
+#define ENA_REGS_ADMIN_INTR_MASK 1
+
 /*****************************************************************************/
 /*****************************************************************************/
 /*****************************************************************************/
@@ -97,8 +99,8 @@ static inline int ena_com_mem_addr_set(struct ena_com_dev *ena_dev,
                return -EINVAL;
        }
 
-       ena_addr->mem_addr_low = (u32)addr;
-       ena_addr->mem_addr_high = (u64)addr >> 32;
+       ena_addr->mem_addr_low = lower_32_bits(addr);
+       ena_addr->mem_addr_high = (u16)upper_32_bits(addr);
 
        return 0;
 }
@@ -232,11 +234,9 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu
        tail_masked = admin_queue->sq.tail & queue_size_mask;
 
        /* In case of queue FULL */
-       cnt = admin_queue->sq.tail - admin_queue->sq.head;
+       cnt = atomic_read(&admin_queue->outstanding_cmds);
        if (cnt >= admin_queue->q_depth) {
-               pr_debug("admin queue is FULL (tail %d head %d depth: %d)\n",
-                        admin_queue->sq.tail, admin_queue->sq.head,
-                        admin_queue->q_depth);
+               pr_debug("admin queue is full.\n");
                admin_queue->stats.out_of_space++;
                return ERR_PTR(-ENOSPC);
        }
@@ -329,7 +329,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
        size_t size;
        int dev_node = 0;
 
-       memset(&io_sq->desc_addr, 0x0, sizeof(struct ena_com_io_desc_addr));
+       memset(&io_sq->desc_addr, 0x0, sizeof(io_sq->desc_addr));
 
        io_sq->desc_entry_size =
                (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ?
@@ -383,7 +383,7 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev,
        size_t size;
        int prev_node = 0;
 
-       memset(&io_cq->cdesc_addr, 0x0, sizeof(struct ena_com_io_desc_addr));
+       memset(&io_cq->cdesc_addr, 0x0, sizeof(io_cq->cdesc_addr));
 
        /* Use the basic completion descriptor for Rx */
        io_cq->cdesc_entry_size_in_bytes =
@@ -494,7 +494,7 @@ static int ena_com_comp_status_to_errno(u8 comp_status)
        case ENA_ADMIN_RESOURCE_ALLOCATION_FAILURE:
                return -ENOMEM;
        case ENA_ADMIN_UNSUPPORTED_OPCODE:
-               return -EPERM;
+               return -EOPNOTSUPP;
        case ENA_ADMIN_BAD_OPCODE:
        case ENA_ADMIN_MALFORMED_REQUEST:
        case ENA_ADMIN_ILLEGAL_PARAMETER:
@@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status)
 static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx,
                                                     struct ena_com_admin_queue *admin_queue)
 {
-       unsigned long flags;
-       u32 start_time;
+       unsigned long flags, timeout;
        int ret;
 
-       start_time = ((u32)jiffies_to_usecs(jiffies));
+       timeout = jiffies + usecs_to_jiffies(admin_queue->completion_timeout);
+
+       while (1) {
+               spin_lock_irqsave(&admin_queue->q_lock, flags);
+               ena_com_handle_admin_completion(admin_queue);
+               spin_unlock_irqrestore(&admin_queue->q_lock, flags);
+
+               if (comp_ctx->status != ENA_CMD_SUBMITTED)
+                       break;
 
-       while (comp_ctx->status == ENA_CMD_SUBMITTED) {
-               if ((((u32)jiffies_to_usecs(jiffies)) - start_time) >
-                   ADMIN_CMD_TIMEOUT_US) {
+               if (time_is_before_jiffies(timeout)) {
                        pr_err("Wait for completion (polling) timeout\n");
                        /* ENA didn't have any completion */
                        spin_lock_irqsave(&admin_queue->q_lock, flags);
@@ -528,10 +533,6 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c
                        goto err;
                }
 
-               spin_lock_irqsave(&admin_queue->q_lock, flags);
-               ena_com_handle_admin_completion(admin_queue);
-               spin_unlock_irqrestore(&admin_queue->q_lock, flags);
-
                msleep(100);
        }
 
@@ -560,7 +561,8 @@ static int ena_com_wait_and_process_admin_cq_interrupts(struct ena_comp_ctx *com
        int ret;
 
        wait_for_completion_timeout(&comp_ctx->wait_event,
-                                   usecs_to_jiffies(ADMIN_CMD_TIMEOUT_US));
+                                   usecs_to_jiffies(
+                                           admin_queue->completion_timeout));
 
        /* In case the command wasn't completed find out the root cause.
         * There might be 2 kinds of errors
@@ -600,12 +602,15 @@ static u32 ena_com_reg_bar_read32(struct ena_com_dev *ena_dev, u16 offset)
        struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read;
        volatile struct ena_admin_ena_mmio_req_read_less_resp *read_resp =
                mmio_read->read_resp;
-       u32 mmio_read_reg, ret;
+       u32 mmio_read_reg, ret, i;
        unsigned long flags;
-       int i;
+       u32 timeout = mmio_read->reg_read_to;
 
        might_sleep();
 
+       if (timeout == 0)
+               timeout = ENA_REG_READ_TIMEOUT;
+
        /* If readless is disabled, perform regular read */
        if (!mmio_read->readless_supported)
                return readl(ena_dev->reg_bar + offset);
@@ -626,14 +631,14 @@ static u32 ena_com_reg_bar_read32(struct ena_com_dev *ena_dev, u16 offset)
 
        writel(mmio_read_reg, ena_dev->reg_bar + ENA_REGS_MMIO_REG_READ_OFF);
 
-       for (i = 0; i < ENA_REG_READ_TIMEOUT; i++) {
+       for (i = 0; i < timeout; i++) {
                if (read_resp->req_id == mmio_read->seq_num)
                        break;
 
                udelay(1);
        }
 
-       if (unlikely(i == ENA_REG_READ_TIMEOUT)) {
+       if (unlikely(i == timeout)) {
                pr_err("reading reg failed for timeout. expected: req id[%hu] offset[%hu] actual: req id[%hu] offset[%hu]\n",
                       mmio_read->seq_num, offset, read_resp->req_id,
                       read_resp->reg_off);
@@ -680,7 +685,7 @@ static int ena_com_destroy_io_sq(struct ena_com_dev *ena_dev,
        u8 direction;
        int ret;
 
-       memset(&destroy_cmd, 0x0, sizeof(struct ena_admin_aq_destroy_sq_cmd));
+       memset(&destroy_cmd, 0x0, sizeof(destroy_cmd));
 
        if (io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX)
                direction = ENA_ADMIN_SQ_DIRECTION_TX;
@@ -784,8 +789,8 @@ static int ena_com_get_feature_ex(struct ena_com_dev *ena_dev,
        int ret;
 
        if (!ena_com_check_supported_feature_id(ena_dev, feature_id)) {
-               pr_info("Feature %d isn't supported\n", feature_id);
-               return -EPERM;
+               pr_debug("Feature %d isn't supported\n", feature_id);
+               return -EOPNOTSUPP;
        }
 
        memset(&get_cmd, 0x0, sizeof(get_cmd));
@@ -962,7 +967,7 @@ static int ena_com_create_io_sq(struct ena_com_dev *ena_dev,
        u8 direction;
        int ret;
 
-       memset(&create_cmd, 0x0, sizeof(struct ena_admin_aq_create_sq_cmd));
+       memset(&create_cmd, 0x0, sizeof(create_cmd));
 
        create_cmd.aq_common_descriptor.opcode = ENA_ADMIN_CREATE_SQ;
 
@@ -1126,7 +1131,13 @@ int ena_com_execute_admin_command(struct ena_com_admin_queue *admin_queue,
        comp_ctx = ena_com_submit_admin_cmd(admin_queue, cmd, cmd_size,
                                            comp, comp_size);
        if (unlikely(IS_ERR(comp_ctx))) {
-               pr_err("Failed to submit command [%ld]\n", PTR_ERR(comp_ctx));
+               if (comp_ctx == ERR_PTR(-ENODEV))
+                       pr_debug("Failed to submit command [%ld]\n",
+                                PTR_ERR(comp_ctx));
+               else
+                       pr_err("Failed to submit command [%ld]\n",
+                              PTR_ERR(comp_ctx));
+
                return PTR_ERR(comp_ctx);
        }
 
@@ -1148,7 +1159,7 @@ int ena_com_create_io_cq(struct ena_com_dev *ena_dev,
        struct ena_admin_acq_create_cq_resp_desc cmd_completion;
        int ret;
 
-       memset(&create_cmd, 0x0, sizeof(struct ena_admin_aq_create_cq_cmd));
+       memset(&create_cmd, 0x0, sizeof(create_cmd));
 
        create_cmd.aq_common_descriptor.opcode = ENA_ADMIN_CREATE_CQ;
 
@@ -1256,7 +1267,7 @@ int ena_com_destroy_io_cq(struct ena_com_dev *ena_dev,
        struct ena_admin_acq_destroy_cq_resp_desc destroy_resp;
        int ret;
 
-       memset(&destroy_cmd, 0x0, sizeof(struct ena_admin_aq_destroy_sq_cmd));
+       memset(&destroy_cmd, 0x0, sizeof(destroy_cmd));
 
        destroy_cmd.cq_idx = io_cq->idx;
        destroy_cmd.aq_common_descriptor.opcode = ENA_ADMIN_DESTROY_CQ;
@@ -1317,7 +1328,7 @@ int ena_com_set_aenq_config(struct ena_com_dev *ena_dev, u32 groups_flag)
        if ((get_resp.u.aenq.supported_groups & groups_flag) != groups_flag) {
                pr_warn("Trying to set unsupported aenq events. supported flag: %x asked flag: %x\n",
                        get_resp.u.aenq.supported_groups, groups_flag);
-               return -EPERM;
+               return -EOPNOTSUPP;
        }
 
        memset(&cmd, 0x0, sizeof(cmd));
@@ -1449,6 +1460,12 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev)
 
 void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)
 {
+       u32 mask_value = 0;
+
+       if (polling)
+               mask_value = ENA_REGS_ADMIN_INTR_MASK;
+
+       writel(mask_value, ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF);
        ena_dev->admin_queue.polling = polling;
 }
 
@@ -1606,8 +1623,8 @@ int ena_com_create_io_queue(struct ena_com_dev *ena_dev,
        io_sq = &ena_dev->io_sq_queues[ctx->qid];
        io_cq = &ena_dev->io_cq_queues[ctx->qid];
 
-       memset(io_sq, 0x0, sizeof(struct ena_com_io_sq));
-       memset(io_cq, 0x0, sizeof(struct ena_com_io_cq));
+       memset(io_sq, 0x0, sizeof(*io_sq));
+       memset(io_cq, 0x0, sizeof(*io_cq));
 
        /* Init CQ */
        io_cq->q_depth = ctx->queue_size;
@@ -1717,6 +1734,20 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
        memcpy(&get_feat_ctx->offload, &get_resp.u.offload,
               sizeof(get_resp.u.offload));
 
+       /* Driver hints isn't mandatory admin command. So in case the
+        * command isn't supported set driver hints to 0
+        */
+       rc = ena_com_get_feature(ena_dev, &get_resp, ENA_ADMIN_HW_HINTS);
+
+       if (!rc)
+               memcpy(&get_feat_ctx->hw_hints, &get_resp.u.hw_hints,
+                      sizeof(get_resp.u.hw_hints));
+       else if (rc == -EOPNOTSUPP)
+               memset(&get_feat_ctx->hw_hints, 0x0,
+                      sizeof(get_feat_ctx->hw_hints));
+       else
+               return rc;
+
        return 0;
 }
 
@@ -1794,7 +1825,8 @@ void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data)
        writel((u32)aenq->head, dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF);
 }
 
-int ena_com_dev_reset(struct ena_com_dev *ena_dev)
+int ena_com_dev_reset(struct ena_com_dev *ena_dev,
+                     enum ena_regs_reset_reason_types reset_reason)
 {
        u32 stat, timeout, cap, reset_val;
        int rc;
@@ -1822,6 +1854,8 @@ int ena_com_dev_reset(struct ena_com_dev *ena_dev)
 
        /* start reset */
        reset_val = ENA_REGS_DEV_CTL_DEV_RESET_MASK;
+       reset_val |= (reset_reason << ENA_REGS_DEV_CTL_RESET_REASON_SHIFT) &
+                    ENA_REGS_DEV_CTL_RESET_REASON_MASK;
        writel(reset_val, ena_dev->reg_bar + ENA_REGS_DEV_CTL_OFF);
 
        /* Write again the MMIO read request address */
@@ -1842,6 +1876,14 @@ int ena_com_dev_reset(struct ena_com_dev *ena_dev)
                return rc;
        }
 
+       timeout = (cap & ENA_REGS_CAPS_ADMIN_CMD_TO_MASK) >>
+               ENA_REGS_CAPS_ADMIN_CMD_TO_SHIFT;
+       if (timeout)
+               /* the resolution of timeout reg is 100ms */
+               ena_dev->admin_queue.completion_timeout = timeout * 100000;
+       else
+               ena_dev->admin_queue.completion_timeout = ADMIN_CMD_TIMEOUT_US;
+
        return 0;
 }
 
@@ -1895,8 +1937,8 @@ int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, int mtu)
        int ret;
 
        if (!ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_MTU)) {
-               pr_info("Feature %d isn't supported\n", ENA_ADMIN_MTU);
-               return -EPERM;
+               pr_debug("Feature %d isn't supported\n", ENA_ADMIN_MTU);
+               return -EOPNOTSUPP;
        }
 
        memset(&cmd, 0x0, sizeof(cmd));
@@ -1948,9 +1990,9 @@ int ena_com_set_hash_function(struct ena_com_dev *ena_dev)
 
        if (!ena_com_check_supported_feature_id(ena_dev,
                                                ENA_ADMIN_RSS_HASH_FUNCTION)) {
-               pr_info("Feature %d isn't supported\n",
-                       ENA_ADMIN_RSS_HASH_FUNCTION);
-               return -EPERM;
+               pr_debug("Feature %d isn't supported\n",
+                        ENA_ADMIN_RSS_HASH_FUNCTION);
+               return -EOPNOTSUPP;
        }
 
        /* Validate hash function is supported */
@@ -1962,7 +2004,7 @@ int ena_com_set_hash_function(struct ena_com_dev *ena_dev)
        if (get_resp.u.flow_hash_func.supported_func & (1 << rss->hash_func)) {
                pr_err("Func hash %d isn't supported by device, abort\n",
                       rss->hash_func);
-               return -EPERM;
+               return -EOPNOTSUPP;
        }
 
        memset(&cmd, 0x0, sizeof(cmd));
@@ -2021,7 +2063,7 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
 
        if (!((1 << func) & get_resp.u.flow_hash_func.supported_func)) {
                pr_err("Flow hash function %d isn't supported\n", func);
-               return -EPERM;
+               return -EOPNOTSUPP;
        }
 
        switch (func) {
@@ -2112,8 +2154,9 @@ int ena_com_set_hash_ctrl(struct ena_com_dev *ena_dev)
 
        if (!ena_com_check_supported_feature_id(ena_dev,
                                                ENA_ADMIN_RSS_HASH_INPUT)) {
-               pr_info("Feature %d isn't supported\n", ENA_ADMIN_RSS_HASH_INPUT);
-               return -EPERM;
+               pr_debug("Feature %d isn't supported\n",
+                        ENA_ADMIN_RSS_HASH_INPUT);
+               return -EOPNOTSUPP;
        }
 
        memset(&cmd, 0x0, sizeof(cmd));
@@ -2184,7 +2227,7 @@ int ena_com_set_default_hash_ctrl(struct ena_com_dev *ena_dev)
        hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP4_FRAG].fields =
                ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA;
 
-       hash_ctrl->selected_fields[ENA_ADMIN_RSS_IP4_FRAG].fields =
+       hash_ctrl->selected_fields[ENA_ADMIN_RSS_NOT_IP].fields =
                ENA_ADMIN_RSS_L2_DA | ENA_ADMIN_RSS_L2_SA;
 
        for (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; i++) {
@@ -2194,7 +2237,7 @@ int ena_com_set_default_hash_ctrl(struct ena_com_dev *ena_dev)
                        pr_err("hash control doesn't support all the desire configuration. proto %x supported %x selected %x\n",
                               i, hash_ctrl->supported_fields[i].fields,
                               hash_ctrl->selected_fields[i].fields);
-                       return -EPERM;
+                       return -EOPNOTSUPP;
                }
        }
 
@@ -2270,9 +2313,9 @@ int ena_com_indirect_table_set(struct ena_com_dev *ena_dev)
 
        if (!ena_com_check_supported_feature_id(
                    ena_dev, ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG)) {
-               pr_info("Feature %d isn't supported\n",
-                       ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG);
-               return -EPERM;
+               pr_debug("Feature %d isn't supported\n",
+                        ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG);
+               return -EOPNOTSUPP;
        }
 
        ret = ena_com_ind_tbl_convert_to_device(ena_dev);
@@ -2444,11 +2487,9 @@ int ena_com_set_host_attributes(struct ena_com_dev *ena_dev)
 
        int ret;
 
-       if (!ena_com_check_supported_feature_id(ena_dev,
-                                               ENA_ADMIN_HOST_ATTR_CONFIG)) {
-               pr_warn("Set host attribute isn't supported\n");
-               return -EPERM;
-       }
+       /* Host attribute config is called before ena_com_get_dev_attr_feat
+        * so ena_com can't check if the feature is supported.
+        */
 
        memset(&cmd, 0x0, sizeof(cmd));
        admin_queue = &ena_dev->admin_queue;
@@ -2541,9 +2582,9 @@ int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
                                 ENA_ADMIN_INTERRUPT_MODERATION);
 
        if (rc) {
-               if (rc == -EPERM) {
-                       pr_info("Feature %d isn't supported\n",
-                               ENA_ADMIN_INTERRUPT_MODERATION);
+               if (rc == -EOPNOTSUPP) {
+                       pr_debug("Feature %d isn't supported\n",
+                                ENA_ADMIN_INTERRUPT_MODERATION);
                        rc = 0;
                } else {
                        pr_err("Failed to get interrupt moderation admin cmd. rc: %d\n",