zd_mac.c 28.5 KB
Newer Older
Daniel Drake's avatar
Daniel Drake committed
1
/* ZD1211 USB-WLAN driver for Linux
Daniel Drake's avatar
Daniel Drake committed
2
 *
Daniel Drake's avatar
Daniel Drake committed
3
4
5
 * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
 * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
 * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
Daniel Drake's avatar
Daniel Drake committed
6
 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/usb.h>
#include <linux/jiffies.h>
#include <net/ieee80211_radiotap.h>

#include "zd_def.h"
#include "zd_chip.h"
#include "zd_mac.h"
#include "zd_ieee80211.h"
#include "zd_rf.h"

Daniel Drake's avatar
Daniel Drake committed
35
36
/* This table contains the hardware specific values for the modulation rates. */
static const struct ieee80211_rate zd_rates[] = {
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	{ .bitrate = 10,
	  .hw_value = ZD_CCK_RATE_1M, },
	{ .bitrate = 20,
	  .hw_value = ZD_CCK_RATE_2M,
	  .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 55,
	  .hw_value = ZD_CCK_RATE_5_5M,
	  .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 110,
	  .hw_value = ZD_CCK_RATE_11M,
	  .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 60,
	  .hw_value = ZD_OFDM_RATE_6M,
	  .flags = 0 },
	{ .bitrate = 90,
	  .hw_value = ZD_OFDM_RATE_9M,
	  .flags = 0 },
	{ .bitrate = 120,
	  .hw_value = ZD_OFDM_RATE_12M,
	  .flags = 0 },
	{ .bitrate = 180,
	  .hw_value = ZD_OFDM_RATE_18M,
	  .flags = 0 },
	{ .bitrate = 240,
	  .hw_value = ZD_OFDM_RATE_24M,
	  .flags = 0 },
	{ .bitrate = 360,
	  .hw_value = ZD_OFDM_RATE_36M,
	  .flags = 0 },
	{ .bitrate = 480,
	  .hw_value = ZD_OFDM_RATE_48M,
	  .flags = 0 },
	{ .bitrate = 540,
	  .hw_value = ZD_OFDM_RATE_54M,
	  .flags = 0 },
Daniel Drake's avatar
Daniel Drake committed
75
76
77
};

static const struct ieee80211_channel zd_channels[] = {
78
79
80
81
82
83
84
85
86
87
88
89
90
91
	{ .center_freq = 2412, .hw_value = 1 },
	{ .center_freq = 2417, .hw_value = 2 },
	{ .center_freq = 2422, .hw_value = 3 },
	{ .center_freq = 2427, .hw_value = 4 },
	{ .center_freq = 2432, .hw_value = 5 },
	{ .center_freq = 2437, .hw_value = 6 },
	{ .center_freq = 2442, .hw_value = 7 },
	{ .center_freq = 2447, .hw_value = 8 },
	{ .center_freq = 2452, .hw_value = 9 },
	{ .center_freq = 2457, .hw_value = 10 },
	{ .center_freq = 2462, .hw_value = 11 },
	{ .center_freq = 2467, .hw_value = 12 },
	{ .center_freq = 2472, .hw_value = 13 },
	{ .center_freq = 2484, .hw_value = 14 },
Daniel Drake's avatar
Daniel Drake committed
92
};
93

94
95
96
97
static void housekeeping_init(struct zd_mac *mac);
static void housekeeping_enable(struct zd_mac *mac);
static void housekeeping_disable(struct zd_mac *mac);

Daniel Drake's avatar
Daniel Drake committed
98
int zd_mac_preinit_hw(struct ieee80211_hw *hw)
99
100
101
{
	int r;
	u8 addr[ETH_ALEN];
Daniel Drake's avatar
Daniel Drake committed
102
	struct zd_mac *mac = zd_hw_mac(hw);
103
104
105
106
107

	r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
	if (r)
		return r;

Daniel Drake's avatar
Daniel Drake committed
108
109
	SET_IEEE80211_PERM_ADDR(hw, addr);

110
111
112
	return 0;
}

Daniel Drake's avatar
Daniel Drake committed
113
int zd_mac_init_hw(struct ieee80211_hw *hw)
114
115
{
	int r;
Daniel Drake's avatar
Daniel Drake committed
116
	struct zd_mac *mac = zd_hw_mac(hw);
117
	struct zd_chip *chip = &mac->chip;
118
119
120
121
122
	u8 default_regdomain;

	r = zd_chip_enable_int(chip);
	if (r)
		goto out;
123
	r = zd_chip_init_hw(chip);
124
125
126
127
128
129
130
131
132
133
134
135
	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);

136
137
138
	/* We must inform the device that we are doing encryption/decryption in
	 * software at the moment. */
	r = zd_set_encryption_type(chip, ENC_SNIFFER);
139
140
141
	if (r)
		goto disable_int;

