patch-2.2.15 linux/drivers/s390/net/ctc.c

Next file: linux/drivers/s390/net/iucv.c
Previous file: linux/drivers/s390/char/hwc_tty.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/s390/net/ctc.c linux/drivers/s390/net/ctc.c
@@ -3,8 +3,42 @@
  *    CTC / ESCON network driver
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Dieter Wellerdiek (wel@de.ibm.com)
+ *
+ *
+ *  Description of the Kernel Parameter
+ *    Normally the CTC driver selects the channels in order (automatic channel 
+ *    selection). If your installation needs to use the channels in a different 
+ *    order or doesn't want to have automatic channel selection on, you can do 
+ *    this with the "ctc= kernel keyword". 
+ *
+ *       ctc=0,0xrrrr,0xwwww,ddddd
+ *
+ *     Where:
+ *
+ *       "rrrr" is the read channel address
+ *       "wwww" is the write channel address
+ *       "dddd" is the network device (ctc0 to ctc7 for a parallel channel, escon0
+ *              to escon7 for ESCON channels).
+ *
+ *     To switch the automatic channel selection off use the ctc= keyword with 
+ *     parameter "noauto". This may be necessary if you 3271 devices or other devices 
+ *     which use the ctc device type and model, but operate with a different protocol. 
+ *     
+ *       ctc=noauto
+ *
+ *  Change History
+ *    0.50  Initial release shipped
+ *    0.51  Bug fixes
+ *          - CTC / ESCON network device can now handle up to 64 channels 
+ *          - 3088-61 info message supperssed - CISCO 7206 - CLAW - ESCON 
+ *          - 3088-62 info message suppressed - OSA/D   
+ *          - channel: def ffffffed ... error message suppressed 
+ *          - CTC / ESCON device was not recoverable after a lost connection with 
+ *            IFCONFIG dev DOWN and IFCONFIG dev UP 
+ *          - Possibility to switch the automatic selection off
+ *          - Minor bug fixes 
  */
 
 #include <linux/kernel.h>
@@ -28,12 +62,12 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
  
-#include "../../../arch/s390/kernel/irq.h"
+#include <asm/irq.h>
 
 
 //#define DEBUG 
 
-/* Redefine message level, so that all messages occure on 3215 console in DEBUG mode */
+/* Redefine message level, so that all messages occur on 3215 console in DEBUG mode */
 #ifdef DEBUG                
         #undef  KERN_INFO
         #undef  KERN_WARNING
@@ -49,8 +83,8 @@
 #define CCW_CMD_SET_EXTENDED    0xc3
 #define CCW_CMD_PREPARE         0xe3
 
-#define MAX_DEVICES             16 
-#define MAX_ADAPTERS            MAX_DEVICES / 2
+#define MAX_CHANNEL_DEVICES     64 
+#define MAX_ADAPTERS            8
 #define CTC_DEFAULT_MTU_SIZE    1500
 #define READ                    0
 #define WRITE                   1
@@ -77,7 +111,7 @@
 
 typedef enum { 
         channel_type_none,           /* Device is not a channel */
-        channel_type_undefined,      /* Device is a channel but we dont know anything about it */
+        channel_type_undefined,      /* Device is a channel but we don't know anything about it */
         channel_type_ctca,           /* Device is a CTC/A and we can deal with it */
         channel_type_escon,          /* Device is a ESCON channel and we can deal with it */
         channel_type_unsupported     /* Device is a unsupported model */
@@ -99,7 +133,7 @@
 }; 
 
 static struct {
-        struct devicelist  list[MAX_DEVICES]; 
+        struct devicelist  list[MAX_CHANNEL_DEVICES]; 
         int                count;
         int                left;
 } channel[CHANNEL_MEDIA];
@@ -113,7 +147,7 @@
         __u16              protocol;
 };
 
-static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS];
+static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS];  /* 0 = CTC  / 1 = ESCON */
 
 
 /* 
@@ -131,7 +165,7 @@
 struct channel {
         unsigned int        devno;
         int                 irq;
-        int                 IO_active;
+        unsigned long       IO_active;
         ccw1_t              ccw[3];
         __u32               state; 
         int                 buffer_count;
@@ -152,7 +186,7 @@
 
 
 struct ctc_priv {                                                                    
-        struct net_device_stats  stats;
+        struct enet_statistics   stats;
         struct channel           channel[2]; 
         __u16                    protocol;
 };  
@@ -224,7 +258,7 @@
         if (!test_and_set_bit(0, (void *)& channel_tab_initialized)){
                 channel_scan(); 
                 for (m = 0; m < CHANNEL_MEDIA; m++) { 
-                        channel_sort (channel[m].list, MAX_DEVICES); 
+                        channel_sort (channel[m].list, MAX_CHANNEL_DEVICES); 
                         channel[m].left = channel[m].count;   
                 }
                 if (channel[CTC].count == 0 && channel[ESCON].count == 0) 
@@ -234,7 +268,7 @@
                             channel[CTC].count, channel[ESCON].count);  
 #ifdef DEBUG 
                 for (m = 0; m < CHANNEL_MEDIA;  m++) { 
-                        for (c = 0; c < MAX_DEVICES; c++){
+                        for (c = 0; c < MAX_CHANNEL_DEVICES; c++){
                                 printk(KERN_DEBUG "channel: Adapter=%x Entry=%x devno=%04x\n", 
                                      m, c, channel[m].list[c].devno);
                         }
@@ -255,14 +289,14 @@
         dev_info_t temp;
         
         for (m = 0; m < CHANNEL_MEDIA;  m++) { 
-                for (c = 0; c < MAX_DEVICES; c++){
+                for (c = 0; c < MAX_CHANNEL_DEVICES; c++){
                         channel[m].list[c].devno = -ENODEV;
                 }
         }
         
         for (irq = 0; irq < NR_IRQS; irq++) {
                 /* CTC/A */
