📄 update-2.4.19-axis.patch
字号:
+e100rxtx_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = (struct net_device *)dev_id;+ struct net_local *np = (struct net_local *)dev->priv; unsigned long irqbits = *R_IRQ_MASK2_RD; + /* Handle received packets */ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) { /* acknowledge the eop interrupt */ @@ -1014,44 +1016,26 @@ so we have to loop back and check if so */ } }-} -/* the transmit dma channel interrupt- *- * this is supposed to free the skbuff which was pending during transmission,- * and inform the kernel that we can send one more buffer- */+ /* Report any packets that have been sent */+ while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) &&+ myFirstTxDesc != myNextTxDesc)+ {+ np->stats.tx_bytes += myFirstTxDesc->skb->len;+ np->stats.tx_packets++; -static void-e100tx_interrupt(int irq, void *dev_id, struct pt_regs * regs)-{- struct net_device *dev = (struct net_device *)dev_id;- unsigned long irqbits = *R_IRQ_MASK2_RD;- struct net_local *np = (struct net_local *)dev->priv;+ /* dma is ready with the transmission of the data in tx_skb, so now+ we can release the skb memory */+ dev_kfree_skb_irq(myFirstTxDesc->skb);+ myFirstTxDesc->skb = 0;+ myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);+ } - /* check for a dma0_eop interrupt */ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {- /* Report all sent packets */- do {- /* acknowledge the eop interrupt */- *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);-- np->stats.tx_bytes += myFirstTxDesc->skb->len;- np->stats.tx_packets++;-- /* dma is ready with the transmission of the data in tx_skb, so now- we can release the skb memory */- dev_kfree_skb_irq(myFirstTxDesc->skb);- myFirstTxDesc->skb = 0;-- if (netif_queue_stopped(dev)) {- /* Queue is running, disable tx IRQ */- *R_IRQ_MASK2_CLR = IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr); - netif_wake_queue(dev);- }- myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);- } while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) &&- myFirstTxDesc != myNextTxDesc);+ /* acknowledge the eop interrupt and wake up queue */+ *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);+ *R_IRQ_MASK2_CLR = IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr); + netif_wake_queue(dev); } } @@ -1140,11 +1124,18 @@ memcpy(skb_data_ptr, phys_to_virt(myNextRxDesc->descr.buf), length); } else {- /* Large packet, send directly to upper layers and allocate new memory */ + /* Large packet, send directly to upper layers and allocate new + * memory (aligned to cache line boundary to avoid bug).+ * Before sending the skb to upper layers we must make sure that + * skb->data points to the aligned start of the packet. + */+ int align; skb = myNextRxDesc->skb;- skb_put(skb, length);- myNextRxDesc->skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE);- myNextRxDesc->descr.buf = virt_to_phys(myNextRxDesc->skb->data);+ align = phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data; + skb_put(skb, length + align); + skb_pull(skb, align); /* Remove alignment bytes */+ myNextRxDesc->skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);+ myNextRxDesc->descr.buf = L1_CACHE_ALIGN(virt_to_phys(myNextRxDesc->skb->data)); } skb->dev = dev;@@ -1220,7 +1211,6 @@ static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {- /* Maybe default should return -EINVAL instead? */ switch (cmd) { case SET_ETH_SPEED_10: /* 10 Mbps */ e100_set_speed(10);@@ -1240,10 +1230,8 @@ case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/ e100_set_duplex(autoneg); break;- default: /* Auto neg */- e100_set_speed(0);- e100_set_duplex(autoneg);- break;+ default:+ return -EINVAL; } return 0; }diff -Nur /home/starvik/download/kernel/linux-2.4.19/arch/cris/drivers/gpio.c ./arch/cris/drivers/gpio.c--- /home/starvik/download/kernel/linux-2.4.19/arch/cris/drivers/gpio.c Sat Aug 3 02:39:42 2002+++ ./arch/cris/drivers/gpio.c Wed Oct 23 12:28:59 2002@@ -1,4 +1,4 @@-/* $Id: update-2.4.19-axis.patch,v 1.1.1.1 2004/06/06 14:14:02 rpm Exp $+/* $Id: update-2.4.19-axis.patch,v 1.1.1.1 2004/06/06 14:14:02 rpm Exp $ * * Etrax general port I/O device *@@ -9,6 +9,38 @@ * Johan Adolfsson (read/set directions, write, port G) * * $Log: update-2.4.19-axis.patch,v $ * Revision 1.1.1.1 2004/06/06 14:14:02 rpm * Vesuvio baseline * * Revision 1.1.1.1 2004/04/04 19:00:54 pgerum * Vesuvio baseline * * Revision 1.1.1.1 2004/02/15 11:56:24 pgerum * Magma baseline * * Revision 1.1 2004/01/02 15:11:03 pgerum * Add Axis update to 2.4.19 *+ * Revision 1.20 2002/10/16 21:16:24 johana+ * Added support for PA high level interrupt.+ * That gives 2ms response time with iodtest for high levels and 2-12 ms+ * response time on low levels if the check is not made in+ * process.c:cpu_idle() as well.+ *+ * Revision 1.19 2002/10/14 18:27:33 johana+ * Implemented alarm handling so select() now works.+ * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in+ * cpu_idle().+ * Otherwise I get 15-18 ms (same as doing the poll in userspace -+ * but less overhead).+ * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it+ * is in 2.4) as well?+ * TODO? Perhaps call request_irq()/free_irq() only when needed?+ * Increased version to 2.5+ *+ * Revision 1.18 2002/10/11 15:02:00 johana+ * Mask inverted 8 bit value in setget_input().+ *+ * Revision 1.17 2002/06/17 15:53:01 johana+ * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT+ * that take a pointer as argument and thus can handle 32 bit ports (G)+ * correctly.+ * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.+ * (especially if Port G bit 31 is used)+ *+ * Revision 1.16 2002/06/17 09:59:51 johana+ * Returning 32 bit values in the ioctl return value doesn't work if bit+ * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.+ * A new set of ioctl's will be added.+ * * Revision 1.15 2002/05/06 13:19:13 johana * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well. *@@ -83,11 +115,19 @@ #include <asm/svinto.h> #include <asm/io.h> #include <asm/system.h>+#include <asm/irq.h> #define GPIO_MAJOR 120 /* experimental MAJOR number */ #define D(x) +#if 0+static int dp_cnt;+#define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)+#else+#define DP(x)+#endif+ static char gpio_name[] = "etrax gpio"; #if 0@@ -125,6 +165,8 @@ static struct gpio_private *alarmlist = 0; +static int gpio_some_alarms = 0; /* Set if someone uses alarm */+ /* Port A and B use 8 bit access, but Port G is 32 bit */ #define NUM_PORTS (GPIO_MINOR_B+1) @@ -185,21 +227,81 @@ static unsigned int -gpio_poll(struct file *filp,- struct poll_table_struct *wait)+gpio_poll(struct file *file,+ poll_table *wait) {- /* TODO poll on alarms! */-#if 0- if (!ANYTHING_WANTED) {- D(printk("gpio_select sleeping task\n"));- select_wait(&gpio_wq, table);+ unsigned int mask = 0;+ struct gpio_private *priv = (struct gpio_private *)file->private_data;+ unsigned long data;+ poll_wait(file, &priv->alarm_wq, wait);+ if (priv->minor == GPIO_MINOR_A) {+ unsigned long tmp;+ data = *R_PORT_PA_DATA;+ /* PA has support for high level interrupt -+ * lets activate for those low and with highalarm set+ */+ tmp = ~data & priv->highalarm & 0xFF;+ *R_IRQ_MASK1_SET = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);+ } else if (priv->minor == GPIO_MINOR_B)+ data = *R_PORT_PB_DATA;+ else if (priv->minor == GPIO_MINOR_G)+ data = *R_PORT_G_DATA;+ else return 0;+ + if ((data & priv->highalarm) ||+ (~data & priv->lowalarm)) {+ mask = POLLIN|POLLRDNORM;+ }+ + DP(printk("gpio_poll ready: mask 0x%08X\n", mask));+ return mask;+}++void etrax_gpio_wake_up_check(void)+{+ struct gpio_private *priv = alarmlist;+ unsigned long data = 0;+ while (priv) {+ if (USE_PORTS(priv)) {+ data = *priv->port;+ } else if (priv->minor == GPIO_MINOR_G) {+ data = *R_PORT_G_DATA;+ }+ if ((data & priv->highalarm) ||+ (~data & priv->lowalarm)) {+ DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));+ wake_up_interruptible(&priv->alarm_wq);+ }+ priv = priv->next;+ }+}++static void +gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)+{+ if (gpio_some_alarms) {+ etrax_gpio_wake_up_check();+ }+}++static void +gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)+{+ unsigned long tmp;+ /* Find what PA interrupts are active */+ tmp = (*R_IRQ_READ1 >> R_IRQ_READ1__pa0__BITNR) & 0xFF;+ /* Clear them.. */+ /* NOTE: Maybe we need to be more careful here if some other+ * driver uses PA interrupt as well?+ */+ *R_IRQ_MASK1_CLR = (tmp << R_IRQ_MASK1_CLR__pa0__BITNR);+ if (gpio_some_alarms) {+ etrax_gpio_wake_up_check(); }- D(printk("gpio_select ready\n"));-#endif- return 1; } + static ssize_t gpio_write(struct file * file, const char * buf, size_t count, loff_t *off) {@@ -310,7 +412,7 @@ { struct gpio_private *p = alarmlist; struct gpio_private *todel = (struct gpio_private *)filp->private_data;-+ /* unlink from alarmlist and free the private structure */ if (p == todel) {@@ -322,7 +424,17 @@ } kfree(todel);-+ /* Check if there are still any alarms set */+ p = alarmlist;+ while (p) {+ if (p->highalarm | p->lowalarm) {+ gpio_some_alarms = 1;+ return 0;+ }+ p = p->next;+ }+ gpio_some_alarms = 0;+ return 0; } @@ -330,6 +442,107 @@ * set alarms to wait for using a subsequent select(). */ +unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)+{+ /* Set direction 0=unchanged 1=input, + * return mask with 1=input + */+ unsigned long flags;+ if (USE_PORTS(priv)) {+ save_flags(flags); cli();+ *priv->dir = *priv->dir_shadow &= + ~((unsigned char)arg & priv->changeable_dir);+ restore_flags(flags);+ return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */+ } else if (priv->minor == GPIO_MINOR_G) {+ /* We must fiddle with R_GEN_CONFIG to change dir */+ if (((arg & dir_g_in_bits) != arg) && + (arg & changeable_dir_g)) {+ arg &= changeable_dir_g;+ /* Clear bits in genconfig to set to input */+ if (arg & (1<<0)) {+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);+ dir_g_in_bits |= (1<<0);+ dir_g_out_bits &= ~(1<<0);+ }+ if ((arg & 0x0000FF00) == 0x0000FF00) {+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);+ dir_g_in_bits |= 0x0000FF00;+ dir_g_out_bits &= ~0x0000FF00;+ }+ if ((arg & 0x00FF0000) == 0x00FF0000) {+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);+ dir_g_in_bits |= 0x00FF0000;+ dir_g_out_bits &= ~0x00FF0000;+ }+ if (arg & (1<<24)) {+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -