Example #1
0
int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
                                   const u8 request, const u8 requesttype,
                                   const u16 offset, void *buffer,
                                   const u16 buffer_length, const int timeout)
{
    int status;

    BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex));

    /*
     * Check for Cache availability.
     */
    if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
        rt2x00_err(rt2x00dev, "CSR cache not available\n");
        return -ENOMEM;
    }

    if (requesttype == USB_VENDOR_REQUEST_OUT)
        memcpy(rt2x00dev->csr.cache, buffer, buffer_length);

    status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
                                      offset, 0, rt2x00dev->csr.cache,
                                      buffer_length, timeout);

    if (!status && requesttype == USB_VENDOR_REQUEST_IN)
        memcpy(buffer, rt2x00dev->csr.cache, buffer_length);

    return status;
}
static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
{
	unsigned int i;
	u32 reg;

	/*
	 * SOC devices don't support MCU requests.
	 */
	if (rt2x00_is_soc(rt2x00dev))
		return;

	for (i = 0; i < 200; i++) {
		rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);

		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) ||
		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token))
			break;

		udelay(REGISTER_BUSY_DELAY);
	}

	if (i == 200)
		rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");

	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
}
static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
{
	const struct firmware *ee;
	const char *ee_name;
	int retval;

	if (!rt2800lib_read_eeprom_mtd(rt2x00dev))
		return 0;

	ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
	if (!ee_name) {
		rt2x00_err(rt2x00dev,
			   "Invalid EEPROM filename.\n"
			   "Please file bug report to %s.\n", DRV_PROJECT);
		return -EINVAL;
	}

	rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);

	retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
	if (retval) {
		rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n");
		return retval;
	}

	if (!ee || !ee->size || !ee->data) {
		rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n");
		retval = -ENOENT;
		goto err_exit;
	}

	if (ee->size != rt2x00dev->ops->eeprom_size) {
		rt2x00_err(rt2x00dev,
			   "EEPROM file size is invalid, it should be %d bytes\n",
			   rt2x00dev->ops->eeprom_size);
		retval = -EINVAL;
		goto err_release_ee;
	}

	rt2x00dev->eeprom_file = ee;
	return 0;

err_release_ee:
	release_firmware(ee);
err_exit:
	return retval;
}
Example #4
0
int rt2x00pci_resume(struct pci_dev *pci_dev)
{
    struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
    struct rt2x00_dev *rt2x00dev = hw->priv;

    if (pci_set_power_state(pci_dev, PCI_D0) ||
            pci_enable_device(pci_dev)) {
        rt2x00_err(rt2x00dev, "Failed to resume device\n");
        return -EIO;
    }

    pci_restore_state(pci_dev);
    return rt2x00lib_resume(rt2x00dev);
}
Example #5
0
static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
{
    struct usb_interface *intf = to_usb_interface(rt2x00dev->dev);
    struct usb_host_interface *intf_desc = intf->cur_altsetting;
    struct usb_endpoint_descriptor *ep_desc;
    struct data_queue *queue = rt2x00dev->tx;
    struct usb_endpoint_descriptor *tx_ep_desc = NULL;
    unsigned int i;

    /*
     * Walk through all available endpoints to search for "bulk in"
     * and "bulk out" endpoints. When we find such endpoints collect
     * the information we need from the descriptor and assign it
     * to the queue.
     */
    for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
        ep_desc = &intf_desc->endpoint[i].desc;

        if (usb_endpoint_is_bulk_in(ep_desc)) {
            rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
        } else if (usb_endpoint_is_bulk_out(ep_desc) &&
                   (queue != queue_end(rt2x00dev))) {
            rt2x00usb_assign_endpoint(queue, ep_desc);
            queue = queue_next(queue);

            tx_ep_desc = ep_desc;
        }
    }

    /*
     * At least 1 endpoint for RX and 1 endpoint for TX must be available.
     */
    if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
        rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
        return -EPIPE;
    }

    /*
     * It might be possible not all queues have a dedicated endpoint.
     * Loop through all TX queues and copy the endpoint information
     * which we have gathered from already assigned endpoints.
     */
    txall_queue_for_each(rt2x00dev, queue) {
        if (!queue->usb_endpoint)
            rt2x00usb_assign_endpoint(queue, tx_ep_desc);
    }

    return 0;
}
Example #6
0
/*
 * Interfacing with the HW.
 */
