ibmtr: possible Read buffer overflow?
[safe/jmp/linux-2.6] / drivers / net / tokenring / ibmtr.c
index 65e21eb..6a3c751 100644 (file)
@@ -191,7 +191,8 @@ static int  tok_init_card(struct net_device *dev);
 static void    tok_open_adapter(unsigned long dev_addr);
 static void    open_sap(unsigned char type, struct net_device *dev);
 static void    tok_set_multicast_list(struct net_device *dev);
-static int     tok_send_packet(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t tok_send_packet(struct sk_buff *skb,
+                                        struct net_device *dev);
 static int     tok_close(struct net_device *dev);
 static irqreturn_t tok_interrupt(int irq, void *dev_id);
 static void    initial_tok_int(struct net_device *dev);
@@ -200,7 +201,6 @@ static void         tr_rx(struct net_device *dev);
 static void    ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev);
 static void    tok_rerun(unsigned long dev_addr);
 static void    ibmtr_readlog(struct net_device *dev);
-static struct  net_device_stats *tok_get_stats(struct net_device *dev);
 static int     ibmtr_change_mtu(struct net_device *dev, int mtu);
 static void    find_turbo_adapters(int *iolist);
 
@@ -702,9 +702,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
                channel_def[cardpresent - 1], adapter_def(ti->adapter_type));
        DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n",
                        irq, PIOaddr, ti->mapped_ram_size / 2);
-       DPRINTK("Hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n",
-               dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-               dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+       DPRINTK("Hardware address : %pM\n", dev->dev_addr);
        if (ti->page_mask)
                DPRINTK("Shared RAM paging enabled. "
                        "Page size: %uK Shared Ram size %dK\n",
@@ -818,18 +816,21 @@ static unsigned char __devinit get_sram_size(struct tok_info *adapt_info)
 
 /*****************************************************************************/
 
+static const struct net_device_ops trdev_netdev_ops = {
+       .ndo_open               = tok_open,
+       .ndo_stop               = tok_close,
+       .ndo_start_xmit         = tok_send_packet,
+       .ndo_set_multicast_list = tok_set_multicast_list,
+       .ndo_change_mtu         = ibmtr_change_mtu,
+};
+
 static int __devinit trdev_init(struct net_device *dev)
 {
        struct tok_info *ti = netdev_priv(dev);
 
        SET_PAGE(ti->srb_page);
         ti->open_failure = NO    ;
-       dev->open = tok_open;
-       dev->stop = tok_close;
-       dev->hard_start_xmit = tok_send_packet;
-       dev->get_stats = tok_get_stats;
-       dev->set_multicast_list = tok_set_multicast_list;
-       dev->change_mtu = ibmtr_change_mtu;
+       dev->netdev_ops = &trdev_netdev_ops;
 
        return 0;
 }
@@ -1022,7 +1023,8 @@ static void tok_set_multicast_list(struct net_device *dev)
 
 #define STATION_ID_OFST 4
 
-static int tok_send_packet(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t tok_send_packet(struct sk_buff *skb,
+                                        struct net_device *dev)
 {
        struct tok_info *ti;
        unsigned long flags;
@@ -1041,7 +1043,7 @@ static int tok_send_packet(struct sk_buff *skb, struct net_device *dev)
        writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
        spin_unlock_irqrestore(&(ti->lock), flags);
        dev->trans_start = jiffies;
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /*****************************************************************************/
@@ -1141,9 +1143,16 @@ static void dir_open_adapter (struct net_device *dev)
                 } else {
                        char **prphase = printphase;
                        char **prerror = printerror;
+                       int pnr = err / 16 - 1;
+                       int enr = err % 16 - 1;
                        DPRINTK("TR Adapter misc open failure, error code = ");
-                       printk("0x%x, Phase: %s, Error: %s\n",
-                               err, prphase[err/16 -1], prerror[err%16 -1]);
+                       if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) ||
+                                       enr < 0 ||
+                                       enr >= ARRAY_SIZE(printerror))
+                               printk("0x%x, invalid Phase/Error.", err);
+                       else
+                               printk("0x%x, Phase: %s, Error: %s\n", err,
+                                               prphase[pnr], prerror[enr]);
                        printk(" retrying after %ds delay...\n",
                                        TR_RETRY_INTERVAL/HZ);
                 }
@@ -1462,7 +1471,7 @@ static irqreturn_t tok_interrupt(int irq, void *dev_id)
                                        "%02X\n",
                                        (int)retcode, (int)readb(ti->ssb + 6));
                        else
-                               ti->tr_stats.tx_packets++;
+                               dev->stats.tx_packets++;
                        break;
                case XMIT_XID_CMD:
                        DPRINTK("xmit xid ret_code: %02X\n",
@@ -1648,7 +1657,7 @@ static void tr_tx(struct net_device *dev)
                break;
        }
        writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
