* 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)
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];
}
}
-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 |
}
}
-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);
}
* 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);
}
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);
}
}
-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;
}
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");
}
/*
* @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);
}
* @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);
% 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);
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)
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;
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;
}
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 */
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;
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;
}
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;
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);
}
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);
}
*/
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]);
}
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;
}