int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
                             const u8 request, const u8 requesttype,
                             const u16 offset, const u16 value,
                             void *buffer, const u16 buffer_length,
                             const int timeout)
{
    struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
    int status;
    unsigned int i;
    unsigned int pipe =
        (requesttype == USB_VENDOR_REQUEST_IN) ?
        usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);

    if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
        return -ENODEV;

    for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
        status = usb_control_msg(usb_dev, pipe, request, requesttype,
                                 value, offset, buffer, buffer_length,
                                 timeout);
        if (status >= 0)
            return 0;

        /*
         * Check for errors
         * -ENODEV: Device has disappeared, no point continuing.
         * All other errors: Try again.
         */
        else if (status == -ENODEV) {
            clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
            break;
        }
    }

    rt2x00_err(rt2x00dev,
               "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
               request, offset, status);

    return status;
}
Example #7
0
static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
				      enum dev_state state)
{
	int retval = 0;

	switch (state) {
	case STATE_RADIO_ON:
		retval = rt2800mmio_enable_radio(rt2x00dev);
		break;

	case STATE_RADIO_OFF:
		rt2800soc_disable_radio(rt2x00dev);
		break;

	case STATE_RADIO_IRQ_ON:
	case STATE_RADIO_IRQ_OFF:
		rt2800mmio_toggle_irq(rt2x00dev, state);
		break;

	case STATE_DEEP_SLEEP:
	case STATE_SLEEP:
	case STATE_STANDBY:
	case STATE_AWAKE:
		/* These states are not supported, but don't report an error */
		retval = 0;
		break;

	default:
		retval = -ENOTSUPP;
		break;
	}

	if (unlikely(retval))
		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
			   state, retval);

	return retval;
}
Example #8
0
static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
				      enum dev_state state)
{
	int retval = 0;

	switch (state) {
	case STATE_RADIO_ON:
		retval = rt2800pci_enable_radio(rt2x00dev);
		break;
	case STATE_RADIO_OFF:
		/*
		 * After the radio has been disabled, the device should
		 * be put to sleep for powersaving.
		 */
		rt2800pci_disable_radio(rt2x00dev);
		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
		break;
	case STATE_RADIO_IRQ_ON:
	case STATE_RADIO_IRQ_OFF:
		rt2800pci_toggle_irq(rt2x00dev, state);
		break;
	case STATE_DEEP_SLEEP:
	case STATE_SLEEP:
	case STATE_STANDBY:
	case STATE_AWAKE:
		retval = rt2800pci_set_state(rt2x00dev, state);
		break;
	default:
		retval = -ENOTSUPP;
		break;
	}

	if (unlikely(retval))
		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
			   state, retval);

	return retval;
}
Example #9
0
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
                           const unsigned int offset,
                           const struct rt2x00_field32 field,
                           u32 *reg)
{
    unsigned int i;

    if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
        return -ENODEV;

    for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
        rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
        if (!rt2x00_get_field32(*reg, field))
            return 1;
        udelay(REGISTER_BUSY_DELAY);
    }

    rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
               offset, *reg);
    *reg = ~0;

    return 0;
}
Example #10
0
/*
 * Interfacing with the HW.
 */