-       ti->tr_stats.tx_bytes += ti->current_skb->len;
+       dev->stats.tx_bytes += ti->current_skb->len;
        dev_kfree_skb_irq(ti->current_skb);
        ti->current_skb = NULL;
        netif_wake_queue(dev);
@@ -1724,7 +1733,7 @@ static void tr_rx(struct net_device *dev)
        if (readb(llc + offsetof(struct trllc, llc)) != UI_CMD) {
                SET_PAGE(ti->asb_page);
                writeb(DATA_LOST, ti->asb + RETCODE_OFST);
-               ti->tr_stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
                return;
        }
@@ -1739,18 +1748,18 @@ static void tr_rx(struct net_device *dev)
        if (!IPv4_p) {
 
                void __iomem *trhhdr = rbuf + offsetof(struct rec_buf, data);
-
+               u8 saddr[6];
+               u8 daddr[6];
+               int i;
+               for (i = 0 ; i < 6 ; i++)
+                       saddr[i] = readb(trhhdr + SADDR_OFST + i);
+               for (i = 0 ; i < 6 ; i++)
+                       daddr[i] = readb(trhhdr + DADDR_OFST + i);
                DPRINTK("Probably non-IP frame received.\n");
                DPRINTK("ssap: %02X dsap: %02X "
-                       "saddr: %02X:%02X:%02X:%02X:%02X:%02X "
-                       "daddr: %02X:%02X:%02X:%02X:%02X:%02X\n",
+                       "saddr: %pM daddr: %pM\n",
                        readb(llc + SSAP_OFST), readb(llc + DSAP_OFST),
-                       readb(trhhdr+SADDR_OFST), readb(trhhdr+ SADDR_OFST+1),
-                       readb(trhhdr+SADDR_OFST+2), readb(trhhdr+SADDR_OFST+3),
-                       readb(trhhdr+SADDR_OFST+4), readb(trhhdr+SADDR_OFST+5),
-                       readb(trhhdr+DADDR_OFST), readb(trhhdr+DADDR_OFST + 1),
-                       readb(trhhdr+DADDR_OFST+2), readb(trhhdr+DADDR_OFST+3),
-                       readb(trhhdr+DADDR_OFST+4), readb(trhhdr+DADDR_OFST+5));
+                       saddr, daddr);
        }
 #endif
 
@@ -1759,7 +1768,7 @@ static void tr_rx(struct net_device *dev)
 
        if (!(skb = dev_alloc_skb(skb_size))) {
                DPRINTK("out of memory. frame dropped.\n");
-               ti->tr_stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                SET_PAGE(ti->asb_page);
                writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));
                writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
@@ -1815,8 +1824,8 @@ static void tr_rx(struct net_device *dev)
 
        writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
 
-       ti->tr_stats.rx_bytes += skb->len;
-       ti->tr_stats.rx_packets++;
+       dev->stats.rx_bytes += skb->len;
+       dev->stats.rx_packets++;
 
        skb->protocol = tr_type_trans(skb, dev);
        if (IPv4_p) {
@@ -1824,7 +1833,6 @@ static void tr_rx(struct net_device *dev)
                skb->ip_summed = CHECKSUM_COMPLETE;
        }
        netif_rx(skb);
-       dev->last_rx = jiffies;
 }                              /*tr_rx */
 
 /*****************************************************************************/
@@ -1840,8 +1848,8 @@ static void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev)
 
 /*****************************************************************************/
 
-void tok_rerun(unsigned long dev_addr){
-
+static void tok_rerun(unsigned long dev_addr)
+{
        struct net_device *dev = (struct net_device *)dev_addr;
        struct tok_info *ti = netdev_priv(dev);
 
@@ -1879,21 +1887,6 @@ static void ibmtr_readlog(struct net_device *dev)
 
 /*****************************************************************************/
 
-/* tok_get_stats():  Basically a scaffold routine which will return
-   the address of the tr_statistics structure associated with
-   this device -- the tr.... structure is an ethnet look-alike
-   so at least for this iteration may suffice.   */
-
-static struct net_device_stats *tok_get_stats(struct net_device *dev)
-{
-
-       struct tok_info *toki;
-       toki = netdev_priv(dev);
-       return (struct net_device_stats *) &toki->tr_stats;
-}
-
-/*****************************************************************************/
-
 static int ibmtr_change_mtu(struct net_device *dev, int mtu)
 {
        struct tok_info *ti = netdev_priv(dev);
@@ -1928,7 +1921,7 @@ static int __init ibmtr_init(void)
 
        find_turbo_adapters(io);
 
-       for (i = 0; io[i] && (i < IBMTR_MAX_ADAPTERS); i++) {
+       for (i = 0; i < IBMTR_MAX_ADAPTERS && io[i]; i++) {
                struct net_device *dev;
                irq[i] = 0;
                mem[i] = 0;