Daniel Drake's avatar
Daniel Drake committed
142
	zd_geo_init(hw, mac->regdomain);
143
144
145
146
147
148
149
150
151
152

	r = 0;
disable_int:
	zd_chip_disable_int(chip);
out:
	return r;
}

void zd_mac_clear(struct zd_mac *mac)
{
153
	flush_workqueue(zd_workqueue);
154
	zd_chip_clear(&mac->chip);
Ulrich Kunitz's avatar
Ulrich Kunitz committed
155
156
	ZD_ASSERT(!spin_is_locked(&mac->lock));
	ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
157
158
}

159
static int set_rx_filter(struct zd_mac *mac)
160
{
Daniel Drake's avatar
Daniel Drake committed
161
162
	unsigned long flags;
	u32 filter = STA_RX_FILTER;
163

Daniel Drake's avatar
Daniel Drake committed
164
165
166
167
168
169
	spin_lock_irqsave(&mac->lock, flags);
	if (mac->pass_ctrl)
		filter |= RX_FILTER_CTRL;
	spin_unlock_irqrestore(&mac->lock, flags);

	return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
170
171
172
173
174
175
176
177
178
}

static int set_mc_hash(struct zd_mac *mac)
{
	struct zd_mc_hash hash;
	zd_mc_clear(&hash);
	return zd_chip_set_multicast_hash(&mac->chip, &hash);
}

Daniel Drake's avatar
Daniel Drake committed
179
static int zd_op_start(struct ieee80211_hw *hw)
180
{
Daniel Drake's avatar
Daniel Drake committed
181
	struct zd_mac *mac = zd_hw_mac(hw);
182
	struct zd_chip *chip = &mac->chip;
183
	struct zd_usb *usb = &chip->usb;
184
185
	int r;

186
187
188
189
190
191
	if (!usb->initialized) {
		r = zd_usb_init_hw(usb);
		if (r)
			goto out;
	}

192
193
194
195
196
197
198
	r = zd_chip_enable_int(chip);
	if (r < 0)
		goto out;

	r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
	if (r < 0)
		goto disable_int;
199
200
201
202
	r = set_rx_filter(mac);
	if (r)
		goto disable_int;
	r = set_mc_hash(mac);
203
204
205
206
207
	if (r)
		goto disable_int;
	r = zd_chip_switch_radio_on(chip);
	if (r < 0)
		goto disable_int;
Daniel Drake's avatar
Daniel Drake committed
208
	r = zd_chip_enable_rxtx(chip);
209
210
211
212
	if (r < 0)
		goto disable_radio;
	r = zd_chip_enable_hwint(chip);
	if (r < 0)
Daniel Drake's avatar
Daniel Drake committed
213
		goto disable_rxtx;
214

215
	housekeeping_enable(mac);
216
	return 0;
Daniel Drake's avatar
Daniel Drake committed
217
218
disable_rxtx:
	zd_chip_disable_rxtx(chip);
219
220
221
222
223
224
225
226
disable_radio:
	zd_chip_switch_radio_off(chip);
disable_int:
	zd_chip_disable_int(chip);
out:
	return r;
}

Daniel Drake's avatar
Daniel Drake committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/**
 * clear_tx_skb_control_block - clears the control block of tx skbuffs
 * @skb: a &struct sk_buff pointer
 *
 * This clears the control block of skbuff buffers, which were transmitted to
 * the device. Notify that the function is not thread-safe, so prevent
 * multiple calls.
 */
static void clear_tx_skb_control_block(struct sk_buff *skb)
{
	struct zd_tx_skb_control_block *cb =
		(struct zd_tx_skb_control_block *)skb->cb;

	kfree(cb->control);
	cb->control = NULL;
}

/**
 * kfree_tx_skb - frees a tx skbuff
 * @skb: a &struct sk_buff pointer
 *
 * Frees the tx skbuff. Frees also the allocated control structure in the
 * control block if necessary.
 */
static void kfree_tx_skb(struct sk_buff *skb)
252
{
Daniel Drake's avatar
Daniel Drake committed
253
254
255
	clear_tx_skb_control_block(skb);
	dev_kfree_skb_any(skb);
}
256

Daniel Drake's avatar
Daniel Drake committed
257
258
259
260
261
262
static void zd_op_stop(struct ieee80211_hw *hw)
{
	struct zd_mac *mac = zd_hw_mac(hw);
	struct zd_chip *chip = &mac->chip;
	struct sk_buff *skb;
	struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
263

Daniel Drake's avatar
Daniel Drake committed
264
	/* The order here deliberately is a little different from the open()
265
	 * method, since we need to make sure there is no opportunity for RX
Daniel Drake's avatar
Daniel Drake committed
266
	 * frames to be processed by mac80211 after we have stopped it.
267
268
	 */

Daniel Drake's avatar
Daniel Drake committed
269
	zd_chip_disable_rxtx(chip);
270
	housekeeping_disable(mac);
271
272
	flush_workqueue(zd_workqueue);

273
274
275
276
277
	zd_chip_disable_hwint(chip);
	zd_chip_switch_radio_off(chip);
	zd_chip_disable_int(chip);


Daniel Drake's avatar
Daniel Drake committed
278
279
	while ((skb = skb_dequeue(ack_wait_queue)))
		kfree_tx_skb(skb);
280
281
}