int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
			     const u8 request, const u8 requesttype,
			     const u16 offset, const u16 value,
			     void *buffer, const u16 buffer_length,
			     const int timeout)
{
	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
	int status;
	unsigned int pipe =
	    (requesttype == USB_VENDOR_REQUEST_IN) ?
	    usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
	unsigned long expire = jiffies + msecs_to_jiffies(timeout);

	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
		return -ENODEV;

	do {
		status = usb_control_msg(usb_dev, pipe, request, requesttype,
					 value, offset, buffer, buffer_length,
					 timeout / 2);
		if (status >= 0)
			return 0;

		if (status == -ENODEV) {
			/* Device has disappeared. */
			clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
			break;
		}
	} while (time_before(jiffies, expire));

	rt2x00_err(rt2x00dev,
		   "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
		   request, offset, status);

	return status;
}
Example #11
0
void rt2x00mac_tx(struct ieee80211_hw *hw,
		  struct ieee80211_tx_control *control,
		  struct sk_buff *skb)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	enum data_queue_qid qid = skb_get_queue_mapping(skb);
	struct data_queue *queue = NULL;

	/*
	 * Mac80211 might be calling this function while we are trying
	 * to remove the device or perhaps suspending it.
	 * Note that we can only stop the TX queues inside the TX path
	 * due to possible race conditions in mac80211.
	 */
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
		goto exit_free_skb;

	/*
	 * Use the ATIM queue if appropriate and present.
	 */
	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
	    test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags))
		qid = QID_ATIM;

	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
	if (unlikely(!queue)) {
		rt2x00_err(rt2x00dev,
			   "Attempt to send packet over invalid queue %d\n"
			   "Please file bug report to %s\n", qid, DRV_PROJECT);
		goto exit_free_skb;
	}

	/*
	 * If CTS/RTS is required. create and queue that frame first.
	 * Make sure we have at least enough entries available to send
	 * this CTS/RTS frame as well as the data frame.
	 * Note that when the driver has set the set_rts_threshold()
	 * callback function it doesn't need software generation of
	 * either RTS or CTS-to-self frame and handles everything
	 * inside the hardware.
	 */
	if (!rt2x00dev->ops->hw->set_rts_threshold &&
	    (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
						IEEE80211_TX_RC_USE_CTS_PROTECT))) {
		if (rt2x00queue_available(queue) <= 1)
			goto exit_fail;

		if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb))
			goto exit_fail;
	}

	if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false)))
		goto exit_fail;

	/*
	 * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
	 * we should not use spin_lock_bh variant as bottom halve was already
	 * disabled before ieee80211_xmit() call.
	 */
	spin_lock(&queue->tx_lock);
	if (rt2x00queue_threshold(queue))
		rt2x00queue_pause_queue(queue);
	spin_unlock(&queue->tx_lock);

	return;

 exit_fail:
	spin_lock(&queue->tx_lock);
	rt2x00queue_pause_queue(queue);
	spin_unlock(&queue->tx_lock);
 exit_free_skb:
	ieee80211_free_txskb(hw, skb);
}
Example #12
0
static int rt2x00lib_reject_firmware(struct rt2x00_dev *rt2x00dev)
{
	struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
	const struct firmware *fw;
	char *fw_name;
	int retval;

	/*
	 * Read correct firmware from harddisk.
	 */
	fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
	if (!fw_name) {
		rt2x00_err(rt2x00dev,
			   "Invalid firmware filename\n"
			   "Please file bug report to %s\n", DRV_PROJECT);
		return -EINVAL;
	}

	rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);

	retval = reject_firmware(&fw, fw_name, device);
	if (retval) {
		rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
		return retval;
	}

	if (!fw || !fw->size || !fw->data) {
		rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
		release_firmware(fw);
		return -ENOENT;
	}

	rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n",
		    fw->data[fw->size - 4], fw->data[fw->size - 3]);
	snprintf(rt2x00dev->hw->wiphy->fw_version,
			sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
			fw->data[fw->size - 4], fw->data[fw->size - 3]);

	retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
	switch (retval) {
	case FW_OK:
		break;
	case FW_BAD_CRC:
		rt2x00_err(rt2x00dev, "Firmware checksum error\n");
		goto exit;
	case FW_BAD_LENGTH:
		rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n",
			   fw->size);
		goto exit;
	case FW_BAD_VERSION:
		rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");
		goto exit;
	}

	rt2x00dev->fw = fw;

	return 0;

exit:
	release_firmware(fw);

	return -ENOENT;
}