Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * qdio queue initialization
0004  *
0005  * Copyright IBM Corp. 2008
0006  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
0007  */
0008 #include <linux/kernel.h>
0009 #include <linux/slab.h>
0010 #include <linux/export.h>
0011 #include <linux/io.h>
0012 
0013 #include <asm/ebcdic.h>
0014 #include <asm/qdio.h>
0015 
0016 #include "cio.h"
0017 #include "css.h"
0018 #include "device.h"
0019 #include "ioasm.h"
0020 #include "chsc.h"
0021 #include "qdio.h"
0022 #include "qdio_debug.h"
0023 
0024 #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
0025 
0026 static struct kmem_cache *qdio_q_cache;
0027 
0028 /**
0029  * qdio_free_buffers() - free qdio buffers
0030  * @buf: array of pointers to qdio buffers
0031  * @count: number of qdio buffers to free
0032  */
0033 void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count)
0034 {
0035     int pos;
0036 
0037     for (pos = 0; pos < count; pos += QBUFF_PER_PAGE)
0038         free_page((unsigned long) buf[pos]);
0039 }
0040 EXPORT_SYMBOL_GPL(qdio_free_buffers);
0041 
0042 /**
0043  * qdio_alloc_buffers() - allocate qdio buffers
0044  * @buf: array of pointers to qdio buffers
0045  * @count: number of qdio buffers to allocate
0046  */
0047 int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count)
0048 {
0049     int pos;
0050 
0051     for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) {
0052         buf[pos] = (void *) get_zeroed_page(GFP_KERNEL);
0053         if (!buf[pos]) {
0054             qdio_free_buffers(buf, count);
0055             return -ENOMEM;
0056         }
0057     }
0058     for (pos = 0; pos < count; pos++)
0059         if (pos % QBUFF_PER_PAGE)
0060             buf[pos] = buf[pos - 1] + 1;
0061     return 0;
0062 }
0063 EXPORT_SYMBOL_GPL(qdio_alloc_buffers);
0064 
0065 /**
0066  * qdio_reset_buffers() - reset qdio buffers
0067  * @buf: array of pointers to qdio buffers
0068  * @count: number of qdio buffers that will be zeroed
0069  */
0070 void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count)
0071 {
0072     int pos;
0073 
0074     for (pos = 0; pos < count; pos++)
0075         memset(buf[pos], 0, sizeof(struct qdio_buffer));
0076 }
0077 EXPORT_SYMBOL_GPL(qdio_reset_buffers);
0078 
0079 static void __qdio_free_queues(struct qdio_q **queues, unsigned int count)
0080 {
0081     struct qdio_q *q;
0082     unsigned int i;
0083 
0084     for (i = 0; i < count; i++) {
0085         q = queues[i];
0086         free_page((unsigned long) q->slib);
0087         kmem_cache_free(qdio_q_cache, q);
0088     }
0089 }
0090 
0091 void qdio_free_queues(struct qdio_irq *irq_ptr)
0092 {
0093     __qdio_free_queues(irq_ptr->input_qs, irq_ptr->max_input_qs);
0094     irq_ptr->max_input_qs = 0;
0095 
0096     __qdio_free_queues(irq_ptr->output_qs, irq_ptr->max_output_qs);
0097     irq_ptr->max_output_qs = 0;
0098 }
0099 
0100 static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
0101 {
0102     struct qdio_q *q;
0103     int i;
0104 
0105     for (i = 0; i < nr_queues; i++) {
0106         q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL);
0107         if (!q) {
0108             __qdio_free_queues(irq_ptr_qs, i);
0109             return -ENOMEM;
0110         }
0111 
0112         q->slib = (struct slib *) __get_free_page(GFP_KERNEL);
0113         if (!q->slib) {
0114             kmem_cache_free(qdio_q_cache, q);
0115             __qdio_free_queues(irq_ptr_qs, i);
0116             return -ENOMEM;
0117         }
0118         irq_ptr_qs[i] = q;
0119     }
0120     return 0;
0121 }
0122 
0123 int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs)
0124 {
0125     int rc;
0126 
0127     rc = __qdio_allocate_qs(irq_ptr->input_qs, nr_input_qs);
0128     if (rc)
0129         return rc;
0130 
0131     rc = __qdio_allocate_qs(irq_ptr->output_qs, nr_output_qs);
0132     if (rc) {
0133         __qdio_free_queues(irq_ptr->input_qs, nr_input_qs);
0134         return rc;
0135     }
0136 
0137     irq_ptr->max_input_qs = nr_input_qs;
0138     irq_ptr->max_output_qs = nr_output_qs;
0139     return 0;
0140 }
0141 
0142 static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
0143                   qdio_handler_t *handler, int i)
0144 {
0145     struct slib *slib = q->slib;
0146 
0147     /* queue must be cleared for qdio_establish */
0148     memset(q, 0, sizeof(*q));
0149     memset(slib, 0, PAGE_SIZE);
0150     q->slib = slib;
0151     q->irq_ptr = irq_ptr;
0152     q->mask = 1 << (31 - i);
0153     q->nr = i;
0154     q->handler = handler;
0155 }
0156 
0157 static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
0158                 struct qdio_buffer **sbals_array, int i)
0159 {
0160     struct qdio_q *prev;
0161     int j;
0162 
0163     DBF_HEX(&q, sizeof(void *));
0164     q->sl = (struct sl *)((char *)q->slib + PAGE_SIZE / 2);
0165 
0166     /* fill in sbal */
0167     for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
0168         q->sbal[j] = *sbals_array++;
0169 
0170     /* fill in slib */
0171     if (i > 0) {
0172         prev = (q->is_input_q) ? irq_ptr->input_qs[i - 1]
0173             : irq_ptr->output_qs[i - 1];
0174         prev->slib->nsliba = (unsigned long)q->slib;
0175     }
0176 
0177     q->slib->sla = (unsigned long)q->sl;
0178     q->slib->slsba = (unsigned long)&q->slsb.val[0];
0179 
0180     /* fill in sl */
0181     for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
0182         q->sl->element[j].sbal = virt_to_phys(q->sbal[j]);
0183 }
0184 
0185 static void setup_queues(struct qdio_irq *irq_ptr,
0186              struct qdio_initialize *qdio_init)
0187 {
0188     struct qdio_q *q;
0189     int i;
0190 
0191     for_each_input_queue(irq_ptr, q, i) {
0192         DBF_EVENT("inq:%1d", i);
0193         setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
0194 
0195         q->is_input_q = 1;
0196 
0197         setup_storage_lists(q, irq_ptr,
0198                     qdio_init->input_sbal_addr_array[i], i);
0199     }
0200 
0201     for_each_output_queue(irq_ptr, q, i) {
0202         DBF_EVENT("outq:%1d", i);
0203         setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i);
0204 
0205         q->is_input_q = 0;
0206         setup_storage_lists(q, irq_ptr,
0207                     qdio_init->output_sbal_addr_array[i], i);
0208     }
0209 }
0210 
0211 static void check_and_setup_qebsm(struct qdio_irq *irq_ptr,
0212                   unsigned char qdioac, unsigned long token)
0213 {
0214     if (!(irq_ptr->qib.rflags & QIB_RFLAGS_ENABLE_QEBSM))
0215         goto no_qebsm;
0216     if (!(qdioac & AC1_SC_QEBSM_AVAILABLE) ||
0217         (!(qdioac & AC1_SC_QEBSM_ENABLED)))
0218         goto no_qebsm;
0219 
0220     irq_ptr->sch_token = token;
0221 
0222     DBF_EVENT("V=V:1");
0223     DBF_EVENT("%8lx", irq_ptr->sch_token);
0224     return;
0225 
0226 no_qebsm:
0227     irq_ptr->sch_token = 0;
0228     irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
0229     DBF_EVENT("noV=V");
0230 }
0231 
0232 /*
0233  * If there is a qdio_irq we use the chsc_page and store the information
0234  * in the qdio_irq, otherwise we copy it to the specified structure.
0235  */
0236 int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr,
0237             struct subchannel_id *schid,
0238             struct qdio_ssqd_desc *data)
0239 {
0240     struct chsc_ssqd_area *ssqd;
0241     int rc;
0242 
0243     DBF_EVENT("getssqd:%4x", schid->sch_no);
0244     if (!irq_ptr) {
0245         ssqd = (struct chsc_ssqd_area *)__get_free_page(GFP_KERNEL);
0246         if (!ssqd)
0247             return -ENOMEM;
0248     } else {
0249         ssqd = (struct chsc_ssqd_area *)irq_ptr->chsc_page;
0250     }
0251 
0252     rc = chsc_ssqd(*schid, ssqd);
0253     if (rc)
0254         goto out;
0255 
0256     if (!(ssqd->qdio_ssqd.flags & CHSC_FLAG_QDIO_CAPABILITY) ||
0257         !(ssqd->qdio_ssqd.flags & CHSC_FLAG_VALIDITY) ||
0258         (ssqd->qdio_ssqd.sch != schid->sch_no))
0259         rc = -EINVAL;
0260 
0261     if (!rc)
0262         memcpy(data, &ssqd->qdio_ssqd, sizeof(*data));
0263 
0264 out:
0265     if (!irq_ptr)
0266         free_page((unsigned long)ssqd);
0267 
0268     return rc;
0269 }
0270 
0271 void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr)
0272 {
0273     unsigned char qdioac;
0274     int rc;
0275 
0276     rc = qdio_setup_get_ssqd(irq_ptr, &irq_ptr->schid, &irq_ptr->ssqd_desc);
0277     if (rc) {
0278         DBF_ERROR("%4x ssqd ERR", irq_ptr->schid.sch_no);
0279         DBF_ERROR("rc:%x", rc);
0280         /* all flags set, worst case */
0281         qdioac = AC1_SIGA_INPUT_NEEDED | AC1_SIGA_OUTPUT_NEEDED |
0282              AC1_SIGA_SYNC_NEEDED;
0283     } else
0284         qdioac = irq_ptr->ssqd_desc.qdioac1;
0285 
0286     check_and_setup_qebsm(irq_ptr, qdioac, irq_ptr->ssqd_desc.sch_token);
0287     irq_ptr->qdioac1 = qdioac;
0288     DBF_EVENT("ac 1:%2x 2:%4x", qdioac, irq_ptr->ssqd_desc.qdioac2);
0289     DBF_EVENT("3:%4x qib:%4x", irq_ptr->ssqd_desc.qdioac3, irq_ptr->qib.ac);
0290 }
0291 
0292 static void qdio_fill_qdr_desc(struct qdesfmt0 *desc, struct qdio_q *queue)
0293 {
0294     desc->sliba = virt_to_phys(queue->slib);
0295     desc->sla = virt_to_phys(queue->sl);
0296     desc->slsba = virt_to_phys(&queue->slsb);
0297 
0298     desc->akey = PAGE_DEFAULT_KEY >> 4;
0299     desc->bkey = PAGE_DEFAULT_KEY >> 4;
0300     desc->ckey = PAGE_DEFAULT_KEY >> 4;
0301     desc->dkey = PAGE_DEFAULT_KEY >> 4;
0302 }
0303 
0304 static void setup_qdr(struct qdio_irq *irq_ptr,
0305               struct qdio_initialize *qdio_init)
0306 {
0307     struct qdesfmt0 *desc = &irq_ptr->qdr->qdf0[0];
0308     int i;
0309 
0310     memset(irq_ptr->qdr, 0, sizeof(struct qdr));
0311 
0312     irq_ptr->qdr->qfmt = qdio_init->q_format;
0313     irq_ptr->qdr->ac = qdio_init->qdr_ac;
0314     irq_ptr->qdr->iqdcnt = qdio_init->no_input_qs;
0315     irq_ptr->qdr->oqdcnt = qdio_init->no_output_qs;
0316     irq_ptr->qdr->iqdsz = sizeof(struct qdesfmt0) / 4; /* size in words */
0317     irq_ptr->qdr->oqdsz = sizeof(struct qdesfmt0) / 4;
0318     irq_ptr->qdr->qiba = virt_to_phys(&irq_ptr->qib);
0319     irq_ptr->qdr->qkey = PAGE_DEFAULT_KEY >> 4;
0320 
0321     for (i = 0; i < qdio_init->no_input_qs; i++)
0322         qdio_fill_qdr_desc(desc++, irq_ptr->input_qs[i]);
0323 
0324     for (i = 0; i < qdio_init->no_output_qs; i++)
0325         qdio_fill_qdr_desc(desc++, irq_ptr->output_qs[i]);
0326 }
0327 
0328 static void setup_qib(struct qdio_irq *irq_ptr,
0329               struct qdio_initialize *init_data)
0330 {
0331     memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib));
0332 
0333     irq_ptr->qib.qfmt = init_data->q_format;
0334     irq_ptr->qib.pfmt = init_data->qib_param_field_format;
0335 
0336     irq_ptr->qib.rflags = init_data->qib_rflags;
0337     if (css_general_characteristics.qebsm)
0338         irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM;
0339 
0340     if (init_data->no_input_qs)
0341         irq_ptr->qib.isliba =
0342             (unsigned long)(irq_ptr->input_qs[0]->slib);
0343     if (init_data->no_output_qs)
0344         irq_ptr->qib.osliba =
0345             (unsigned long)(irq_ptr->output_qs[0]->slib);
0346     memcpy(irq_ptr->qib.ebcnam, dev_name(&irq_ptr->cdev->dev), 8);
0347     ASCEBC(irq_ptr->qib.ebcnam, 8);
0348 
0349     if (init_data->qib_param_field)
0350         memcpy(irq_ptr->qib.parm, init_data->qib_param_field,
0351                sizeof(irq_ptr->qib.parm));
0352 }
0353 
0354 void qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
0355 {
0356     struct ccw_device *cdev = irq_ptr->cdev;
0357 
0358     irq_ptr->qdioac1 = 0;
0359     memset(&irq_ptr->ssqd_desc, 0, sizeof(irq_ptr->ssqd_desc));
0360     memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
0361 
0362     irq_ptr->debugfs_dev = NULL;
0363     irq_ptr->sch_token = irq_ptr->perf_stat_enabled = 0;
0364     irq_ptr->state = QDIO_IRQ_STATE_INACTIVE;
0365     irq_ptr->error_handler = init_data->input_handler;
0366 
0367     irq_ptr->int_parm = init_data->int_parm;
0368     irq_ptr->nr_input_qs = init_data->no_input_qs;
0369     irq_ptr->nr_output_qs = init_data->no_output_qs;
0370     ccw_device_get_schid(cdev, &irq_ptr->schid);
0371     setup_queues(irq_ptr, init_data);
0372 
0373     irq_ptr->irq_poll = init_data->irq_poll;
0374     set_bit(QDIO_IRQ_DISABLED, &irq_ptr->poll_state);
0375 
0376     setup_qib(irq_ptr, init_data);
0377 
0378     /* fill input and output descriptors */
0379     setup_qdr(irq_ptr, init_data);
0380 
0381     /* qdr, qib, sls, slsbs, slibs, sbales are filled now */
0382 
0383     /* set our IRQ handler */
0384     spin_lock_irq(get_ccwdev_lock(cdev));
0385     irq_ptr->orig_handler = cdev->handler;
0386     cdev->handler = qdio_int_handler;
0387     spin_unlock_irq(get_ccwdev_lock(cdev));
0388 }
0389 
0390 void qdio_shutdown_irq(struct qdio_irq *irq)
0391 {
0392     struct ccw_device *cdev = irq->cdev;
0393 
0394     /* restore IRQ handler */
0395     spin_lock_irq(get_ccwdev_lock(cdev));
0396     cdev->handler = irq->orig_handler;
0397     cdev->private->intparm = 0;
0398     spin_unlock_irq(get_ccwdev_lock(cdev));
0399 }
0400 
0401 void qdio_print_subchannel_info(struct qdio_irq *irq_ptr)
0402 {
0403     dev_info(&irq_ptr->cdev->dev,
0404          "qdio: %s on SC %x using AI:%d QEBSM:%d PRI:%d TDD:%d SIGA:%s%s%s\n",
0405          (irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" :
0406             ((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"),
0407          irq_ptr->schid.sch_no,
0408          is_thinint_irq(irq_ptr),
0409          (irq_ptr->sch_token) ? 1 : 0,
0410          pci_out_supported(irq_ptr) ? 1 : 0,
0411          css_general_characteristics.aif_tdd,
0412          qdio_need_siga_in(irq_ptr) ? "R" : " ",
0413          qdio_need_siga_out(irq_ptr) ? "W" : " ",
0414          qdio_need_siga_sync(irq_ptr) ? "S" : " ");
0415 }
0416 
0417 int __init qdio_setup_init(void)
0418 {
0419     qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q),
0420                      256, 0, NULL);
0421     if (!qdio_q_cache)
0422         return -ENOMEM;
0423 
0424     /* Check for OSA/FCP thin interrupts (bit 67). */
0425     DBF_EVENT("thinint:%1d",
0426           (css_general_characteristics.aif_osa) ? 1 : 0);
0427 
0428     /* Check for QEBSM support in general (bit 58). */
0429     DBF_EVENT("cssQEBSM:%1d", css_general_characteristics.qebsm);
0430 
0431     return 0;
0432 }
0433 
0434 void qdio_setup_exit(void)
0435 {
0436     kmem_cache_destroy(qdio_q_cache);
0437 }