/* block ack control, write: * - "add <ringid> <agg_size> <timeout>" to trigger ADDBA * - "del_tx <ringid> <reason>" to trigger DELBA for Tx side * - "del_rx <CID> <TID> <reason>" to trigger DELBA for Rx side */ static ssize_t wil_write_back(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct wil6210_priv *wil = file->private_data; int rc; char *kbuf = kmalloc(len + 1, GFP_KERNEL); char cmd[9]; int p1, p2, p3; if (!kbuf) return -ENOMEM; rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); if (rc != len) { kfree(kbuf); return rc >= 0 ? -EIO : rc; } kbuf[len] = '\0'; rc = sscanf(kbuf, "%8s %d %d %d", cmd, &p1, &p2, &p3); kfree(kbuf); if (rc < 0) return rc; if (rc < 2) return -EINVAL; if (0 == strcmp(cmd, "add")) { if (rc < 3) { wil_err(wil, "BACK: add require at least 2 params\n"); return -EINVAL; } if (rc < 4) p3 = 0; wmi_addba(wil, p1, p2, p3); } else if (0 == strcmp(cmd, "del_tx")) { if (rc < 3) p2 = WLAN_REASON_QSTA_LEAVE_QBSS; wmi_delba_tx(wil, p1, p2); } else if (0 == strcmp(cmd, "del_rx")) { if (rc < 3) { wil_err(wil, "BACK: del_rx require at least 2 params\n"); return -EINVAL; } if (rc < 4) p3 = WLAN_REASON_QSTA_LEAVE_QBSS; wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3); } else { wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); return -EINVAL; } return len; }
/* block ack control, write: * - "add <ringid> <agg_size> <timeout>" to trigger ADDBA * - "del_tx <ringid> <reason>" to trigger DELBA for Tx side * - "del_rx <CID> <TID> <reason>" to trigger DELBA for Rx side */ static ssize_t wil_write_back(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct wil6210_priv *wil = file->private_data; int rc; char *kbuf = kmalloc(len + 1, GFP_KERNEL); char cmd[9]; int p1, p2, p3; if (!kbuf) return -ENOMEM; rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); if (rc != len) { kfree(kbuf); return rc >= 0 ? -EIO : rc; } kbuf[len] = '\0'; rc = sscanf(kbuf, "%8s %d %d %d", cmd, &p1, &p2, &p3); kfree(kbuf); if (rc < 0) return rc; if (rc < 2) return -EINVAL; if ((strcmp(cmd, "add") == 0) || (strcmp(cmd, "del_tx") == 0)) { struct vring_tx_data *txdata; if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) { wil_err(wil, "BACK: invalid ring id %d\n", p1); return -EINVAL; } txdata = &wil->vring_tx_data[p1]; if (strcmp(cmd, "add") == 0) { if (rc < 3) { wil_err(wil, "BACK: add require at least 2 params\n"); return -EINVAL; } if (rc < 4) p3 = 0; wmi_addba(wil, txdata->mid, p1, p2, p3); } else { if (rc < 3) p2 = WLAN_REASON_QSTA_LEAVE_QBSS; wmi_delba_tx(wil, txdata->mid, p1, p2); } } else if (strcmp(cmd, "del_rx") == 0) { struct wil_sta_info *sta; if (rc < 3) { wil_err(wil, "BACK: del_rx require at least 2 params\n"); return -EINVAL; } if (p1 < 0 || p1 >= WIL6210_MAX_CID) { wil_err(wil, "BACK: invalid CID %d\n", p1); return -EINVAL; } if (rc < 4) p3 = WLAN_REASON_QSTA_LEAVE_QBSS; sta = &wil->sta[p1]; wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3); } else { wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); return -EINVAL; } return len; }