/* Returns 1 if the data packet is for us and 0 otherwise. */ static int is_data_packet_for_us(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *hdr) { struct net_device *netdev = ieee->dev; u16 fc = le16_to_cpu(hdr->frame_ctl); ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA); switch (ieee->iw_mode) { case IW_MODE_ADHOC: if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 || memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0) return 0; break; case IW_MODE_AUTO: case IW_MODE_INFRA: if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != IEEE80211_FCTL_FROMDS || memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0) return 0; break; default: ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR); return 0; } return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || (is_multicast_ether_addr(hdr->addr1) && memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) || (netdev->flags & IFF_PROMISC); }
static void rx_urb_complete(struct urb *urb) { struct zd_usb *usb; struct zd_usb_rx *rx; const u8 *buffer; unsigned int length; switch (urb->status) { case 0: break; case -ESHUTDOWN: case -EINVAL: case -ENODEV: case -ENOENT: case -ECONNRESET: case -EPIPE: return; default: dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); goto resubmit; } buffer = urb->transfer_buffer; length = urb->actual_length; usb = urb->context; rx = &usb->rx; if (length%rx->usb_packet_size > rx->usb_packet_size-4) { /* If there is an old first fragment, we don't care. */ dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment)); spin_lock(&rx->lock); memcpy(rx->fragment, buffer, length); rx->fragment_length = length; spin_unlock(&rx->lock); goto resubmit; } spin_lock(&rx->lock); if (rx->fragment_length > 0) { /* We are on a second fragment, we believe */ ZD_ASSERT(length + rx->fragment_length <= ARRAY_SIZE(rx->fragment)); dev_dbg_f(urb_dev(urb), "*** second fragment ***\n"); memcpy(rx->fragment+rx->fragment_length, buffer, length); handle_rx_packet(usb, rx->fragment, rx->fragment_length + length); rx->fragment_length = 0; spin_unlock(&rx->lock); } else { spin_unlock(&rx->lock); handle_rx_packet(usb, buffer, length); } resubmit: usb_submit_urb(urb, GFP_ATOMIC); }
static int fill_ctrlset(struct zd_mac *mac, struct sk_buff *skb, struct ieee80211_tx_control *control) { int r; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; unsigned int frag_len = skb->len + FCS_LEN; unsigned int packet_length; struct zd_ctrlset *cs = (struct zd_ctrlset *) skb_push(skb, sizeof(struct zd_ctrlset)); ZD_ASSERT(frag_len <= 0xffff); cs->modulation = control->tx_rate->hw_value; if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) cs->modulation = control->tx_rate->hw_value_short; cs->tx_length = cpu_to_le16(frag_len); cs_set_control(mac, cs, hdr, control->flags); packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; ZD_ASSERT(packet_length <= 0xffff); /* ZD1211B: Computing the length difference this way, gives us * flexibility to compute the packet length. */ cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ? packet_length - frag_len : packet_length); /* * CURRENT LENGTH: * - transmit frame length in microseconds * - seems to be derived from frame length * - see Cal_Us_Service() in zdinlinef.h * - if macp->bTxBurstEnable is enabled, then multiply by 4 * - bTxBurstEnable is never set in the vendor driver * * SERVICE: * - "for PLCP configuration" * - always 0 except in some situations at 802.11b 11M * - see line 53 of zdinlinef.h */ cs->service = 0; r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation), le16_to_cpu(cs->tx_length)); if (r < 0) return r; cs->current_length = cpu_to_le16(r); cs->next_frame_length = 0; return 0; }
int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain) { int r; u8 channel; ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&mac->lock); if (regdomain == 0) { regdomain = mac->default_regdomain; } if (!zd_regdomain_supported(regdomain)) { spin_unlock_irq(&mac->lock); return -EINVAL; } mac->regdomain = regdomain; channel = mac->requested_channel; spin_unlock_irq(&mac->lock); r = zd_geo_init(zd_mac_to_ieee80211(mac), regdomain); if (r) return r; if (!zd_regdomain_supports_channel(regdomain, channel)) { r = reset_channel(mac); if (r) return r; } return 0; }
void zd_mac_clear(struct zd_mac *mac) { flush_workqueue(zd_workqueue); zd_chip_clear(&mac->chip); ZD_ASSERT(!spin_is_locked(&mac->lock)); ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); }
static inline void handle_regs_int(struct urb *urb) { struct zd_usb *usb = urb->context; struct zd_usb_interrupt *intr = &usb->intr; int len; u16 int_num; ZD_ASSERT(in_interrupt()); spin_lock(&intr->lock); int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2)); if (int_num == CR_INTERRUPT) { struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); spin_lock(&mac->lock); memcpy(&mac->intr_buffer, urb->transfer_buffer, USB_MAX_EP_INT_BUFFER); spin_unlock(&mac->lock); schedule_work(&mac->process_intr); } else if (intr->read_regs_enabled) { intr->read_regs.length = len = urb->actual_length; if (len > sizeof(intr->read_regs.buffer)) len = sizeof(intr->read_regs.buffer); memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); intr->read_regs_enabled = 0; complete(&intr->read_regs.completion); goto out; } out: spin_unlock(&intr->lock); }
static int read_e2p_mac_addr(struct zd_chip *chip) { static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; ZD_ASSERT(mutex_is_locked(&chip->mutex)); return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr); }
int zd_mac_set_mode(struct zd_mac *mac, u32 mode) { struct ieee80211_device *ieee; switch (mode) { case IW_MODE_AUTO: case IW_MODE_ADHOC: case IW_MODE_INFRA: mac->netdev->type = ARPHRD_ETHER; break; case IW_MODE_MONITOR: mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP; break; default: dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode); return -EINVAL; } ieee = zd_mac_to_ieee80211(mac); ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&ieee->lock); ieee->iw_mode = mode; spin_unlock_irq(&ieee->lock); if (netif_running(mac->netdev)) return reset_mode(mac); return 0; }
int zd_iowrite16a_locked(struct zd_chip *chip, const struct zd_ioreq16 *ioreqs, unsigned int count) { int r; unsigned int i, j, t, max; ZD_ASSERT(mutex_is_locked(&chip->mutex)); for (i = 0; i < count; i += j + t) { t = 0; max = count-i; if (max > USB_MAX_IOWRITE16_COUNT) max = USB_MAX_IOWRITE16_COUNT; for (j = 0; j < max; j++) { if (!ioreqs[i+j].addr) { t = 1; break; } } r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j); if (r) { dev_dbg_f(zd_chip_dev(chip), "error zd_usb_iowrite16v. Error number %d\n", r); return r; } } return 0; }
void zd_chip_clear(struct zd_chip *chip) { ZD_ASSERT(!mutex_is_locked(&chip->mutex)); zd_usb_clear(&chip->usb); zd_rf_clear(&chip->rf); mutex_destroy(&chip->mutex); ZD_MEMCLEAR(chip, sizeof(*chip)); }
int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) { int i; const struct channel_range *channel_range; u8 regdomain; memset(range, 0, sizeof(*range)); /* FIXME: Not so important and depends on the mode. For 802.11g * usually this value is used. It seems to be that Bit/s number is * given here. */ range->throughput = 27 * 1000 * 1000; range->max_qual.qual = 100; range->max_qual.level = 100; /* FIXME: Needs still to be tuned. */ range->avg_qual.qual = 71; range->avg_qual.level = 80; /* FIXME: depends on standard? */ range->min_rts = 256; range->max_rts = 2346; range->min_frag = MIN_FRAG_THRESHOLD; range->max_frag = MAX_FRAG_THRESHOLD; range->max_encoding_tokens = WEP_KEYS; range->num_encoding_sizes = 2; range->encoding_size[0] = 5; range->encoding_size[1] = WEP_KEY_LEN; range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 20; range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&mac->lock); regdomain = mac->regdomain; spin_unlock_irq(&mac->lock); channel_range = zd_channel_range(regdomain); range->num_channels = channel_range->end - channel_range->start; range->old_num_channels = range->num_channels; range->num_frequency = range->num_channels; range->old_num_frequency = range->num_frequency; for (i = 0; i < range->num_frequency; i++) { struct iw_freq *freq = &range->freq[i]; freq->i = channel_range->start + i; zd_channel_to_freq(freq, freq->i); } return 0; }
void zd_mac_clear(struct zd_mac *mac) { flush_workqueue(zd_workqueue); skb_queue_purge(&mac->rx_queue); tasklet_kill(&mac->rx_tasklet); zd_chip_clear(&mac->chip); ZD_ASSERT(!spin_is_locked(&mac->lock)); ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); }
int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) { int r; struct zd_chip *chip = &mac->chip; u8 addr[ETH_ALEN]; u8 default_regdomain; r = zd_chip_enable_int(chip); if (r) goto out; r = zd_chip_init_hw(chip, device_type); if (r) goto disable_int; zd_get_e2p_mac_addr(chip, addr); r = zd_write_mac_addr(chip, addr); if (r) goto disable_int; ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&mac->lock); memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); spin_unlock_irq(&mac->lock); r = zd_read_regdomain(chip, &default_regdomain); if (r) goto disable_int; if (!zd_regdomain_supported(default_regdomain)) { dev_dbg_f(zd_mac_dev(mac), "Regulatory Domain %#04x is not supported.\n", default_regdomain); r = -EINVAL; goto disable_int; } spin_lock_irq(&mac->lock); mac->regdomain = mac->default_regdomain = default_regdomain; spin_unlock_irq(&mac->lock); r = reset_channel(mac); if (r) goto disable_int; /* We must inform the device that we are doing encryption/decryption in * software at the moment. */ r = zd_set_encryption_type(chip, ENC_SNIFFER); if (r) goto disable_int; r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain); if (r) goto disable_int; r = 0; disable_int: zd_chip_disable_int(chip); out: return r; }
static inline void init_usb_rx(struct zd_usb *usb) { struct zd_usb_rx *rx = &usb->rx; spin_lock_init(&rx->lock); if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { rx->usb_packet_size = 512; } else { rx->usb_packet_size = 64; } ZD_ASSERT(rx->fragment_length == 0); }
static int __zd_usb_enable_rx(struct zd_usb *usb) { int i, r; struct zd_usb_rx *rx = &usb->rx; struct urb **urbs; dev_dbg_f(zd_usb_dev(usb), "\n"); r = -ENOMEM; urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL); if (!urbs) goto error; for (i = 0; i < RX_URBS_COUNT; i++) { urbs[i] = alloc_rx_urb(usb); if (!urbs[i]) goto error; } ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&rx->lock); if (rx->urbs) { spin_unlock_irq(&rx->lock); r = 0; goto error; } rx->urbs = urbs; rx->urbs_count = RX_URBS_COUNT; spin_unlock_irq(&rx->lock); for (i = 0; i < RX_URBS_COUNT; i++) { r = usb_submit_urb(urbs[i], GFP_KERNEL); if (r) goto error_submit; } return 0; error_submit: for (i = 0; i < RX_URBS_COUNT; i++) { usb_kill_urb(urbs[i]); } spin_lock_irq(&rx->lock); rx->urbs = NULL; rx->urbs_count = 0; spin_unlock_irq(&rx->lock); error: if (urbs) { for (i = 0; i < RX_URBS_COUNT; i++) free_rx_urb(urbs[i]); } return r; }
/** * tx_status - reports tx status of a packet if required * @hw - a &struct ieee80211_hw pointer * @skb - a sk-buffer * @status - the tx status of the packet without control information * @success - True for successfull transmission of the frame * * This information calls ieee80211_tx_status_irqsafe() if required by the * control information. It copies the control information into the status * information. * * If no status information has been requested, the skb is freed. */ static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_status *status, bool success) { struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *) skb->cb; ZD_ASSERT(cb->control != NULL); memcpy(&status->control, cb->control, sizeof(status->control)); if (!success) status->excessive_retries = 1; clear_tx_skb_control_block(skb); ieee80211_tx_status_irqsafe(hw, skb, status); }
int zd_switch_radio_on(struct zd_rf *rf) { int r, t; struct zd_chip *chip = zd_rf_to_chip(rf); ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_chip_lock_phy_regs(chip); if (r) return r; t = rf->switch_radio_on(rf); r = zd_chip_unlock_phy_regs(chip); if (t) r = t; return r; }
int zd_rf_set_channel(struct zd_rf *rf, u8 channel) { int r; ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); if (channel < MIN_CHANNEL24) return -EINVAL; if (channel > MAX_CHANNEL24) return -EINVAL; dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); r = rf->set_channel(rf, channel); if (r >= 0) rf->channel = channel; return r; }
int zd_switch_radio_off(struct zd_rf *rf) { int r, t; struct zd_chip *chip = zd_rf_to_chip(rf); /* TODO: move phy regs handling to zd_chip */ ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_chip_lock_phy_regs(chip); if (r) return r; t = rf->switch_radio_off(rf); r = zd_chip_unlock_phy_regs(chip); if (t) r = t; return r; }
/** * init_tx_skb_control_block - initializes skb control block * @skb: a &sk_buff pointer * @dev: pointer to the mac80221 device * @control: mac80211 tx control applying for the frame in @skb * * Initializes the control block of the skbuff to be transmitted. */ static int init_tx_skb_control_block(struct sk_buff *skb, struct ieee80211_hw *hw, struct ieee80211_tx_control *control) { struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *)skb->cb; ZD_ASSERT(sizeof(*cb) <= sizeof(skb->cb)); memset(cb, 0, sizeof(*cb)); cb->hw= hw; cb->control = kmalloc(sizeof(*control), GFP_ATOMIC); if (cb->control == NULL) return -ENOMEM; memcpy(cb->control, control, sizeof(*control)); return 0; }
static int read_pod(struct zd_chip *chip, u8 *rf_type) { int r; u32 value; ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_ioread32_locked(chip, &value, E2P_POD); if (r) goto error; dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value); /* FIXME: AL2230 handling (Bit 7 in POD) */ *rf_type = value & 0x0f; chip->pa_type = (value >> 16) & 0x0f; chip->patch_cck_gain = (value >> 8) & 0x1; chip->patch_cr157 = (value >> 13) & 0x1; chip->patch_6m_band_edge = (value >> 21) & 0x1; chip->new_phy_layout = (value >> 31) & 0x1; chip->al2230s_bit = (value >> 7) & 0x1; chip->link_led = ((value >> 4) & 1) ? LED1 : LED2; chip->supports_tx_led = 1; if (value & (1 << 24)) { /* LED scenario */ if (value & (1 << 29)) chip->supports_tx_led = 0; } dev_dbg_f(zd_chip_dev(chip), "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " "patch 6M %d new PHY %d link LED%d tx led %d\n", zd_rf_name(*rf_type), *rf_type, chip->pa_type, chip->patch_cck_gain, chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout, chip->link_led == LED1 ? 1 : 2, chip->supports_tx_led); return 0; error: *rf_type = 0; chip->pa_type = 0; chip->patch_cck_gain = 0; chip->patch_cr157 = 0; chip->patch_6m_band_edge = 0; chip->new_phy_layout = 0; return r; }
int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, unsigned int count) { int i, j, r; struct zd_ioreq16 *ioreqs16; unsigned int count16; ZD_ASSERT(mutex_is_locked(&chip->mutex)); if (count == 0) return 0; if (count > USB_MAX_IOWRITE32_COUNT) return -EINVAL; /* Allocate a single memory block for values and addresses. */ count16 = 2*count; ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_KERNEL); if (!ioreqs16) { r = -ENOMEM; dev_dbg_f(zd_chip_dev(chip), "error %d in ioreqs16 allocation\n", r); goto out; } for (i = 0; i < count; i++) { j = 2*i; /* We write the high word always first. */ ioreqs16[j].value = ioreqs[i].value >> 16; ioreqs16[j].addr = inc_addr(ioreqs[i].addr); ioreqs16[j+1].value = ioreqs[i].value; ioreqs16[j+1].addr = ioreqs[i].addr; } r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16); #ifdef DEBUG if (r) { dev_dbg_f(zd_chip_dev(chip), "error %d in zd_usb_write16v\n", r); } #endif /* DEBUG */ out: kfree(ioreqs16); return r; }
int zd_rf_init_hw(struct zd_rf *rf, u8 type) { int r = 0; int t; struct zd_chip *chip = zd_rf_to_chip(rf); ZD_ASSERT(mutex_is_locked(&chip->mutex)); switch (type) { case RF2959_RF: r = zd_rf_init_rf2959(rf); break; case AL2230_RF: case AL2230S_RF: r = zd_rf_init_al2230(rf); break; case AL7230B_RF: r = zd_rf_init_al7230b(rf); break; case MAXIM_NEW_RF: case UW2453_RF: r = zd_rf_init_uw2453(rf); break; default: dev_err(zd_chip_dev(chip), "RF %s %#x is not supported\n", zd_rf_name(type), type); rf->type = 0; return -ENODEV; } if (r) return r; rf->type = type; r = zd_chip_lock_phy_regs(chip); if (r) return r; t = rf->init_hw(rf); r = zd_chip_unlock_phy_regs(chip); if (t) r = t; return r; }
/* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ static u8 zd_rate_typed(u8 zd_rate) { static const u8 typed_rates[16] = { [ZD_CCK_RATE_1M] = ZD_CS_CCK|ZD_CCK_RATE_1M, [ZD_CCK_RATE_2M] = ZD_CS_CCK|ZD_CCK_RATE_2M, [ZD_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CCK_RATE_5_5M, [ZD_CCK_RATE_11M] = ZD_CS_CCK|ZD_CCK_RATE_11M, [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, [ZD_OFDM_RATE_18M] = ZD_CS_OFDM|ZD_OFDM_RATE_18M, [ZD_OFDM_RATE_24M] = ZD_CS_OFDM|ZD_OFDM_RATE_24M, [ZD_OFDM_RATE_36M] = ZD_CS_OFDM|ZD_OFDM_RATE_36M, [ZD_OFDM_RATE_48M] = ZD_CS_OFDM|ZD_OFDM_RATE_48M, [ZD_OFDM_RATE_54M] = ZD_CS_OFDM|ZD_OFDM_RATE_54M, }; ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); return typed_rates[zd_rate & ZD_CS_RATE_MASK]; }
static int _zd_iowrite32v_async_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, unsigned int count) { int i, j, r; struct zd_ioreq16 ioreqs16[USB_MAX_IOWRITE32_COUNT * 2]; unsigned int count16; /* Use stack for values and addresses. */ ZD_ASSERT(mutex_is_locked(&chip->mutex)); if (count == 0) return 0; if (count > USB_MAX_IOWRITE32_COUNT) return -EINVAL; count16 = 2 * count; BUG_ON(count16 * sizeof(struct zd_ioreq16) > sizeof(ioreqs16)); for (i = 0; i < count; i++) { j = 2*i; /* We write the high word always first. */ ioreqs16[j].value = ioreqs[i].value >> 16; ioreqs16[j].addr = inc_addr(ioreqs[i].addr); ioreqs16[j+1].value = ioreqs[i].value; ioreqs16[j+1].addr = ioreqs[i].addr; } r = zd_usb_iowrite16v_async(&chip->usb, ioreqs16, count16); #ifdef DEBUG if (r) { dev_dbg_f(zd_chip_dev(chip), "error %d in zd_usb_write16v\n", r); } #endif /* DEBUG */ return r; }
int zd_mac_init_hw(struct ieee80211_hw *hw) { int r; struct zd_mac *mac = zd_hw_mac(hw); struct zd_chip *chip = &mac->chip; u8 default_regdomain; r = zd_chip_enable_int(chip); if (r) goto out; r = zd_chip_init_hw(chip); if (r) goto disable_int; ZD_ASSERT(!irqs_disabled()); r = zd_read_regdomain(chip, &default_regdomain); if (r) goto disable_int; spin_lock_irq(&mac->lock); mac->regdomain = mac->default_regdomain = default_regdomain; spin_unlock_irq(&mac->lock); /* We must inform the device that we are doing encryption/decryption in * software at the moment. */ r = zd_set_encryption_type(chip, ENC_SNIFFER); if (r) goto disable_int; zd_geo_init(hw, mac->regdomain); r = 0; disable_int: zd_chip_disable_int(chip); out: return r; }
static inline void handle_regs_int(struct urb *urb) { struct zd_usb *usb = urb->context; struct zd_usb_interrupt *intr = &usb->intr; int len; ZD_ASSERT(in_interrupt()); spin_lock(&intr->lock); if (intr->read_regs_enabled) { intr->read_regs.length = len = urb->actual_length; if (len > sizeof(intr->read_regs.buffer)) len = sizeof(intr->read_regs.buffer); memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); intr->read_regs_enabled = 0; complete(&intr->read_regs.completion); goto out; } dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); out: spin_unlock(&intr->lock); }
int zd_usb_enable_int(struct zd_usb *usb) { int r; struct usb_device *udev; struct zd_usb_interrupt *intr = &usb->intr; void *transfer_buffer = NULL; struct urb *urb; dev_dbg_f(zd_usb_dev(usb), "\n"); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { r = -ENOMEM; goto out; } ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&intr->lock); if (intr->urb) { spin_unlock_irq(&intr->lock); r = 0; goto error_free_urb; } intr->urb = urb; spin_unlock_irq(&intr->lock); /* TODO: make it a DMA buffer */ r = -ENOMEM; transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL); if (!transfer_buffer) { dev_dbg_f(zd_usb_dev(usb), "couldn't allocate transfer_buffer\n"); goto error_set_urb_null; } udev = zd_usb_to_usbdev(usb); usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), transfer_buffer, USB_MAX_EP_INT_BUFFER, int_urb_complete, usb, intr->interval); dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); r = usb_submit_urb(urb, GFP_KERNEL); if (r) { dev_dbg_f(zd_usb_dev(usb), "Couldn't submit urb. Error number %d\n", r); goto error; } return 0; error: kfree(transfer_buffer); error_set_urb_null: spin_lock_irq(&intr->lock); intr->urb = NULL; spin_unlock_irq(&intr->lock); error_free_urb: usb_free_urb(urb); out: return r; }
static int fill_ctrlset(struct zd_mac *mac, struct ieee80211_txb *txb, int frag_num) { int r; struct sk_buff *skb = txb->fragments[frag_num]; struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data; unsigned int frag_len = skb->len + IEEE80211_FCS_LEN; unsigned int next_frag_len; unsigned int packet_length; struct zd_ctrlset *cs = (struct zd_ctrlset *) skb_push(skb, sizeof(struct zd_ctrlset)); if (frag_num+1 < txb->nr_frags) { next_frag_len = txb->fragments[frag_num+1]->len + IEEE80211_FCS_LEN; } else { next_frag_len = 0; } ZD_ASSERT(frag_len <= 0xffff); ZD_ASSERT(next_frag_len <= 0xffff); cs_set_modulation(mac, cs, hdr); cs->tx_length = cpu_to_le16(frag_len); cs_set_control(mac, cs, hdr); packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; ZD_ASSERT(packet_length <= 0xffff); /* ZD1211B: Computing the length difference this way, gives us * flexibility to compute the packet length. */ cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ? packet_length - frag_len : packet_length); /* * CURRENT LENGTH: * - transmit frame length in microseconds * - seems to be derived from frame length * - see Cal_Us_Service() in zdinlinef.h * - if macp->bTxBurstEnable is enabled, then multiply by 4 * - bTxBurstEnable is never set in the vendor driver * * SERVICE: * - "for PLCP configuration" * - always 0 except in some situations at 802.11b 11M * - see line 53 of zdinlinef.h */ cs->service = 0; r = zd_calc_tx_length_us(&cs->service, ZD_CS_RATE(cs->modulation), le16_to_cpu(cs->tx_length)); if (r < 0) return r; cs->current_length = cpu_to_le16(r); if (next_frag_len == 0) { cs->next_frame_length = 0; } else { r = zd_calc_tx_length_us(NULL, ZD_CS_RATE(cs->modulation), next_frag_len); if (r < 0) return r; cs->next_frame_length = cpu_to_le16(r); } return 0; }
int zd_usb_enable_int(struct zd_usb *usb) { int r; struct usb_device *udev = zd_usb_to_usbdev(usb); struct zd_usb_interrupt *intr = &usb->intr; struct urb *urb; dev_dbg_f(zd_usb_dev(usb), "\n"); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { r = -ENOMEM; goto out; } ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&intr->lock); if (intr->urb) { spin_unlock_irq(&intr->lock); r = 0; goto error_free_urb; } intr->urb = urb; spin_unlock_irq(&intr->lock); r = -ENOMEM; intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER, GFP_KERNEL, &intr->buffer_dma); if (!intr->buffer) { dev_dbg_f(zd_usb_dev(usb), "couldn't allocate transfer_buffer\n"); goto error_set_urb_null; } usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), intr->buffer, USB_MAX_EP_INT_BUFFER, int_urb_complete, usb, intr->interval); urb->transfer_dma = intr->buffer_dma; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); r = usb_submit_urb(urb, GFP_KERNEL); if (r) { dev_dbg_f(zd_usb_dev(usb), "Couldn't submit urb. Error number %d\n", r); goto error; } return 0; error: usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER, intr->buffer, intr->buffer_dma); error_set_urb_null: spin_lock_irq(&intr->lock); intr->urb = NULL; spin_unlock_irq(&intr->lock); error_free_urb: usb_free_urb(urb); out: return r; }