Commit e2dc0bba authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley

[PATCH] fix check_region usage in eata_pio

I'd love to rework the init sequence a bit more, but without beeing able
to actually test the driver I'd rather stick to the bulletproof fix.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 587600a0
...@@ -593,14 +593,14 @@ static int get_pio_conf_PIO(u32 base, struct get_conf *buf) ...@@ -593,14 +593,14 @@ static int get_pio_conf_PIO(u32 base, struct get_conf *buf)
int z; int z;
unsigned short *p; unsigned short *p;
if (check_region(base, 9)) if (!request_region(base, 8, "eata_pio"))
return (FALSE); return 0;
memset(buf, 0, sizeof(struct get_conf)); memset(buf, 0, sizeof(struct get_conf));
while (inb(base + HA_RSTATUS) & HA_SBUSY) while (inb(base + HA_RSTATUS) & HA_SBUSY)
if (--loop == 0) if (--loop == 0)
return (FALSE); goto fail;
DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base)); DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base));
eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG);
...@@ -609,30 +609,40 @@ static int get_pio_conf_PIO(u32 base, struct get_conf *buf) ...@@ -609,30 +609,40 @@ static int get_pio_conf_PIO(u32 base, struct get_conf *buf)
for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) { for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) {
while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
if (--loop == 0) if (--loop == 0)
return (FALSE); goto fail;
loop = HZ / 2; loop = HZ / 2;
*p = inw(base + HA_RDATA); *p = inw(base + HA_RDATA);
} }
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ if (inb(base + HA_RSTATUS) & HA_SERROR) {
if (htonl(EATA_SIGNATURE) == buf->signature) { DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during "
DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " "at %#4x EATA Level: %x\n", base, (uint) (buf->version))); "transfer for HBA at %x\n", base));
goto fail;
while (inb(base + HA_RSTATUS) & HA_SDRQ) }
inw(base + HA_RDATA);
if (ALLOW_DMA_BOARDS == FALSE) { if (htonl(EATA_SIGNATURE) != buf->signature)
for (z = 0; z < MAXISA; z++) goto fail;
if (base == ISAbases[z]) {
buf->IRQ = ISAirqs[z]; DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found "
break; "at %#4x EATA Level: %x\n",
} base, (uint) (buf->version)));
while (inb(base + HA_RSTATUS) & HA_SDRQ)
inw(base + HA_RDATA);
if (ALLOW_DMA_BOARDS == FALSE) {
for (z = 0; z < MAXISA; z++)
if (base == ISAbases[z]) {
buf->IRQ = ISAirqs[z];
break;
} }
return (TRUE);
}
} else {
DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " "for HBA at %x\n", base));
} }
return (FALSE);
return 1;
fail:
release_region(base, 8);
return 0;
} }
static void print_pio_config(struct get_conf *gc) static void print_pio_config(struct get_conf *gc)
...@@ -689,23 +699,19 @@ static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * ...@@ -689,23 +699,19 @@ static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template *
if ((buff = get_pio_board_data((uint) base, gc->IRQ, gc->scsi_id[3], cplen = (htonl(gc->cplen) + 1) / 2, cppadlen = (htons(gc->cppadlen) + 1) / 2)) == NULL) { if ((buff = get_pio_board_data((uint) base, gc->IRQ, gc->scsi_id[3], cplen = (htonl(gc->cplen) + 1) / 2, cppadlen = (htons(gc->cppadlen) + 1) / 2)) == NULL) {
printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (unsigned long) base); printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (unsigned long) base);
return (FALSE); return 0;
} }
if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) { if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) {
printk("HBA at %#lx failed while performing self test & setup.\n", (unsigned long) base); printk("HBA at %#lx failed while performing self test & setup.\n", (unsigned long) base);
return (FALSE); return 0;
} }
request_region(base, 8, "eata_pio");
size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz));
sh = scsi_register(tpnt, size); sh = scsi_register(tpnt, size);
if (sh == NULL) { if (sh == NULL)
release_region(base, 8); return 0;
return FALSE;
}
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) { if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) {
...@@ -714,14 +720,12 @@ static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * ...@@ -714,14 +720,12 @@ static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template *
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
} else { } else {
printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ); printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);
release_region(base, 8); return 0;
return (FALSE);
} }
} else { /* More than one HBA on this IRQ */ } else { /* More than one HBA on this IRQ */
if (reg_IRQL[gc->IRQ] == TRUE) { if (reg_IRQL[gc->IRQ] == TRUE) {
printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n"); printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n");
release_region(base, 8); return 0;
return (FALSE);
} else } else
reg_IRQ[gc->IRQ]++; reg_IRQ[gc->IRQ]++;
} }
...@@ -816,12 +820,14 @@ static void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) ...@@ -816,12 +820,14 @@ static void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
int i; int i;
for (i = 0; i < MAXISA; i++) { for (i = 0; i < MAXISA; i++) {
if (ISAbases[i]) { if (!ISAbases[i])
if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE) { continue;
register_pio_HBA(ISAbases[i], buf, tpnt); if (!get_pio_conf_PIO(ISAbases[i], buf))
} continue;
if (!register_pio_HBA(ISAbases[i], buf, tpnt))
release_region(ISAbases[i], 8);
else
ISAbases[i] = 0; ISAbases[i] = 0;
}
} }
return; return;
} }
...@@ -847,12 +853,15 @@ static void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) ...@@ -847,12 +853,15 @@ static void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) { if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) {
DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3)); DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3));
#endif #endif
if (get_pio_conf_PIO(base, buf) == TRUE) { if (get_pio_conf_PIO(base, buf)) {
DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));
if (buf->IRQ) { if (buf->IRQ) {
register_pio_HBA(base, buf, tpnt); if (!register_pio_HBA(base, buf, tpnt))
} else release_region(base, 8);
} else {
printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n"); printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n");
release_region(base, 8);
}
} }
/* Nothing found here so we take it from the list */ /* Nothing found here so we take it from the list */
EISAbases[i] = 0; EISAbases[i] = 0;
...@@ -889,16 +898,21 @@ static void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) ...@@ -889,16 +898,21 @@ static void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
base += 0x10; /* Now, THIS is the real address */ base += 0x10; /* Now, THIS is the real address */
if (base != 0x1f8) { if (base != 0x1f8) {
/* We didn't find it in the primary search */ /* We didn't find it in the primary search */
if (get_pio_conf_PIO(base, buf) == TRUE) { if (get_pio_conf_PIO(base, buf)) {
if (buf->FORCADR) /* If the address is forced */ if (buf->FORCADR) { /* If the address is forced */
release_region(base, 8);
continue; /* we'll find it later */ continue; /* we'll find it later */
}
/* OK. We made it till here, so we can go now /* OK. We made it till here, so we can go now
* and register it. We only have to check and * and register it. We only have to check and
* eventually remove it from the EISA and ISA list * eventually remove it from the EISA and ISA list
*/ */
register_pio_HBA(base, buf, tpnt); if (!register_pio_HBA(base, buf, tpnt)) {
release_region(base, 8);
continue;
}
if (base < 0x1000) { if (base < 0x1000) {
for (x = 0; x < MAXISA; ++x) { for (x = 0; x < MAXISA; ++x) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment