[SCSI] zfcp: Only issue one test link command per port
[safe/jmp/linux-2.6] / drivers / s390 / scsi / zfcp_qdio.c
index 72e3094..e0a2153 100644 (file)
@@ -6,11 +6,11 @@
  * Copyright IBM Corporation 2002, 2008
  */
 
+#define KMSG_COMPONENT "zfcp"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include "zfcp_ext.h"
 
-/* FIXME(tune): free space should be one max. SBAL chain plus what? */
-#define ZFCP_QDIO_PCI_INTERVAL (QDIO_MAX_BUFFERS_PER_Q \
-                               - (FSF_MAX_SBALS_PER_REQ + 4))
 #define QBUFF_PER_PAGE         (PAGE_SIZE / sizeof(struct qdio_buffer))
 
 static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
@@ -28,7 +28,7 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
        return 0;
 }
 
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
 zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
 {
        return &q->sbal[sbal_idx]->element[sbale_idx];
@@ -55,9 +55,9 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter)
        }
 }
 
-static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id)
+static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, char *id)
 {
-       dev_warn(&adapter->ccw_device->dev, "QDIO problem occurred.\n");
+       dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
 
        zfcp_erp_adapter_reopen(adapter,
                                ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
@@ -74,24 +74,40 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
        }
 }
 
-static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int status,
-                             unsigned int qdio_err, unsigned int siga_err,
-                             unsigned int queue_no, int first, int count,
+/* this needs to be called prior to updating the queue fill level */
+static void zfcp_qdio_account(struct zfcp_adapter *adapter)
+{
+       ktime_t now;
+       s64 span;
+       int free, used;
+
+       spin_lock(&adapter->qdio_stat_lock);
+       now = ktime_get();
+       span = ktime_us_delta(now, adapter->req_q_time);
+       free = max(0, atomic_read(&adapter->req_q.count));
+       used = QDIO_MAX_BUFFERS_PER_Q - free;
+       adapter->req_q_util += used * span;
+       adapter->req_q_time = now;
+       spin_unlock(&adapter->qdio_stat_lock);
+}
+
+static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
+                             int queue_no, int first, int count,
                              unsigned long parm)
 {
        struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
        struct zfcp_qdio_queue *queue = &adapter->req_q;
 
-       if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
-               zfcp_hba_dbf_event_qdio(adapter, status, qdio_err, siga_err,
-                                       first, count);
-               zfcp_qdio_handler_error(adapter, 140);
+       if (unlikely(qdio_err)) {
+               zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
+               zfcp_qdio_handler_error(adapter, "qdireq1");
                return;
        }
 
        /* cleanup all SBALs being program-owned now */
        zfcp_qdio_zero_sbals(queue->sbal, first, count);
 
+       zfcp_qdio_account(adapter);
        atomic_add(count, &queue->count);
        wake_up(&adapter->request_wq);
 }
@@ -111,12 +127,13 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
                 * corruption and must stop the machine immediatly.
                 */
                panic("error: unknown request id (%lx) on adapter %s.\n",
-                     req_id, zfcp_get_busid_by_adapter(adapter));
+                     req_id, dev_name(&adapter->ccw_device->dev));
 
        zfcp_reqlist_remove(adapter, fsf_req);
        spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
        fsf_req->sbal_response = sbal_idx;
+       fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
        zfcp_fsf_req_complete(fsf_req);
 }
 
@@ -129,8 +146,7 @@ static void zfcp_qdio_resp_put_back(struct zfcp_adapter *adapter, int processed)
 
        count = atomic_read(&queue->count) + processed;
 
-       retval = do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
-                        0, start, count, NULL);
+       retval = do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, start, count);
 
        if (unlikely(retval)) {
                atomic_set(&queue->count, count);
@@ -142,20 +158,18 @@ static void zfcp_qdio_resp_put_back(struct zfcp_adapter *adapter, int processed)
        }
 }
 
