Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / s390 / scsi / zfcp_qdio.c
index ca238c0..dbd9f48 100644 (file)
@@ -1,17 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_qdio.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * QDIO related routines
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *      Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *      Wolfgang Taphorn
- *      Heiko Carstens <heiko.carstens@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * 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
@@ -28,8 +19,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_QDIO_C_REVISION "$Revision: 1.18 $"
-
 #include "zfcp_ext.h"
 
 static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
@@ -53,8 +42,7 @@ static inline int zfcp_qdio_sbals_from_buffer
 static qdio_handler_t zfcp_qdio_request_handler;
 static qdio_handler_t zfcp_qdio_response_handler;
 static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
-                                        unsigned int,
-                                        unsigned int, unsigned int);
+       unsigned int, unsigned int, unsigned int, int, int);
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_QDIO
 
@@ -180,7 +168,8 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter)
 
        init_data->cdev = adapter->ccw_device;
        init_data->q_format = QDIO_SCSI_QFMT;
-       memcpy(init_data->adapter_name, &adapter->name, 8);
+       memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8);
+       ASCEBC(init_data->adapter_name, 8);
        init_data->qib_param_field_format = 0;
        init_data->qib_param_field = NULL;
        init_data->input_slib_elements = NULL;
@@ -213,70 +202,23 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter)
  *
  */
 static inline int
-zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
-                             unsigned int status,
-                             unsigned int qdio_error, unsigned int siga_error)
+zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
+                             unsigned int qdio_error, unsigned int siga_error,
+                             int first_element, int elements_processed)
 {
        int retval = 0;
 
-       if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE)) {
-               if (status & QDIO_STATUS_INBOUND_INT) {
-                       ZFCP_LOG_TRACE("status is"
-                                      " QDIO_STATUS_INBOUND_INT \n");
-               }
-               if (status & QDIO_STATUS_OUTBOUND_INT) {
-                       ZFCP_LOG_TRACE("status is"
-                                      " QDIO_STATUS_OUTBOUND_INT \n");
-               }
-       }                       // if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE))
        if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
                retval = -EIO;
 
-               ZFCP_LOG_FLAGS(1, "QDIO_STATUS_LOOK_FOR_ERROR \n");
-
                ZFCP_LOG_INFO("QDIO problem occurred (status=0x%x, "
                              "qdio_error=0x%x, siga_error=0x%x)\n",
                              status, qdio_error, siga_error);
 
