* [PATCH] IBM Lanstreamer bugfixes (round 3) @ 2002-02-15 21:44 Kent Yoder 2002-02-16 11:12 ` Jeff Garzik 0 siblings, 1 reply; 15+ messages in thread From: Kent Yoder @ 2002-02-15 21:44 UTC (permalink / raw) To: jgarzik; +Cc: linux-kernel, marcelo [-- Attachment #1: Type: TEXT/PLAIN, Size: 734 bytes --] Second try.. :-) When and if this passes code inspection, it should be included in 2.4 and 2.5. Thanks, Kent ------------- Sorry, in round 2 I neglected to #include version.h. Please ignore round 2. Below is the old changelog, with this now added: * #include linux/version.h for in-kernel support -------------- Changes made: * No more magic numbers, all come from pci.h * no more udelay()'s, which covered up PCI posting effects * got rid of a __u8/__u16 here and there for u8/u16 * ioctl code disabled for kernel >= 2.5 (now with version.h, too!) * bounded the number of times we could loop inside the interrupt function * spin_lock_irqsave/restore in open()/close() * better formatting Thanks, Kent [-- Attachment #2: Type: APPLICATION/X-GZIP, Size: 4883 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-02-15 21:44 [PATCH] IBM Lanstreamer bugfixes (round 3) Kent Yoder @ 2002-02-16 11:12 ` Jeff Garzik 2002-03-04 16:51 ` Kent Yoder 0 siblings, 1 reply; 15+ messages in thread From: Jeff Garzik @ 2002-02-16 11:12 UTC (permalink / raw) To: Kent Yoder; +Cc: linux-kernel, marcelo Sorry I've been slow to respond... I'm going to apply your driver locally, so you and I have a good baseline to work with, but there are some small issues related to PCI initialization that I want to review and discuss with you, before submitting officially to Marcelo... (another message should follow during the upcoming work week) Regards, Jeff -- Jeff Garzik | "Why is it that attractive girls like you Building 1024 | always seem to have a boyfriend?" MandrakeSoft | "Because I'm a nympho that owns a brewery?" | - BBC TV show "Coupling" ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-02-16 11:12 ` Jeff Garzik @ 2002-03-04 16:51 ` Kent Yoder 2002-03-04 17:04 ` Jeff Garzik 0 siblings, 1 reply; 15+ messages in thread From: Kent Yoder @ 2002-03-04 16:51 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel, marcelo Jeff, I have a feeling you're talking about this section: > pci_write_config_byte (pdev, PCI_CACHE_LINE_SIZE, cls); > pci_read_config_word (pdev, PCI_COMMAND, &pcr); > > /* Turn off Fast B2B enable */ > pcr &= ~PCI_COMMAND_FAST_BACK; > /* Turn on SERR# enable and others */ > pcr |= (PCI_COMMAND_SERR | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | > PCI_COMMAND_IO | PCI_COMMAND_MEMORY); > > pci_write_config_word (pdev, PCI_COMMAND, pcr); > pci_read_config_word (pdev, PCI_COMMAND, &pcr); Basically, this section exists from a time when I had no idea why the card was behaving badly, so I was trying everything :-). So, after revisiting them, I see that setting cache line size to 0 and then using memory write and invalidate doesn't make any sense. I'm thinking both can just be dropped, since I haven't seen any change in performance on the machines I've made netperf runs with (a constant 14.7 Mb/s) after changing these. Any thoughts? Kent Thus Spake Jeff Garzik: >Sorry I've been slow to respond... I'm going to apply your driver >locally, so you and I have a good baseline to work with, but there are >some small issues related to PCI initialization that I want to review >and discuss with you, before submitting officially to Marcelo... > >(another message should follow during the upcoming work week) > >Regards, > > Jeff > > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 16:51 ` Kent Yoder @ 2002-03-04 17:04 ` Jeff Garzik 2002-03-04 17:27 ` David Dillow 2002-03-04 18:58 ` Kent Yoder 0 siblings, 2 replies; 15+ messages in thread From: Jeff Garzik @ 2002-03-04 17:04 UTC (permalink / raw) To: Kent Yoder; +Cc: linux-kernel, marcelo Kent Yoder wrote: > > Jeff, > > I have a feeling you're talking about this section: > > > pci_write_config_byte (pdev, PCI_CACHE_LINE_SIZE, cls); > > pci_read_config_word (pdev, PCI_COMMAND, &pcr); > > > > /* Turn off Fast B2B enable */ > > pcr &= ~PCI_COMMAND_FAST_BACK; > > /* Turn on SERR# enable and others */ > > pcr |= (PCI_COMMAND_SERR | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | > > PCI_COMMAND_IO | PCI_COMMAND_MEMORY); > > > > pci_write_config_word (pdev, PCI_COMMAND, pcr); > > pci_read_config_word (pdev, PCI_COMMAND, &pcr); > > Basically, this section exists from a time when I had no idea why the > card was behaving badly, so I was trying everything :-). > > So, after revisiting them, I see that setting cache line size to 0 and > then using memory write and invalidate doesn't make any sense. I'm thinking > both can just be dropped, since I haven't seen any change in performance on > the machines I've made netperf runs with (a constant 14.7 Mb/s) after > changing these. I agree to the first part :) Set cache line size just like drivers/net/acenic.c does, and enable memory-write-invalidate... Jeff -- Jeff Garzik | Building 1024 | MandrakeSoft | Choose life. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 17:04 ` Jeff Garzik @ 2002-03-04 17:27 ` David Dillow 2002-03-04 17:46 ` Jeff Garzik 2002-03-04 18:58 ` Kent Yoder 1 sibling, 1 reply; 15+ messages in thread From: David Dillow @ 2002-03-04 17:27 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel Jeff Garzik wrote: > Set cache line size just like drivers/net/acenic.c does, and enable > memory-write-invalidate... Does this mean the setup pci_enable_device() does on the cache line size is not sufficient? I ask, because I've been relying on it for a driver I'm working on; should I be setting this as acenic does? It would seem that this is something many drivers would need to do... Thanks, Dave Dillow dillowd@y12.doe.gov ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 17:27 ` David Dillow @ 2002-03-04 17:46 ` Jeff Garzik 2002-03-04 18:45 ` David Dillow 0 siblings, 1 reply; 15+ messages in thread From: Jeff Garzik @ 2002-03-04 17:46 UTC (permalink / raw) To: David Dillow; +Cc: linux-kernel David Dillow wrote: > > Jeff Garzik wrote: > > Set cache line size just like drivers/net/acenic.c does, and enable > > memory-write-invalidate... > > Does this mean the setup pci_enable_device() does on the cache line size > is not sufficient? pci_enable_device doesn't touch the PCI_COMMAND_INVALIDATE bit at all... > I ask, because I've been relying on it for a driver I'm working on; > should I be setting this as acenic does? It would seem that this is > something many drivers would need to do... Yes, acenic is the code to copy, for setting that up. I need to create a pci_set_mwi() helper function. Jeff -- Jeff Garzik | Building 1024 | MandrakeSoft | Choose life. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 17:46 ` Jeff Garzik @ 2002-03-04 18:45 ` David Dillow 2002-03-04 18:52 ` Jeff Garzik 0 siblings, 1 reply; 15+ messages in thread From: David Dillow @ 2002-03-04 18:45 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel Jeff Garzik wrote: > > David Dillow wrote: > > > > Jeff Garzik wrote: > > > Set cache line size just like drivers/net/acenic.c does, and enable > > > memory-write-invalidate... > > > > Does this mean the setup pci_enable_device() does on the cache line size > > is not sufficient? > > pci_enable_device doesn't touch the PCI_COMMAND_INVALIDATE bit at all... Right, I was talking more about the cache line size... is it sufficient for that? As for PCI_COMMAND_INVALIDATE, what does that do for me; my PCI spec isn't handy.... > > I ask, because I've been relying on it for a driver I'm working on; > > should I be setting this as acenic does? It would seem that this is > > something many drivers would need to do... > > Yes, acenic is the code to copy, for setting that up. INVALIDATE, or cache line size? Thanks, Dave Dillow dillowd@y12.doe.gov ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 18:45 ` David Dillow @ 2002-03-04 18:52 ` Jeff Garzik 2002-03-04 19:02 ` David Dillow 0 siblings, 1 reply; 15+ messages in thread From: Jeff Garzik @ 2002-03-04 18:52 UTC (permalink / raw) To: David Dillow; +Cc: linux-kernel David Dillow wrote: > > Jeff Garzik wrote: > > > > David Dillow wrote: > > > > > > Jeff Garzik wrote: > > > > Set cache line size just like drivers/net/acenic.c does, and enable > > > > memory-write-invalidate... > > > > > > Does this mean the setup pci_enable_device() does on the cache line size > > > is not sufficient? > > > > pci_enable_device doesn't touch the PCI_COMMAND_INVALIDATE bit at all... > > Right, I was talking more about the cache line size... is it sufficient > for that? pci_enable_device doesn't touch PCI_COMMAND_INVALIDATE either, on most platforms (particularly ia32, i.e. the popular one :)) > As for PCI_COMMAND_INVALIDATE, what does that do for me; my PCI spec > isn't handy.... Enables Memory-Write-Invalidate (MWI). > > > I ask, because I've been relying on it for a driver I'm working on; > > > should I be setting this as acenic does? It would seem that this is > > > something many drivers would need to do... > > > > Yes, acenic is the code to copy, for setting that up. > > INVALIDATE, or cache line size? both. Jeff -- Jeff Garzik | Building 1024 | MandrakeSoft | Choose life. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 18:52 ` Jeff Garzik @ 2002-03-04 19:02 ` David Dillow 2002-03-04 19:12 ` Jeff Garzik 0 siblings, 1 reply; 15+ messages in thread From: David Dillow @ 2002-03-04 19:02 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel Jeff Garzik wrote: > > David Dillow wrote: > > Right, I was talking more about the cache line size... is it sufficient > > for that? > > pci_enable_device doesn't touch PCI_COMMAND_INVALIDATE either, on most > platforms (particularly ia32, i.e. the popular one :)) Doh! I see my mistake; I was reading pdev_enable_device() which sets it to L1_CACHE_BYTES. And a quick grep shows me that it is called from pci_assign_unassigned_resources(), which is not called on ia32 as far as I can see.... This seems to be a common thing to set; shouldn't we have a helper for it as well, or have pci_enable_device() do it? Thanks, Dave Dillow dillowd@y12.doe.gov ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 19:02 ` David Dillow @ 2002-03-04 19:12 ` Jeff Garzik 0 siblings, 0 replies; 15+ messages in thread From: Jeff Garzik @ 2002-03-04 19:12 UTC (permalink / raw) To: David Dillow; +Cc: linux-kernel David Dillow wrote: > Jeff Garzik wrote: > > pci_enable_device doesn't touch PCI_COMMAND_INVALIDATE either, on most > > platforms (particularly ia32, i.e. the popular one :)) > This seems to be a common thing to set; shouldn't we have a helper for > it as well, or have pci_enable_device() do it? Quoting my message to you from a couple hours ago: > I need to create a pci_set_mwi() helper function. Jeff -- Jeff Garzik | Building 1024 | MandrakeSoft | Choose life. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 17:04 ` Jeff Garzik 2002-03-04 17:27 ` David Dillow @ 2002-03-04 18:58 ` Kent Yoder 2002-03-04 19:10 ` Jeff Garzik 1 sibling, 1 reply; 15+ messages in thread From: Kent Yoder @ 2002-03-04 18:58 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel, marcelo Thus Spake Jeff Garzik: >I agree to the first part :) > >Set cache line size just like drivers/net/acenic.c does, and enable >memory-write-invalidate... > Ok, hopefully below is the section you were referring to: ------- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls); cls <<= 2; if (cls != SMP_CACHE_BYTES) { printk(KERN_INFO " PCI cache line size set incorrectly " "(%i bytes) by BIOS/FW, ", cls); if (cls > SMP_CACHE_BYTES) printk("expecting %i\n", SMP_CACHE_BYTES); else { printk("correcting to %i\n", SMP_CACHE_BYTES); pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, SMP_CACHE_BYTES >> 2); } } pci_read_config_word (pdev, PCI_COMMAND, &pcr); /* Turn off Fast B2B enable */ pcr &= ~PCI_COMMAND_FAST_BACK; /* Turn on SERR# enable and others */ pcr |= (PCI_COMMAND_SERR | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_IO | PCI_COMMAND_MEMORY); pci_write_config_word (pdev, PCI_COMMAND, pcr); pci_read_config_word (pdev, PCI_COMMAND, &pcr); ------ Out of curiosity, does it in fact make sense to use memory write and invalidate and set cache line size to 0 in some cases? This seems to go against the PCI spec, which, if I'm reading it correctly, says that memory write and invalidate is the same as a memory write, but it guarantees that at least 1 cache line will be written. So, setting cacheline size =0 would negate this effect(?) Kent > > Jeff > > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 18:58 ` Kent Yoder @ 2002-03-04 19:10 ` Jeff Garzik 2002-03-05 14:59 ` pjd 2002-03-05 15:37 ` Kent Yoder 0 siblings, 2 replies; 15+ messages in thread From: Jeff Garzik @ 2002-03-04 19:10 UTC (permalink / raw) To: Kent Yoder; +Cc: linux-kernel, marcelo Kent Yoder wrote: > Ok, hopefully below is the section you were referring to: > > ------- > > pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls); > cls <<= 2; > if (cls != SMP_CACHE_BYTES) { > printk(KERN_INFO " PCI cache line size set incorrectly " > "(%i bytes) by BIOS/FW, ", cls); > if (cls > SMP_CACHE_BYTES) > printk("expecting %i\n", SMP_CACHE_BYTES); > else { > printk("correcting to %i\n", SMP_CACHE_BYTES); > pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, > SMP_CACHE_BYTES >> 2); > } > } this gets cache line size correct > /* Turn off Fast B2B enable */ > pcr &= ~PCI_COMMAND_FAST_BACK; > /* Turn on SERR# enable and others */ > pcr |= (PCI_COMMAND_SERR | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | > PCI_COMMAND_IO | PCI_COMMAND_MEMORY); > > pci_write_config_word (pdev, PCI_COMMAND, pcr); > pci_read_config_word (pdev, PCI_COMMAND, &pcr); You only need to worry about the PCI_COMMAND_INVALIDATE bit here, unless your chip requires other setup, or you care to handle PCI hard errors in the driver. > Out of curiosity, does it in fact make sense to use memory write and > invalidate and set cache line size to 0 in some cases? This seems to go > against the PCI spec, which, if I'm reading it correctly, says that memory > write and invalidate is the same as a memory write, but it guarantees that > at least 1 cache line will be written. So, setting cacheline size =0 would > negate this effect(?) The rule is, never ever enable MWI if cache line size is zero. MWI -does- make a difference in performance, though you may need to check lanstreamer docs to see if there is a chip-specific MWI bit you need to enable, over and above the PCI_COMMAND bit. Jeff -- Jeff Garzik | Building 1024 | MandrakeSoft | Choose life. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 19:10 ` Jeff Garzik @ 2002-03-05 14:59 ` pjd 2002-03-05 15:37 ` Kent Yoder 1 sibling, 0 replies; 15+ messages in thread From: pjd @ 2002-03-05 14:59 UTC (permalink / raw) To: Jeff Garzik; +Cc: Kent Yoder, linux-kernel, marcelo Jeff Garzik wrote: > > MWI -does- make a difference in performance, though you may need to > check lanstreamer docs to see if there is a chip-specific MWI bit you > need to enable, over and above the PCI_COMMAND bit. My experience - which is 2-3 years old now - is that many BIOSes will enable MWI for you. Which makes it very easy to forget to do this, and then have it discovered by your customers who have machines that don't set MWI... ............................................................................ Peter Desnoyers 162 Pleasant St. (617) 661-1979 pjd@fred.cambridge.ma.us Cambridge, Mass. 02139 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] IBM Lanstreamer bugfixes (round 3) 2002-03-04 19:10 ` Jeff Garzik 2002-03-05 14:59 ` pjd @ 2002-03-05 15:37 ` Kent Yoder 1 sibling, 0 replies; 15+ messages in thread From: Kent Yoder @ 2002-03-05 15:37 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel, marcelo Ok, below is the current patch including the MWI changes as well as adding printk log levels (as suggested by someone). *fingers crossed* :-) Kent diff -urN linux-2.4.17.vanilla/drivers/net/tokenring/lanstreamer.c linux-2.4.17/drivers/net/tokenring/lanstreamer.c --- linux-2.4.17.vanilla/drivers/net/tokenring/lanstreamer.c Mon Feb 4 11:09:30 2002 +++ linux-2.4.17/drivers/net/tokenring/lanstreamer.c Mon Mar 4 17:40:16 2002 @@ -60,6 +60,11 @@ * malloc free checks, reviewed code. <alan@redhat.com> * 03/13/00 - Added spinlocks for smp * 03/08/01 - Added support for module_init() and module_exit() + * 08/15/01 - Added ioctl() functionality for debugging, changed netif_*_queue + * calls and other incorrectness - Kent Yoder <yoder1@us.ibm.com> + * 11/05/01 - Restructured the interrupt function, added delays, reduced the + * the number of TX descriptors to 1, which together can prevent + * the card from locking up the box - <yoder1@us.ibm.com> * * To Do: * @@ -84,6 +89,14 @@ #define STREAMER_NETWORK_MONITOR 0 +/* #define CONFIG_PROC_FS */ + +/* + * Allow or disallow ioctl's for debugging + */ + +#define STREAMER_IOCTL 0 + #include <linux/config.h> #include <linux/module.h> @@ -105,6 +118,7 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/spinlock.h> +#include <linux/version.h> #include <net/checksum.h> #include <asm/io.h> @@ -121,7 +135,8 @@ * Official releases will only have an a.b.c version number format. */ -static char version[] = "LanStreamer.c v0.4.0 03/08/01 - Mike Sullivan"; +static char version[] = "LanStreamer.c v0.4.0 03/08/01 - Mike Sullivan\n" + " v0.5.1 03/04/02 - Kent Yoder"; static struct pci_device_id streamer_pci_tbl[] __initdata = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR, PCI_ANY_ID, PCI_ANY_ID,}, @@ -175,6 +190,10 @@ MODULE_PARM(message_level, "1-" __MODULE_STRING(STREAMER_MAX_ADAPTERS) "i"); +#if STREAMER_IOCTL +static int streamer_ioctl(struct net_device *, struct ifreq *, int); +#endif + static int streamer_reset(struct net_device *dev); static int streamer_open(struct net_device *dev); static int streamer_xmit(struct sk_buff *skb, struct net_device *dev); @@ -206,6 +225,8 @@ __u32 mmio_start, mmio_end, mmio_flags, mmio_len; int rc=0; static int card_no=-1; + u16 pcr; + u8 cls = 0; #if STREAMER_DEBUG printk("lanstreamer::streamer_init_one, entry pdev %p\n",pdev); @@ -281,7 +302,11 @@ dev->hard_start_xmit = &streamer_xmit; dev->change_mtu = &streamer_change_mtu; dev->stop = &streamer_close; +#if STREAMER_IOCTL + dev->do_ioctl = &streamer_ioctl; +#else dev->do_ioctl = NULL; +#endif dev->set_multicast_list = &streamer_set_rx_mode; dev->get_stats = &streamer_get_stats; dev->set_mac_address = &streamer_set_mac_address; @@ -303,6 +328,27 @@ spin_lock_init(&streamer_priv->streamer_lock); + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls); + cls <<= 2; + if (cls != SMP_CACHE_BYTES) { + printk(KERN_INFO " PCI cache line size set incorrectly " + "(%i bytes) by BIOS/FW, ", cls); + if (cls > SMP_CACHE_BYTES) + printk("expecting %i\n", SMP_CACHE_BYTES); + else { + printk("correcting to %i\n", SMP_CACHE_BYTES); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + } + } + + pci_read_config_word (pdev, PCI_COMMAND, &pcr); + + pcr |= (PCI_COMMAND_INVALIDATE | PCI_COMMAND_SERR); + + pci_write_config_word (pdev, PCI_COMMAND, pcr); + pci_read_config_word (pdev, PCI_COMMAND, &pcr); + printk("%s \n", version); printk("%s: %s. I/O at %hx, MMIO at %p, using irq %d\n",dev->name, streamer_priv->streamer_card_name, @@ -403,6 +449,7 @@ printk("GPR: %x\n", readw(streamer_mmio + GPR)); printk("SISRMASK: %x\n", readw(streamer_mmio + SISR_MASK)); #endif + writew(readw(streamer_mmio + BCTL) | (BCTL_RX_FIFO_8 | BCTL_TX_FIFO_8), streamer_mmio + BCTL ); if (streamer_priv->streamer_ring_speed == 0) { /* Autosense */ writew(readw(streamer_mmio + GPR) | GPR_AUTOSENSE, @@ -558,8 +605,6 @@ do { int i; - save_flags(flags); - cli(); for (i = 0; i < SRB_COMMAND_SIZE; i += 2) { writew(0, streamer_mmio + LAPDINC); } @@ -599,11 +644,12 @@ } printk("\n"); #endif - + spin_lock_irqsave(&streamer_priv->streamer_lock, flags); streamer_priv->srb_queued = 1; /* signal solo that SRB command has been issued */ writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM); + spin_unlock_irqrestore(&streamer_priv->streamer_lock, flags); while (streamer_priv->srb_queued) { interruptible_sleep_on_timeout(&streamer_priv->srb_wait, 5 * HZ); @@ -617,7 +663,6 @@ break; } } - restore_flags(flags); #if STREAMER_DEBUG printk("SISR_MASK: %x\n", readw(streamer_mmio + SISR_MASK)); @@ -767,9 +812,12 @@ streamer_priv->streamer_tx_ring[i].bufcnt_framelen = 0; streamer_priv->streamer_tx_ring[i].buffer = 0; streamer_priv->streamer_tx_ring[i].buflen = 0; + streamer_priv->streamer_tx_ring[i].rsvd1 = 0; + streamer_priv->streamer_tx_ring[i].rsvd2 = 0; + streamer_priv->streamer_tx_ring[i].rsvd3 = 0; } streamer_priv->streamer_tx_ring[STREAMER_TX_RING_SIZE - 1].forward = - virt_to_bus(&streamer_priv->streamer_tx_ring[0]);; + virt_to_bus(&streamer_priv->streamer_tx_ring[0]); streamer_priv->free_tx_ring_entries = STREAMER_TX_RING_SIZE; streamer_priv->tx_ring_free = 0; /* next entry in tx ring to use */ @@ -941,37 +989,30 @@ __u8 *streamer_mmio = streamer_priv->streamer_mmio; __u16 sisr; __u16 misr; - __u16 sisrmask; + u8 max_intr = MAX_INTR; - sisrmask = SISR_MI; - writew(~sisrmask, streamer_mmio + SISR_MASK_RUM); + spin_lock(&streamer_priv->streamer_lock); sisr = readw(streamer_mmio + SISR); - writew(~sisr, streamer_mmio + SISR_RUM); - misr = readw(streamer_mmio + MISR_RUM); - writew(~misr, streamer_mmio + MISR_RUM); - if (!sisr) - { /* Interrupt isn't for us */ - writew(~misr,streamer_mmio+MISR_RUM); - return; - } + while((sisr & (SISR_MI | SISR_SRB_REPLY | SISR_ADAPTER_CHECK | SISR_ASB_FREE | + SISR_ARB_CMD | SISR_TRB_REPLY | SISR_PAR_ERR | SISR_SERR_ERR)) + && (max_intr > 0)) { - spin_lock(&streamer_priv->streamer_lock); + if(sisr & SISR_PAR_ERR) { + writew(~SISR_PAR_ERR, streamer_mmio + SISR_RUM); + (void)readw(streamer_mmio + SISR_RUM); + } - if ((sisr & (SISR_SRB_REPLY | SISR_ADAPTER_CHECK | SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY)) - || (misr & (MISR_TX2_EOF | MISR_RX_NOBUF | MISR_RX_EOF))) { - if (sisr & SISR_SRB_REPLY) { - if (streamer_priv->srb_queued == 1) { - wake_up_interruptible(&streamer_priv->srb_wait); - } else if (streamer_priv->srb_queued == 2) { - streamer_srb_bh(dev); - } - streamer_priv->srb_queued = 0; + else if(sisr & SISR_SERR_ERR) { + writew(~SISR_SERR_ERR, streamer_mmio + SISR_RUM); + (void)readw(streamer_mmio + SISR_RUM); } - /* SISR_SRB_REPLY */ + + else if(sisr & SISR_MI) { + misr = readw(streamer_mmio + MISR_RUM); + if (misr & MISR_TX2_EOF) { - while (streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) - { + while(streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) { streamer_priv->tx_ring_last_status = (streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1); streamer_priv->free_tx_ring_entries++; streamer_priv->streamer_stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len; @@ -981,6 +1022,9 @@ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].status = 0; streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].bufcnt_framelen = 0; streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buflen = 0; + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].rsvd1 = 0; + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].rsvd2 = 0; + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].rsvd3 = 0; } netif_wake_queue(dev); } @@ -989,7 +1033,30 @@ streamer_rx(dev); } /* MISR_RX_EOF */ - if (sisr & SISR_ADAPTER_CHECK) { + + if (misr & MISR_RX_NOBUF) { + /* According to the documentation, we don't have to do anything, + * but trapping it keeps it out of /var/log/messages. + */ + } /* SISR_RX_NOBUF */ + + writew(~misr, streamer_mmio + MISR_RUM); + (void)readw(streamer_mmio + MISR_RUM); + } + + else if (sisr & SISR_SRB_REPLY) { + if (streamer_priv->srb_queued == 1) { + wake_up_interruptible(&streamer_priv->srb_wait); + } else if (streamer_priv->srb_queued == 2) { + streamer_srb_bh(dev); + } + streamer_priv->srb_queued = 0; + + writew(~SISR_SRB_REPLY, streamer_mmio + SISR_RUM); + (void)readw(streamer_mmio + SISR_RUM); + } + + else if (sisr & SISR_ADAPTER_CHECK) { printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name); writel(readl(streamer_mmio + LAPWWO), streamer_mmio + LAPA); printk(KERN_WARNING "%s: Words %x:%x:%x:%x:\n", @@ -1001,38 +1068,37 @@ } /* SISR_ADAPTER_CHECK */ - if (sisr & SISR_ASB_FREE) { + else if (sisr & SISR_ASB_FREE) { /* Wake up anything that is waiting for the asb response */ if (streamer_priv->asb_queued) { streamer_asb_bh(dev); } + writew(~SISR_ASB_FREE, streamer_mmio + SISR_RUM); + (void)readw(streamer_mmio + SISR_RUM); } /* SISR_ASB_FREE */ - if (sisr & SISR_ARB_CMD) { + else if (sisr & SISR_ARB_CMD) { streamer_arb_cmd(dev); + writew(~SISR_ARB_CMD, streamer_mmio + SISR_RUM); + (void)readw(streamer_mmio + SISR_RUM); } /* SISR_ARB_CMD */ - if (sisr & SISR_TRB_REPLY) { + else if (sisr & SISR_TRB_REPLY) { /* Wake up anything that is waiting for the trb response */ if (streamer_priv->trb_queued) { wake_up_interruptible(&streamer_priv-> trb_wait); } streamer_priv->trb_queued = 0; + writew(~SISR_TRB_REPLY, streamer_mmio + SISR_RUM); + (void)readw(streamer_mmio + SISR_RUM); } /* SISR_TRB_REPLY */ - if (misr & MISR_RX_NOBUF) { - /* According to the documentation, we don't have to do anything, but trapping it keeps it out of - /var/log/messages. */ - } /* SISR_RX_NOBUF */ - } else { - printk(KERN_WARNING "%s: Unexpected interrupt: %x\n", - dev->name, sisr); - printk(KERN_WARNING "%s: SISR_MASK: %x\n", dev->name, - readw(streamer_mmio + SISR_MASK)); - } /* One if the interrupts we want */ - writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); + sisr = readw(streamer_mmio + SISR); + max_intr--; + } /* while() */ + spin_unlock(&streamer_priv->streamer_lock) ; } @@ -1044,13 +1110,16 @@ unsigned long flags ; spin_lock_irqsave(&streamer_priv->streamer_lock, flags); - netif_stop_queue(dev); if (streamer_priv->free_tx_ring_entries) { streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].status = 0; - streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].bufcnt_framelen = 0x00010000 | skb->len; + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].bufcnt_framelen = 0x00020000 | skb->len; streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].buffer = virt_to_bus(skb->data); + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].rsvd1 = skb->len; + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].rsvd2 = 0; + streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].rsvd3 = 0; streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].buflen = skb->len; + streamer_priv->tx_ring_skb[streamer_priv->tx_ring_free] = skb; streamer_priv->free_tx_ring_entries--; #if STREAMER_DEBUG_PACKETS @@ -1067,12 +1136,13 @@ #endif writel(virt_to_bus (&streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free]),streamer_mmio + TX2LFDA); + (void)readl(streamer_mmio + TX2LFDA); streamer_priv->tx_ring_free = (streamer_priv->tx_ring_free + 1) & (STREAMER_TX_RING_SIZE - 1); - netif_wake_queue(dev); spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags); return 0; } else { + netif_stop_queue(dev); spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags); return 1; } @@ -1092,12 +1162,13 @@ writew(htons(SRB_CLOSE_ADAPTER << 8),streamer_mmio+LAPDINC); writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC); - save_flags(flags); - cli(); + spin_lock_irqsave(&streamer_priv->streamer_lock, flags); streamer_priv->srb_queued = 1; writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM); + spin_unlock_irqrestore(&streamer_priv->streamer_lock, flags); + while (streamer_priv->srb_queued) { interruptible_sleep_on_timeout(&streamer_priv->srb_wait, @@ -1114,7 +1185,6 @@ } } - restore_flags(flags); streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1); for (i = 0; i < STREAMER_RX_RING_SIZE; i++) { @@ -1808,6 +1878,64 @@ #endif #endif +#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static int streamer_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + int i; + struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; + u8 *streamer_mmio = streamer_priv->streamer_mmio; + + switch(cmd) { + case IOCTL_SISR_MASK: + writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); + break; + case IOCTL_SPIN_LOCK_TEST: + printk(KERN_INFO "spin_lock() called.\n"); + spin_lock(&streamer_priv->streamer_lock); + spin_unlock(&streamer_priv->streamer_lock); + printk(KERN_INFO "spin_unlock() finished.\n"); + break; + case IOCTL_PRINT_BDAS: + printk(KERN_INFO "bdas: RXBDA: %x RXLBDA: %x TX2FDA: %x TX2LFDA: %x\n", + readw(streamer_mmio + RXBDA), + readw(streamer_mmio + RXLBDA), + readw(streamer_mmio + TX2FDA), + readw(streamer_mmio + TX2LFDA)); + break; + case IOCTL_PRINT_REGISTERS: + printk(KERN_INFO "registers:\n"); + printk(KERN_INFO "SISR: %04x MISR: %04x LISR: %04x BCTL: %04x BMCTL: %04x\nmask %04x mask %04x\n", + readw(streamer_mmio + SISR), + readw(streamer_mmio + MISR_RUM), + readw(streamer_mmio + LISR), + readw(streamer_mmio + BCTL), + readw(streamer_mmio + BMCTL_SUM), + readw(streamer_mmio + SISR_MASK), + readw(streamer_mmio + MISR_MASK)); + break; + case IOCTL_PRINT_RX_BUFS: + printk(KERN_INFO "Print rx bufs:\n"); + for(i=0; i<STREAMER_RX_RING_SIZE; i++) + printk(KERN_INFO "rx_ring %d status: 0x%x\n", i, + streamer_priv->streamer_rx_ring[i].status); + break; + case IOCTL_PRINT_TX_BUFS: + printk(KERN_INFO "Print tx bufs:\n"); + for(i=0; i<STREAMER_TX_RING_SIZE; i++) + printk(KERN_INFO "tx_ring %d status: 0x%x\n", i, + streamer_priv->streamer_tx_ring[i].status); + break; + case IOCTL_RX_CMD: + streamer_rx(dev); + printk(KERN_INFO "Sent rx command.\n"); + break; + default: + printk(KERN_INFO "Bad ioctl!\n"); + } + return 0; +} +#endif + static struct pci_driver streamer_pci_driver = { name: "lanstreamer", id_table: streamer_pci_tbl, diff -urN linux-2.4.17.vanilla/drivers/net/tokenring/lanstreamer.h linux-2.4.17/drivers/net/tokenring/lanstreamer.h --- linux-2.4.17.vanilla/drivers/net/tokenring/lanstreamer.h Mon Feb 4 11:09:30 2002 +++ linux-2.4.17/drivers/net/tokenring/lanstreamer.h Mon Feb 4 10:21:42 2002 @@ -56,11 +56,36 @@ * * 12/10/99 - Alpha Release 0.1.0 * First release to the public + * 08/15/01 - Added ioctl() definitions and others - Kent Yoder <yoder1@us.ibm.com> * */ +#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include <asm/ioctl.h> +#define IOCTL_PRINT_RX_BUFS SIOCDEVPRIVATE +#define IOCTL_PRINT_TX_BUFS SIOCDEVPRIVATE+1 +#define IOCTL_RX_CMD SIOCDEVPRIVATE+2 +#define IOCTL_TX_CMD SIOCDEVPRIVATE+3 +#define IOCTL_PRINT_REGISTERS SIOCDEVPRIVATE+4 +#define IOCTL_PRINT_BDAS SIOCDEVPRIVATE+5 +#define IOCTL_SPIN_LOCK_TEST SIOCDEVPRIVATE+6 +#define IOCTL_SISR_MASK SIOCDEVPRIVATE+7 +#endif + +/* MAX_INTR - the maximum number of times we can loop + * inside the interrupt function before returning + * control to the OS (maximum value is 256) + */ +#define MAX_INTR 5 + +#define CLS 0x0C +#define MLR 0x86 +#define LTR 0x0D + #define BCTL 0x60 #define BCTL_SOFTRESET (1<<15) +#define BCTL_RX_FIFO_8 (1<<1) +#define BCTL_TX_FIFO_8 (1<<3) #define GPR 0x4a #define GPR_AUTOSENSE (1<<2) @@ -89,6 +114,7 @@ #define SISR_MASK_RUM 0x58 #define SISR_MI (1<<15) +#define SISR_SERR_ERR (1<<14) #define SISR_TIMER (1<<11) #define SISR_LAP_PAR_ERR (1<<10) #define SISR_LAP_ACC_ERR (1<<9) @@ -218,7 +244,13 @@ /* Streamer defaults for buffers */ #define STREAMER_RX_RING_SIZE 16 /* should be a power of 2 */ -#define STREAMER_TX_RING_SIZE 8 /* should be a power of 2 */ +/* Setting the number of TX descriptors to 1 is a workaround for an + * undocumented hardware problem with the lanstreamer board. Setting + * this to something higher may slightly increase the throughput you + * can get from the card, but at the risk of locking up the box. - + * <yoder1@us.ibm.com> + */ +#define STREAMER_TX_RING_SIZE 1 /* should be a power of 2 */ #define PKT_BUF_SZ 4096 /* Default packet size */ ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] IBM Lanstreamer bugfixes (round 3) @ 2002-02-04 17:16 Kent Yoder 0 siblings, 0 replies; 15+ messages in thread From: Kent Yoder @ 2002-02-04 17:16 UTC (permalink / raw) To: jgarzik; +Cc: linux-kernel, marcelo [-- Attachment #1: Type: TEXT/PLAIN, Size: 601 bytes --] Sorry, in round 2 I neglected to #include version.h. Please ignore round 2. Below is the old changelog, with this now added: * #include linux/version.h for in-kernel support -------------- Changes made: * No more magic numbers, all come from pci.h * no more udelay()'s, which covered up PCI posting effects * got rid of a __u8/__u16 here and there for u8/u16 * ioctl code disabled for kernel >= 2.5 (now with version.h, too!) * bounded the number of times we could loop inside the interrupt function * spin_lock_irqsave/restore in open()/close() * better formatting Thanks, Kent [-- Attachment #2: Type: APPLICATION/x-gzip, Size: 4883 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2002-03-05 15:39 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-02-15 21:44 [PATCH] IBM Lanstreamer bugfixes (round 3) Kent Yoder 2002-02-16 11:12 ` Jeff Garzik 2002-03-04 16:51 ` Kent Yoder 2002-03-04 17:04 ` Jeff Garzik 2002-03-04 17:27 ` David Dillow 2002-03-04 17:46 ` Jeff Garzik 2002-03-04 18:45 ` David Dillow 2002-03-04 18:52 ` Jeff Garzik 2002-03-04 19:02 ` David Dillow 2002-03-04 19:12 ` Jeff Garzik 2002-03-04 18:58 ` Kent Yoder 2002-03-04 19:10 ` Jeff Garzik 2002-03-05 14:59 ` pjd 2002-03-05 15:37 ` Kent Yoder -- strict thread matches above, loose matches on Subject: below -- 2002-02-04 17:16 Kent Yoder
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox