X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fdc395x.c;fp=drivers%2Fscsi%2Fdc395x.c;h=cbf825263f3b4a89512cf3ea18afc7aa74f92571;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=cca41cf8d3e7cf23fc78cdb41e425c2cc2941767;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index cca41cf8d..cbf825263 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -183,7 +183,7 @@ * cross a page boundy. */ #define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) -#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY) + struct SGentry { u32 address; /* bus! address */ @@ -235,7 +235,6 @@ struct ScsiReqBlk { u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ - void **virt_map; unsigned char *virt_addr; /* Virtual address of current transfer position */ /* @@ -247,6 +246,7 @@ struct ScsiReqBlk { * total_xfer_length in xferred. These values are restored in * pci_unmap_srb_sense. This is the only place xferred is used. */ + unsigned char *virt_addr_req; /* Saved virtual address of the request buffer */ u32 xferred; /* Saved copy of total_xfer_length */ u16 state; @@ -744,7 +744,7 @@ static void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) /* Find cmd in SRB list */ -inline static struct ScsiReqBlk *find_cmd(struct scsi_cmnd *cmd, +static inline struct ScsiReqBlk *find_cmd(struct scsi_cmnd *cmd, struct list_head *head) { struct ScsiReqBlk *i; @@ -977,6 +977,16 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) } } +static inline void pio_trigger(void) +{ + static int feedback_requested; + + if (!feedback_requested) { + feedback_requested = 1; + printk(KERN_WARNING "%s: Please, contact " + "to help improve support for your system.\n", __FILE__); + } +} /* Prepare SRB for being sent to Device DCB w/ command *cmd */ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, @@ -1022,14 +1032,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, reqlen, cmd->request_buffer, cmd->use_sg, srb->sg_count); + srb->virt_addr = page_address(sl->page); for (i = 0; i < srb->sg_count; i++) { - u32 seglen = (u32)sg_dma_len(sl + i); - sgp[i].address = (u32)sg_dma_address(sl + i); + u32 busaddr = (u32)sg_dma_address(&sl[i]); + u32 seglen = (u32)sl[i].length; + sgp[i].address = busaddr; sgp[i].length = seglen; srb->total_xfer_length += seglen; - srb->virt_map[i] = kmap(sl[i].page); } - srb->virt_addr = srb->virt_map[0]; sgp += srb->sg_count - 1; /* @@ -1310,7 +1320,7 @@ static void reset_dev_param(struct AdapterCtlBlk *acb) * @cmd - some command for this host (for fetching hooks) * Returns: SUCCESS (0x2002) on success, else FAILED (0x2003). */ -static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd) +static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) { struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)cmd->device->host->hostdata; @@ -1356,6 +1366,16 @@ static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd) return SUCCESS; } +static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd) +{ + int rc; + + spin_lock_irq(cmd->device->host->host_lock); + rc = __dc395x_eh_bus_reset(cmd); + spin_unlock_irq(cmd->device->host->host_lock); + + return rc; +} /* * abort an errant SCSI command @@ -1966,7 +1986,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) int segment = cmd->use_sg; u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ struct SGentry *psge = srb->segment_x + srb->sg_index; - void **virt = srb->virt_map; dprintkdbg(DBG_0, "sg_update_list: Transfered %i of %i bytes, %i remain\n", @@ -1999,23 +2018,23 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) sg_verify_length(srb); /* we need the corresponding virtual address */ - if (!segment) { + if (!segment || (srb->flag & AUTO_REQSENSE)) { srb->virt_addr += xferred; return; } /* We have to walk the scatterlist to find it */ sg = (struct scatterlist *)cmd->request_buffer; - idx = 0; while (segment--) { unsigned long mask = ~((unsigned long)sg->length - 1) & PAGE_MASK; if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { - srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK); + srb->virt_addr = (page_address(sg->page) + + psge->address - + (psge->address & PAGE_MASK)); return; } ++sg; - ++idx; } dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); @@ -2141,7 +2160,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); } /* - * calculate all the residue data that not yet transfered + * calculate all the residue data that not yet tranfered * SCSI transfer counter + left in SCSI FIFO data * * .....TRM_S1040_SCSI_COUNTER (24bits) @@ -2312,6 +2331,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, CFG2_WIDEFIFO); while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) { u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + pio_trigger(); *(srb->virt_addr)++ = byte; if (debug_enabled(DBG_PIO)) printk(" %02x", byte); @@ -2323,6 +2343,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, /* Read the last byte ... */ if (srb->total_xfer_length > 0) { u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + pio_trigger(); *(srb->virt_addr)++ = byte; srb->total_xfer_length--; if (debug_enabled(DBG_PIO)) @@ -2499,6 +2520,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, if (debug_enabled(DBG_PIO)) printk(" %02x", (unsigned char) *(srb->virt_addr)); + pio_trigger(); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *(srb->virt_addr)++); @@ -3259,7 +3281,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) struct scsi_cmnd *cmd = srb->cmd; enum dma_data_direction dir = cmd->sc_data_direction; if (cmd->use_sg && dir != PCI_DMA_NONE) { - int i; /* unmap DC395x SG list */ dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", srb->sg_bus_addr, SEGMENTX_LEN); @@ -3269,8 +3290,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", cmd->use_sg, cmd->request_buffer); /* unmap the sg segments */ - for (i = 0; i < srb->sg_count; i++) - kunmap(virt_to_page(srb->virt_map[i])); pci_unmap_sg(acb->dev, (struct scatterlist *)cmd->request_buffer, cmd->use_sg, dir); @@ -3300,6 +3319,7 @@ static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address; srb->segment_x[0].length = srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length; + srb->virt_addr = srb->virt_addr_req; } @@ -3317,7 +3337,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (cmd->use_sg) { struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; - ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset); + ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); } else { ptr = (struct ScsiInqData *)(cmd->request_buffer); } @@ -3693,6 +3713,8 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, srb->xferred = srb->total_xfer_length; /* srb->segment_x : a one entry of S/G list table */ srb->total_xfer_length = sizeof(cmd->sense_buffer); + srb->virt_addr_req = srb->virt_addr; + srb->virt_addr = cmd->sense_buffer; srb->segment_x[0].length = sizeof(cmd->sense_buffer); /* Map sense buffer */ srb->segment_x[0].address = @@ -4253,8 +4275,6 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) kfree(acb->srb_array[i].segment_x); - - vfree(acb->srb_array[0].virt_map); } @@ -4270,12 +4290,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) int srb_idx = 0; unsigned i = 0; struct SGentry *ptr; - void **virt_array; - for (i = 0; i < DC395x_MAX_SRB_CNT; i++) { + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) acb->srb_array[i].segment_x = NULL; - acb->srb_array[i].virt_map = NULL; - } dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); while (pages--) { @@ -4296,19 +4313,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) ptr + (i * DC395x_MAX_SG_LISTENTRY); else dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); - - virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*)); - - if (!virt_array) { - adapter_sg_tables_free(acb); - return 1; - } - - for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) { - acb->srb_array[i].virt_map = virt_array; - virt_array += DC395x_MAX_SG_LISTENTRY; - } - return 0; }