-static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int status,
-                              unsigned int qdio_err, unsigned int siga_err,
-                              unsigned int queue_no, int first, int count,
+static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
+                              int queue_no, int first, int count,
                               unsigned long parm)
 {
        struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
        struct zfcp_qdio_queue *queue = &adapter->resp_q;
-       volatile struct qdio_buffer_element *sbale;
+       struct qdio_buffer_element *sbale;
        int sbal_idx, sbale_idx, sbal_no;
 
-       if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
-               zfcp_hba_dbf_event_qdio(adapter, status, qdio_err, siga_err,
-                                       first, count);
-               zfcp_qdio_handler_error(adapter, 147);
+       if (unlikely(qdio_err)) {
+               zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
+               zfcp_qdio_handler_error(adapter, "qdires1");
                return;
        }
 
@@ -179,8 +193,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int status,
 
                if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
                        dev_warn(&adapter->ccw_device->dev,
-                                "Protocol violation by adapter. "
-                                "Continuing operations.\n");
+                                "A QDIO protocol error occurred, "
+                                "operations continue\n");
        }
 
        /*
@@ -195,8 +209,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int status,
  * @fsf_req: pointer to struct fsf_req
  * Returns: pointer to qdio_buffer_element (SBALE) structure
  */
-volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
 {
        return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0);
 }
@@ -206,8 +219,7 @@ zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
  * @fsf_req: pointer to struct fsf_req
  * Returns: pointer to qdio_buffer_element (SBALE) structure
  */
-volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
 {
        return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last,
                               req->sbale_curr);
@@ -221,10 +233,10 @@ static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
                                        % QDIO_MAX_BUFFERS_PER_Q;
 }
 
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
 zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
-       volatile struct qdio_buffer_element *sbale;
+       struct qdio_buffer_element *sbale;
 
        /* set last entry flag in current SBALE of current SBAL */
        sbale = zfcp_qdio_sbale_curr(fsf_req);
@@ -255,7 +267,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
        return sbale;
 }
 
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
 zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
        if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
@@ -278,7 +290,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
                                unsigned int sbtype, void *start_addr,
                                unsigned int total_length)
 {
-       volatile struct qdio_buffer_element *sbale;
+       struct qdio_buffer_element *sbale;
        unsigned long remaining, length;
        void *addr;
 
@@ -287,6 +299,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
             addr += length, remaining -= length) {
                sbale = zfcp_qdio_sbale_next(fsf_req, sbtype);
                if (!sbale) {
+                       atomic_inc(&fsf_req->adapter->qdio_outb_full);
                        zfcp_qdio_undo_sbals(fsf_req);
                        return -EINVAL;
                }
@@ -312,7 +325,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
 int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                            struct scatterlist *sg, int max_sbals)
 {
-       volatile struct qdio_buffer_element *sbale;
+       struct qdio_buffer_element *sbale;
        int retval, bytes = 0;
 
        /* figure out last allowed SBAL */
@@ -348,21 +361,12 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
        struct zfcp_qdio_queue *req_q = &adapter->req_q;
        int first = fsf_req->sbal_first;
        int count = fsf_req->sbal_number;
-       int retval, pci, pci_batch;
-       volatile struct qdio_buffer_element *sbale;
-
-       /* acknowledgements for transferred buffers */
-       pci_batch = req_q->pci_batch + count;
-       if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) {
-               pci_batch %= ZFCP_QDIO_PCI_INTERVAL;
-               pci = first + count - (pci_batch + 1);
-               pci %= QDIO_MAX_BUFFERS_PER_Q;
-               sbale = zfcp_qdio_sbale(req_q, pci, 0);
-               sbale->flags |= SBAL_FLAGS0_PCI;
-       }
+       int retval;
+       unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
+
+       zfcp_qdio_account(adapter);
 