Daniel Drake's avatar
Daniel Drake committed
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/**
 * 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));
304
305
306
307

	return 0;
}

Daniel Drake's avatar
Daniel Drake committed
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/**
 * 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)
324
{
Daniel Drake's avatar
Daniel Drake committed
325
326
	struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *)
		skb->cb;
327

Daniel Drake's avatar
Daniel Drake committed
328
329
330
331
332
333
	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);
334
335
}

Daniel Drake's avatar
Daniel Drake committed
336
337
338
339
340
341
342
343
344
/**
 * zd_mac_tx_failed - callback for failed frames
 * @dev: the mac80211 wireless device
 *
 * This function is called if a frame couldn't be succesfully be
 * transferred. The first frame from the tx queue, will be selected and
 * reported as error to the upper layers.
 */
void zd_mac_tx_failed(struct ieee80211_hw *hw)
345
{
Daniel Drake's avatar
Daniel Drake committed
346
347
	struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
	struct sk_buff *skb;
Johannes Berg's avatar
Johannes Berg committed
348
	struct ieee80211_tx_status status;
349

Daniel Drake's avatar
Daniel Drake committed
350
351
352
	skb = skb_dequeue(q);
	if (skb == NULL)
		return;
Johannes Berg's avatar
Johannes Berg committed
353
354
355

	memset(&status, 0, sizeof(status));

Daniel Drake's avatar
Daniel Drake committed
356
	tx_status(hw, skb, &status, 0);
357
358
}

Daniel Drake's avatar
Daniel Drake committed
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/**
 * zd_mac_tx_to_dev - callback for USB layer
 * @skb: a &sk_buff pointer
 * @error: error value, 0 if transmission successful
 *
 * Informs the MAC layer that the frame has successfully transferred to the
 * device. If an ACK is required and the transfer to the device has been
 * successful, the packets are put on the @ack_wait_queue with
 * the control set removed.
 */
