* [PATCH 19/32] rt2x00: Fix panics in interrupt handlers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 3624 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Fix panics when the interrupt handlers are being
run while the ring is empty.
During the interrupt handling break the loop
correctly when an error has been detected,
more work is being done after the loop.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:50:36.000000000 +0200
@@ -844,7 +844,7 @@ rt2400pci_rxdone(void *data)
&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
skb = dev_alloc_skb(size + NET_IP_ALIGN);
if (!skb)
- return;
+ break;
skb_reserve(skb, NET_IP_ALIGN);
@@ -859,7 +859,7 @@ rt2400pci_rxdone(void *data)
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
- rt2x00_ring_index_inc(&rt2x00pci->rx);
+ rt2x00_ring_index_inc(ring);
}
/*
@@ -879,7 +879,7 @@ rt2400pci_txdone(void *data)
int tx_status;
int ack;
- do {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -925,7 +925,7 @@ rt2400pci_txdone(void *data)
entry->skb = NULL;
rt2x00_ring_index_done_inc(ring);
- } while (!rt2x00_ring_empty(ring));
+ }
/*
* Check if we are waiting on an empty queue
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:50:36.000000000 +0200
@@ -926,7 +926,7 @@ rt2500pci_rxdone(void *data)
&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
skb = dev_alloc_skb(size + NET_IP_ALIGN);
if (!skb)
- return;
+ break;
skb_reserve(skb, NET_IP_ALIGN);
@@ -943,7 +943,7 @@ rt2500pci_rxdone(void *data)
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
- rt2x00_ring_index_inc(&rt2x00pci->rx);
+ rt2x00_ring_index_inc(ring);
}
/*
@@ -964,7 +964,7 @@ rt2500pci_txdone(void *data)
int tx_status;
int ack;
- do {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -1010,7 +1010,7 @@ rt2500pci_txdone(void *data)
entry->skb = NULL;
rt2x00_ring_index_done_inc(ring);
- } while (!rt2x00_ring_empty(ring));
+ }
/*
* Check if we are waiting on an empty queue
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:50:36.000000000 +0200
@@ -808,7 +808,7 @@ rt2500usb_txdone(void *data)
struct txd *txd;
int ack;
- do {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -843,7 +843,7 @@ rt2500usb_txdone(void *data)
entry->skb = NULL;
rt2x00_ring_index_done_inc(entry->ring);
- } while (!rt2x00_ring_empty(ring));
+ }
/*
* Check if we are waiting on an empty queue
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 20/32] rt2x00: byte ordering correctness
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 3998 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Fix various little/big endian conversions.
rt2500pci should use cpu_to_le32 and rt2500usb should not.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:50:36.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:51:11.000000000 +0200
@@ -441,7 +441,7 @@ rt2500pci_config_channel(struct rt2x00_p
txpower = (txpower > 31) ? 31 : txpower;
if (rt2x00_rf(&rt2x00pci->chip, RF2525E) && channel == 14)
- rf4 |= 0x00000010;
+ rf4 |= cpu_to_le32(0x00000010);
if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
if (channel < 14) {
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:50:36.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:51:11.000000000 +0200
@@ -324,20 +324,20 @@ rt2500usb_config_channel(struct rt2x00_u
if (rt2x00_rf(&rt2x00usb->chip, RF5222)) {
if (channel < 14) {
- rf1 = cpu_to_le32(0x00022020);
- rf4 = cpu_to_le32(0x00000a0b);
+ rf1 = 0x00022020;
+ rf4 = 0x00000a0b;
} else if (channel == 14) {
- rf1 = cpu_to_le32(0x00022010);
- rf4 = cpu_to_le32(0x00000a1b);
+ rf1 = 0x00022010;
+ rf4 = 0x00000a1b;
} else if (channel < 64) {
- rf1 = cpu_to_le32(0x00022010);
- rf4 = cpu_to_le32(0x00000a1f);
+ rf1 = 0x00022010;
+ rf4 = 0x00000a1f;
} else if (channel < 140) {
- rf1 = cpu_to_le32(0x00022010);
- rf4 = cpu_to_le32(0x00000a0f);
+ rf1 = 0x00022010;
+ rf4 = 0x00000a0f;
} else if (channel < 161) {
- rf1 = cpu_to_le32(0x00022020);
- rf4 = cpu_to_le32(0x00000a07);
+ rf1 = 0x00022020;
+ rf4 = 0x00000a07;
}
}
@@ -1829,7 +1829,7 @@ rt2500usb_init_hw_channels(struct rt2x00
};
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
- channels[counter].val = cpu_to_le32(vals[counter]);
+ channels[counter].val = vals[counter];
} else if (rt2x00_rf(&rt2x00usb->chip, RF2523)
|| rt2x00_rf(&rt2x00usb->chip, RF2524)
|| rt2x00_rf(&rt2x00usb->chip, RF2525)) {
@@ -1841,8 +1841,7 @@ rt2500usb_init_hw_channels(struct rt2x00
};
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
- channels[counter].val =
- cpu_to_le32(vals[counter] | rf2_base);
+ channels[counter].val = vals[counter] | rf2_base;
} else if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
u32 vals[] = {
0x0000089a, 0x0000089e, 0x0000089e, 0x000008a2,
@@ -1852,7 +1851,7 @@ rt2500usb_init_hw_channels(struct rt2x00
};
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
- channels[counter].val = cpu_to_le32(vals[counter]);
+ channels[counter].val = vals[counter];
} else if (rt2x00_rf(&rt2x00usb->chip, RF5222)) {
static u32 vals[] = {
0x00001136, 0x0000113a, 0x0000113e, 0x00001182,
@@ -1868,7 +1867,7 @@ rt2500usb_init_hw_channels(struct rt2x00
};
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
- channels[counter].val = cpu_to_le32(vals[counter]);
+ channels[counter].val = vals[counter];
}
/*
@@ -1895,9 +1894,9 @@ rt2500usb_init_hw_channels(struct rt2x00
*/
for (counter = 0; counter < ARRAY_SIZE(rf); counter++) {
if (rt2x00_rf(&rt2x00usb->chip, rf[counter].chip)) {
- rt2x00usb->rf1 = cpu_to_le32(rf[counter].val[0]);
- rt2x00usb->rf3 = cpu_to_le32(rf[counter].val[1]);
- rt2x00usb->rf4 = cpu_to_le32(rf[counter].val[2]);
+ rt2x00usb->rf1 = rf[counter].val[0];
+ rt2x00usb->rf3 = rf[counter].val[1];
+ rt2x00usb->rf4 = rf[counter].val[2];
}
}
}
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 21/32] rt2x00: PRIO ring should be treated as regular TX ring
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 3215 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Remove PRIO_ENTRIES define, the prio ring
should be treated as a regular TX ring.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:50:36.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:52:01.000000000 +0200
@@ -1145,7 +1145,7 @@ rt2400pci_allocate_rings(struct rt2x00_p
ATIM_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))
|| rt2400pci_alloc_ring(
rt2x00pci, &rt2x00pci->prio, rt2400pci_txdone,
- PRIO_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
+ TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
|| rt2400pci_alloc_ring(
rt2x00pci, &rt2x00pci->beacon, rt2400pci_beacondone,
BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:51:11.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:52:01.000000000 +0200
@@ -1227,7 +1227,7 @@ rt2500pci_allocate_rings(struct rt2x00_p
ATIM_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))
|| rt2500pci_alloc_ring(
rt2x00pci, &rt2x00pci->prio, rt2500pci_txdone,
- PRIO_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
+ TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
|| rt2500pci_alloc_ring(
rt2x00pci, &rt2x00pci->beacon, rt2500pci_beacondone,
BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:51:11.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:52:01.000000000 +0200
@@ -996,7 +996,7 @@ rt2500usb_allocate_rings(struct rt2x00_u
ATIM_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))
|| rt2500usb_alloc_ring(
rt2x00usb, &rt2x00usb->prio, &rt2500usb_txdone,
- PRIO_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
+ TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd))
|| rt2500usb_alloc_ring(
rt2x00usb, &rt2x00usb->beacon, &rt2500usb_beacondone,
BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:52:01.000000000 +0200
@@ -90,7 +90,6 @@ static int rt2x00_debug_level = 0;
#define RX_ENTRIES 12
#define TX_ENTRIES 12
#define ATIM_ENTRIES 1
-#define PRIO_ENTRIES 6
#define BEACON_ENTRIES 1
/*
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 22/32] rt2x00: Allocate ring structures in single array
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 406 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Allocate all ring structures seperately and
as an array of rings. This will make the
rt2x00_pci and rt2x00_usb structures more generic
for all rt2x00 modules.
Use seperate function to convert a dscape ring ID
to the address of the actual ring.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Available on server:
http://mendiosus.nl/rt2x00/rt2x00-22-rings.diff
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 23/32] rt2x00: Make correct cast in USB interrupt
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 1760 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
The USB interrupt handler receives the entry
in the ring and not the ring itself.
Also check if the status indicates an error
before queueing the work.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:54:33.000000000 +0200
@@ -856,11 +856,14 @@ rt2500usb_txdone(void *data)
static void
rt2500usb_interrupt(struct urb *urb, struct pt_regs *regs)
{
- struct data_ring *ring = (struct data_ring*)urb->context;
+ struct data_entry *entry = (struct data_entry*)urb->context;
struct rt2x00_usb *rt2x00usb =
- ieee80211_dev_hw_data(ring->net_dev);
+ ieee80211_dev_hw_data(entry->ring->net_dev);
- queue_work(rt2x00usb->workqueue, &ring->irq_work);
+ if (urb->status)
+ return;
+
+ queue_work(rt2x00usb->workqueue, &entry->ring->irq_work);
}
/*
@@ -1064,7 +1067,6 @@ rt2500usb_init_txring(struct rt2x00_usb
}
}
-
static int
rt2500usb_init_rings(struct rt2x00_usb *rt2x00usb)
{
@@ -1798,7 +1800,7 @@ rt2500usb_init_hw_channels(struct rt2x00
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
channels[counter].val = vals[counter] | rf2_base;
} else if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x0000089a, 0x0000089e, 0x0000089e, 0x000008a2,
0x000008a2, 0x000008a6, 0x000008a6, 0x000008aa,
0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 26/32] rt2x00: Move all USB and PCI common data into seperate headers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 364 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Now that rt2x00_pci and rt2x00_usb structures in the various
headers are generic enough, add 2 header files rt2x00pci and rt2x00usb
and make them contain all common information of the PCI or USB modules.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Available on server:
http://mendiosus.nl/rt2x00/rt2x00-26-dev.diff
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 24/32] rt2x00: Use correct desc_addr and data_addr
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 7557 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
USB buffer don't have a seperate descriptor ring and data ring.
The location of the descriptor area and data area depends
on the type of ring. Add functions to determine the correct
location and use these instead of the invalid desc_addr and data_addr
pointers.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:54:33.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:55:14.000000000 +0200
@@ -740,7 +740,7 @@ rt2500usb_rxdone(void *data)
while (1) {
entry = rt2x00_get_data_entry(ring);
- rxd = entry->desc_addr;
+ rxd = rt2x00usb_rxdesc_addr(entry);
/*
* There has been a problem. Ignore packet.
@@ -769,7 +769,8 @@ rt2500usb_rxdone(void *data)
skb_reserve(skb, NET_IP_ALIGN);
- memcpy(skb_put(skb, size), entry->data_addr, size);
+ memcpy(skb_put(skb, size),
+ rt2x00usb_rxdata_addr(entry), size);
rt2x00usb->rx_params.ssi =
rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
@@ -805,7 +806,7 @@ rt2500usb_txdone(void *data)
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
- txd = entry->desc_addr;
+ txd = rt2x00usb_txdesc_addr(entry);
ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
@@ -937,16 +938,14 @@ rt2500usb_alloc_ring(
entry[counter].urb = usb_alloc_urb(0, GFP_KERNEL);
else
entry[counter].urb = NULL;
- if (entry[counter].urb == NULL)
+ if (!entry[counter].urb)
status = -ENOMEM;
entry[counter].skb = NULL;
- entry[counter].desc_addr = ring->data_addr
- + (counter * ring->desc_size);
entry[counter].data_addr = ring->data_addr
- + (ring->stats.limit * ring->desc_size)
+ + (counter * ring->desc_size)
+ (counter * ring->data_size);
entry[counter].data_dma = ring->data_dma
- + (ring->stats.limit * ring->desc_size)
+ + (counter * ring->desc_size)
+ (counter * ring->data_size);
}
@@ -959,7 +958,7 @@ rt2500usb_free_ring(struct rt2x00_usb *r
struct data_entry *entry;
u8 counter;
- if (ring->entry)
+ if (!ring->entry)
goto exit;
entry = (struct data_entry*)ring->entry;
@@ -1091,9 +1090,9 @@ rt2500usb_init_registers(struct rt2x00_u
return -EBUSY;
rt2x00_vendor_request(rt2x00usb, USB_DEVICE_MODE,
- USB_VENDOR_REQUEST_OUT, USB_MODE_TEST, 0x00, NULL, 0);
+ USB_VENDOR_REQUEST_OUT, 0x00, USB_MODE_TEST, NULL, 0);
rt2x00_vendor_request(rt2x00usb, USB_SINGLE_WRITE,
- USB_VENDOR_REQUEST_OUT, 0x0308, 0x00f0, NULL, 0);
+ USB_VENDOR_REQUEST_OUT, 0x0308, 0xf0, NULL, 0);
rt2x00_register_write(rt2x00usb, TXRX_CSR2, 0x0001);
rt2x00_register_write(rt2x00usb, MAC_CSR13, 0x1111);
@@ -1242,9 +1241,9 @@ rt2500usb_tx(struct net_device *net_dev,
return NET_RX_DROP;
entry = rt2x00_get_data_entry(ring);
- txd = entry->desc_addr;
+ txd = rt2x00usb_txdesc_addr(entry);
- memcpy(entry->data_addr, skb->data, skb->len);
+ memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt2500usb_write_tx_desc(rt2x00usb, txd, skb, control);
entry->skb = skb;
@@ -1621,8 +1620,9 @@ rt2500usb_beacon_update(struct net_devic
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
- memcpy(entry->data_addr, skb->data, skb->len);
- rt2500usb_write_tx_desc(rt2x00usb, entry->desc_addr, skb, control);
+ memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
+ rt2500usb_write_tx_desc(rt2x00usb,
+ rt2x00usb_txdesc_addr(entry), skb, control);
usb_fill_bulk_urb(
entry->urb,
@@ -1658,6 +1658,14 @@ rt2500usb_init_eeprom(struct rt2x00_usb
rt2x00_set_chip(&rt2x00usb->chip, RT2570,
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE));
+ if (!rt2x00_rf(&rt2x00usb->chip, RF2522)
+ && !rt2x00_rf(&rt2x00usb->chip, RF2523)
+ && !rt2x00_rf(&rt2x00usb->chip, RF2524)
+ && !rt2x00_rf(&rt2x00usb->chip, RF2525)
+ && !rt2x00_rf(&rt2x00usb->chip, RF2525E)
+ && !rt2x00_rf(&rt2x00usb->chip, RF5222))
+ return -ENODEV;
+
/*
* 3 - Identify default antenna configuration.
* Ralink devices have have antenna options for both TX as RX.
@@ -1691,26 +1699,27 @@ rt2500usb_init_mac(struct rt2x00_usb *rt
{
struct net_device *net_dev = usb_get_intfdata(
rt2x00usb->usb_intf);
- u16 reg[3] = {0, 0, 0};
+ u16 eeprom[3] = {0, 0, 0};
/*
* Read MAC address from EEPROM.
*/
- rt2x00_eeprom_multiread(rt2x00usb, EEPROM_MAC_ADDR, ®[0], 6);
+ rt2x00_eeprom_multiread(rt2x00usb, EEPROM_MAC_ADDR, &eeprom[0], 6);
- net_dev->dev_addr[0] = rt2x00_get_field16(reg[0], MAC_CSR2_BYTE0);
- net_dev->dev_addr[1] = rt2x00_get_field16(reg[0], MAC_CSR2_BYTE1);
- net_dev->dev_addr[2] = rt2x00_get_field16(reg[1], MAC_CSR3_BYTE2);
- net_dev->dev_addr[3] = rt2x00_get_field16(reg[1], MAC_CSR3_BYTE3);
- net_dev->dev_addr[4] = rt2x00_get_field16(reg[2], MAC_CSR4_BYTE4);
- net_dev->dev_addr[5] = rt2x00_get_field16(reg[2], MAC_CSR4_BYTE5);
+ net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0], MAC_CSR2_BYTE0);
+ net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0], MAC_CSR2_BYTE1);
+ net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1], MAC_CSR3_BYTE2);
+ net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1], MAC_CSR3_BYTE3);
+ net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2], MAC_CSR4_BYTE4);
+ net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2], MAC_CSR4_BYTE5);
net_dev->addr_len = 6;
/*
* Write MAC address to register.
*/
- rt2x00_register_multiwrite(rt2x00usb, MAC_CSR2, ®[0], sizeof(reg));
+ rt2x00_register_multiwrite(rt2x00usb, MAC_CSR2,
+ &eeprom[0], sizeof(reg));
return 0;
}
@@ -1730,7 +1739,7 @@ rt2500usb_init_hw_channels(struct rt2x00
{ RF2523, { 0x00022010, 0x000e0111, 0x00000a1b } },
{ RF2524, { 0x00032020, 0x00000101, 0x00000a1b } },
{ RF2525, { 0x00022020, 0x00060111, 0x00000a1b } },
- { RF2525E, { 0x00022020, 0x00060111, 0x00000000 } },
+ { RF2525E, { 0x00022010, 0x00060111, 0x00000000 } },
{ RF5222, { 0x00000000, 0x00000101, 0x00000000 } }
};
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:55:14.000000000 +0200
@@ -683,6 +683,36 @@ struct data_entry{
} __attribute__ ((packed));
/*
+ * The location of the descriptor is variating and depends
+ * on the fact if it is a TX or RX ring and the length of the packet.
+ * We need some small handlers to properly access the descriptors.
+ */
+static inline void*
+rt2x00usb_rxdata_addr(struct data_entry *entry)
+{
+ return entry->data_addr;
+}
+
+static inline void*
+rt2x00usb_rxdesc_addr(struct data_entry *entry)
+{
+ return entry->data_addr +
+ (entry->urb->actual_length - entry->ring->desc_size);
+}
+
+static inline void*
+rt2x00usb_txdata_addr(struct data_entry *entry)
+{
+ return entry->data_addr + entry->ring->desc_size;
+}
+
+static inline void*
+rt2x00usb_txdesc_addr(struct data_entry *entry)
+{
+ return entry->data_addr;
+}
+
+/*
* Device specific structure.
*/
struct rt2x00_usb{
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 25/32] rt2x00: Add flag handlers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 12734 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Add flag handlers to set the state and capabilities of
the driver.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:56:05.000000000 +0200
@@ -1099,7 +1099,7 @@ rt2400pci_allocate_rings(struct rt2x00_p
return -ENOMEM;
}
- rt2x00pci->atim_available = 1;
+ SET_FLAG(rt2x00pci, ATIM_AVAILABLE);
if (rt2400pci_alloc_ring(
rt2x00pci, &rt2x00pci->ring[RING_RX], rt2400pci_rxdone,
@@ -1549,6 +1549,8 @@ rt2400pci_open(struct net_device *net_de
rt2x00_set_field32(®, CSR8_RXDONE, 0);
rt2x00_register_write(rt2x00pci, CSR8, reg);
+ SET_FLAG(rt2x00pci, RADIO_ENABLED);
+
return 0;
exit_fail:
@@ -1563,6 +1565,8 @@ rt2400pci_stop(struct net_device *net_de
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
u32 reg;
+ CLEAR_FLAG(rt2x00pci, RADIO_ENABLED);
+
rt2x00_register_write(rt2x00pci, PWRCSR0, 0);
/*
@@ -1972,16 +1976,11 @@ rt2400pci_init_eeprom(struct rt2x00_pci
rt2x00pci->led_mode = rt2x00_get_field16(eeprom,
EEPROM_ANTENNA_LED_MODE);
-#ifdef CONFIG_RT2400PCI_BUTTON
/*
* 6 - Detect if this device has an hardware controlled radio.
- * If this device is not hardware controlled, disable polling timer.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- rt2x00pci->button_status = BUTTON_STATUS_OFF;
- else
- rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
-#endif /* CONFIG_RT2400PCI_BUTTON */
+ SET_FLAG(rt2x00pci, HARDWARE_BUTTON);
/*
* 7 - Read BBP data from EEPROM and store in private structure.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:56:05.000000000 +0200
@@ -868,6 +868,11 @@ struct data_entry{
* Device specific structure.
*/
struct rt2x00_pci{
+ /*
+ * Device flags.
+ */
+ unsigned int flags;
+
#ifdef CONFIG_RT2400PCI_BUTTON
/*
* ACPI device for generation of ACPI events.
@@ -935,8 +940,6 @@ struct rt2x00_pci{
*/
int false_cca;
- int atim_available;
-
/*
* EEPROM bus width.
*/
@@ -987,7 +990,7 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
{
u8 atim;
- atim = rt2x00pci->atim_available;
+ atim = GET_FLAG(rt2x00pci, ATIM_AVAILABLE);
/*
* Check if the rings have been allocated.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:56:05.000000000 +0200
@@ -1180,7 +1180,7 @@ rt2500pci_allocate_rings(struct rt2x00_p
return -ENOMEM;
}
- rt2x00pci->atim_available = 1;
+ SET_FLAG(rt2x00pci, ATIM_AVAILABLE);
if (rt2500pci_alloc_ring(
rt2x00pci, &rt2x00pci->ring[RING_RX], rt2500pci_rxdone,
@@ -1657,6 +1657,8 @@ rt2500pci_open(struct net_device *net_de
rt2x00_set_field32(®, CSR8_RXDONE, 0);
rt2x00_register_write(rt2x00pci, CSR8, reg);
+ SET_FLAG(rt2x00pci, RADIO_ENABLED);
+
return 0;
exit_fail:
@@ -1671,6 +1673,8 @@ rt2500pci_stop(struct net_device *net_de
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
u32 reg;
+ CLEAR_FLAG(rt2x00pci, RADIO_ENABLED);
+
rt2x00_register_write(rt2x00pci, PWRCSR0, 0);
/*
@@ -1929,7 +1933,7 @@ rt2500pci_conf_tx(struct net_device *net
/*
* The passed variables are stored as real value ((2^n)-1).
- * RT2400 registers require to know the bit number 'n'.
+ * RT2500 registers require to know the bit number 'n'.
*/
if (params->cw_min)
ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
@@ -2075,16 +2079,11 @@ rt2500pci_init_eeprom(struct rt2x00_pci
rt2x00pci->led_mode = rt2x00_get_field16(eeprom,
EEPROM_ANTENNA_LED_MODE);
-#ifdef CONFIG_RT2500PCI_BUTTON
/*
* 6 - Detect if this device has an hardware controlled radio.
- * If this device is not hardware controlled, disable polling timer.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- rt2x00pci->button_status = BUTTON_STATUS_OFF;
- else
- rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
-#endif /* CONFIG_RT2500PCI_BUTTON */
+ SET_FLAG(rt2x00pci, HARDWARE_BUTTON);
/*
* 7 - Read BBP data from EEPROM and store in private structure.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:53:13.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:56:05.000000000 +0200
@@ -1137,6 +1137,11 @@ struct data_entry{
* Device specific structure.
*/
struct rt2x00_pci{
+ /*
+ * Device flags.
+ */
+ unsigned int flags;
+
#ifdef CONFIG_RT2500PCI_BUTTON
/*
* ACPI device for generation of ACPI events.
@@ -1200,8 +1205,6 @@ struct rt2x00_pci{
*/
struct ieee80211_rx_status rx_params;
- u16 atim_available;
-
/*
* EEPROM bus width.
*/
@@ -1252,7 +1255,7 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
{
u8 atim;
- atim = rt2x00pci->atim_available;
+ atim = GET_FLAG(rt2x00pci, ATIM_AVAILABLE);
/*
* Check if the rings have been allocated.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:55:14.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:56:05.000000000 +0200
@@ -742,10 +742,14 @@ rt2500usb_rxdone(void *data)
entry = rt2x00_get_data_entry(ring);
rxd = rt2x00usb_rxdesc_addr(entry);
+ if (GET_FLAG(entry, ENTRY_OWNER_NIC))
+ break;
+
/*
- * There has been a problem. Ignore packet.
- */
+ * There has been a problem. Ignore packet.
+ */
if (entry->urb->status) {
+ SET_FLAG(entry, ENTRY_OWNER_NIC);
usb_submit_urb(entry->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
continue;
@@ -782,6 +786,7 @@ rt2500usb_rxdone(void *data)
total_rssi += rt2x00usb->rx_params.ssi;
}
+ SET_FLAG(entry, ENTRY_OWNER_NIC);
usb_submit_urb(entry->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
@@ -808,6 +813,9 @@ rt2500usb_txdone(void *data)
entry = rt2x00_get_data_entry_done(ring);
txd = rt2x00usb_txdesc_addr(entry);
+ if (GET_FLAG(entry, ENTRY_OWNER_NIC))
+ break;
+
ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
/*
@@ -861,6 +869,9 @@ rt2500usb_interrupt(struct urb *urb, str
struct rt2x00_usb *rt2x00usb =
ieee80211_dev_hw_data(entry->ring->net_dev);
+ if (!GET_FLAG(rt2x00usb, RADIO_ENABLED))
+ return;
+
if (urb->status)
return;
@@ -989,7 +1000,7 @@ rt2500usb_allocate_rings(struct rt2x00_u
return -ENOMEM;
}
- rt2x00usb->atim_available = 1;
+ SET_FLAG(rt2x00usb, ATIM_AVAILABLE);
if (rt2500usb_alloc_ring(
rt2x00usb, &rt2x00usb->ring[RING_RX], &rt2500usb_rxdone,
@@ -1049,6 +1060,7 @@ rt2500usb_init_rxring(struct rt2x00_usb
ring->entry_size + ring->desc_size,
rt2500usb_interrupt,
&entry[counter]);
+ SET_FLAG(&entry[counter], ENTRY_OWNER_NIC | ENTRY_TYPE_RX);
usb_submit_urb(entry[counter].urb, GFP_ATOMIC);
}
}
@@ -1063,6 +1075,7 @@ rt2500usb_init_txring(struct rt2x00_usb
for (counter = 0; counter < ring->stats.limit; counter++) {
entry[counter].urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
entry[counter].urb->transfer_dma = entry[counter].data_dma;
+ CLEAR_FLAGS(&entry[counter]);
}
}
@@ -1223,6 +1236,8 @@ rt2500usb_tx(struct net_device *net_dev,
struct sk_buff *skb, struct ieee80211_tx_control *control)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ struct usb_devive *usb_dev =
+ interface_to_usbdev(rt2x00usb->usb_intf);
struct data_ring *ring;
struct data_entry *entry;
struct txd *txd;
@@ -1247,6 +1262,7 @@ rt2500usb_tx(struct net_device *net_dev,
rt2500usb_write_tx_desc(rt2x00usb, txd, skb, control);
entry->skb = skb;
+ SET_FLAG(entry, ENTRY_OWNER_NIC);
usb_fill_bulk_urb(
entry->urb,
usb_dev,
@@ -1320,6 +1336,8 @@ rt2500usb_open(struct net_device *net_de
rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 0);
rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+ SET_FLAG(rt2x00usb, RADIO_ENABLED);
+
return 0;
exit_fail:
@@ -1336,6 +1354,8 @@ rt2500usb_stop(struct net_device *net_de
int counter;
u16 reg;
+ CLEAR_FLAG(rt2x00usb, RADIO_ENABLED);
+
/*
* Cancel RX.
*/
@@ -1609,6 +1629,8 @@ rt2500usb_beacon_update(struct net_devic
struct sk_buff *skb, struct ieee80211_tx_control *control)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ struct usb_devive *usb_dev =
+ interface_to_usbdev(rt2x00usb->usb_intf);
struct data_entry *entry;
entry = rt2x00_get_data_entry(&rt2x00usb->ring[RING_BEACON]);
@@ -1624,6 +1646,7 @@ rt2500usb_beacon_update(struct net_devic
rt2500usb_write_tx_desc(rt2x00usb,
rt2x00usb_txdesc_addr(entry), skb, control);
+ SET_FLAG(entry, ENTRY_OWNER_NIC);
usb_fill_bulk_urb(
entry->urb,
usb_dev,
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:55:14.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:56:05.000000000 +0200
@@ -648,6 +648,13 @@ struct rxd{
*/
struct data_entry{
/*
+ * Status flag.
+ */
+ unsigned int flags;
+#define ENTRY_OWNER_NIC 0x00000001
+#define ENTRY_TYPE_RX 0x00000002
+
+ /*
* Ring we belong to.
*/
struct data_ring *ring;
@@ -717,6 +724,11 @@ rt2x00usb_txdesc_addr(struct data_entry
*/
struct rt2x00_usb{
/*
+ * Device flags.
+ */
+ unsigned int flags;
+
+ /*
* PCI device structure.
*/
struct usb_interface *usb_intf;
@@ -748,8 +760,6 @@ struct rt2x00_usb{
*/
struct ieee80211_rx_status rx_params;
- u8 atim_available;
-
/*
* Alignment.
*/
@@ -798,7 +808,7 @@ rt2x00usb_get_ring(struct rt2x00_usb *rt
{
u8 atim;
- atim = rt2x00usb->atim_available;
+ atim = GET_FLAG(rt2x00usb, ATIM_AVAILABLE);
/*
* Check if the rings have been allocated.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:52:01.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:56:05.000000000 +0200
@@ -93,6 +93,32 @@ static int rt2x00_debug_level = 0;
#define BEACON_ENTRIES 1
/*
+ * Flag handlers
+ */
+#define SET_FLAG(__dev, __flag) ( (__dev)->flags |= (__flag) )
+#define GET_FLAG(__dev, __flag) ( !!((__dev)->flags & (__flag)) )
+#define CLEAR_FLAG(__dev, __flag) ( (__dev)->flags &= ~(__flag) )
+#define CLEAR_FLAGS(__dev) ( (__dev)->flags = 0 )
+
+/*
+ * Device flags
+ */
+#define INTERFACE_INITIALIZED 0x00000001
+#define INTERFACE_PROMISC 0x00000002
+#define FIRMWARE_FAILED 0x00000004
+#define FIRMWARE_LOADED 0x00000008
+#define RADIO_ENABLED 0x00000010
+#define RADIO_RESUME 0x00000020
+#define ATIM_AVAILABLE 0x00000040
+#define FRAME_TYPE 0x00000080
+#define EXTERNAL_LNA 0x00000100
+#define EXTERNAL_LNA_A 0x00000200
+#define EXTERNAL_LNA_BG 0x00000400
+#define RF_SEQUENCE 0x00000800
+#define DOUBLE_ANTENNA 0x00001000
+#define HARDWARE_BUTTON 0x00002000
+
+/*
* TX result flags.
*/
enum TX_STATUS {
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 27/32] rt2x00: Put Hardware button in generic header
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 14042 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Put the hardware button handling as much as possible
in the new generic header for PCI.
The individial .c files should now only contain
the polling function to check the state of the hardware button.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:03:48.000000000 +0200
@@ -38,10 +38,6 @@
#include <net/iw_handler.h>
#include <net/d80211.h>
-#ifdef CONFIG_RT2400PCI_BUTTON
-#include <acpi/acpi_bus.h>
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
#include <asm/io.h>
/*
@@ -364,6 +360,24 @@ rt2x00_eeprom_multiread(
rt2x00_eeprom_read(rt2x00pci, word + counter, data++);
}
+#ifdef CONFIG_RT2400PCI_BUTTON
+/*
+ * Hardware button poll handler.
+ */
+static void
+rt2400pci_button_poll(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ u32 reg;
+
+ rt2x00_register_read(rt2x00pci, GPIOCSR, ®);
+ rt2x00pci_button_status(
+ rt2x00pci, rt2x00_get_field32(reg, GPIOCSR_BIT0));
+}
+#else /* CONFIG_RT2400PCI_BUTTON */
+static void rt2400pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+#endif /* CONFIG_RT2400PCI_BUTTON */
+
/*
* Configuration handlers.
*/
@@ -2258,24 +2272,10 @@ rt2400pci_initialize(struct pci_dev *pci
|| rt2400pci_init_hw(rt2x00pci))
goto exit_destroy_workqueue;
-#ifdef CONFIG_RT2400PCI_BUTTON
- strcpy(acpi_device_class(&rt2x00pci->acpi_dev), DRV_NAME "_button");
- strcpy(acpi_device_bid(&rt2x00pci->acpi_dev), DRV_NAME);
- strcpy(acpi_device_name(&rt2x00pci->acpi_dev), DRV_NAME);
-
- init_timer(&rt2x00pci->poll_timer);
-
- if (rt2x00_poll_delay
- && rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE) {
- rt2x00pci->button_status = rt2400pci_poll(rt2x00pci);
- rt2x00pci->poll_delay = rt2x00_poll_delay * (HZ / 10);
- rt2x00pci->poll_timer.function = rt2400pci_poll_expire;
- rt2x00pci->poll_timer.data = (unsigned long)rt2x00pci;
- rt2x00pci->poll_timer.expires =
- jiffies + rt2x00pci->poll_delay;
- add_timer(&rt2x00pci->poll_timer);
- };
-#endif /* CONFIG_RT2400PCI_BUTTON */
+ /*
+ * If required start hardware button polling.
+ */
+ rt2x00pci_button_start(rt2x00pci, rt2400pci_button_poll);
return 0;
@@ -2294,13 +2294,10 @@ rt2400pci_uninitialize(struct net_device
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
-#ifdef CONFIG_RT2400PCI_BUTTON
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
- del_timer_sync(&rt2x00pci->poll_timer);
-#endif /* CONFIG_RT2400PCI_BUTTON */
+ rt2x00pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
@@ -2506,40 +2503,6 @@ rt2400pci_resume(struct pci_dev *pci_dev
}
#endif /* CONFIG_PM */
-#ifdef CONFIG_RT2400PCI_BUTTON
-static int
-rt2400pci_poll(struct rt2x00_pci *rt2x00pci)
-{
- u32 reg;
-
- rt2x00_register_read(rt2x00pci, GPIOCSR, ®);
- return rt2x00_get_field32(reg, GPIOCSR_BIT0);
-}
-
-static void
-rt2400pci_poll_expire(unsigned long data)
-{
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
- u16 status;
-
- status = rt2400pci_poll(rt2x00pci);
-
- if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
- return;
-
- if (status != rt2x00pci->button_status) {
- rt2x00pci->button_status = status;
- acpi_bus_generate_event(&rt2x00pci->acpi_dev,
- ACPI_TYPE_EVENT, rt2x00pci->button_status);
- }
-
- rt2x00pci->poll_timer.expires = jiffies + rt2x00pci->poll_delay;
-
- if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
- add_timer(&rt2x00pci->poll_timer);
-}
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
/*
* RT2400pci module information.
*/
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 22:03:48.000000000 +0200
@@ -863,21 +863,4 @@ static int rt2400pci_beacon_update(struc
struct sk_buff *skb, struct ieee80211_tx_control *control);
static int rt2400pci_tx_last_beacon(struct net_device *net_dev);
-/*
- * HW button support structures and variables.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2400PCI_BUTTON
-/*
- * Module parameter.
- */
-static int rt2x00_poll_delay = 100;
-
-/*
- * Declaration of several required functions.
- */
-static int rt2400pci_poll(struct rt2x00_pci *rt2x00pci);
-static void rt2400pci_poll_expire(unsigned long data);
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
#endif /* RT2400PCI_H */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:03:48.000000000 +0200
@@ -38,10 +38,6 @@
#include <net/iw_handler.h>
#include <net/d80211.h>
-#ifdef CONFIG_RT2500PCI_BUTTON
-#include <acpi/acpi_bus.h>
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
#include <asm/io.h>
/*
@@ -364,6 +360,24 @@ rt2x00_eeprom_multiread(
rt2x00_eeprom_read(rt2x00pci, word + counter, data++);
}
+#ifdef CONFIG_RT2500PCI_BUTTON
+/*
+ * Hardware button poll handler.
+ */
+static void
+rt2500pci_button_poll(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ u32 reg;
+
+ rt2x00_register_read(rt2x00pci, GPIOCSR, ®);
+ rt2x00pci_button_status(
+ rt2x00pci, rt2x00_get_field32(reg, GPIOCSR_BIT0));
+}
+#else /* CONFIG_RT2500PCI_BUTTON */
+static void rt2500pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+#endif /* CONFIG_RT2500PCI_BUTTON */
+
/*
* Configuration handlers.
*/
@@ -2547,24 +2561,10 @@ rt2500pci_initialize(struct pci_dev *pci
|| rt2500pci_init_hw(rt2x00pci))
goto exit_destroy_workqueue;
-#ifdef CONFIG_RT2500PCI_BUTTON
- strcpy(acpi_device_class(&rt2x00pci->acpi_dev), DRV_NAME "_button");
- strcpy(acpi_device_bid(&rt2x00pci->acpi_dev), DRV_NAME);
- strcpy(acpi_device_name(&rt2x00pci->acpi_dev), DRV_NAME);
-
- init_timer(&rt2x00pci->poll_timer);
-
- if (rt2x00_poll_delay
- && rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE) {
- rt2x00pci->button_status = rt2500pci_poll(rt2x00pci);
- rt2x00pci->poll_delay = rt2x00_poll_delay * (HZ / 10);
- rt2x00pci->poll_timer.function = rt2500pci_poll_expire;
- rt2x00pci->poll_timer.data = (unsigned long)rt2x00pci;
- rt2x00pci->poll_timer.expires =
- jiffies + rt2x00pci->poll_delay;
- add_timer(&rt2x00pci->poll_timer);
- };
-#endif /* CONFIG_RT2500PCI_BUTTON */
+ /*
+ * If required start hardware button polling.
+ */
+ rt2x00pci_button_start(rt2x00pci, rt2500pci_button_poll);
return 0;
@@ -2583,13 +2583,10 @@ rt2500pci_uninitialize(struct net_device
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
-#ifdef CONFIG_RT2500PCI_BUTTON
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci->button_status = BUTTON_STATUS_UNAVAILABLE;
- del_timer_sync(&rt2x00pci->poll_timer);
-#endif /* CONFIG_RT2500PCI_BUTTON */
+ rt2x00pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
@@ -2791,40 +2788,6 @@ rt2500pci_resume(struct pci_dev *pci_dev
}
#endif /* CONFIG_PM */
-#ifdef CONFIG_RT2500PCI_BUTTON
-static int
-rt2500pci_poll(struct rt2x00_pci *rt2x00pci)
-{
- u32 reg;
-
- rt2x00_register_read(rt2x00pci, GPIOCSR, ®);
- return rt2x00_get_field32(reg, GPIOCSR_BIT0);
-}
-
-static void
-rt2500pci_poll_expire(unsigned long data)
-{
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
- u16 status;
-
- status = rt2500pci_poll(rt2x00pci);
-
- if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
- return;
-
- if (status != rt2x00pci->button_status) {
- rt2x00pci->button_status = status;
- acpi_bus_generate_event(&rt2x00pci->acpi_dev,
- ACPI_TYPE_EVENT, rt2x00pci->button_status);
- }
-
- rt2x00pci->poll_timer.expires = jiffies + rt2x00pci->poll_delay;
-
- if (rt2x00pci->button_status != BUTTON_STATUS_UNAVAILABLE)
- add_timer(&rt2x00pci->poll_timer);
-}
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
/*
* RT2500pci module information.
*/
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 22:03:48.000000000 +0200
@@ -1132,21 +1132,4 @@ static int rt2500pci_beacon_update(struc
struct sk_buff *skb, struct ieee80211_tx_control *control);
static int rt2500pci_tx_last_beacon(struct net_device *net_dev);
-/*
- * HW button support structures and variables.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2500PCI_BUTTON
-/*
- * Module parameter.
- */
-static int rt2x00_poll_delay = 100;
-
-/*
- * Declaration of several required functions.
- */
-static int rt2500pci_poll(struct rt2x00_pci *rt2x00pci);
-static void rt2500pci_poll_expire(unsigned long data);
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
#endif /* RT2500PCI_H */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h 2006-04-27 22:00:04.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h 2006-04-27 22:03:48.000000000 +0200
@@ -45,6 +45,37 @@
#define EEPROM_READ_OPCODE 0x06
/*
+ * HW button structure.
+ */
+#ifdef CONFIG_RT2X00_BUTTON
+#include <acpi/acpi_bus.h>
+
+struct rt2x00_button{
+ /*
+ * ACPI device for generation of ACPI events.
+ */
+ struct acpi_device acpi_dev;
+
+ /*
+ * Timer for register polling.
+ */
+ struct timer_list poll_timer;
+
+ /*
+ * Timer delay.
+ */
+ short poll_delay;
+
+ /*
+ * Current status of button.
+ */
+ short button_status:1;
+ short active_poll:1;
+ short __pad:14;
+} __attribute__ ((packed));
+#endif /* CONFIG_RT2X00_BUTTON */
+
+/*
* data_entry
* The data ring is a list of data entries.
* Each entry holds a reference to the descriptor
@@ -92,28 +123,7 @@ struct rt2x00_pci{
struct pci_dev *pci_dev;
#ifdef CONFIG_RT2X00_BUTTON
- /*
- * ACPI device for generation of ACPI events.
- */
- struct acpi_device acpi_dev;
-
- /*
- * Timer for register polling.
- */
- struct timer_list poll_timer;
-
- /*
- * Timer delay.
- */
- u16 poll_delay;
-
- /*
- * Current status of button.
- */
- u16 button_status;
-#define BUTTON_STATUS_UNAVAILABLE 2
-#define BUTTON_STATUS_ON 1
-#define BUTTON_STATUS_OFF 0
+ struct rt2x00_button button;
#endif /* CONFIG_RT2X00_BUTTON */
/*
@@ -257,4 +267,85 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
return NULL;
}
+/*
+ * HW button variables & functions.
+ * The delay between each poll is set by the module parameter.
+ */
+#ifdef CONFIG_RT2X00_BUTTON
+/*
+ * Module parameter.
+ */
+static short rt2x00_poll_delay = 0;
+
+static inline void
+rt2x00pci_button_status(struct rt2x00_pci *rt2x00pci, char status)
+{
+ struct rt2x00_button *button = &rt2x00pci->button;
+
+ if (!button->active_poll)
+ return;
+
+ if (status != button->button_status) {
+ button->button_status = status;
+ acpi_bus_generate_event(
+ &button->acpi_dev, ACPI_TYPE_EVENT, status);
+ }
+
+ button->poll_timer.expires = jiffies + button->poll_delay;
+
+ if (button->active_poll)
+ add_timer(&button->poll_timer);
+}
+
+static inline void
+rt2x00pci_button_start(struct rt2x00_pci *rt2x00pci,
+ void (*handler)(unsigned long data))
+{
+ struct rt2x00_button *button = &rt2x00pci->button;
+
+ /*
+ * Only enable polling when the user has
+ * set the poll delay module parameter,
+ * and the device contains a hardware button.
+ */
+ if(!GET_FLAG(rt2x00pci, HARDWARE_BUTTON) || !rt2x00_poll_delay)
+ return;
+
+ strcpy(acpi_device_class(&button->acpi_dev), DRV_NAME "_button");
+ strcpy(acpi_device_bid(&button->acpi_dev), DRV_NAME);
+ strcpy(acpi_device_name(&button->acpi_dev), DRV_NAME);
+
+ init_timer(&button->poll_timer);
+
+ button->poll_delay = rt2x00_poll_delay * (HZ / 10);
+ button->button_status = 0;
+ button->active_poll = 1;
+
+ button->poll_timer.function = handler;
+ button->poll_timer.data = (unsigned long)rt2x00pci;
+ button->poll_timer.expires = jiffies + button->poll_delay;
+
+ add_timer(&button->poll_timer);
+}
+
+static inline void
+rt2x00pci_button_stop(struct rt2x00_pci *rt2x00pci)
+{
+ /*
+ * Shutdown poll_timer for hardware button,
+ * make sure only to disable polling when
+ * it was enabled in the first place.
+ */
+ if(!rt2x00pci->button.active_poll)
+ return;
+
+ rt2x00pci->button.active_poll = 0;
+ del_timer_sync(&rt2x00pci->button.poll_timer);
+}
+#else /* CONFIG_RT2X00_BUTTON */
+static inline void rt2x00pci_button_start(struct rt2x00_pci *rt2x00pci,
+ int (*handler)(struct rt2x00_pci *rt2x00pci)){}
+static inline void rt2x00pci_button_stop(struct rt2x00_pci *rt2x00pci){}
+#endif /* CONFIG_RT2X00_BUTTON */
+
#endif /* RT2X00PCI_H */
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 28/32] rt2x00: Support TXRX led handling
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 11843 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Create more advanced led handling, enable txrx activity
by switching on and off the led at interrupt time.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:03:48.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:04:19.000000000 +0200
@@ -669,6 +669,57 @@ rt2400pci_link_tuner(struct rt2x00_pci *
}
/*
+ * LED functions.
+ */
+static void
+rt2400pci_enable_led(struct rt2x00_pci *rt2x00pci)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00pci, LEDCSR, ®);
+
+ rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 30);
+ rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 70);
+
+ if (rt2x00pci->led_mode == LED_MODE_TXRX_ACTIVITY) {
+ rt2x00_set_field32(®, LEDCSR_LINK, 1);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
+ } else if (rt2x00pci->led_mode == LED_MODE_ASUS) {
+ rt2x00_set_field32(®, LEDCSR_LINK, 0);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1);
+ } else {
+ rt2x00_set_field32(®, LEDCSR_LINK, 1);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1);
+ }
+
+ rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2400pci_disable_led(struct rt2x00_pci *rt2x00pci)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00pci, LEDCSR, ®);
+ rt2x00_set_field32(®, LEDCSR_LINK, 0);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
+ rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2400pci_activity_led(struct rt2x00_pci *rt2x00pci, char activity)
+{
+ u32 reg;
+
+ if (rt2x00pci->led_mode != LED_MODE_TXRX_ACTIVITY)
+ return;
+
+ rt2x00_register_read(rt2x00pci, LEDCSR, ®);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, activity);
+ rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+/*
* Device state switch.
* This will put the device to sleep, or awake it.
*/
@@ -882,6 +933,11 @@ rt2400pci_rxdone(void *data)
* Tune link for optimal performance.
*/
rt2400pci_link_tuner(rt2x00pci);
+
+ /*
+ * Update LED.
+ */
+ rt2400pci_activity_led(rt2x00pci, 0);
}
static void
@@ -987,10 +1043,13 @@ rt2400pci_interrupt(int irq, void *dev_i
/*
* 2 - Rx ring done interrupt.
+ * Enable the TXRX activity led.
*/
- if (rt2x00_get_field32(reg, CSR7_RXDONE))
+ if (rt2x00_get_field32(reg, CSR7_RXDONE)) {
queue_work(rt2x00pci->workqueue,
&rt2x00pci->ring[RING_RX].irq_work);
+ rt2400pci_activity_led(rt2x00pci, 1);
+ }
/*
* 3 - Atim ring transmit done interrupt.
@@ -1333,13 +1392,6 @@ rt2400pci_init_registers(struct rt2x00_p
rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 154);
rt2x00_register_write(rt2x00pci, RALINKCSR, reg);
- rt2x00_register_read(rt2x00pci, LEDCSR, ®);
- rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 30);
- rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 70);
- rt2x00_set_field32(®, LEDCSR_LINK, 0);
- rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
- rt2x00_register_write(rt2x00pci, LEDCSR, reg);
-
rt2x00_register_read(rt2x00pci, CSR1, ®);
rt2x00_set_field32(®, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(®, CSR1_BBP_RESET, 0);
@@ -1555,6 +1607,11 @@ rt2400pci_open(struct net_device *net_de
}
/*
+ * Enable LED
+ */
+ rt2400pci_enable_led(rt2x00pci);
+
+ /*
* Enable interrupts.
*/
rt2x00_register_read(rt2x00pci, CSR8, ®);
@@ -1597,11 +1654,9 @@ rt2400pci_stop(struct net_device *net_de
rt2x00_register_write(rt2x00pci, RXCSR0, reg);
/*
- * Switch off LED.
+ * Disable LED
*/
- rt2x00_register_read(rt2x00pci, LEDCSR, ®);
- rt2x00_set_field32(®, LEDCSR_LINK, 0);
- rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+ rt2400pci_disable_led(rt2x00pci);
/*
* Disable interrupts.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:03:48.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:04:19.000000000 +0200
@@ -722,6 +722,57 @@ dynamic_cca_tune:
}
/*
+ * LED functions.
+ */
+static void
+rt2500pci_enable_led(struct rt2x00_pci *rt2x00pci)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00pci, LEDCSR, ®);
+
+ rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 30);
+ rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 70);
+
+ if (rt2x00pci->led_mode == LED_MODE_TXRX_ACTIVITY) {
+ rt2x00_set_field32(®, LEDCSR_LINK, 1);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
+ } else if (rt2x00pci->led_mode == LED_MODE_ASUS) {
+ rt2x00_set_field32(®, LEDCSR_LINK, 0);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1);
+ } else {
+ rt2x00_set_field32(®, LEDCSR_LINK, 1);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1);
+ }
+
+ rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2500pci_disable_led(struct rt2x00_pci *rt2x00pci)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00pci, LEDCSR, ®);
+ rt2x00_set_field32(®, LEDCSR_LINK, 0);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
+ rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+static void
+rt2500pci_activity_led(struct rt2x00_pci *rt2x00pci, char activity)
+{
+ u32 reg;
+
+ if (rt2x00pci->led_mode != LED_MODE_TXRX_ACTIVITY)
+ return;
+
+ rt2x00_register_read(rt2x00pci, LEDCSR, ®);
+ rt2x00_set_field32(®, LEDCSR_ACTIVITY, activity);
+ rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+}
+
+/*
* Device state switch.
* This will put the device to sleep, or awake it.
*/
@@ -962,6 +1013,11 @@ rt2500pci_rxdone(void *data)
*/
if (total_rssi && rssi_count)
rt2500pci_link_tuner(rt2x00pci, total_rssi / rssi_count);
+
+ /*
+ * Update LED.
+ */
+ rt2500pci_activity_led(rt2x00pci, 0);
}
static void
@@ -1067,10 +1123,13 @@ rt2500pci_interrupt(int irq, void *dev_i
/*
* 2 - Rx ring done interrupt.
+ * Enable the TXRX activity led.
*/
- if (rt2x00_get_field32(reg, CSR7_RXDONE))
+ if (rt2x00_get_field32(reg, CSR7_RXDONE)) {
queue_work(rt2x00pci->workqueue,
&rt2x00pci->ring[RING_RX].irq_work);
+ rt2500pci_activity_led(rt2x00pci, 1);
+ }
/*
* 3 - Atim ring transmit done interrupt.
@@ -1435,13 +1494,6 @@ rt2500pci_init_registers(struct rt2x00_p
rt2x00_register_write(rt2x00pci, ARTCSR1, cpu_to_le32(0x1d21252d));
rt2x00_register_write(rt2x00pci, ARTCSR2, cpu_to_le32(0x1919191d));
- rt2x00_register_read(rt2x00pci, LEDCSR, ®);
- rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 30);
- rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 70);
- rt2x00_set_field32(®, LEDCSR_LINK, 0);
- rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
- rt2x00_register_write(rt2x00pci, LEDCSR, reg);
-
rt2x00_register_read(rt2x00pci, CSR1, ®);
rt2x00_set_field32(®, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(®, CSR1_BBP_RESET, 0);
@@ -1663,6 +1715,11 @@ rt2500pci_open(struct net_device *net_de
}
/*
+ * Enable LED
+ */
+ rt2500pci_enable_led(rt2x00pci);
+
+ /*
* Enable interrupts.
*/
rt2x00_register_read(rt2x00pci, CSR8, ®);
@@ -1705,11 +1762,9 @@ rt2500pci_stop(struct net_device *net_de
rt2x00_register_write(rt2x00pci, RXCSR0, reg);
/*
- * Switch off LED.
+ * Disable LED
*/
- rt2x00_register_read(rt2x00pci, LEDCSR, ®);
- rt2x00_set_field32(®, LEDCSR_LINK, 0);
- rt2x00_register_write(rt2x00pci, LEDCSR, reg);
+ rt2500pci_disable_led(rt2x00pci);
/*
* Disable interrupts.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:04:19.000000000 +0200
@@ -532,6 +532,59 @@ rt2500usb_link_tuner(struct rt2x00_usb *
}
/*
+ * LED functions.
+ */
+static void
+rt2500usb_enable_led(struct rt2x00_usb *rt2x00usb)
+{
+ u16 reg;
+
+ rt2x00_register_read(rt2x00usb, MAC_CSR21, ®);
+ rt2x00_set_field16_nb(®, MAC_CSR21_ON_PERIOD, 30);
+ rt2x00_set_field16_nb(®, MAC_CSR21_OFF_PERIOD, 70);
+ rt2x00_register_write(rt2x00usb, MAC_CSR21, reg);
+
+ rt2x00_register_read(rt2x00usb, MAC_CSR20, ®);
+
+ if (rt2x00usb->led_mode == LED_MODE_TXRX_ACTIVITY) {
+ rt2x00_set_field16_nb(®, MAC_CSR20_LINK, 1);
+ rt2x00_set_field16_nb(®, MAC_CSR20_ACTIVITY, 0);
+ } else if (rt2x00usb->led_mode == LED_MODE_ASUS) {
+ rt2x00_set_field16_nb(®, MAC_CSR20_LINK, 0);
+ rt2x00_set_field16_nb(®, MAC_CSR20_ACTIVITY, 1);
+ } else {
+ rt2x00_set_field16_nb(®, MAC_CSR20_LINK, 1);
+ rt2x00_set_field16_nb(®, MAC_CSR20_ACTIVITY, 1);
+ }
+
+ rt2x00_register_write(rt2x00usb, MAC_CSR20, reg);
+}
+
+static void
+rt2500usb_disable_led(struct rt2x00_usb *rt2x00usb)
+{
+ u16 reg;
+
+ rt2x00_register_read(rt2x00usb, MAC_CSR20, ®);
+ rt2x00_set_field16_nb(®, MAC_CSR20_LINK, 0);
+ rt2x00_set_field16_nb(®, MAC_CSR20_ACTIVITY, 0);
+ rt2x00_register_write(rt2x00usb, MAC_CSR20, reg);
+}
+
+static void
+rt2500usb_activity_led(struct rt2x00_usb *rt2x00usb, char activity)
+{
+ u16 reg;
+
+ if (rt2x00usb->led_mode != LED_MODE_TXRX_ACTIVITY)
+ return;
+
+ rt2x00_register_read(rt2x00usb, MAC_CSR20, ®);
+ rt2x00_set_field16_nb(®, MAC_CSR20_ACTIVITY, activity);
+ rt2x00_register_write(rt2x00usb, MAC_CSR20, reg);
+}
+
+/*
* Device state switch.
* This will put the device to sleep, or awake it.
*/
@@ -782,6 +835,11 @@ rt2500usb_rxdone(void *data)
*/
if (total_rssi && rssi_count)
rt2500usb_link_tuner(rt2x00usb, total_rssi / rssi_count);
+
+ /*
+ * Update LED.
+ */
+ rt2500usb_activity_led(rt2x00usb, 0);
}
static void
@@ -857,9 +915,14 @@ rt2500usb_interrupt(struct urb *urb, str
if (!GET_FLAG(rt2x00usb, RADIO_ENABLED))
return;
+ CLEAR_FLAG(entry, ENTRY_OWNER_NIC);
+
if (urb->status)
return;
+ if (GET_FLAG(entry, ENTRY_TYPE_RX))
+ rt2500usb_activity_led(rt2x00usb, 1);
+
queue_work(rt2x00usb->workqueue, &entry->ring->irq_work);
}
@@ -1104,7 +1167,6 @@ rt2500usb_init_registers(struct rt2x00_u
rt2x00_register_write(rt2x00usb, TXRX_CSR21, 0xe78f);
rt2x00_register_write(rt2x00usb, MAC_CSR9, 0xff1d);
rt2x00_register_write(rt2x00usb, MAC_CSR1, 0x0004);
- rt2x00_register_write(rt2x00usb, MAC_CSR20, 0x0000);
reg = 0;
rt2x00_register_read(rt2x00usb, MAC_CSR0, ®);
@@ -1321,6 +1383,11 @@ rt2500usb_open(struct net_device *net_de
rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 0);
rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+ /*
+ * Enable LED
+ */
+ rt2500usb_enable_led(rt2x00usb);
+
SET_FLAG(rt2x00usb, RADIO_ENABLED);
return 0;
@@ -1348,16 +1415,16 @@ rt2500usb_stop(struct net_device *net_de
rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 1);
rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+ /*
+ * Disable LED
+ */
+ rt2500usb_disable_led(rt2x00usb);
+
entry = (struct data_entry*)rt2x00usb->ring[RING_RX].entry;
for (counter = 0; counter < rt2x00usb->ring[RING_RX].stats.limit; counter++) {
usb_kill_urb(entry[counter].urb);
}
- /*
- * Switch off LED.
- */
- rt2x00_register_write(rt2x00usb, MAC_CSR20, 0);
-
rt2x00_vendor_request(rt2x00usb, USB_RX_CONTROL,
USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 29/32] rt2x00: dscape compatibilitiy
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 255 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Latest dscape patches have broken rt2x00,
fix compile issues, and support the new features.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Available on server:
http://mendiosus.nl/rt2x00/rt2x00-29-compat.diff
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 30/32] rt2x00: Correctly initialize TX power in registers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 14733 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
The rate does not need to be configured for each
TX packet. The actual rate for sending is determined
in the PLCP, the rate configuration is only capable
of setting the supported rates, which is dependent
of the physical mode we are in.
When we the configuration function is called,
disable the RX for proper behaviour.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:04:47.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:05:21.000000000 +0200
@@ -660,6 +660,22 @@ rt2400pci_config_rate(struct rt2x00_pci
}
static void
+rt2400pci_config_phymode(struct rt2x00_pci *rt2x00pci, const int phymode)
+{
+ struct ieee80211_rate *rate;
+
+ rate = &rt2x00pci->hw.modes[0].rates[
+ rt2x00pci->hw.modes[0].num_rates - 1];
+
+ rt2400pci_config_rate(rt2x00pci, rate->val2);
+
+ /*
+ * Update physical mode for rx ring.
+ */
+ rt2x00pci->rx_params.phymode = phymode;
+}
+
+static void
rt2400pci_config_mac_address(struct rt2x00_pci *rt2x00pci, void *addr)
{
u32 reg[2] = {0, 0};
@@ -815,11 +831,6 @@ rt2400pci_write_tx_desc(
u16 signal;
u16 service;
- /*
- * Update rate control register.
- */
- rt2400pci_config_rate(rt2x00pci, control->tx_rate);
-
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
@@ -1545,14 +1556,6 @@ rt2400pci_tx(struct net_device *net_dev,
rt2x00_ring_index_inc(ring);
- /*
- * We are going to cheat now, we update the register
- * with the CWmin and CWmax values for the current
- * queue. This is the alternative since we cannot
- * set the CWmin and CWmax per descriptor.
- */
- rt2400pci_config_cw(rt2x00pci, &ring->tx_params);
-
rt2x00_register_read(rt2x00pci, TXCSR0, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
@@ -1769,19 +1772,46 @@ rt2400pci_config_update(void *data)
struct rt2x00_pci *rt2x00pci = data;
struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ u32 reg;
+
+ /*
+ * Some configuration changes require the RX to be disabled.
+ */
+ if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ rt2x00_register_read(rt2x00pci, RXCSR0, ®);
+ rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
+ rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+ }
- rt2400pci_config_bssid(rt2x00pci, conf->client_bssid);
- rt2400pci_config_type(rt2x00pci, conf->mode);
rt2400pci_config_channel(rt2x00pci,
conf->channel_val, conf->channel, conf->freq);
rt2400pci_config_txpower(rt2x00pci, conf->power_level);
rt2400pci_config_antenna(rt2x00pci, conf->antenna_sel);
rt2400pci_config_duration(rt2x00pci, conf->short_slot_time);
+ rt2400pci_config_phymode(rt2x00pci, conf->phymode);
/*
- * Update active info for RX.
+ * Reenable RX only if the radio should be on.
*/
- rt2x00pci->rx_params.phymode = conf->phymode;
+ if (conf->radio_enabled) {
+ if (!GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ if (rt2400pci_open(net_dev)) {
+ ERROR("Failed to enabled radio.\n");
+ return;
+ }
+ } else {
+ rt2x00_register_read(rt2x00pci, RXCSR0, ®);
+ rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
+ rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+ }
+ } else {
+ if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ if (rt2400pci_stop(net_dev)) {
+ ERROR("Failed to disable radio.\n");
+ return;
+ }
+ }
+ }
}
static int
@@ -1863,8 +1893,8 @@ rt2400pci_scan(void *data)
* Switch channel and update active info for RX.
*/
if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
- rt2x00pci->rx_params.phymode =
- rt2x00pci->scan->conf.scan_phymode;
+ rt2400pci_config_phymode(rt2x00pci,
+ rt2x00pci->scan->conf.scan_phymode);
rt2400pci_config_channel(rt2x00pci,
rt2x00pci->scan->conf.scan_channel_val,
@@ -1874,8 +1904,8 @@ rt2400pci_scan(void *data)
rt2400pci_config_txpower(rt2x00pci,
rt2x00pci->scan->conf.scan_power_level);
} else {
- rt2x00pci->rx_params.phymode =
- rt2x00pci->scan->conf.running_phymode;
+ rt2400pci_config_phymode(rt2x00pci,
+ rt2x00pci->scan->conf.running_phymode);
rt2400pci_config_channel(rt2x00pci,
rt2x00pci->scan->conf.running_channel_val,
@@ -2000,10 +2030,6 @@ rt2400pci_conf_tx(struct net_device *net
memcpy(&ring->tx_params, params, sizeof(*params));
/*
- * TODO: We can't use different cw_min and cw_max variables
- * per queue, we need to find a good method for dealing with
- * this shortage. Also we need to find a method to possibly
- * support the other values passed in ieee80211_tx_queue_params.
* The passed variables are stored as real value ((2^n)-1).
* RT2400 registers require to know the bit number 'n'.
*/
@@ -2017,6 +2043,11 @@ rt2400pci_conf_tx(struct net_device *net
else
ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
+ /*
+ * Write configuration to register.
+ */
+ rt2400pci_config_cw(rt2x00pci, &ring->tx_params);
+
return 0;
}
@@ -2330,7 +2361,7 @@ rt2400pci_init_hw(struct rt2x00_pci *rt2
* RF2420 is capable of faster channel switches.
*/
if (rt2x00_rf(&rt2x00pci->chip, RF2420))
- hw->channel_change_time = 100;
+ hw->channel_change_time = 150;
else
hw->channel_change_time = 2500;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:04:47.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:05:21.000000000 +0200
@@ -703,6 +703,30 @@ rt2500pci_config_rate(struct rt2x00_pci
}
static void
+rt2500pci_config_phymode(struct rt2x00_pci *rt2x00pci, const int phymode)
+{
+ struct ieee80211_rate *rate;
+
+ if (phymode == MODE_IEEE80211A
+ && rt2x00_rf(&rt2x00pci->chip, RF5222))
+ rate = &rt2x00pci->hw.modes[2].rates[
+ rt2x00pci->hw.modes[2].num_rates - 1];
+ else if (phymode == MODE_IEEE80211B)
+ rate = &rt2x00pci->hw.modes[1].rates[
+ rt2x00pci->hw.modes[1].num_rates - 1];
+ else
+ rate = &rt2x00pci->hw.modes[0].rates[
+ rt2x00pci->hw.modes[0].num_rates - 1];
+
+ rt2500pci_config_rate(rt2x00pci, rate->val2);
+
+ /*
+ * Update physical mode for rx ring.
+ */
+ rt2x00pci->rx_params.phymode = phymode;
+}
+
+static void
rt2500pci_config_mac_address(struct rt2x00_pci *rt2x00pci, void *addr)
{
u32 reg[2] = {0, 0};
@@ -870,11 +894,6 @@ rt2500pci_write_tx_desc(
u16 service;
u8 rate;
- /*
- * Update rate control register.
- */
- rt2500pci_config_rate(rt2x00pci, control->tx_rate);
-
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
@@ -1879,19 +1898,46 @@ rt2500pci_config_update(void *data)
struct rt2x00_pci *rt2x00pci = data;
struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ u32 reg;
+
+ /*
+ * Some configuration changes require the RX to be disabled.
+ */
+ if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ rt2x00_register_read(rt2x00pci, RXCSR0, ®);
+ rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
+ rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+ }
- rt2500pci_config_bssid(rt2x00pci, conf->client_bssid);
- rt2500pci_config_type(rt2x00pci, conf->mode);
rt2500pci_config_channel(rt2x00pci,
conf->channel_val, conf->channel, conf->freq,
conf->power_level);
rt2500pci_config_antenna(rt2x00pci, conf->antenna_sel);
rt2500pci_config_duration(rt2x00pci, conf->short_slot_time);
+ rt2500pci_config_phymode(rt2x00pci, conf->phymode);
/*
- * Update active info for RX.
+ * Reenable RX only if the radio should be on.
*/
- rt2x00pci->rx_params.phymode = conf->phymode;
+ if (conf->radio_enabled) {
+ if (!GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ if (rt2500pci_open(net_dev)) {
+ ERROR("Failed to enabled radio.\n");
+ return;
+ }
+ } else {
+ rt2x00_register_read(rt2x00pci, RXCSR0, ®);
+ rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
+ rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+ }
+ } else {
+ if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ if (rt2500pci_stop(net_dev)) {
+ ERROR("Failed to disable radio.\n");
+ return;
+ }
+ }
+ }
}
static int
@@ -1973,17 +2019,17 @@ rt2500pci_scan(void *data)
* Switch channel and update active info for RX.
*/
if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
- rt2x00pci->rx_params.phymode =
- rt2x00pci->scan->conf.scan_phymode;
-
+ rt2500pci_config_phymode(rt2x00pci,
+ rt2x00pci->scan->conf.scan_phymode);
+
rt2500pci_config_channel(rt2x00pci,
rt2x00pci->scan->conf.scan_channel_val,
rt2x00pci->scan->conf.scan_channel,
rt2x00pci->scan->conf.scan_freq,
rt2x00pci->scan->conf.scan_power_level);
} else {
- rt2x00pci->rx_params.phymode =
- rt2x00pci->scan->conf.running_phymode;
+ rt2500pci_config_phymode(rt2x00pci,
+ rt2x00pci->scan->conf.running_phymode);
rt2500pci_config_channel(rt2x00pci,
rt2x00pci->scan->conf.running_channel_val,
@@ -2570,7 +2616,7 @@ rt2500pci_init_hw(struct rt2x00_pci *rt2
hw->device_strips_mic = 0;
hw->monitor_during_oper = 1;
hw->fraglist = 0;
- hw->channel_change_time = 2500;
+ hw->channel_change_time = 2000;
/*
* We have 2 TX queues: TX and PRIO.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:04:47.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:05:21.000000000 +0200
@@ -384,6 +384,12 @@ rt2500usb_config_channel(struct rt2x00_u
rt2x00_rf_write(rt2x00usb, rf3);
if (rf4)
rt2x00_rf_write(rt2x00usb, rf4);
+
+ /*
+ * Update active info for RX.
+ */
+ rt2x00usb->rx_params.freq = freq;
+ rt2x00usb->rx_params.channel = channel;
}
static void
@@ -509,9 +515,32 @@ rt2500usb_config_rate(struct rt2x00_usb
}
static void
-rt2500usb_config_mac_address(struct net_device *net_dev, void *addr)
+rt2500usb_config_phymode(struct rt2x00_usb *rt2x00usb, const int phymode)
+{
+ struct ieee80211_rate *rate;
+
+ if (phymode == MODE_IEEE80211A
+ && rt2x00_rf(&rt2x00usb->chip, RF5222))
+ rate = &rt2x00usb->hw.modes[2].rates[
+ rt2x00usb->hw.modes[2].num_rates - 1];
+ else if (phymode == MODE_IEEE80211B)
+ rate = &rt2x00usb->hw.modes[1].rates[
+ rt2x00usb->hw.modes[1].num_rates - 1];
+ else
+ rate = &rt2x00usb->hw.modes[0].rates[
+ rt2x00usb->hw.modes[0].num_rates - 1];
+
+ rt2500usb_config_rate(rt2x00usb, rate->val2);
+
+ /*
+ * Update physical mode for rx ring.
+ */
+ rt2x00usb->rx_params.phymode = phymode;
+}
+
+static void
+rt2500usb_config_mac_address(struct rt2x00_usb *rt2x00usb, void *addr)
{
- struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
u16 reg[3] = {0, 0, 0};
rt2x00_set_field16_nb(®[0], MAC_CSR2_BYTE0, ((u8*)addr)[0]);
@@ -698,11 +727,6 @@ rt2500usb_write_tx_desc(
u8 service;
u8 rate;
- /*
- * Update rate control register.
- */
- rt2500usb_config_rate(rt2x00usb, control->tx_rate);
-
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
ring = rt2x00usb_get_ring(rt2x00usb, control->queue);
@@ -1546,19 +1570,46 @@ rt2500usb_config_update(void *data)
struct net_device *net_dev =
usb_get_intfdata(rt2x00usb->usb_intf);
struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ u16 reg;
+
+ /*
+ * Some configuration changes require the RX to be disabled.
+ */
+ if (GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+ rt2x00_register_read(rt2x00usb, TXRX_CSR2, ®);
+ rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 1);
+ rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+ }
- rt2500usb_config_bssid(rt2x00usb, conf->client_bssid);
- rt2500usb_config_type(rt2x00usb, conf->mode);
rt2500usb_config_channel(rt2x00usb,
conf->channel_val, conf->channel, conf->freq,
conf->power_level);
rt2500usb_config_antenna(rt2x00usb, conf->antenna_sel);
rt2500usb_config_duration(rt2x00usb, conf->short_slot_time);
+ rt2500usb_config_phymode(rt2x00usb, conf->phymode);
/*
- * Update active info for RX.
+ * Reenable RX only if the radio should be on.
*/
- rt2x00usb->rx_params.phymode = conf->phymode;
+ if (conf->radio_enabled) {
+ if (!GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+ if (rt2500usb_open(net_dev)) {
+ ERROR("Failed to enabled radio.\n");
+ return;
+ }
+ } else {
+ rt2x00_register_read(rt2x00usb, TXRX_CSR2, ®);
+ rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 0);
+ rt2x00_register_write(rt2x00usb, TXRX_CSR2, reg);
+ }
+ } else {
+ if (GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+ if (rt2500usb_stop(net_dev)) {
+ ERROR("Failed to disable radio.\n");
+ return;
+ }
+ }
+ }
}
static int
@@ -1640,8 +1691,8 @@ rt2500usb_scan(void *data)
* Switch channel and update active info for RX.
*/
if (rt2x00usb->scan->state == IEEE80211_SCAN_START) {
- rt2x00usb->rx_params.phymode =
- rt2x00usb->scan->conf.scan_phymode;
+ rt2500usb_config_phymode(rt2x00usb,
+ rt2x00usb->scan->conf.scan_phymode);
rt2500usb_config_channel(rt2x00usb,
rt2x00usb->scan->conf.scan_channel_val,
@@ -1649,8 +1700,8 @@ rt2500usb_scan(void *data)
rt2x00usb->scan->conf.scan_freq,
rt2x00usb->scan->conf.scan_power_level);
} else {
- rt2x00usb->rx_params.phymode =
- rt2x00usb->scan->conf.running_phymode;
+ rt2500usb_config_phymode(rt2x00usb,
+ rt2x00usb->scan->conf.running_phymode);
rt2500usb_config_channel(rt2x00usb,
rt2x00usb->scan->conf.running_channel_val,
@@ -2186,7 +2237,7 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
hw->device_strips_mic = 0;
hw->monitor_during_oper = 1;
hw->fraglist = 0;
- hw->channel_change_time = 500;
+ hw->channel_change_time = 500000;
/*
* We have 2 TX queues: TX and PRIO.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 31/32] rt2x00: Correctly initialization and uninitialization of device
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 12718 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Fix several hardware initialization and uninitalization
problems by incorrectly flushing workqueues.
Fix the memory leak when freeing the ieee80211_hw structure.
Allow device to connect to 802.11g networks by default
instead of 802.11b.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:05:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:05:52.000000000 +0200
@@ -1719,6 +1719,11 @@ rt2400pci_stop(struct net_device *net_de
}
/*
+ * Flush out all pending work.
+ */
+ flush_workqueue(rt2x00pci->workqueue);
+
+ /*
* Free DMA rings.
*/
rt2400pci_free_rings(rt2x00pci);
@@ -2441,7 +2446,7 @@ rt2400pci_initialize(struct pci_dev *pci
rt2x00pci->workqueue = create_singlethread_workqueue(DRV_NAME);
if (!rt2x00pci->workqueue)
- goto exit_iounmap;
+ goto exit;
/*
* Initialize cofniguration work.
@@ -2457,21 +2462,25 @@ rt2400pci_initialize(struct pci_dev *pci
if (rt2400pci_init_eeprom(rt2x00pci)
|| rt2400pci_init_mac(rt2x00pci)
|| rt2400pci_init_hw(rt2x00pci))
- goto exit_destroy_workqueue;
+ goto exit;
/*
* If required start hardware button polling.
*/
rt2x00pci_button_start(rt2x00pci, rt2400pci_button_poll);
- return 0;
+ /*
+ * Register hardware.
+ */
+ if (ieee80211_register_hw(net_dev, &rt2x00pci->hw)) {
+ ERROR("Failed to register device.\n");
+ goto exit;
+ }
-exit_destroy_workqueue:
- destroy_workqueue(rt2x00pci->workqueue);
+ return 0;
-exit_iounmap:
- iounmap(rt2x00pci->csr_addr);
- rt2x00pci->csr_addr = NULL;
+exit:
+ rt2400pci_uninitialize(net_dev);
return -ENODEV;
}
@@ -2482,26 +2491,39 @@ rt2400pci_uninitialize(struct net_device
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
+ * Unregister hardware.
+ */
+ ieee80211_unregister_hw(net_dev);
+
+ /*
* Shutdown poll_timer for hardware button.
*/
rt2x00pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
+ /*
+ * Release CSR memory.
+ */
if (likely(rt2x00pci->csr_addr)) {
iounmap(rt2x00pci->csr_addr);
rt2x00pci->csr_addr = NULL;
}
+ /*
+ * Free workqueue.
+ */
if (likely(rt2x00pci->workqueue)) {
- flush_workqueue(rt2x00pci->workqueue);
destroy_workqueue(rt2x00pci->workqueue);
rt2x00pci->workqueue = NULL;
}
+ /*
+ * Free ieee80211_hw memory.
+ */
if (likely(rt2x00pci->hw.modes)) {
- kfree(rt2x00pci->hw.modes->channels);
- kfree(rt2x00pci->hw.modes->rates);
+ kfree(rt2x00pci->hw.modes->channels);
+ kfree(rt2x00pci->hw.modes->rates);
kfree(rt2x00pci->hw.modes);
rt2x00pci->hw.modes = NULL;
}
@@ -2514,7 +2536,6 @@ static int
rt2400pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
struct net_device *net_dev;
- struct rt2x00_pci *rt2x00pci;
int status;
if (unlikely(id->driver_data != RT2460)) {
@@ -2559,19 +2580,9 @@ rt2400pci_probe(struct pci_dev *pci_dev,
ERROR("Failed to initialize device.\n");
goto exit_free_device;
}
- rt2x00pci = ieee80211_dev_hw_data(net_dev);
-
- status = ieee80211_register_hw(net_dev, &rt2x00pci->hw);
- if (status) {
- ERROR("Failed to register device.\n");
- goto exit_uninitialize_device;
- }
return 0;
-exit_uninitialize_device:
- rt2400pci_uninitialize(net_dev);
-
exit_free_device:
ieee80211_free_hw(net_dev);
@@ -2592,7 +2603,7 @@ rt2400pci_remove(struct pci_dev *pci_dev
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
- ieee80211_unregister_hw(net_dev);
+ net_dev->stop(net_dev);
rt2400pci_uninitialize(net_dev);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:05:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:05:52.000000000 +0200
@@ -1845,6 +1845,11 @@ rt2500pci_stop(struct net_device *net_de
}
/*
+ * Flush out all pending work.
+ */
+ flush_workqueue(rt2x00pci->workqueue);
+
+ /*
* Free DMA rings.
*/
rt2500pci_free_rings(rt2x00pci);
@@ -2675,22 +2680,22 @@ rt2500pci_init_hw(struct rt2x00_pci *rt2
}
/*
- * Intitialize 802.11b
- * Rates: CCK.
+ * Intitialize 802.11g
+ * Rates: CCK, OFDM.
* Channels: OFDM.
*/
- hw->modes[0].mode = MODE_IEEE80211B;
+ hw->modes[0].mode = MODE_IEEE80211G;
hw->modes[0].num_channels = 14;
- hw->modes[0].num_rates = 4;
+ hw->modes[0].num_rates = 12;
/*
- * Intitialize 802.11g
- * Rates: CCK, OFDM.
+ * Intitialize 802.11b
+ * Rates: CCK.
* Channels: OFDM.
*/
- hw->modes[1].mode = MODE_IEEE80211G;
+ hw->modes[1].mode = MODE_IEEE80211B;
hw->modes[1].num_channels = 14;
- hw->modes[1].num_rates = 12;
+ hw->modes[1].num_rates = 4;
hw->modes[1].channels = hw->modes[0].channels;
hw->modes[1].rates = hw->modes[0].rates;
@@ -2747,7 +2752,7 @@ rt2500pci_initialize(struct pci_dev *pci
rt2x00pci->workqueue = create_singlethread_workqueue(DRV_NAME);
if (!rt2x00pci->workqueue)
- goto exit_iounmap;
+ goto exit;
/*
* Initialize cofniguration work.
@@ -2763,21 +2768,25 @@ rt2500pci_initialize(struct pci_dev *pci
if (rt2500pci_init_eeprom(rt2x00pci)
|| rt2500pci_init_mac(rt2x00pci)
|| rt2500pci_init_hw(rt2x00pci))
- goto exit_destroy_workqueue;
+ goto exit;
/*
* If required start hardware button polling.
*/
rt2x00pci_button_start(rt2x00pci, rt2500pci_button_poll);
- return 0;
+ /*
+ * Register hardware.
+ */
+ if (ieee80211_register_hw(net_dev, &rt2x00pci->hw)) {
+ ERROR("Failed to register device.\n");
+ goto exit;
+ }
-exit_destroy_workqueue:
- destroy_workqueue(rt2x00pci->workqueue);
+ return 0;
-exit_iounmap:
- iounmap(rt2x00pci->csr_addr);
- rt2x00pci->csr_addr = NULL;
+exit:
+ rt2500pci_uninitialize(net_dev);
return -ENODEV;
}
@@ -2788,25 +2797,42 @@ rt2500pci_uninitialize(struct net_device
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
+ * Unregister hardware.
+ */
+ ieee80211_unregister_hw(net_dev);
+
+ /*
* Shutdown poll_timer for hardware button.
*/
rt2x00pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
+ /*
+ * Release CSR memory.
+ */
if (likely(rt2x00pci->csr_addr)) {
iounmap(rt2x00pci->csr_addr);
rt2x00pci->csr_addr = NULL;
}
+ /*
+ * Free workqueue.
+ */
if (likely(rt2x00pci->workqueue)) {
- flush_workqueue(rt2x00pci->workqueue);
destroy_workqueue(rt2x00pci->workqueue);
rt2x00pci->workqueue = NULL;
}
- kfree(rt2x00pci->hw.modes);
- rt2x00pci->hw.modes = NULL;
+ /*
+ * Free ieee80211_hw memory.
+ */
+ if (likely(rt2x00pci->hw.modes)) {
+ kfree(rt2x00pci->hw.modes->channels);
+ kfree(rt2x00pci->hw.modes->rates);
+ kfree(rt2x00pci->hw.modes);
+ rt2x00pci->hw.modes = NULL;
+ }
}
/*
@@ -2816,7 +2842,6 @@ static int
rt2500pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
struct net_device *net_dev;
- struct rt2x00_pci *rt2x00pci;
int status;
if (unlikely(id->driver_data != RT2560)) {
@@ -2861,19 +2886,9 @@ rt2500pci_probe(struct pci_dev *pci_dev,
ERROR("Failed to initialize device.\n");
goto exit_free_device;
}
- rt2x00pci = ieee80211_dev_hw_data(net_dev);
-
- status = ieee80211_register_hw(net_dev, &rt2x00pci->hw);
- if (status) {
- ERROR("Failed to register device.\n");
- goto exit_uninitialize_device;
- }
return 0;
-exit_uninitialize_device:
- rt2500pci_uninitialize(net_dev);
-
exit_free_device:
ieee80211_free_hw(net_dev);
@@ -2894,7 +2909,7 @@ rt2500pci_remove(struct pci_dev *pci_dev
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
- ieee80211_unregister_hw(net_dev);
+ net_dev->stop(net_dev);
rt2500pci_uninitialize(net_dev);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:05:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:05:52.000000000 +0200
@@ -1480,8 +1480,6 @@ static int
rt2500usb_stop(struct net_device *net_dev)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
- struct data_entry *entry;
- int counter;
u16 reg;
CLEAR_FLAG(rt2x00usb, RADIO_ENABLED);
@@ -1498,11 +1496,6 @@ rt2500usb_stop(struct net_device *net_de
*/
rt2500usb_disable_led(rt2x00usb);
- entry = (struct data_entry*)rt2x00usb->ring[RING_RX].entry;
- for (counter = 0; counter < rt2x00usb->ring[RING_RX].stats.limit; counter++) {
- usb_kill_urb(entry[counter].urb);
- }
-
rt2x00_vendor_request(rt2x00usb, USB_RX_CONTROL,
USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0);
@@ -1518,6 +1511,11 @@ rt2500usb_stop(struct net_device *net_de
}
/*
+ * Flush out all pending work.
+ */
+ flush_workqueue(rt2x00usb->workqueue);
+
+ /*
* Free DMA rings.
*/
rt2500usb_free_rings(rt2x00usb);
@@ -2296,22 +2294,23 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
}
/*
- * Intitialize 802.11b
- * Rates: CCK.
+ * Intitialize 802.11g
+ * Rates: CCK, OFDM.
* Channels: OFDM.
*/
- hw->modes[0].mode = MODE_IEEE80211B;
+ hw->modes[0].mode = MODE_IEEE80211G;
hw->modes[0].num_channels = 14;
- hw->modes[0].num_rates = 4;
+ hw->modes[0].num_rates = 12;
+
/*
- * Intitialize 802.11g
- * Rates: CCK, OFDM.
+ * Intitialize 802.11b
+ * Rates: CCK.
* Channels: OFDM.
*/
- hw->modes[1].mode = MODE_IEEE80211G;
+ hw->modes[1].mode = MODE_IEEE80211B;
hw->modes[1].num_channels = 14;
- hw->modes[1].num_rates = 12;
+ hw->modes[1].num_rates = 4;
hw->modes[1].channels = hw->modes[0].channels;
hw->modes[1].rates = hw->modes[0].rates;
@@ -2376,12 +2375,23 @@ rt2500usb_initialize(struct usb_interfac
if (rt2500usb_init_eeprom(rt2x00usb)
|| rt2500usb_init_mac(rt2x00usb)
- || rt2500usb_init_hw(rt2x00usb)) {
- destroy_workqueue(rt2x00usb->workqueue);
- return -ENODEV;
+ || rt2500usb_init_hw(rt2x00usb))
+ goto exit;
+
+ /*
+ * Register hardware.
+ */
+ if (ieee80211_register_hw(net_dev, &rt2x00usb->hw)) {
+ ERROR("Failed to register device.\n");
+ goto exit;
}
return 0;
+
+exit:
+ rt2500usb_uninitialize(net_dev);
+
+ return -ENODEV;
}
static void
@@ -2389,16 +2399,30 @@ rt2500usb_uninitialize(struct net_device
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ /*
+ * Unregister hardware.
+ */
+ ieee80211_unregister_hw(net_dev);
+
kfree(rt2x00usb->eeprom);
+ /*
+ * Free workqueue.
+ */
if (likely(rt2x00usb->workqueue)) {
- flush_workqueue(rt2x00usb->workqueue);
destroy_workqueue(rt2x00usb->workqueue);
rt2x00usb->workqueue = NULL;
}
- kfree(rt2x00usb->hw.modes);
- rt2x00usb->hw.modes = NULL;
+ /*
+ * Free ieee80211_hw memory.
+ */
+ if (likely(rt2x00usb->hw.modes)) {
+ kfree(rt2x00usb->hw.modes->channels);
+ kfree(rt2x00usb->hw.modes->rates);
+ kfree(rt2x00usb->hw.modes);
+ rt2x00usb->hw.modes = NULL;
+ }
}
/*
@@ -2409,7 +2433,6 @@ rt2500usb_probe(struct usb_interface *us
{
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct net_device *net_dev;
- struct rt2x00_usb *rt2x00usb;
int status;
if (unlikely(id->driver_info != RT2570)) {
@@ -2433,19 +2456,9 @@ rt2500usb_probe(struct usb_interface *us
ERROR("Failed to initialize device.\n");
goto exit_free_device;
}
- rt2x00usb = ieee80211_dev_hw_data(net_dev);
-
- status = ieee80211_register_hw(net_dev, &rt2x00usb->hw);
- if (status) {
- ERROR("Failed to register device.\n");
- goto exit_uninitialize_device;
- }
return 0;
-exit_uninitialize_device:
- rt2500usb_uninitialize(net_dev);
-
exit_free_device:
ieee80211_free_hw(net_dev);
@@ -2460,7 +2473,7 @@ rt2500usb_disconnect(struct usb_interfac
{
struct net_device *net_dev = usb_get_intfdata(usb_intf);
- ieee80211_unregister_hw(net_dev);
+ net_dev->stop(net_dev);
rt2500usb_uninitialize(net_dev);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 32/32] rt2x00: misc fixes
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 6511 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Misc. small fixes. Add small comments,
remove unwanted whitespaces etc.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:05:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 22:06:22.000000000 +0200
@@ -1003,7 +1003,7 @@ rt2400pci_txdone(void *data)
int tx_status;
int ack;
- while (!rt2x00_ring_empty(ring)) {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -1212,7 +1212,7 @@ rt2400pci_free_ring(struct rt2x00_pci *r
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
- kfree(ring->entry);
+ kfree(ring->entry);
ring->entry = NULL;
}
@@ -1318,6 +1318,9 @@ rt2400pci_init_rings(struct rt2x00_pci *
{
u32 reg;
+ /*
+ * Initialize rings.
+ */
rt2400pci_init_rxdesc(rt2x00pci, &rt2x00pci->ring[RING_RX]);
rt2400pci_init_txdesc(rt2x00pci, &rt2x00pci->ring[RING_TX]);
rt2400pci_init_txdesc(rt2x00pci, &rt2x00pci->ring[RING_ATIM]);
@@ -1847,7 +1850,7 @@ rt2400pci_config_interface(struct net_de
rt2400pci_config_bssid(rt2x00pci, conf->bssid);
return 0;
- }
+}
static void
rt2400pci_set_multicast_list(struct net_device *net_dev,
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:05:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 22:06:22.000000000 +0200
@@ -487,7 +487,7 @@ rt2500pci_config_channel(struct rt2x00_p
if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
if (channel < 14) {
- rf1 = cpu_to_le32(0x00022020);
+ rf1 = cpu_to_le32(0x00022020);
rf4 = cpu_to_le32(0x00000a0b);
} else if (channel == 14) {
rf1 = cpu_to_le32(0x00022010);
@@ -501,7 +501,7 @@ rt2500pci_config_channel(struct rt2x00_p
} else if (channel < 161) {
rf1 = cpu_to_le32(0x00022020);
rf4 = cpu_to_le32(0x00000a07);
- }
+ }
}
INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, "
@@ -1091,7 +1091,7 @@ rt2500pci_txdone(void *data)
int tx_status;
int ack;
- while (!rt2x00_ring_empty(ring)) {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -1301,7 +1301,7 @@ rt2500pci_free_ring(struct rt2x00_pci *r
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
- kfree(ring->entry);
+ kfree(ring->entry);
ring->entry = NULL;
}
@@ -2438,7 +2438,7 @@ rt2500pci_init_hw_channels(struct rt2x00
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
channels[counter].val =
cpu_to_le32(vals[counter] | rf2_base);
- }
+ }
if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
static u32 vals[] = {
0x00018896, 0x0001889a, 0x0001889e, 0x000188a2,
@@ -2453,7 +2453,7 @@ rt2500pci_init_hw_channels(struct rt2x00
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
(chan++)->val = cpu_to_le32(vals[counter]);
- }
+ }
/*
* Set TX power, each EEPROM TXpower entry
@@ -2472,7 +2472,7 @@ rt2500pci_init_hw_channels(struct rt2x00
rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2);
if (channels[(counter * 2) + 1].power_level > 0x20)
channels[(counter * 2) + 1].power_level = 0x18;
- }
+ }
/*
* Set device specific, but channel independent RF values.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:05:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 22:08:38.000000000 +0200
@@ -335,7 +335,7 @@ rt2500usb_config_channel(struct rt2x00_u
|| rt2x00_rf(&rt2x00usb->chip, RF2524)
|| rt2x00_rf(&rt2x00usb->chip, RF2525))
&& channel == 14)
- rf4 &= ~0x00000018;
+ rf4 &= ~0x00000018;
if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
if (channel & 0x01)
@@ -951,7 +951,7 @@ rt2500usb_txdone(void *data)
* Check if we have received an
* ACK response when ACK was requested and status
* was succesfull.
- */
+ */
entry->tx_status.ack = 0;
if (ack && (entry->urb->status == TX_SUCCESS))
entry->tx_status.ack = 1;
@@ -1636,7 +1636,7 @@ rt2500usb_config_interface(struct net_de
return 0;
rt2500usb_config_bssid(rt2x00usb, conf->bssid);
-
+
return 0;
}
@@ -2071,12 +2071,12 @@ rt2500usb_init_hw_channels(struct rt2x00
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
channels[counter].val = vals[counter];
- }
+ }
/*
* Set TX power, each EEPROM TXpower entry
* contains the TXpower value for 2 channels.
- */
+ */
for (counter = 0; counter < EEPROM_TXPOWER_SIZE; counter++) {
rt2x00_eeprom_read(rt2x00usb,
EEPROM_TXPOWER_START + counter, &eeprom);
@@ -2090,7 +2090,7 @@ rt2500usb_init_hw_channels(struct rt2x00
rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2);
if (channels[(counter * 2) + 1].power_level > 0x20)
channels[(counter * 2) + 1].power_level = 0x18;
- }
+ }
/*
* Set device specific, but channel independent RF values.
@@ -2302,7 +2302,6 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
hw->modes[0].num_channels = 14;
hw->modes[0].num_rates = 12;
-
/*
* Intitialize 802.11b
* Rates: CCK.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:57:18.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 22:07:42.000000000 +0200
@@ -44,6 +44,9 @@
* and should be switched on using the module parameter.
*/
#ifdef CONFIG_RT2X00_DEBUG
+/*
+ * Module parameter.
+ */
static int rt2x00_debug_level = 0;
#define DEBUG_PRINTK(__message...) \
do { if (rt2x00_debug_level) printk(__message); } while (0)
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 3/32] rt2x00: use pci_*_consistent for DMA mapping
From: Christoph Hellwig @ 2006-04-27 22:11 UTC (permalink / raw)
To: Ivo van Doorn; +Cc: netdev, rt2x00-devel
In-Reply-To: <200604280002.52839.IvDoorn@gmail.com>
On Fri, Apr 28, 2006 at 12:02:52AM +0200, Ivo van Doorn wrote:
> From: Ivo van Doorn <IvDoorn@gmail.com>
>
> Instead of dma_*_coherent
> use pci_*consistent functions.
No point in doing that, quite reverse as you use the gfp_mask argument
which is a (small) pessimation here.
^ permalink raw reply
* Re: [PATCH 20/32] rt2x00: byte ordering correctness
From: Christoph Hellwig @ 2006-04-27 22:13 UTC (permalink / raw)
To: Ivo van Doorn; +Cc: netdev, rt2x00-devel
In-Reply-To: <200604280003.12743.IvDoorn@gmail.com>
On Fri, Apr 28, 2006 at 12:03:12AM +0200, Ivo van Doorn wrote:
> From: Ivo van Doorn <IvDoorn@gmail.com>
>
> Fix various little/big endian conversions.
> rt2500pci should use cpu_to_le32 and rt2500usb should not.
While you're at it can you add __be* annotations to the hardware
datastructures so the endianess handling can be verified using sparse?
^ permalink raw reply
* Re: IP1000 gigabit nic driver
From: David Vrabel @ 2006-04-27 22:26 UTC (permalink / raw)
To: Francois Romieu; +Cc: Linux-kernel, netdev, david
In-Reply-To: <20060427185627.GA30871@electric-eye.fr.zoreil.com>
Francois Romieu wrote:
> David Gómez <david@pleyades.net> :
> [...]
>> Does anybody in this list know why the IP1000 driver is not
>> included in the kernel ?
>
> Afaik the driver has never been submitted for inclusion.
> At least not on netdev@vger.kernel.org (hint, hint).
>
> [...]
>> The card in question is:
>>
>> Sundance Technology Inc IC Plus IP1000
>>
>> and the driver can be found in sundance web, sources
>
> URL please ?
>
>> included. I tried to contact the author but my email
>> bounced.
>>
>> There's no LICENSE in the source, just copyrigth
>> sentences in the .c files, so i'm not sure under
>> which license it's distributed :-?.
>
> /me goes to http://www.icplus.com.tw/driver-pp-IP1000A.html
>
> $ unzip -c IP1000A-Linux-driver-v2.09f.zip | grep MODULE_LICENSE
> MODULE_LICENSE("GPL");
>
> It's a bit bloaty but it does not seem too bad (not mergeable "as
> is" though). Do you volunteer to test random cra^W^W carefully
> engineered code on your computer to help the rework/merging process ?
I finally got around to putting a 2nd NIC in my box that has one of this
chips and was going to start fixing the driver up and preparing it for
submission this weekend. Or I might try rewriting from scratch based on
the datasheet depending on how horrific the code looks on closer inspection.
Not got a whole lot of time to do this so no timescale for completion...
David Vrabel
^ permalink raw reply
* Re: [PATCH 0/10] [IOAT] I/OAT patches repost
From: Chris Leech @ 2006-04-27 23:45 UTC (permalink / raw)
To: David S. Miller; +Cc: olof, andrew.grover, netdev
In-Reply-To: <20060420.204200.103377406.davem@davemloft.net>
On 4/20/06, David S. Miller <davem@davemloft.net> wrote:
> Yes, and it means that the memory bandwidth costs are equivalent
> between I/O AT and cpu copy.
The following is a response from the I/OAT architects. I only point
out that this is not coming directly from me because I have not seen
the data to verify the claims regarding the speed of a copy vs a load
and the cost of the rep mov instruction. I'll encourage more direct
participation in this discussion from the architects moving forward.
- Chris
Let's talk about the caching benefits that is seemingly lost when
using the DMA engine. The intent of the DMA engine is to save CPU
cycles spent in copying data (rep mov). In cases where the destination
is already warm in cache (due to destination buffer re-use) and the
source is in memory, the cycles spent in a host copy is not just due
to the cache misses it encounters in the process of bringing in the
source but also due to the execution of rep move itself within the
host core. If you contrast this to simply touching (loading) the data
residing in memory, the cost of this load is primarily the cost of the
cache misses and not so much CPU execution time. Given this, some of
the following points are noteworthy:
1. While the DMA engine forces the destination to be in memory and
touching it may cause the same number of observable cache misses as a
host copy assuming a cache warmed destination, the cost of the host
copy (in terms of CPU cycles) is much more than the cost of the touch.
2. CPU hardware prefetchers do a pretty good job of staying ahead of
the fetch stream to minimize cache misses. So for loads of medium to
large buffers, cache misses form a much smaller component of the data
fetch time…most of it is dominated by front side bus (FSB) or Memory
bandwidth. For small buffers, we do not use the DMA engine but if we
had to, we would insert SW prefetches that do reasonably well.
3. If the destination wasn't already warm in cache i.e., it was in
memory or some CPU other cache, host copy will have to snoop and bring
the destination in and will encounter additional misses on the
destination buffer as well. These misses are the same as those
encountered in #1 above when using the DMA engine and touching the
data afterwards. So in effect it becomes a wash when compared to the
DMA engine's behavior. The case where the destination is already warm
in cache is common in benchmarks such as iperf, ttcp etc. where the
same buffer is reused over and over again. Real applications typically
will not exhibit this aggressive buffer re-use behavior.
4. It may take a large number of packets (and several interrupts) to
satisfy a large posted buffer (say 64KB). Even if you use host copy to
warm the cache with the destination, there is no guarantee that some
or all of the destination will stay in the cache before the
application has a chance to read the data.
5. The source data payload (skb ->data) is typically needed only once
for the copy and has no use later. The host copy brings it into the
cache and may end up polluting the cache, and consuming FSB bandwidth
whereas the DMA engine avoids this altogether.
The IxChariot data posted earlier that touches the data and yet shows
I/OAT benefit is due to some of the reasons above. Bottom line is that
I agree with the cache benefit argument of host copy for small buffers
(64B to 512B) but for larger buffers and certain application scenarios
(destination in memory), the DMA engine will show better performance
regardless of where the destination buffer resided to begin with and
where it is accessed from.
^ permalink raw reply
* Re: [PATCH 0/10] [IOAT] I/OAT patches repost
From: Chris Leech @ 2006-04-27 23:49 UTC (permalink / raw)
To: Rick Jones; +Cc: David S. Miller, olof, andrew.grover, netdev
In-Reply-To: <4449127A.8050404@hp.com>
> Netperf2 TOT now accesses the buffer that was just recv()'d rather than
> the one that is about to be recv()'d.
We've posted netperf2 results with I/OAT enabled/disabled and the data
access option on/off at
http://kernel.org/pub/linux/kernel/people/grover/ioat/netperf-icb-1.5-postscaling-both.pdf
This link has also been added to the I/OAT page on the LinuxNet wiki.
- Chris
^ permalink raw reply
* Re: [PATCH 0/10] [IOAT] I/OAT patches repost
From: Rick Jones @ 2006-04-27 23:53 UTC (permalink / raw)
To: chris.leech; +Cc: David S. Miller, olof, andrew.grover, netdev
In-Reply-To: <41b516cb0604271649o31315086ma1c82b824da263e7@mail.gmail.com>
Chris Leech wrote:
>>Netperf2 TOT now accesses the buffer that was just recv()'d rather than
>>the one that is about to be recv()'d.
>
>
> We've posted netperf2 results with I/OAT enabled/disabled and the data
> access option on/off at
> http://kernel.org/pub/linux/kernel/people/grover/ioat/netperf-icb-1.5-postscaling-both.pdf
>
calling it netperf data verification is a quite overstated - all netperf
does is read from or write to the buffer. there is no check of data
integrity or anything
rick jones
^ permalink raw reply
* E1000 stopped transmitting in rc3.
From: Dave Jones @ 2006-04-28 0:13 UTC (permalink / raw)
To: netdev
With 2.6.17-rc3, my E1000 won't get a dhcp lease.
Looking at tcpdump and ifconfig output, it's easy to see why.
It's recieving packets, but the packets transmitted field
of ifconfig never increases.
The last version I have built that worked ok was 2.6.17rc2-git3
NIC is ..
03:0e.0 Ethernet controller: Intel Corporation 82545GM Gigabit Ethernet Controller (rev 04)
(8086:1026)
Dave
--
http://www.codemonkey.org.uk
^ permalink raw reply
* [patch 20/24] NET: e1000: Update truesize with the length of the packet for packet split
From: Greg KH @ 2006-04-28 0:22 UTC (permalink / raw)
To: linux-kernel, stable, jgarzik
Cc: Justin Forbes, Zwane Mwaikambo, Theodore Ts'o, Randy Dunlap,
Dave Jones, Chuck Wolber, torvalds, akpm, alan, netdev,
jesse.brandeburg, john.ronciak, Jeffrey.t.kirsher, auke, davem,
Auke Kok, Greg Kroah-Hartman
In-Reply-To: <20060428001557.GA18750@kroah.com>
[-- Attachment #1: net-e1000-update-truesize-with-the-length-of-the-packet-for-packet-split.patch --]
[-- Type: text/plain, Size: 764 bytes --]
-stable review patch. If anyone has any objections, please let us know.
------------------
Update skb with the real packet size.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/net/e1000/e1000_main.c | 1 +
1 file changed, 1 insertion(+)
--- linux-2.6.16.11.orig/drivers/net/e1000/e1000_main.c
+++ linux-2.6.16.11/drivers/net/e1000/e1000_main.c
@@ -3851,6 +3851,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapt
skb_shinfo(skb)->nr_frags++;
skb->len += length;
skb->data_len += length;
+ skb->truesize += length;
}
e1000_rx_checksum(adapter, staterr,
--
^ permalink raw reply
* Re: [LARTC] how to change classful netem loss probability?
From: George P Nychis @ 2006-04-28 1:18 UTC (permalink / raw)
To: George Nychis; +Cc: lartc, netdev
In-Reply-To: <444FF846.7050600@cmu.edu>
And if its not possible to change the probability, is there another method I can use instead?
> Hi,
>
> I am using netem to add loss and then adding another qdisc within netem
> according to the wiki. Then i want to change the netem drop probability
> without having to delete the qdisc and recreate it. I try it but I get
> invalid argument:
>
> thorium-ini hedpe # tc qdisc add dev ath0 root handle 1:0 netem drop 1%
> thorium-ini hedpe # tc qdisc add dev ath0 parent 1:1 handle 10: xcp
> capacity 54Mbit limit 500 thorium-ini hedpe # tc -s qdisc ls dev ath0 qdisc
> netem 1: limit 1000 loss 1% Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
> qdisc xcp 10: parent 1:1 capacity 52734Kbit limit 500p Sent 0 bytes 0 pkts
> (dropped 0, overlimits 0) thorium-ini hedpe # tc qdisc change dev ath0
> root handle 1:0 netem drop 1% RTNETLINK answers: Invalid argument
> thorium-ini hedpe # tc qdisc change dev ath0 root netem drop 1% RTNETLINK
> answers: Invalid argument
>
> any ideas?
>
> Thanks! George _______________________________________________ LARTC mailing
> list LARTC@mailman.ds9a.nl
> http://mailman.ds9a.nl/cgi-bin/mailman/listinfo/lartc
>
>
--
^ permalink raw reply
* Re: E1000 stopped transmitting in rc3.
From: Auke Kok @ 2006-04-28 1:54 UTC (permalink / raw)
To: Dave Jones; +Cc: netdev
In-Reply-To: <20060428001352.GA3319@redhat.com>
Dave Jones wrote:
> With 2.6.17-rc3, my E1000 won't get a dhcp lease.
> Looking at tcpdump and ifconfig output, it's easy to see why.
> It's recieving packets, but the packets transmitted field
> of ifconfig never increases.
>
> The last version I have built that worked ok was 2.6.17rc2-git3
*puzzled*
the only patch between 2.6.17rc2 and 2.6.17rc3 contains an rx-path patch, but
nothing that affects tx. All the other patches sent earlier are queued for
2.6.18 so they don't apply.
Auke
^ permalink raw reply
* Re: [PATCH 1/3] Rough VJ Channel Implementation - vj_core.patch
From: Evgeniy Polyakov @ 2006-04-28 6:05 UTC (permalink / raw)
To: David S. Miller; +Cc: kelly, rusty, netdev
In-Reply-To: <20060427.130918.65400512.davem@davemloft.net>
On Thu, Apr 27, 2006 at 01:09:18PM -0700, David S. Miller (davem@davemloft.net) wrote:
> Evgeniy, the difference between this and your work is that you did not
> have an intelligent piece of hardware that could be told to recognize
> flows, and only put packets for a specific flow into that's flow's
> buffer pool.
There are the most "intellegent" NICs which use MMIO copy like Realtek 8139 :)
which were used in receiving zero-copy [1] project.
There was special alorithm researched for receiving zero-copy [1] to allow
to put not page-aligned TCP frames into pages, but there was other
problem when page was committed, since no byte commit is allowed in VFS.
In this case we do not have that problem, but instead we must force userspace to
be very smart when dealing with mapped buffers, instead of simple recv().
And for sending it must be even smarter, since data must be properly
aligned. And what about crappy hardware which can DMA only into limited
memory area, or NIC that can not do sg? Or do we need remapping for NIC
that can not do checksum calculation?
> > If we want to dma data from nic into premapped userspace area, this will
> > strike with message sizes/misalignment/slow read and so on, so
> > preallocation has even more problems.
>
> I do not really think this is an issue, we put the full packet into
> user space and teach it where the offset is to the actual data.
> We'll do the same things we do today to try and get the data area
> aligned. User can do whatever is logical and relevant on his end
> to deal with strange cases.
>
> In fact we can specify that card has to take some care to get data
> area of packet aligned on say an 8 byte boundary or something like
> that. When we don't have hardware assist, we are going to be doing
> copies.
Userspace must be too smart, and as we saw with various java tests, it
can not be so even now.
And what if pages are shared and several threads are trying to write
into the same remapped area? Will we use COW and be blamed like Mach
and FreeBSD developers? :)
> > I do think that significant win in VJ's tests belongs not to remapping
> > and cache-oriented changes, but to move all protocol processing into
> > process' context.
>
> I partly disagree. The biggest win is eliminating all of the control
> overhead (all of "softint RX + protocol demux + IP route lookup +
> socket lookup" is turned into single flow demux), and the SMP safe
> data structure which makes it realistic enough to always move the bulk
> of the packet work to the socket's home cpu.
>
> I do not think userspace protocol implementation buys enough to
> justify it. We have to do the protection switch in and out of kernel
> space anyways, so why not still do the protected protocol processing
> work in the kernel? It is still being done on the user's behalf,
> contributes to his time slice, and avoids all of the terrible issues
> of userspace protocol implementations.
After hard irq softirq is scheduled, then later userspace is scheduled,
at least 2 context switch just to move a packet, and "slow" userspace
code is interrupted by both irqs again...
I run some tests on ppc32 embedded boards which showed that rescheduling
latency tend to have milliseconds delay sometimes (about 4 running processes
on 200mhz cpu), although we do not have some real-time requirements here
it is not a good sign...
> And I also want to note that even if the whole idea explodes and
> cannot be made to work, there are good arguments for transitioning
> to SKB'less drivers for their own sake. So work will really not
> be lost.
>
> Let's have 100 different implementations of net channels! :-)
:)
--
Evgeniy Polyakov
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox