]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/s390/cio/chsc.c
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb...
[karo-tx-linux.git] / drivers / s390 / cio / chsc.c
index 68e80e2734a4be89763ca466a48621911570bce4..31ceef1beb8b06715090b9459f879997067896dd 100644 (file)
@@ -283,7 +283,7 @@ struct chsc_sei_nt2_area {
        u8  ccdf[PAGE_SIZE - 24 - 56];  /* content-code dependent field */
 } __packed;
 
-#define CHSC_SEI_NT0   0ULL
+#define CHSC_SEI_NT0   (1ULL << 63)
 #define CHSC_SEI_NT2   (1ULL << 61)
 
 struct chsc_sei {
@@ -291,7 +291,8 @@ struct chsc_sei {
        u32 reserved1;
        u64 ntsm;                       /* notification type mask */
        struct chsc_header response;
-       u32 reserved2;
+       u32 :24;
+       u8 nt;
        union {
                struct chsc_sei_nt0_area nt0_area;
                struct chsc_sei_nt2_area nt2_area;
@@ -434,7 +435,6 @@ static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area)
 
 static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
 {
-#ifdef CONFIG_PCI
        switch (sei_area->cc) {
        case 1:
                zpci_event_error(sei_area->ccdf);
@@ -443,11 +443,10 @@ static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
                zpci_event_availability(sei_area->ccdf);
                break;
        default:
-               CIO_CRW_EVENT(2, "chsc: unhandled sei content code %d\n",
+               CIO_CRW_EVENT(2, "chsc: sei nt2 unhandled cc=%d\n",
                              sei_area->cc);
                break;
        }
-#endif
 }
 
 static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
@@ -470,13 +469,19 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
                chsc_process_sei_scm_change(sei_area);
                break;
        default: /* other stuff */
-               CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n",
+               CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n",
                              sei_area->cc);
                break;
        }
+
+       /* Check if we might have lost some information. */
+       if (sei_area->flags & 0x40) {
+               CIO_CRW_EVENT(2, "chsc: event overflow\n");
+               css_schedule_eval_all();
+       }
 }
 
-static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm)
+static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm)
 {
        do {
                memset(sei, 0, sizeof(*sei));
@@ -487,40 +492,37 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm)
                if (chsc(sei))
                        break;
 
-               if (sei->response.code == 0x0001) {
-                       CIO_CRW_EVENT(2, "chsc: sei successful\n");
-
-                       /* Check if we might have lost some information. */
-                       if (sei->u.nt0_area.flags & 0x40) {
-                               CIO_CRW_EVENT(2, "chsc: event overflow\n");
-                               css_schedule_eval_all();
-                       }
-
-                       switch (sei->ntsm) {
-                       case CHSC_SEI_NT0:
-                               chsc_process_sei_nt0(&sei->u.nt0_area);
-                               return 1;
-                       case CHSC_SEI_NT2:
-                               chsc_process_sei_nt2(&sei->u.nt2_area);
-                               return 1;
-                       default:
-                               CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n",
-                                             sei->ntsm);
-                               return 0;
-                       }
-               } else {
+               if (sei->response.code != 0x0001) {
                        CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
                                      sei->response.code);
                        break;
                }
-       } while (sei->u.nt0_area.flags & 0x80);
 
-       return 0;
+               CIO_CRW_EVENT(2, "chsc: sei successful (nt=%d)\n", sei->nt);
+               switch (sei->nt) {
+               case 0:
+                       chsc_process_sei_nt0(&sei->u.nt0_area);
+                       break;
+               case 2:
+                       chsc_process_sei_nt2(&sei->u.nt2_area);
+                       break;
+               default:
+                       CIO_CRW_EVENT(2, "chsc: unhandled nt: %d\n", sei->nt);
+                       break;
+               }
+       } while (sei->u.nt0_area.flags & 0x80);
 }
 
+/*
+ * Handle channel subsystem related CRWs.
+ * Use store event information to find out what's going on.
+ *
+ * Note: Access to sei_page is serialized through machine check handler
+ * thread, so no need for locking.
+ */
 static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 {
-       struct chsc_sei *sei;
+       struct chsc_sei *sei = sei_page;
 
        if (overflow) {
                css_schedule_eval_all();
@@ -530,22 +532,9 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
                      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
                      crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
                      crw0->erc, crw0->rsid);
-       if (!sei_page)
-               return;
-       /* Access to sei_page is serialized through machine check handler
-        * thread, so no need for locking. */
-       sei = sei_page;
 
        CIO_TRACE_EVENT(2, "prcss");
-
-       /*
-        * The ntsm does not allow to select NT0 and NT2 together. We need to
-        * first check for NT2, than additionally for NT0...
-        */
-#ifdef CONFIG_PCI
-       if (!__chsc_process_crw(sei, CHSC_SEI_NT2))
-#endif
-               __chsc_process_crw(sei, CHSC_SEI_NT0);
+       chsc_process_event_information(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2);
 }
 
 void chsc_chp_online(struct chp_id chpid)