void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
{
	struct zd_tx_skb_control_block *cb =
		(struct zd_tx_skb_control_block *)skb->cb;
	struct ieee80211_hw *hw = cb->hw;

	if (likely(cb->control)) {
		skb_pull(skb, sizeof(struct zd_ctrlset));
		if (unlikely(error ||
		    (cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
		{
Johannes Berg's avatar
Johannes Berg committed
380
381
			struct ieee80211_tx_status status;
			memset(&status, 0, sizeof(status));
Daniel Drake's avatar
Daniel Drake committed
382
			tx_status(hw, skb, &status, !error);
383
		} else {
Daniel Drake's avatar
Daniel Drake committed
384
385
			struct sk_buff_head *q =
				&zd_hw_mac(hw)->ack_wait_queue;
386

Daniel Drake's avatar
Daniel Drake committed
387
388
389
			skb_queue_tail(q, skb);
			while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
				zd_mac_tx_failed(hw);
390
		}
Daniel Drake's avatar
Daniel Drake committed
391
392
	} else {
		kfree_tx_skb(skb);
393
394
395
	}
}

396
static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
397
{
398
	/* ZD_PURE_RATE() must be used to remove the modulation type flag of
Daniel Drake's avatar
Daniel Drake committed
399
400
	 * the zd-rate values.
	 */
401
	static const u8 rate_divisor[] = {
Daniel Drake's avatar
Daniel Drake committed
402
403
404
405
406
407
408
409
410
411
412
413
414
		[ZD_PURE_RATE(ZD_CCK_RATE_1M)]   =  1,
		[ZD_PURE_RATE(ZD_CCK_RATE_2M)]	 =  2,
		/* Bits must be doubled. */
		[ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
		[ZD_PURE_RATE(ZD_CCK_RATE_11M)]	 = 11,
		[ZD_PURE_RATE(ZD_OFDM_RATE_6M)]  =  6,
		[ZD_PURE_RATE(ZD_OFDM_RATE_9M)]  =  9,
		[ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
		[ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
		[ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
		[ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
		[ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
		[ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
415
416
417
418
419
	};

	u32 bits = (u32)tx_length * 8;
	u32 divisor;

420
	divisor = rate_divisor[ZD_PURE_RATE(zd_rate)];
421
422
423
	if (divisor == 0)
		return -EINVAL;

424
425
	switch (zd_rate) {
	case ZD_CCK_RATE_5_5M:
426
427
		bits = (2*bits) + 10; /* round up to the next integer */
		break;
428
	case ZD_CCK_RATE_11M:
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
		if (service) {
			u32 t = bits % 11;
			*service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION;
			if (0 < t && t <= 3) {
				*service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION;
			}
		}
		bits += 10; /* round up to the next integer */
		break;
	}

	return bits/divisor;
}

static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
Daniel Drake's avatar
Daniel Drake committed
444
	                   struct ieee80211_hdr *header, u32 flags)
445
{
Daniel Drake's avatar
Daniel Drake committed
446
	u16 fctl = le16_to_cpu(header->frame_control);
447
448

	/*
449
	 * CONTROL TODO:
450
451
452
453
454
455
456
	 * - if backoff needed, enable bit 0
	 * - if burst (backoff not needed) disable bit 0
	 */

	cs->control = 0;

	/* First fragment */
Daniel Drake's avatar
Daniel Drake committed
457
	if (flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
458
459
460
461
462
463
464
		cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;

	/* Multicast */
	if (is_multicast_ether_addr(header->addr1))
		cs->control |= ZD_CS_MULTICAST;

	/* PS-POLL */
Daniel Drake's avatar
Daniel Drake committed
465
466
	if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) ==
	    (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL))
467
468
		cs->control |= ZD_CS_PS_POLL_FRAME;

Daniel Drake's avatar
Daniel Drake committed
469
	if (flags & IEEE80211_TXCTL_USE_RTS_CTS)
470
471
		cs->control |= ZD_CS_RTS;

Daniel Drake's avatar
Daniel Drake committed
472
	if (flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
473
		cs->control |= ZD_CS_SELF_CTS;
474
475
476
477

	/* FIXME: Management frame? */
}

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
{
	struct zd_mac *mac = zd_hw_mac(hw);
	u32 tmp, j = 0;
	/* 4 more bytes for tail CRC */
	u32 full_len = beacon->len + 4;
	zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
	zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
	while (tmp & 0x2) {
		zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
		if ((++j % 100) == 0) {
			printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
			if (j >= 500)  {
				printk(KERN_ERR "Giving up beacon config.\n");
				return;
			}
		}
		msleep(1);
	}

	zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
	if (zd_chip_is_zd1211b(&mac->chip))
		zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);

	for (j = 0 ; j < beacon->len; j++)
		zd_iowrite32(&mac->chip, CR_BCN_FIFO,
				*((u8 *)(beacon->data + j)));

	for (j = 0; j < 4; j++)
		zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);

	zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
	/* 802.11b/g 2.4G CCK 1Mb
	 * 802.11a, not yet implemented, uses different values (see GPL vendor
	 * driver)
	 */
	zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
			(full_len << 19));
}

518
static int fill_ctrlset(struct zd_mac *mac,
Daniel Drake's avatar
Daniel Drake committed
519
520
			struct sk_buff *skb,
			struct ieee80211_tx_control *control)
521
522
{
	int r;
Daniel Drake's avatar
Daniel Drake committed
523
524
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	unsigned int frag_len = skb->len + FCS_LEN;
525
526
527
528
529
530
	unsigned int packet_length;
	struct zd_ctrlset *cs = (struct zd_ctrlset *)
		skb_push(skb, sizeof(struct zd_ctrlset));

	ZD_ASSERT(frag_len <= 0xffff);

531
532
533
	cs->modulation = control->tx_rate->hw_value;
	if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
		cs->modulation = control->tx_rate->hw_value_short;
534
535
536

	cs->tx_length = cpu_to_le16(frag_len);

Daniel Drake's avatar
Daniel Drake committed
537
	cs_set_control(mac, cs, hdr, control->flags);
538
539
540
541
542
543

	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.
	 */
544
	cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
			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;
561
	r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation),
562
563
564
565
		                 le16_to_cpu(cs->tx_length));
	if (r < 0)
		return r;
	cs->current_length = cpu_to_le16(r);
Daniel Drake's avatar
Daniel Drake committed
566
	cs->next_frame_length = 0;
567
568
569
570

	return 0;
}

Daniel Drake's avatar
Daniel Drake committed
571
572
573
574
575
576
577
578
579
580
581
582
583
/**
 * zd_op_tx - transmits a network frame to the device
 *
 * @dev: mac80211 hardware device
 * @skb: socket buffer
 * @control: the control structure
 *
 * This function transmit an IEEE 802.11 network frame to the device. The
 * control block of the skbuff will be initialized. If necessary the incoming
 * mac80211 queues will be stopped.
 */
static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
		     struct ieee80211_tx_control *control)
584
{
Daniel Drake's avatar
Daniel Drake committed
585
586
	struct zd_mac *mac = zd_hw_mac(hw);
	int r;
587

Daniel Drake's avatar
Daniel Drake committed
588
589
590
	r = fill_ctrlset(mac, skb, control);
	if (r)
		return r;
591

Daniel Drake's avatar
Daniel Drake committed
592
593
594
595
596
597
598
	r = init_tx_skb_control_block(skb, hw, control);
	if (r)
		return r;
	r = zd_usb_tx(&mac->chip.usb, skb);
	if (r) {
		clear_tx_skb_control_block(skb);
		return r;
599
600
601
602
	}
	return 0;
}

Daniel Drake's avatar
Daniel Drake committed
603
604
605
606
607
/**
 * filter_ack - filters incoming packets for acknowledgements
 * @dev: the mac80211 device
 * @rx_hdr: received header
 * @stats: the status for the received packet
Ulrich Kunitz's avatar
Ulrich Kunitz committed
608
 *
Daniel Drake's avatar
Daniel Drake committed
609
610
611
612
613
 * This functions looks for ACK packets and tries to match them with the
 * frames in the tx queue. If a match is found the frame will be dequeued and
 * the upper layers is informed about the successful transmission. If
 * mac80211 queues have been stopped and the number of frames still to be
 * transmitted is low the queues will be opened again.
614
 *
Daniel Drake's avatar
Daniel Drake committed
615
 * Returns 1 if the frame was an ACK, 0 if it was ignored.
616
 */
Daniel Drake's avatar
Daniel Drake committed
617
618
static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
		      struct ieee80211_rx_status *stats)
619
{
Daniel Drake's avatar
Daniel Drake committed
620
621
622
623
	u16 fc = le16_to_cpu(rx_hdr->frame_control);
	struct sk_buff *skb;
	struct sk_buff_head *q;
	unsigned long flags;
624

Daniel Drake's avatar
Daniel Drake committed
625
626
	if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
	    (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK))
627
628
		return 0;

Daniel Drake's avatar
Daniel Drake committed
629
630
631
632
633
634
635
636
	q = &zd_hw_mac(hw)->ack_wait_queue;
	spin_lock_irqsave(&q->lock, flags);
	for (skb = q->next; skb != (struct sk_buff *)q; skb = skb->next) {
		struct ieee80211_hdr *tx_hdr;

		tx_hdr = (struct ieee80211_hdr *)skb->data;
		if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
		{
Johannes Berg's avatar
Johannes Berg committed
637
638
639
			struct ieee80211_tx_status status;

			memset(&status, 0, sizeof(status));
Daniel Drake's avatar
Daniel Drake committed
640
641
642
643
644
645
646
647
648
649
			status.flags = IEEE80211_TX_STATUS_ACK;
			status.ack_signal = stats->ssi;
			__skb_unlink(skb, q);
			tx_status(hw, skb, &status, 1);
			goto out;
		}
	}
out:
	spin_unlock_irqrestore(&q->lock, flags);
	return 1;
650
651
}

Daniel Drake's avatar
Daniel Drake committed
652
int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
653
{
Daniel Drake's avatar
Daniel Drake committed
654
655
656
657
658
	struct zd_mac *mac = zd_hw_mac(hw);
	struct ieee80211_rx_status stats;
	const struct rx_status *status;
	struct sk_buff *skb;
	int bad_frame = 0;
659
660
	u16 fc;
	bool is_qos, is_4addr, need_padding;
661
662
	int i;
	u8 rate;
663

Daniel Drake's avatar
Daniel Drake committed
664
665
666
	if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
	             FCS_LEN + sizeof(struct rx_status))
		return -EINVAL;
667

Daniel Drake's avatar
Daniel Drake committed
668
	memset(&stats, 0, sizeof(stats));
669

Daniel Drake's avatar
Daniel Drake committed
670
671
672
673
674
675
676
677
	/* Note about pass_failed_fcs and pass_ctrl access below:
	 * mac locking intentionally omitted here, as this is the only unlocked
	 * reader and the only writer is configure_filter. Plus, if there were
	 * any races accessing these variables, it wouldn't really matter.
	 * If mac80211 ever provides a way for us to access filter flags
	 * from outside configure_filter, we could improve on this. Also, this
	 * situation may change once we implement some kind of DMA-into-skb
	 * RX path. */
678

Daniel Drake's avatar
Daniel Drake committed
679
680
	/* Caller has to ensure that length >= sizeof(struct rx_status). */
	status = (struct rx_status *)
681
		(buffer + (length - sizeof(struct rx_status)));
682
	if (status->frame_status & ZD_RX_ERROR) {
Daniel Drake's avatar
Daniel Drake committed
683
684
685
686
687
688
		if (mac->pass_failed_fcs &&
				(status->frame_status & ZD_RX_CRC32_ERROR)) {
			stats.flag |= RX_FLAG_FAILED_FCS_CRC;
			bad_frame = 1;
		} else {
			return -EINVAL;
689
		}
690
	}
691

692
693
	stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
	stats.band = IEEE80211_BAND_2GHZ;
Daniel Drake's avatar
Daniel Drake committed
694
695
	stats.ssi = status->signal_strength;
	stats.signal = zd_rx_qual_percent(buffer,
696
697
		                          length - sizeof(struct rx_status),
		                          status);
698
699
700
701
702
703
704

	rate = zd_rx_rate(buffer, status);

	/* todo: return index in the big switches in zd_rx_rate instead */
	for (i = 0; i < mac->band.n_bitrates; i++)
		if (rate == mac->band.bitrates[i].hw_value)
			stats.rate_idx = i;
Daniel Drake's avatar
Daniel Drake committed
705
706
707
708
709
710
711
712
713
714
715
716
717

	length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
	buffer += ZD_PLCP_HEADER_SIZE;

	/* Except for bad frames, filter each frame to see if it is an ACK, in
	 * which case our internal TX tracking is updated. Normally we then
	 * bail here as there's no need to pass ACKs on up to the stack, but
	 * there is also the case where the stack has requested us to pass
	 * control frames on up (pass_ctrl) which we must consider. */
	if (!bad_frame &&
			filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
			&& !mac->pass_ctrl)
		return 0;
718

719
720
721
	fc = le16_to_cpu(*((__le16 *) buffer));

	is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
722
		 (fc & IEEE80211_STYPE_QOS_DATA);
723
724
725
726
727
	is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
		   (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
	need_padding = is_qos ^ is_4addr;

	skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
Daniel Drake's avatar
Daniel Drake committed
728
729
	if (skb == NULL)
		return -ENOMEM;
730
731
732
733
734
	if (need_padding) {
		/* Make sure the the payload data is 4 byte aligned. */
		skb_reserve(skb, 2);
	}

Daniel Drake's avatar
Daniel Drake committed
735
736
737
	memcpy(skb_put(skb, length), buffer, length);

	ieee80211_rx_irqsafe(hw, skb, &stats);
738
739
740
	return 0;
}

Daniel Drake's avatar
Daniel Drake committed
741
742
static int zd_op_add_interface(struct ieee80211_hw *hw,
				struct ieee80211_if_init_conf *conf)
743
{
Daniel Drake's avatar
Daniel Drake committed
744
	struct zd_mac *mac = zd_hw_mac(hw);
745

Daniel Drake's avatar
Daniel Drake committed
746
747
748
	/* using IEEE80211_IF_TYPE_INVALID to indicate no mode selected */
	if (mac->type != IEEE80211_IF_TYPE_INVALID)
		return -EOPNOTSUPP;
749

Daniel Drake's avatar
Daniel Drake committed
750
751
	switch (conf->type) {
	case IEEE80211_IF_TYPE_MNTR:
752
	case IEEE80211_IF_TYPE_MESH_POINT:
Daniel Drake's avatar
Daniel Drake committed
753
754
755
756
757
	case IEEE80211_IF_TYPE_STA:
		mac->type = conf->type;
		break;
	default:
		return -EOPNOTSUPP;
758
	}
759

Daniel Drake's avatar
Daniel Drake committed
760
761
	return zd_write_mac_addr(&mac->chip, conf->mac_addr);
}
762

Daniel Drake's avatar
Daniel Drake committed
763
764
765
766
767
768
769
static void zd_op_remove_interface(struct ieee80211_hw *hw,
				    struct ieee80211_if_init_conf *conf)
{
	struct zd_mac *mac = zd_hw_mac(hw);
	mac->type = IEEE80211_IF_TYPE_INVALID;
	zd_write_mac_addr(&mac->chip, NULL);
}
770

Daniel Drake's avatar
Daniel Drake committed
771
772
773
static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
	struct zd_mac *mac = zd_hw_mac(hw);
774
	return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
Daniel Drake's avatar
Daniel Drake committed
775
}
776