-               if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
-                       ZFCP_LOG_FLAGS(2,
-                                      "QDIO_STATUS_ACTIVATE_CHECK_CONDITION\n");
-               }
-               if (status & QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR) {
-                       ZFCP_LOG_FLAGS(2,
-                                      "QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR\n");
-               }
-               if (status & QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR) {
-                       ZFCP_LOG_FLAGS(2,
-                                      "QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR\n");
-               }
-
-               if (siga_error & QDIO_SIGA_ERROR_ACCESS_EXCEPTION) {
-                       ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_ACCESS_EXCEPTION\n");
-               }
-
-               if (siga_error & QDIO_SIGA_ERROR_B_BIT_SET) {
-                       ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_B_BIT_SET\n");
-               }
-
-               switch (qdio_error) {
-               case 0:
-                       ZFCP_LOG_FLAGS(3, "QDIO_OK");
-                       break;
-               case SLSB_P_INPUT_ERROR:
-                       ZFCP_LOG_FLAGS(1, "SLSB_P_INPUT_ERROR\n");
-                       break;
-               case SLSB_P_OUTPUT_ERROR:
-                       ZFCP_LOG_FLAGS(1, "SLSB_P_OUTPUT_ERROR\n");
-                       break;
-               default:
-                       ZFCP_LOG_NORMAL("bug: unknown QDIO error 0x%x\n",
-                                       qdio_error);
-                       break;
-               }
-               /* Restarting IO on the failed adapter from scratch */
-               debug_text_event(adapter->erp_dbf, 1, "qdio_err");
+               zfcp_hba_dbf_event_qdio(adapter, status, qdio_error, siga_error,
+                               first_element, elements_processed);
                /*
+                       * Restarting IO on the failed adapter from scratch.
                 * Since we have been using this adapter, it is save to assume
                 * that it is not failed but recoverable. The card seems to
                 * report link-up events by self-initiated queue shutdown.
@@ -319,7 +261,8 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
                       first_element, elements_processed);
 
        if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
-                                                  siga_error)))
+                                                  siga_error, first_element,
+                                                  elements_processed)))
                goto out;
        /*
         * we stored address of struct zfcp_adapter  data structure
@@ -339,6 +282,37 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
        return;
 }
 
+/**
+ * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status
+ */
+static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, 
+                                unsigned long req_id)
+{
+       struct zfcp_fsf_req *fsf_req;
+       unsigned long flags;
+
+       debug_long_event(adapter->erp_dbf, 4, req_id);
+
+       spin_lock_irqsave(&adapter->req_list_lock, flags);
+       fsf_req = zfcp_reqlist_ismember(adapter, req_id);
+
+       if (!fsf_req) {
+               spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+               ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id);
+               zfcp_erp_adapter_reopen(adapter, 0);
+               return -EINVAL;
+       }
+
+       zfcp_reqlist_remove(adapter, req_id);
+       atomic_dec(&adapter->reqs_active);
+       spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+       /* finish the FSF request */
+       zfcp_fsf_req_complete(fsf_req);
+
+       return 0;
+}
+
 /*
  * function:           zfcp_qdio_response_handler
  *
@@ -371,7 +345,8 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
        queue = &adapter->response_queue;
 
        if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
-                                                  siga_error)))
+                                                  siga_error, first_element,
+                                                  elements_processed)))
                goto out;
 
        /*
@@ -400,7 +375,7 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
                        /* look for QDIO request identifiers in SB */
                        buffere = &buffer->element[buffere_index];
                        retval = zfcp_qdio_reqid_check(adapter,
-                                                      (void *) buffere->addr);
+                                       (unsigned long) buffere->addr);
 
                        if (retval) {
                                ZFCP_LOG_NORMAL("bug: unexpected inbound "
@@ -471,51 +446,6 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
        return;
 }
 
-/*
- * function:   zfcp_qdio_reqid_check
- *
- * purpose:    checks for valid reqids or unsolicited status
- *
- * returns:    0 - valid request id or unsolicited status
- *             !0 - otherwise
- */
-int
-zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
-{
-       struct zfcp_fsf_req *fsf_req;
-       int retval = 0;
-
-       /* invalid (per convention used in this driver) */
-       if (unlikely(!sbale_addr)) {
-               ZFCP_LOG_NORMAL("bug: invalid reqid\n");
-               retval = -EINVAL;
-               goto out;
-       }
-
-       /* valid request id and thus (hopefully :) valid fsf_req address */
-       fsf_req = (struct zfcp_fsf_req *) sbale_addr;
-
-       if (unlikely(adapter != fsf_req->adapter)) {
-               ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
-                               "fsf_req->adapter=%p, adapter=%p)\n",
-                               fsf_req, fsf_req->adapter, adapter);
-               retval = -EINVAL;
-               goto out;
-       }
-
-       ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
-       if (likely(fsf_req->qtcb)) {
-               ZFCP_LOG_TRACE("hex dump of QTCB:\n");
-               ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
-                             sizeof(struct fsf_qtcb));
-       }
-
-       /* finish the FSF request */
-       zfcp_fsf_req_complete(fsf_req);
- out:
-       return retval;
-}
-
 /**
  * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue
  * @queue: queue from which SBALE should be returned
@@ -682,12 +612,6 @@ zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
        sbale = zfcp_qdio_sbale_curr(fsf_req);
        sbale->addr = addr;
        sbale->length = length;
-
-#ifdef ZFCP_STAT_REQSIZES
-        if (sbtype == SBAL_FLAGS0_TYPE_READ)
-                zfcp_statistics_inc(&zfcp_data.read_sg_head, length);
-        else    zfcp_statistics_inc(&zfcp_data.write_sg_head, length);
-#endif
 }
 
 /**
@@ -770,18 +694,7 @@ zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
        /* assume that no other SBALEs are to follow in the same SBAL */
        sbale = zfcp_qdio_sbale_curr(fsf_req);
        sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
-
 out:
-#ifdef ZFCP_STAT_REQSIZES
-       if (sbtype == SBAL_FLAGS0_TYPE_READ) {
-               zfcp_statistics_inc(&zfcp_data.read_sguse_head, sg_count);
-               zfcp_statistics_inc(&zfcp_data.read_req_head, bytes);
-       } else  {
-               zfcp_statistics_inc(&zfcp_data.write_sguse_head, sg_count);
-               zfcp_statistics_inc(&zfcp_data.write_req_head, bytes);
-       }
-#endif
-
        return bytes;
 }