-                if (channel[CTC].count < MAX_DEVICES ) {
+                if (channel[CTC].count < MAX_CHANNEL_DEVICES ) {
                         if (get_dev_info(irq, &temp) == 0 && 
                             channel_check_for_type(&temp.sid_data) == channel_type_ctca) {
                                 channel[CTC].list[channel[CTC].count].devno = temp.devno; 
@@ -271,7 +305,7 @@
                 }
 
                 /* ESCON */
-                if (channel[ESCON].count < MAX_DEVICES ) {
+                if (channel[ESCON].count < MAX_CHANNEL_DEVICES ) {
                         if (get_dev_info(irq, &temp) == 0 && 
                             channel_check_for_type(&temp.sid_data) == channel_type_escon) {
                                 channel[ESCON].list[channel[ESCON].count].devno = temp.devno; 
@@ -363,21 +397,23 @@
 
                         switch (id->cu_model) {
                                 case 0x08:    
-                                        type = channel_type_ctca;  /* 3088/08  ==> CTCA */
+                                        type = channel_type_ctca;  /* 3088-08  ==> CTCA */
                                         break; 
 
                                 case 0x1F:   
-                                        type = channel_type_escon; /* 3088/1F  ==> ESCON channel */
+                                        type = channel_type_escon; /* 3088-1F  ==> ESCON channel */
                                         break;
  
-                                case 0x01:                         /* 3088/01  ==> P390 OSA emulation */
-                                case 0x60:                         /* 3088/60  ==> OSA/2 Adapter */
+                                case 0x01:                         /* 3088-01  ==> P390 OSA emulation */
+                                case 0x60:                         /* 3088-60  ==> OSA/2 adapter */
+                                case 0x61:                         /* 3088-61  ==> CISCO 7206 CLAW protocol ESCON connected */
+                                case 0x62:                         /* 3088-62  ==> OSA/D device */ 
                                         type = channel_type_unsupported;
                                          break; 
 
                                 default:
                                         type = channel_type_undefined;
-                                        printk(KERN_INFO "channel: Unknown model found 3088/%02x\n",id->cu_model);
+                                        printk(KERN_INFO "channel: Unknown model found 3088-%02x\n",id->cu_model);
                         }
                         break;
 
@@ -545,6 +581,11 @@
         
         ctc_no_auto = 1;
 
+        if (!strcmp(dev_name,"noauto")) { 
+                printk(KERN_INFO "ctc: automatic channel selection deactivated\n");
+                return;
+        }
+
         tmp.devno[WRITE] = -ENODEV;
         tmp.devno[READ] = -ENODEV; 
 
@@ -556,7 +597,7 @@
                 case 2: /* read channel passed */
                         tmp.devno[READ] = ints[2];
                         if (tmp.devno[WRITE] == -ENODEV)
-                                tmp.devno[WRITE] = tmp.devno[READ]++; 
+                                tmp.devno[WRITE] = tmp.devno[READ] + 1; 
 
                 case 1: /* protocol type passed */
                         tmp.protocol    = ints[1];
@@ -566,9 +607,10 @@
                                 printk(KERN_WARNING "%s: wrong Channel protocol type passed\n", dev_name);
                                 return;
                         }
+                        break;
 
                 default: 
-                        printk(KERN_WARNING "%s: wrong number of parameter passed\n", dev_name);
+                        printk(KERN_WARNING "ctc: wrong number of parameter passed\n");
                         return;
         }
         ctc_adapter[extract_channel_media(dev_name)][extract_channel_id(dev_name)] = tmp; 
@@ -610,6 +652,9 @@
         if (channel_left(m) <=1) 
                 return -ENODEV;
 
+        if (ctc_no_auto == 1 && (ctc_adapter[m][i].devno[READ] == -ENODEV || ctc_adapter[m][i].devno[WRITE] == -ENODEV))
+                return -ENODEV;
+
         dev->priv = kmalloc(sizeof(struct ctc_priv), GFP_KERNEL);
         if (dev->priv == NULL)
                 return -ENOMEM;
@@ -618,6 +663,7 @@
 
         
         for (c = 0; c < 2; c++) {
+
                 privptr->channel[c].devstat = kmalloc(sizeof(devstat_t), GFP_KERNEL);
                 if (privptr->channel[c].devstat == NULL){
                         if (i == WRITE)
@@ -1031,7 +1077,7 @@
                                 skb->mac.raw = skb->data;
                                 skb->dev = dev;
                                 skb->protocol = htons(ETH_P_IP);
-                                skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happend!!! */
+                                skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happened!!! */
                                 netif_rx(skb);
                                 privptr->stats.rx_packets++;
                         } else {
@@ -1150,6 +1196,7 @@
                 privptr->channel[i].dev = dev;
                 
                 privptr->channel[i].flag_a = 0;
+                privptr->channel[i].IO_active = 0;
 
                 privptr->channel[i].ccw[0].cmd_code  = CCW_CMD_PREPARE;
                 privptr->channel[i].ccw[0].flags     = CCW_FLAG_SLI | CCW_FLAG_CC;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)