put_unaligned_le32(val, skb_put(skb, 4));
}
-static inline void mt76x0_dma_skb_wrap_cmd(struct sk_buff *skb,
- u8 seq, enum mcu_cmd cmd)
-{
- WARN_ON(mt76x0_dma_skb_wrap(skb, CPU_TX_PORT, DMA_COMMAND,
- FIELD_PREP(MT_TXD_CMD_SEQ, seq) |
- FIELD_PREP(MT_TXD_CMD_TYPE, cmd)));
-}
-
-static inline void trace_mt76x0_mcu_msg_send_cs(struct mt76_dev *dev,
- struct sk_buff *skb, bool need_resp)
-{
- u32 i, csum = 0;
-
- for (i = 0; i < skb->len / 4; i++)
- csum ^= get_unaligned_le32(skb->data + i * 4);
-
- trace_mt76x0_mcu_msg_send(dev, skb, csum, need_resp);
-}
-
-static void mt76x0_read_resp_regs(struct mt76x0_dev *dev, int len)
-{
- int i;
- int n = dev->mcu.reg_pairs_len;
- u8 *buf = dev->mcu.resp.buf;
-
- buf += 4;
- len -= 8;
-
- if (dev->mcu.burst_read) {
- u32 reg = dev->mcu.reg_pairs[0].reg - dev->mcu.reg_base;
-
- WARN_ON_ONCE(len/4 != n);
- for (i = 0; i < n; i++) {
- u32 val = get_unaligned_le32(buf + 4*i);
-
- dev->mcu.reg_pairs[i].reg = reg++;
- dev->mcu.reg_pairs[i].value = val;
- }
- } else {
- WARN_ON_ONCE(len/8 != n);
- for (i = 0; i < n; i++) {
- u32 reg = get_unaligned_le32(buf + 8*i) - dev->mcu.reg_base;
- u32 val = get_unaligned_le32(buf + 8*i + 4);
-
- WARN_ON_ONCE(dev->mcu.reg_pairs[i].reg != reg);
- dev->mcu.reg_pairs[i].value = val;
- }
- }
-}
-
-static int mt76x0_mcu_wait_resp(struct mt76x0_dev *dev, u8 seq)
-{
- struct urb *urb = dev->mcu.resp.urb;
- struct mt76_usb *usb = &dev->mt76.usb;
- u32 rxfce;
- int urb_status, ret, try = 5;
-
- while (try--) {
- if (!wait_for_completion_timeout(&usb->mcu.cmpl,
- msecs_to_jiffies(300))) {
- dev_warn(dev->mt76.dev, "Warning: %s retrying\n", __func__);
- continue;
- }
-
- /* Make copies of important data before reusing the urb */
- rxfce = get_unaligned_le32(dev->mcu.resp.buf);
- urb_status = urb->status * mt76x0_urb_has_error(urb);
-
- if (urb_status == 0 && dev->mcu.reg_pairs)
- mt76x0_read_resp_regs(dev, urb->actual_length);
-
- ret = mt76x0_usb_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
- &dev->mcu.resp, GFP_KERNEL,
- mt76u_mcu_complete_urb,
- &usb->mcu.cmpl);
- if (ret)
- return ret;
-
- if (urb_status)
- dev_err(dev->mt76.dev, "Error: MCU resp urb failed:%d\n",
- urb_status);
-
- if (FIELD_GET(MT_RXD_CMD_INFO_CMD_SEQ, rxfce) == seq &&
- FIELD_GET(MT_RXD_CMD_INFO_EVT_TYPE, rxfce) == CMD_DONE)
- return 0;
-
- dev_err(dev->mt76.dev, "Error: MCU resp evt:%lx seq:%hhx-%lx!\n",
- FIELD_GET(MT_RXD_CMD_INFO_EVT_TYPE, rxfce),
- seq, FIELD_GET(MT_RXD_CMD_INFO_CMD_SEQ, rxfce));
- }
-
- dev_err(dev->mt76.dev, "Error: %s timed out\n", __func__);
- return -ETIMEDOUT;
-}
-
-static int
-__mt76x0_mcu_msg_send(struct mt76x0_dev *dev, struct sk_buff *skb,
- enum mcu_cmd cmd, bool wait_resp)
-{
- struct usb_device *usb_dev = mt76x0_to_usb_dev(dev);
- struct mt76_usb *usb = &dev->mt76.usb;
- unsigned cmd_pipe = usb_sndbulkpipe(usb_dev,
- usb->out_ep[MT_EP_OUT_INBAND_CMD]);
- int sent, ret;
- u8 seq = 0;
-
- if (wait_resp)
- while (!seq)
- seq = ++dev->mcu.msg_seq & 0xf;
-
- mt76x0_dma_skb_wrap_cmd(skb, seq, cmd);
-
- if (&usb->mcu.cmpl.done)
- dev_err(dev->mt76.dev, "Error: MCU response pre-completed!\n");
-
- trace_mt76x0_mcu_msg_send_cs(&dev->mt76, skb, wait_resp);
- trace_mt76x0_submit_urb_sync(&dev->mt76, cmd_pipe, skb->len);
-
- ret = usb_bulk_msg(usb_dev, cmd_pipe, skb->data, skb->len, &sent, 500);
- if (ret) {
- dev_err(dev->mt76.dev, "Error: send MCU cmd failed:%d\n", ret);
- goto out;
- }
- if (sent != skb->len)
- dev_err(dev->mt76.dev, "Error: %s sent != skb->len\n", __func__);
-
- if (wait_resp)
- ret = mt76x0_mcu_wait_resp(dev, seq);
-
-out:
- return ret;
-}
-
-static int
-mt76x0_mcu_msg_send(struct mt76x0_dev *dev, struct sk_buff *skb,
- enum mcu_cmd cmd, bool wait_resp)
-{
- int ret;
-
- if (test_bit(MT76_REMOVED, &dev->mt76.state))
- return 0;
-
- mutex_lock(&dev->mcu.mutex);
- ret = __mt76x0_mcu_msg_send(dev, skb, cmd, wait_resp);
- mutex_unlock(&dev->mcu.mutex);
-
- consume_skb(skb);
-
- return ret;
-}
-
int mt76x0_mcu_function_select(struct mt76x0_dev *dev,
enum mcu_function func, u32 val)
{
skb = mt76u_mcu_msg_alloc(&msg, sizeof(msg));
if (!skb)
return -ENOMEM;
- return mt76x0_mcu_msg_send(dev, skb, CMD_FUN_SET_OP, func == 5);
+ return mt76u_mcu_send_msg(&dev->mt76, skb, CMD_FUN_SET_OP,
+ func == 5);
}
int
skb = mt76u_mcu_msg_alloc(&msg, sizeof(msg));
if (!skb)
return -ENOMEM;
- return mt76x0_mcu_msg_send(dev, skb, CMD_CALIBRATION_OP, true);
+ return mt76u_mcu_send_msg(&dev->mt76, skb, CMD_CALIBRATION_OP,
+ true);
}
int mt76x0_write_reg_pairs(struct mt76x0_dev *dev, u32 base,
skb_put_le32(skb, data[i].value);
}
- ret = mt76x0_mcu_msg_send(dev, skb, CMD_RANDOM_WRITE, cnt == n);
+ ret = mt76u_mcu_send_msg(&dev->mt76, skb, CMD_RANDOM_WRITE,
+ cnt == n);
if (ret)
return ret;
struct mt76_reg_pair *data, int n)
{
const int max_vals_per_cmd = INBAND_PACKET_MAX_LEN / 8;
+ struct mt76_usb *usb = &dev->mt76.usb;
struct sk_buff *skb;
int cnt, i, ret;
skb_put_le32(skb, data[i].value);
}
- mutex_lock(&dev->mcu.mutex);
-
- dev->mcu.reg_pairs = data;
- dev->mcu.reg_pairs_len = n;
- dev->mcu.reg_base = base;
- dev->mcu.burst_read = false;
+ mutex_lock(&usb->mcu.mutex);
- ret = __mt76x0_mcu_msg_send(dev, skb, CMD_RANDOM_READ, true);
+ usb->mcu.rp = data;
+ usb->mcu.rp_len = n;
+ usb->mcu.base = base;
+ usb->mcu.burst = false;
- dev->mcu.reg_pairs = NULL;
+ ret = __mt76u_mcu_send_msg(&dev->mt76, skb, CMD_RANDOM_READ,
+ true);
- mutex_unlock(&dev->mcu.mutex);
+ usb->mcu.rp = NULL;
- consume_skb(skb);
+ mutex_unlock(&usb->mcu.mutex);
return ret;
for (i = 0; i < cnt; i++)
skb_put_le32(skb, data[i]);
- ret = mt76x0_mcu_msg_send(dev, skb, CMD_BURST_WRITE, cnt == n);
+ ret = mt76u_mcu_send_msg(&dev->mt76, skb, CMD_BURST_WRITE,
+ cnt == n);
if (ret)
return ret;
struct mt76_reg_pair *data, int n)
{
const int max_vals_per_cmd = INBAND_PACKET_MAX_LEN / 4 - 1;
+ struct mt76_usb *usb = &dev->mt76.usb;
struct sk_buff *skb;
int cnt, ret;
skb_put_le32(skb, base + data[0].reg);
skb_put_le32(skb, n);
- mutex_lock(&dev->mcu.mutex);
+ mutex_lock(&usb->mcu.mutex);
- dev->mcu.reg_pairs = data;
- dev->mcu.reg_pairs_len = n;
- dev->mcu.reg_base = base;
- dev->mcu.burst_read = true;
+ usb->mcu.rp = data;
+ usb->mcu.rp_len = n;
+ usb->mcu.base = base;
+ usb->mcu.burst = false;
- ret = __mt76x0_mcu_msg_send(dev, skb, CMD_BURST_READ, true);
+ ret = __mt76u_mcu_send_msg(&dev->mt76, skb, CMD_BURST_READ, true);
- dev->mcu.reg_pairs = NULL;
+ usb->mcu.rp = NULL;
- mutex_unlock(&dev->mcu.mutex);
+ mutex_unlock(&usb->mcu.mutex);
consume_skb(skb);
int mt76x0_mcu_cmd_init(struct mt76x0_dev *dev)
{
- struct mt76_usb *usb = &dev->mt76.usb;
- int ret;
-
- ret = mt76x0_mcu_function_select(dev, Q_SELECT, 1);
+ int ret = mt76x0_mcu_function_select(dev, Q_SELECT, 1);
if (ret)
return ret;
- if (mt76x0_usb_alloc_buf(dev, MCU_RESP_URB_SIZE, &dev->mcu.resp)) {
- mt76x0_usb_free_buf(dev, &dev->mcu.resp);
- return -ENOMEM;
- }
-
- ret = mt76x0_usb_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
- &dev->mcu.resp, GFP_KERNEL,
- mt76u_mcu_complete_urb, &usb->mcu.cmpl);
- if (ret) {
- mt76x0_usb_free_buf(dev, &dev->mcu.resp);
- return ret;
- }
-
- return 0;
-}
-
-void mt76x0_mcu_cmd_deinit(struct mt76x0_dev *dev)
-{
- usb_kill_urb(dev->mcu.resp.urb);
- mt76x0_usb_free_buf(dev, &dev->mcu.resp);
+ return mt76u_mcu_init_rx(&dev->mt76);
}