777
778
static int zd_op_config_interface(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif,
Daniel Drake's avatar
Daniel Drake committed
779
780
781
				   struct ieee80211_if_conf *conf)
{
	struct zd_mac *mac = zd_hw_mac(hw);
782
783
784
785
786
787
788
789
790
791
792
793
	int associated;

	if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
		associated = true;
		if (conf->beacon) {
			zd_mac_config_beacon(hw, conf->beacon);
			kfree_skb(conf->beacon);
			zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
					hw->conf.beacon_int);
		}
	} else
		associated = is_valid_ether_addr(conf->bssid);
794

Daniel Drake's avatar
Daniel Drake committed
795
	spin_lock_irq(&mac->lock);
796
	mac->associated = associated;
Daniel Drake's avatar
Daniel Drake committed
797
	spin_unlock_irq(&mac->lock);
798

Daniel Drake's avatar
Daniel Drake committed
799
800
	/* TODO: do hardware bssid filtering */
	return 0;
801
802
}

803
804
805
806
807
void zd_process_intr(struct work_struct *work)
{
	u16 int_status;
	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);

Al Viro's avatar
Al Viro committed
808
	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
809
810
811
812
813
814
815
816
817
818
	if (int_status & INT_CFG_NEXT_BCN) {
		if (net_ratelimit())
			dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
	} else
		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");

	zd_chip_enable_hwint(&mac->chip);
}


