0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/dmapool.h>
0034 #include "hns_roce_common.h"
0035 #include "hns_roce_device.h"
0036 #include "hns_roce_cmd.h"
0037
0038 #define CMD_POLL_TOKEN 0xffff
0039 #define CMD_MAX_NUM 32
0040
0041 static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev,
0042 struct hns_roce_mbox_msg *mbox_msg)
0043 {
0044 return hr_dev->hw->post_mbox(hr_dev, mbox_msg);
0045 }
0046
0047
0048 static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev,
0049 struct hns_roce_mbox_msg *mbox_msg)
0050 {
0051 int ret;
0052
0053 ret = hns_roce_cmd_mbox_post_hw(hr_dev, mbox_msg);
0054 if (ret) {
0055 dev_err_ratelimited(hr_dev->dev,
0056 "failed to post mailbox 0x%x in poll mode, ret = %d.\n",
0057 mbox_msg->cmd, ret);
0058 return ret;
0059 }
0060
0061 return hr_dev->hw->poll_mbox_done(hr_dev);
0062 }
0063
0064 static int hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev,
0065 struct hns_roce_mbox_msg *mbox_msg)
0066 {
0067 int ret;
0068
0069 down(&hr_dev->cmd.poll_sem);
0070 ret = __hns_roce_cmd_mbox_poll(hr_dev, mbox_msg);
0071 up(&hr_dev->cmd.poll_sem);
0072
0073 return ret;
0074 }
0075
0076 void hns_roce_cmd_event(struct hns_roce_dev *hr_dev, u16 token, u8 status,
0077 u64 out_param)
0078 {
0079 struct hns_roce_cmd_context *context =
0080 &hr_dev->cmd.context[token % hr_dev->cmd.max_cmds];
0081
0082 if (unlikely(token != context->token)) {
0083 dev_err_ratelimited(hr_dev->dev,
0084 "[cmd] invalid ae token 0x%x, context token is 0x%x.\n",
0085 token, context->token);
0086 return;
0087 }
0088
0089 context->result = (status == HNS_ROCE_CMD_SUCCESS) ? 0 : (-EIO);
0090 context->out_param = out_param;
0091 complete(&context->done);
0092 }
0093
0094 static int __hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev,
0095 struct hns_roce_mbox_msg *mbox_msg)
0096 {
0097 struct hns_roce_cmdq *cmd = &hr_dev->cmd;
0098 struct hns_roce_cmd_context *context;
0099 struct device *dev = hr_dev->dev;
0100 int ret;
0101
0102 spin_lock(&cmd->context_lock);
0103
0104 do {
0105 context = &cmd->context[cmd->free_head];
0106 cmd->free_head = context->next;
0107 } while (context->busy);
0108
0109 context->busy = 1;
0110 context->token += cmd->max_cmds;
0111
0112 spin_unlock(&cmd->context_lock);
0113
0114 reinit_completion(&context->done);
0115
0116 mbox_msg->token = context->token;
0117 ret = hns_roce_cmd_mbox_post_hw(hr_dev, mbox_msg);
0118 if (ret) {
0119 dev_err_ratelimited(dev,
0120 "failed to post mailbox 0x%x in event mode, ret = %d.\n",
0121 mbox_msg->cmd, ret);
0122 goto out;
0123 }
0124
0125 if (!wait_for_completion_timeout(&context->done,
0126 msecs_to_jiffies(HNS_ROCE_CMD_TIMEOUT_MSECS))) {
0127 dev_err_ratelimited(dev, "[cmd] token 0x%x mailbox 0x%x timeout.\n",
0128 context->token, mbox_msg->cmd);
0129 ret = -EBUSY;
0130 goto out;
0131 }
0132
0133 ret = context->result;
0134 if (ret)
0135 dev_err_ratelimited(dev, "[cmd] token 0x%x mailbox 0x%x error %d.\n",
0136 context->token, mbox_msg->cmd, ret);
0137
0138 out:
0139 context->busy = 0;
0140 return ret;
0141 }
0142
0143 static int hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev,
0144 struct hns_roce_mbox_msg *mbox_msg)
0145 {
0146 int ret;
0147
0148 down(&hr_dev->cmd.event_sem);
0149 ret = __hns_roce_cmd_mbox_wait(hr_dev, mbox_msg);
0150 up(&hr_dev->cmd.event_sem);
0151
0152 return ret;
0153 }
0154
0155 int hns_roce_cmd_mbox(struct hns_roce_dev *hr_dev, u64 in_param, u64 out_param,
0156 u8 cmd, unsigned long tag)
0157 {
0158 struct hns_roce_mbox_msg mbox_msg = {};
0159 bool is_busy;
0160
0161 if (hr_dev->hw->chk_mbox_avail)
0162 if (!hr_dev->hw->chk_mbox_avail(hr_dev, &is_busy))
0163 return is_busy ? -EBUSY : 0;
0164
0165 mbox_msg.in_param = in_param;
0166 mbox_msg.out_param = out_param;
0167 mbox_msg.cmd = cmd;
0168 mbox_msg.tag = tag;
0169
0170 if (hr_dev->cmd.use_events) {
0171 mbox_msg.event_en = 1;
0172
0173 return hns_roce_cmd_mbox_wait(hr_dev, &mbox_msg);
0174 } else {
0175 mbox_msg.event_en = 0;
0176 mbox_msg.token = CMD_POLL_TOKEN;
0177
0178 return hns_roce_cmd_mbox_poll(hr_dev, &mbox_msg);
0179 }
0180 }
0181
0182 int hns_roce_cmd_init(struct hns_roce_dev *hr_dev)
0183 {
0184 sema_init(&hr_dev->cmd.poll_sem, 1);
0185 hr_dev->cmd.use_events = 0;
0186 hr_dev->cmd.max_cmds = CMD_MAX_NUM;
0187 hr_dev->cmd.pool = dma_pool_create("hns_roce_cmd", hr_dev->dev,
0188 HNS_ROCE_MAILBOX_SIZE,
0189 HNS_ROCE_MAILBOX_SIZE, 0);
0190 if (!hr_dev->cmd.pool)
0191 return -ENOMEM;
0192
0193 return 0;
0194 }
0195
0196 void hns_roce_cmd_cleanup(struct hns_roce_dev *hr_dev)
0197 {
0198 dma_pool_destroy(hr_dev->cmd.pool);
0199 }
0200
0201 int hns_roce_cmd_use_events(struct hns_roce_dev *hr_dev)
0202 {
0203 struct hns_roce_cmdq *hr_cmd = &hr_dev->cmd;
0204 int i;
0205
0206 hr_cmd->context =
0207 kcalloc(hr_cmd->max_cmds, sizeof(*hr_cmd->context), GFP_KERNEL);
0208 if (!hr_cmd->context) {
0209 hr_dev->cmd_mod = 0;
0210 return -ENOMEM;
0211 }
0212
0213 for (i = 0; i < hr_cmd->max_cmds; ++i) {
0214 hr_cmd->context[i].token = i;
0215 hr_cmd->context[i].next = i + 1;
0216 init_completion(&hr_cmd->context[i].done);
0217 }
0218 hr_cmd->context[hr_cmd->max_cmds - 1].next = 0;
0219 hr_cmd->free_head = 0;
0220
0221 sema_init(&hr_cmd->event_sem, hr_cmd->max_cmds);
0222 spin_lock_init(&hr_cmd->context_lock);
0223
0224 hr_cmd->use_events = 1;
0225
0226 return 0;
0227 }
0228
0229 void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev)
0230 {
0231 struct hns_roce_cmdq *hr_cmd = &hr_dev->cmd;
0232
0233 kfree(hr_cmd->context);
0234 hr_cmd->use_events = 0;
0235 }
0236
0237 struct hns_roce_cmd_mailbox *
0238 hns_roce_alloc_cmd_mailbox(struct hns_roce_dev *hr_dev)
0239 {
0240 struct hns_roce_cmd_mailbox *mailbox;
0241
0242 mailbox = kmalloc(sizeof(*mailbox), GFP_KERNEL);
0243 if (!mailbox)
0244 return ERR_PTR(-ENOMEM);
0245
0246 mailbox->buf =
0247 dma_pool_alloc(hr_dev->cmd.pool, GFP_KERNEL, &mailbox->dma);
0248 if (!mailbox->buf) {
0249 kfree(mailbox);
0250 return ERR_PTR(-ENOMEM);
0251 }
0252
0253 return mailbox;
0254 }
0255
0256 void hns_roce_free_cmd_mailbox(struct hns_roce_dev *hr_dev,
0257 struct hns_roce_cmd_mailbox *mailbox)
0258 {
0259 if (!mailbox)
0260 return;
0261
0262 dma_pool_free(hr_dev->cmd.pool, mailbox->buf, mailbox->dma);
0263 kfree(mailbox);
0264 }
0265
0266 int hns_roce_create_hw_ctx(struct hns_roce_dev *dev,
0267 struct hns_roce_cmd_mailbox *mailbox,
0268 u8 cmd, unsigned long idx)
0269 {
0270 return hns_roce_cmd_mbox(dev, mailbox->dma, 0, cmd, idx);
0271 }
0272
0273 int hns_roce_destroy_hw_ctx(struct hns_roce_dev *dev, u8 cmd, unsigned long idx)
0274 {
0275 return hns_roce_cmd_mbox(dev, 0, 0, cmd, idx);
0276 }