zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2");
}
+static void zfcp_qdio_irq_tasklet(struct tasklet_struct *tasklet)
+{
+ struct zfcp_qdio *qdio = from_tasklet(qdio, tasklet, irq_tasklet);
+ struct ccw_device *cdev = qdio->adapter->ccw_device;
+ unsigned int start, error;
+ int completed;
+
+ /* Check the Response Queue, and kick off the Request Queue tasklet: */
+ completed = qdio_get_next_buffers(cdev, 0, &start, &error);
+ if (completed < 0)
+ return;
+ if (completed > 0)
+ zfcp_qdio_int_resp(cdev, error, 0, start, completed,
+ (unsigned long) qdio);
+
+ if (qdio_start_irq(cdev))
+ /* More work pending: */
+ tasklet_schedule(&qdio->irq_tasklet);
+}
+
+static void zfcp_qdio_poll(struct ccw_device *cdev, unsigned long data)
+{
+ struct zfcp_qdio *qdio = (struct zfcp_qdio *) data;
+
+ tasklet_schedule(&qdio->irq_tasklet);
+}
+
static struct qdio_buffer_element *
zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
{
wake_up(&qdio->req_q_wq);
+ tasklet_disable(&qdio->irq_tasklet);
+ qdio_stop_irq(adapter->ccw_device);
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
/* cleanup used outbound sbals */
init_data.no_output_qs = 1;
init_data.input_handler = zfcp_qdio_int_resp;
init_data.output_handler = zfcp_qdio_int_req;
+ init_data.irq_poll = zfcp_qdio_poll;
init_data.int_parm = (unsigned long) qdio;
init_data.input_sbal_addr_array = input_sbals;
init_data.output_sbal_addr_array = output_sbals;
atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
atomic_or(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
+ /* Enable processing for QDIO interrupts: */
+ tasklet_enable(&qdio->irq_tasklet);
+ /* This results in a qdio_start_irq(): */
+ tasklet_schedule(&qdio->irq_tasklet);
+
zfcp_qdio_shost_update(adapter, qdio);
return 0;
if (!qdio)
return;
+ tasklet_kill(&qdio->irq_tasklet);
+
if (qdio->adapter->ccw_device)
qdio_free(qdio->adapter->ccw_device);
spin_lock_init(&qdio->req_q_lock);
spin_lock_init(&qdio->stat_lock);
+ tasklet_setup(&qdio->irq_tasklet, zfcp_qdio_irq_tasklet);
+ tasklet_disable(&qdio->irq_tasklet);
adapter->qdio = qdio;
return 0;