Daniel Drake's avatar
Daniel Drake committed
819
static void set_multicast_hash_handler(struct work_struct *work)
820
{
Daniel Drake's avatar
Daniel Drake committed
821
822
823
	struct zd_mac *mac =
		container_of(work, struct zd_mac, set_multicast_hash_work);
	struct zd_mc_hash hash;
824

Daniel Drake's avatar
Daniel Drake committed
825
826
827
	spin_lock_irq(&mac->lock);
	hash = mac->multicast_hash;
	spin_unlock_irq(&mac->lock);
828

Daniel Drake's avatar
Daniel Drake committed
829
	zd_chip_set_multicast_hash(&mac->chip, &hash);
830
831
}

Daniel Drake's avatar
Daniel Drake committed
832
static void set_rx_filter_handler(struct work_struct *work)
833
{
Daniel Drake's avatar
Daniel Drake committed
834
835
836
837
838
839
840
841
	struct zd_mac *mac =
		container_of(work, struct zd_mac, set_rx_filter_work);
	int r;

	dev_dbg_f(zd_mac_dev(mac), "\n");
	r = set_rx_filter(mac);
	if (r)
		dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
842
843
}

Daniel Drake's avatar
Daniel Drake committed
844
845
#define SUPPORTED_FIF_FLAGS \
	(FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
846
	FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
Daniel Drake's avatar
Daniel Drake committed
847
848
849
850
static void zd_op_configure_filter(struct ieee80211_hw *hw,
			unsigned int changed_flags,
			unsigned int *new_flags,
			int mc_count, struct dev_mc_list *mclist)
851
{
Daniel Drake's avatar
Daniel Drake committed
852
853
854
855
	struct zd_mc_hash hash;
	struct zd_mac *mac = zd_hw_mac(hw);
	unsigned long flags;
	int i;
856

Daniel Drake's avatar
Daniel Drake committed
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
	/* Only deal with supported flags */
	changed_flags &= SUPPORTED_FIF_FLAGS;
	*new_flags &= SUPPORTED_FIF_FLAGS;

	/* changed_flags is always populated but this driver
	 * doesn't support all FIF flags so its possible we don't
	 * need to do anything */
	if (!changed_flags)
		return;

	if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
		zd_mc_add_all(&hash);
	} else {
		DECLARE_MAC_BUF(macbuf);

		zd_mc_clear(&hash);
		for (i = 0; i < mc_count; i++) {
			if (!mclist)
				break;
			dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
				  print_mac(macbuf, mclist->dmi_addr));
			zd_mc_add_addr(&hash, mclist->dmi_addr);
			mclist = mclist->next;
		}
881
	}
