* state
* @urb: an urb for a transfer to this endpoint
*/
-static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
+static void qset_fill_qh(struct whc *whc, struct whc_qset *qset, struct urb *urb)
{
struct usb_device *usb_dev = urb->dev;
+ struct wusb_dev *wusb_dev = usb_dev->wusb_dev;
struct usb_wireless_ep_comp_descriptor *epcd;
bool is_out;
+ uint8_t phy_rate;
is_out = usb_pipeout(urb->pipe);
qset->max_burst = 1;
}
+ /*
+ * Initial PHY rate is 53.3 Mbit/s for control endpoints or
+ * the maximum supported by the device for other endpoints
+ * (unless limited by the user).
+ */
+ if (usb_pipecontrol(urb->pipe))
+ phy_rate = UWB_PHY_RATE_53;
+ else {
+ uint16_t phy_rates;
+
+ phy_rates = le16_to_cpu(wusb_dev->wusb_cap_descr->wPHYRates);
+ phy_rate = fls(phy_rates) - 1;
+ if (phy_rate > whc->wusbhc.phy_rate)
+ phy_rate = whc->wusbhc.phy_rate;
+ }
+
qset->qh.info1 = cpu_to_le32(
QH_INFO1_EP(usb_pipeendpoint(urb->pipe))
| (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN)
* strength and can presumably guess the Tx power required
* from that? */
qset->qh.info3 = cpu_to_le32(
- QH_INFO3_TX_RATE_53_3
+ QH_INFO3_TX_RATE(phy_rate)
| QH_INFO3_TX_PWR(0) /* 0 == max power */
);
qset->ep = urb->ep;
urb->ep->hcpriv = qset;
- qset_fill_qh(qset, urb);
+ qset_fill_qh(whc, qset, urb);
}
return qset;
}
size_t pl_len;
int p = 0;
- dev_dbg(&whc->umc->dev, "adding urb w/ sg of length %d\n", urb->transfer_buffer_length);
-
remaining = urb->transfer_buffer_length;
for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) {
}
dma_addr = sg_dma_address(sg);
- dma_remaining = min(sg_dma_len(sg), remaining);
-
- dev_dbg(&whc->umc->dev, "adding sg[%d] %08x %d\n", i, (unsigned)dma_addr,
- dma_remaining);
+ dma_remaining = min_t(size_t, sg_dma_len(sg), remaining);
while (dma_remaining) {
size_t dma_len;
* - the previous one isn't full.
*
* If a new std is needed but the previous one
- * did not end on a wMaxPacketSize boundary
- * then this sg list cannot be mapped onto
- * multiple qTDs. Return an error and let the
- * caller sort it out.
+ * was not a whole number of packets then this
+ * sg list cannot be mapped onto multiple
+ * qTDs. Return an error and let the caller
+ * sort it out.
*/
if (!std
|| (prev_end & (WHCI_PAGE_SIZE-1))
|| (dma_addr & (WHCI_PAGE_SIZE-1))
|| std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) {
- if (prev_end % qset->max_packet != 0)
+ if (std->len % qset->max_packet != 0)
return -EINVAL;
- dev_dbg(&whc->umc->dev, "need new std\n");
std = qset_new_std(whc, qset, urb, mem_flags);
if (std == NULL) {
return -ENOMEM;
dma_len = dma_remaining;
/*
- * If the remainder in this element doesn't
- * fit in a single qTD, end the qTD on a
- * wMaxPacketSize boundary.
+ * If the remainder of this element doesn't
+ * fit in a single qTD, limit the qTD to a
+ * whole number of packets. This allows the
+ * remainder to go into the next qTD.
*/
if (std->len + dma_len > QTD_MAX_XFER_SIZE) {
- dma_len = QTD_MAX_XFER_SIZE - std->len;
- ep = ((dma_addr + dma_len) / qset->max_packet) * qset->max_packet;
- dma_len = ep - dma_addr;
+ dma_len = (QTD_MAX_XFER_SIZE / qset->max_packet)
+ * qset->max_packet - std->len;
}
- dev_dbg(&whc->umc->dev, "adding %d\n", dma_len);
-
std->len += dma_len;
std->ntds_remaining = -1; /* filled in later */
num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE);
std->num_pointers += num_pointers;
- dev_dbg(&whc->umc->dev, "need %d more (%d total) page pointers\n",
- num_pointers, std->num_pointers);
-
pl_len = std->num_pointers * sizeof(struct whc_page_list_entry);
std->pl_virt = krealloc(std->pl_virt, pl_len, mem_flags);
}
for (;p < std->num_pointers; p++, entry++) {
- dev_dbg(&whc->umc->dev, "e[%d] %08x\n", p, dma_addr);
std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr);
dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1);
}
}
}
- dev_dbg(&whc->umc->dev, "used %d tds\n", ntds);
-
/* Now the number of stds is know, go back and fill in
std->ntds_remaining. */
list_for_each_entry(std, &qset->stds, list_node) {
break;
}
- sg_remaining = min(remaining, sg->length);
+ sg_remaining = min_t(size_t, remaining, sg->length);
orig = sg_virt(sg);
- dev_dbg(&whc->umc->dev, "adding sg[%d] %d\n", i, sg_remaining);
-
while (sg_remaining) {
if (!std || std->len == max_std_len) {
- dev_dbg(&whc->umc->dev, "need new std\n");
std = qset_new_std(whc, qset, urb, mem_flags);
if (std == NULL)
return -ENOMEM;
len = min(sg_remaining, max_std_len - std->len);
- dev_dbg(&whc->umc->dev, "added %d from sg[%d] @ offset %d\n",
- len, i, orig - sg_virt(sg));
-
if (is_out)
memcpy(bounce, orig, len);
if (urb->sg) {
ret = qset_add_urb_sg(whc, qset, urb, mem_flags);
if (ret == -EINVAL) {
- dev_dbg(&whc->umc->dev, "linearizing %d octet urb\n",
- urb->transfer_buffer_length);
qset_free_stds(qset, urb);
ret = qset_add_urb_sg_linearize(whc, qset, urb, mem_flags);
}