]> git.hungrycats.org Git - linux/commitdiff
[PATCH] s390: LCS network driver.
authorAndrew Morton <akpm@osdl.org>
Thu, 26 Feb 2004 00:19:23 +0000 (16:19 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 26 Feb 2004 00:19:23 +0000 (16:19 -0800)
From: Martin Schwidefsky <schwidefsky@de.ibm.com>

LCS network driver fixes:
 - Fix ccwgroup behaviour, remove should offline cards still online.
 - Better not write to the debug feature before it is registers.
 - Don't free card structure on offline but on remove.
 - Check for deferred condition code 1 in lcs_irq for halt requests.
 - Call free_netdev only if there is a net device.

drivers/s390/net/lcs.c

index fb6da78eeb5759160e14fe161019ce32a0cc066d..bd9f8cc03d949b74a3bdc5ceecfee15f85af0a0c 100644 (file)
@@ -11,7 +11,7 @@
  *                       Frank Pavlic (pavlic@de.ibm.com) and
  *                       Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.61 $         $Date: 2003/12/02 15:18:50 $
+ *    $Revision: 1.66 $         $Date: 2004/02/19 13:46:01 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -58,7 +58,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.61 $"
+#define VERSION_LCS_C  "$Revision: 1.66 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 
@@ -100,7 +100,7 @@ lcs_register_debug_facility(void)
        debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
        debug_set_level(lcs_dbf_setup, 5);
        debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
-       debug_set_level(lcs_dbf_trace, 3);
+       debug_set_level(lcs_dbf_trace, 5);
        return 0;
 }
 
@@ -141,8 +141,11 @@ lcs_free_channel(struct lcs_channel *channel)
        int cnt;
 
        LCS_DBF_TEXT(3, setup, "ichfree");
-       for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++)
-               kfree(channel->iob[cnt].data);
+       for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) {
+               if (channel->iob[cnt].data != NULL)
+                       kfree(channel->iob[cnt].data);
+               channel->iob[cnt].data = NULL;
+       }
 }
 
 /**
@@ -360,7 +363,8 @@ lcs_cleanup_card(struct lcs_card *card)
                kfree(ipm_list);
        }
 #endif
-       free_netdev(card->dev);
+       if (card->dev != NULL)
+               free_netdev(card->dev);
        /* Cleanup channels. */
        lcs_cleanup_channel(&card->write);
        lcs_cleanup_channel(&card->read);
@@ -672,6 +676,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
        struct lcs_cmd *cmd;
        struct timer_list timer;
        int rc;
+       char buf[16];
 
        cmd = (struct lcs_cmd *) buffer->data;
        cmd->sequence_no = ++card->sequence_no;
@@ -695,6 +700,9 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
        add_timer(&timer);
        wait_event(reply.wait_q, reply.received);
        del_timer(&timer);
+       LCS_DBF_TEXT(5, trace, "sendcmd");
+       sprintf(buf, "rc:%d", reply.rc);
+       LCS_DBF_TEXT(5, trace, buf);
        return reply.rc ? -EIO : 0;
 }
 
@@ -794,7 +802,7 @@ lcs_send_startlan(struct lcs_card *card, __u8 initiator)
        struct lcs_buffer *buffer;
        struct lcs_cmd *cmd;
 
-       LCS_DBF_TEXT(2, trace, "cmdstpln");
+       LCS_DBF_TEXT(2, trace, "cmdstaln");
        buffer = lcs_get_lancmd(card, LCS_STD_CMD_SIZE);
        cmd = (struct lcs_cmd *) buffer->data;
        cmd->cmd_code = LCS_CMD_STARTLAN;
@@ -1042,7 +1050,8 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        LCS_DBF_TEXT(5, trace, dbf_text);
 
        /* How far in the ccw chain have we processed? */
-       if (channel->state != CH_STATE_INIT) {
+       if ((channel->state != CH_STATE_INIT) &&
+           (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
                index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) 
                        - channel->ccws;
                if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) ||
@@ -1066,9 +1075,14 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                /* CCW execution stopped on a suspend bit. */
                channel->state = CH_STATE_SUSPENDED;
 
-       if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC)
+       if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
+               if (irb->scsw.cc != 0) {
+                       ccw_device_halt(channel->ccwdev, (addr_t) channel);
+                       return;
+               }
                /* The channel has been stopped by halt_IO. */
                channel->state = CH_STATE_HALTED;
+       }
 
        /* Do the rest in the tasklet. */
        tasklet_schedule(&channel->irq_tasklet);
@@ -1267,7 +1281,7 @@ lcs_startlan(struct lcs_card *card)
                else
                        rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP);
        } else {
-                for (i = 0; i <= card->max_port_no; i++) {
+                for (i = 0; i <= 16; i++) {
                         card->portno = i;
                         if (card->lan_type != LCS_FRAME_TYPE_AUTO)
                                 rc = lcs_send_startlan(card,
@@ -1291,7 +1305,7 @@ lcs_startlan(struct lcs_card *card)
 static int
 lcs_detect(struct lcs_card *card)
 {
-       int rc;
+       int rc = 0;
 
        LCS_DBF_TEXT(3, setup," lcsdetct");
        /* start/reset card */
@@ -1790,7 +1804,6 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
        if (rc) {
                LCS_DBF_TEXT(3, setup, "errinit");
                PRINT_ERR("LCS card Initialization failed\n");
-               lcs_free_card(card);
                return rc;
        }
 
@@ -1798,7 +1811,6 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
        if (rc) {
                lcs_stopcard(card);
                lcs_cleanup_card(card);
-               lcs_free_card(card);
                return -ENODEV;
        }
        switch (card->lan_type) {
@@ -1859,7 +1871,6 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
        return 0;
 out:
        lcs_cleanup_card(card);
-       lcs_free_card(card);
        return -ENODEV;
 }
 
@@ -1932,9 +1943,9 @@ __init lcs_init_module(void)
 {
        int rc;
 
-       LCS_DBF_TEXT(0, setup, "lcsinit");
        PRINT_INFO("Loading %s\n",version);
        rc = lcs_register_debug_facility();
+       LCS_DBF_TEXT(0, setup, "lcsinit");
        if (rc) {
                PRINT_ERR("Initialization failed\n");
                return rc;