Daniel Drake's avatar
Daniel Drake committed
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900

	spin_lock_irqsave(&mac->lock, flags);
	mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
	mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
	mac->multicast_hash = hash;
	spin_unlock_irqrestore(&mac->lock, flags);
	queue_work(zd_workqueue, &mac->set_multicast_hash_work);

	if (changed_flags & FIF_CONTROL)
		queue_work(zd_workqueue, &mac->set_rx_filter_work);

	/* no handling required for FIF_OTHER_BSS as we don't currently
	 * do BSSID filtering */
	/* FIXME: in future it would be nice to enable the probe response
	 * filter (so that the driver doesn't see them) until
	 * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd
	 * have to schedule work to enable prbresp reception, which might
	 * happen too late. For now we'll just listen and forward them all the
	 * time. */
901
902
}

Daniel Drake's avatar
Daniel Drake committed
903
static void set_rts_cts_work(struct work_struct *work)
904
{
Daniel Drake's avatar
Daniel Drake committed
905
906
907
908
909
910
911
912
913
914
915
916
917
918
	struct zd_mac *mac =
		container_of(work, struct zd_mac, set_rts_cts_work);
	unsigned long flags;
	unsigned int short_preamble;

	mutex_lock(&mac->chip.mutex);

	spin_lock_irqsave(&mac->lock, flags);
	mac->updating_rts_rate = 0;
	short_preamble = mac->short_preamble;
	spin_unlock_irqrestore(&mac->lock, flags);

	zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
	mutex_unlock(&mac->chip.mutex);
919
920
}

921
922
923
924
static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   struct ieee80211_bss_conf *bss_conf,
				   u32 changes)
925
{
Daniel Drake's avatar
Daniel Drake committed
926
927
928
929
930
	struct zd_mac *mac = zd_hw_mac(hw);
	unsigned long flags;

	dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);

