]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/sym53c8xx_2/sym_hipd.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm...
[mv-sheeva.git] / drivers / scsi / sym53c8xx_2 / sym_hipd.c
index ccea7db59f498b0b6708c44ef9a7179937fddbb8..69ad4945c9369467f0d2fa5095741845d8156ac8 100644 (file)
@@ -602,7 +602,7 @@ sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fa
 /*
  *  Set initial io register bits from burst code.
  */
-static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
+static inline void sym_init_burst(struct sym_hcb *np, u_char bc)
 {
        np->rv_ctest4   &= ~0x80;
        np->rv_dmode    &= ~(0x3 << 6);
@@ -1896,6 +1896,15 @@ void sym_start_up(struct Scsi_Host *shost, int reason)
                tp->head.sval = 0;
                tp->head.wval = np->rv_scntl3;
                tp->head.uval = 0;
+               if (tp->lun0p)
+                       tp->lun0p->to_clear = 0;
+               if (tp->lunmp) {
+                       int ln;
+
+                       for (ln = 1; ln < SYM_CONF_MAX_LUN; ln++)
+                               if (tp->lunmp[ln])
+                                       tp->lunmp[ln]->to_clear = 0;
+               }
        }
 
        /*
@@ -4988,7 +4997,7 @@ struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
         */
        if (ln && !tp->lunmp) {
                tp->lunmp = kcalloc(SYM_CONF_MAX_LUN, sizeof(struct sym_lcb *),
-                               GFP_KERNEL);
+                               GFP_ATOMIC);
                if (!tp->lunmp)
                        goto fail;
        }
@@ -5008,6 +5017,7 @@ struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
                tp->lun0p = lp;
                tp->head.lun0_sa = cpu_to_scr(vtobus(lp));
        }
+       tp->nlcb++;
 
        /*
         *  Let the itl task point to error handling.
@@ -5084,6 +5094,43 @@ fail:
        return;
 }
 
+/*
+ *  Lun control block deallocation. Returns the number of valid remaing LCBs
+ *  for the target.
+ */
+int sym_free_lcb(struct sym_hcb *np, u_char tn, u_char ln)
+{
+       struct sym_tcb *tp = &np->target[tn];
+       struct sym_lcb *lp = sym_lp(tp, ln);
+
+       tp->nlcb--;
+
+       if (ln) {
+               if (!tp->nlcb) {
+                       kfree(tp->lunmp);
+                       sym_mfree_dma(tp->luntbl, 256, "LUNTBL");
+                       tp->lunmp = NULL;
+                       tp->luntbl = NULL;
+                       tp->head.luntbl_sa = cpu_to_scr(vtobus(np->badluntbl));
+               } else {
+                       tp->luntbl[ln] = cpu_to_scr(vtobus(&np->badlun_sa));
+                       tp->lunmp[ln] = NULL;
+               }
+       } else {
+               tp->lun0p = NULL;
+               tp->head.lun0_sa = cpu_to_scr(vtobus(&np->badlun_sa));
+       }
+
+       if (lp->itlq_tbl) {
+               sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
+               kfree(lp->cb_tags);
+       }
+
+       sym_mfree_dma(lp, sizeof(*lp), "LCB");
+
+       return tp->nlcb;
+}
+
 /*
  *  Queue a SCSI IO to the controller.
  */