-       retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first,
-                        count, NULL);
+       retval = do_QDIO(adapter->ccw_device, qdio_flags, 0, first, count);
        if (unlikely(retval)) {
                zfcp_qdio_zero_sbals(req_q->sbal, first, count);
                return retval;
@@ -372,7 +376,6 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
        atomic_sub(count, &req_q->count);
        req_q->first += count;
        req_q->first %= QDIO_MAX_BUFFERS_PER_Q;
-       req_q->pci_batch = pci_batch;
        return 0;
 }
 
@@ -394,16 +397,12 @@ int zfcp_qdio_allocate(struct zfcp_adapter *adapter)
 
        init_data->cdev = adapter->ccw_device;
        init_data->q_format = QDIO_ZFCP_QFMT;
-       memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8);
+       memcpy(init_data->adapter_name, dev_name(&adapter->ccw_device->dev), 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;
        init_data->output_slib_elements = NULL;
-       init_data->min_input_threshold = 1;
-       init_data->max_input_threshold = 5000;
-       init_data->min_output_threshold = 1;
-       init_data->max_output_threshold = 1000;
        init_data->no_input_qs = 1;
        init_data->no_output_qs = 1;
        init_data->input_handler = zfcp_qdio_int_resp;
@@ -427,18 +426,16 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
        struct zfcp_qdio_queue *req_q;
        int first, count;
 
-       if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+       if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return;
 
        /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
        req_q = &adapter->req_q;
-       spin_lock(&req_q->lock);
+       spin_lock_bh(&adapter->req_q_lock);
        atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
-       spin_unlock(&req_q->lock);
+       spin_unlock_bh(&adapter->req_q_lock);
 
-       while (qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR)
-                       == -EINPROGRESS)
-               ssleep(1);
+       qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
 
        /* cleanup used outbound sbals */
        count = atomic_read(&req_q->count);
@@ -449,7 +446,6 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
        }
        req_q->first = 0;
        atomic_set(&req_q->count, 0);
-       req_q->pci_batch = 0;
        adapter->resp_q.first = 0;
        atomic_set(&adapter->resp_q.count, 0);
 }
@@ -461,23 +457,17 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
  */
 int zfcp_qdio_open(struct zfcp_adapter *adapter)
 {
-       volatile struct qdio_buffer_element *sbale;
+       struct qdio_buffer_element *sbale;
        int cc;
 
-       if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+       if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
                return -EIO;
 
-       if (qdio_establish(&adapter->qdio_init_data)) {
-               dev_err(&adapter->ccw_device->dev,
-                        "Establish of QDIO queues failed.\n");
-               return -EIO;
-       }
+       if (qdio_establish(&adapter->qdio_init_data))
+               goto failed_establish;
 
-       if (qdio_activate(adapter->ccw_device, 0)) {
-               dev_err(&adapter->ccw_device->dev,
-                        "Activate of QDIO queues failed.\n");
+       if (qdio_activate(adapter->ccw_device))
                goto failed_qdio;
-       }
 
        for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
                sbale = &(adapter->resp_q.sbal[cc]->element[0]);
@@ -487,23 +477,19 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter)
        }
 
        if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0,
-                    QDIO_MAX_BUFFERS_PER_Q, NULL)) {
-               dev_err(&adapter->ccw_device->dev,
-                        "Init of QDIO response queue failed.\n");
+                    QDIO_MAX_BUFFERS_PER_Q))
                goto failed_qdio;
-       }
 
        /* set index of first avalable SBALS / number of available SBALS */
        adapter->req_q.first = 0;
        atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
-       adapter->req_q.pci_batch = 0;
 
        return 0;
 
 failed_qdio:
-       while (qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR)
-                       == -EINPROGRESS)
-               ssleep(1);
-
+       qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+failed_establish:
+       dev_err(&adapter->ccw_device->dev,
+               "Setting up the QDIO connection to the FCP adapter failed\n");
        return -EIO;
 }