931
	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
Daniel Drake's avatar
Daniel Drake committed
932
		spin_lock_irqsave(&mac->lock, flags);
933
		mac->short_preamble = bss_conf->use_short_preamble;
Daniel Drake's avatar
Daniel Drake committed
934
935
936
937
938
939
940
941
		if (!mac->updating_rts_rate) {
			mac->updating_rts_rate = 1;
			/* FIXME: should disable TX here, until work has
			 * completed and RTS_CTS reg is updated */
			queue_work(zd_workqueue, &mac->set_rts_cts_work);
		}
		spin_unlock_irqrestore(&mac->lock, flags);
	}
942
943
}

Daniel Drake's avatar
Daniel Drake committed
944
945
946
947
948
949
950
951
952
static const struct ieee80211_ops zd_ops = {
	.tx			= zd_op_tx,
	.start			= zd_op_start,
	.stop			= zd_op_stop,
	.add_interface		= zd_op_add_interface,
	.remove_interface	= zd_op_remove_interface,
	.config			= zd_op_config,
	.config_interface	= zd_op_config_interface,
	.configure_filter	= zd_op_configure_filter,
953
	.bss_info_changed	= zd_op_bss_info_changed,
Daniel Drake's avatar
Daniel Drake committed
954
955
956
};

struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
957
{
Daniel Drake's avatar
Daniel Drake committed
958
959
	struct zd_mac *mac;
	struct ieee80211_hw *hw;
960

Daniel Drake's avatar
Daniel Drake committed
961
962
963
964
	hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
	if (!hw) {
		dev_dbg_f(&intf->dev, "out of memory\n");
		return NULL;
965
	}
Daniel Drake's avatar
Daniel Drake committed
966
967
968
969
970
971
972
973
974
975
976

	mac = zd_hw_mac(hw);

	memset(mac, 0, sizeof(*mac));
	spin_lock_init(&mac->lock);
	mac->hw = hw;

	mac->type = IEEE80211_IF_TYPE_INVALID;

	memcpy(mac->channels, zd_channels, sizeof(zd_channels));
	memcpy(mac->rates, zd_rates, sizeof(zd_rates));
977
978
979
980
981
982
983
	mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
	mac->band.bitrates = mac->rates;
	mac->band.n_channels = ARRAY_SIZE(zd_channels);
	mac->band.channels = mac->channels;

	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;

984
985
	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
		    IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
Daniel Drake's avatar
Daniel Drake committed
986
987
988
989
990
991
992
993
994
995
996
997
998
	hw->max_rssi = 100;
	hw->max_signal = 100;

	hw->queues = 1;
	hw->extra_tx_headroom = sizeof(struct zd_ctrlset);

	skb_queue_head_init(&mac->ack_wait_queue);

	zd_chip_init(&mac->chip, hw, intf);
	housekeeping_init(mac);
	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
	INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
	INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
999
	INIT_WORK(&mac->process_intr, zd_process_intr);
Daniel Drake's avatar
Daniel Drake committed
1000
1001
1002

	SET_IEEE80211_DEV(hw, &intf->dev);
	return hw;
1003
1004
}

1005
1006
#define LINK_LED_WORK_DELAY HZ

David Howells's avatar
David Howells committed
1007
static void link_led_handler(struct work_struct *work)
1008
{
David Howells's avatar
David Howells committed
1009
1010
	struct zd_mac *mac =
		container_of(work, struct zd_mac, housekeeping.link_led_work.work);
1011
1012
1013
1014
1015
	struct zd_chip *chip = &mac->chip;
	int is_associated;
	int r;

	spin_lock_irq(&mac->lock);
Daniel Drake's avatar
Daniel Drake committed
1016
	is_associated = mac->associated;
1017
1018
1019
1020
1021
	spin_unlock_irq(&mac->lock);

	r = zd_chip_control_leds(chip,
		                 is_associated ? LED_ASSOCIATED : LED_SCANNING);
	if (r)
Daniel Drake's avatar
Daniel Drake committed
1022
		dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
1023
1024
1025
1026
1027
1028
1029

	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
		           LINK_LED_WORK_DELAY);
}

static void housekeeping_init(struct zd_mac *mac)
{
David Howells's avatar
David Howells committed
1030
	INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler);
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
}

static void housekeeping_enable(struct zd_mac *mac)
{
	dev_dbg_f(zd_mac_dev(mac), "\n");
	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
			   0);
}

static void housekeeping_disable(struct zd_mac *mac)
{
	dev_dbg_f(zd_mac_dev(mac), "\n");
	cancel_rearming_delayed_workqueue(zd_workqueue,
		&mac->housekeeping.link_led_work);
	zd_chip_control_leds(&mac->chip, LED_OFF);
}