Hi

Here's a fixed patch - thanks to everybody for reviewing and commenting!

However, if it is decided to implement helper functions, as suggested by 
Christoph and others, feel free to drop it. There, probably, was only 1 
user of this card with highmem and he retired his card too:-)

Thanks
Guennadi
---
Guennadi Liakhovetski

Signed-off-by: Guennadi Liakhovetski <[EMAIL PROTECTED]>

diff -u a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
--- a/drivers/scsi/dc395x.c     17 Nov 2004 21:04:51
+++ b/drivers/scsi/dc395x.c     17 Mar 2005 20:18:14
@@ -234,7 +234,8 @@
        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 */
-       unsigned char *virt_addr;       /* Virtual address of current transfer 
position */
+       struct page *page;
+       unsigned int offset;
 
        /*
         * The sense buffer handling function, request_sense, uses
@@ -989,7 +990,8 @@
        srb->sg_count = 0;
        srb->total_xfer_length = 0;
        srb->sg_bus_addr = 0;
-       srb->virt_addr = NULL;
+       srb->page = NULL;
+       srb->offset = 0;
        srb->sg_index = 0;
        srb->adapter_status = 0;
        srb->target_status = 0;
@@ -1020,7 +1022,8 @@
                        reqlen, cmd->request_buffer, cmd->use_sg,
                        srb->sg_count);
 
-               srb->virt_addr = page_address(sl->page);
+               srb->page = sl->page;
+               srb->offset = sl->offset;
                for (i = 0; i < srb->sg_count; i++) {
                        u32 busaddr = (u32)sg_dma_address(&sl[i]);
                        u32 seglen = (u32)sl[i].length;
@@ -1065,7 +1068,8 @@
                        srb->total_xfer_length++;
 
                srb->segment_x[0].length = srb->total_xfer_length;
-               srb->virt_addr = cmd->request_buffer;
+               srb->page = virt_to_page(cmd->request_buffer);
+               srb->offset = (unsigned long)cmd->request_buffer & ~PAGE_MASK;
                dprintkdbg(DBG_0,
                        "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n",
                        srb->total_xfer_length, cmd->request_buffer,
@@ -1984,8 +1988,7 @@
                        psge->length -= xferred;
                        psge->address += xferred;
                        srb->sg_index = idx;
-                       pci_dma_sync_single_for_device(srb->dcb->
-                                           acb->dev,
+                       pci_dma_sync_single_for_device(srb->dcb->acb->dev,
                                            srb->sg_bus_addr,
                                            SEGMENTX_LEN,
                                            PCI_DMA_TODEVICE);
@@ -1995,28 +1998,20 @@
        }
        sg_verify_length(srb);
 
-       /* we need the corresponding virtual address */
-       if (!segment) {
-               srb->virt_addr += xferred;
-               return;
-       }
-
        /* We have to walk the scatterlist to find it */
        sg = (struct scatterlist *)cmd->request_buffer;
        while (segment--) {
                unsigned long mask =
                    ~((unsigned long)sg->length - 1) & PAGE_MASK;
                if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-                       srb->virt_addr = (page_address(sg->page)
-                                          + psge->address -
-                                          (psge->address & PAGE_MASK));
+                       srb->page = sg->page;
+                       srb->offset = psge->address & ~PAGE_MASK;
                        return;
                }
                ++sg;
        }
 
        dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
-       srb->virt_addr = NULL;
 }
 
 
@@ -2138,7 +2133,7 @@
                                DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
                }
                /*
-                * calculate all the residue data that not yet tranfered
+                * calculate all the residue data that not yet transfered
                 * SCSI transfer counter + left in SCSI FIFO data
                 *
                 * .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -2184,15 +2179,10 @@
                            (dcb->sync_period & WIDE_SYNC) ? 2 : 1;
                        sg_update_list(srb, d_left_counter);
                        /* KG: Most ugly hack! Apparently, this works around a 
chip bug */
-                       if ((srb->segment_x[srb->sg_index].length ==
-                            diff && srb->cmd->use_sg)
-                           || ((oldxferred & ~PAGE_MASK) ==
-                               (PAGE_SIZE - diff))
-                           ) {
-                               dprintkl(KERN_INFO, "data_out_phase0: "
-                                       "Work around chip bug (%i)?\n", diff);
-                               d_left_counter =
-                                   srb->total_xfer_length - diff;
+                       if ((srb->segment_x[srb->sg_index].length == diff && 
srb->cmd->use_sg) ||
+                           (oldxferred & ~PAGE_MASK) == PAGE_SIZE - diff) {
+                               dprintkl(KERN_INFO, "data_out_phase0: Work 
around chip bug (%i)?\n", diff);
+                               d_left_counter = srb->total_xfer_length - diff;
                                sg_update_list(srb, d_left_counter);
                                /*srb->total_xfer_length -= diff; */
                                /*srb->virt_addr += diff; */
@@ -2297,19 +2287,18 @@
                    && srb->total_xfer_length <= DC395x_LASTPIO) {
                        /*u32 addr = (srb->segment_x[srb->sg_index].address); */
                        /*sg_update_list (srb, d_left_counter); */
-                       dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to "
-                               "%p for remaining %i bytes:",
-                               DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 
0x1f,
-                               (srb->dcb->sync_period & WIDE_SYNC) ?
-                                   "words" : "bytes",
-                               srb->virt_addr,
-                               srb->total_xfer_length);
+                       char *page_addr, *virt_addr;
+                       unsigned long flags;
                        if (srb->dcb->sync_period & WIDE_SYNC)
                                DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
                                              CFG2_WIDEFIFO);
+                       local_irq_save(flags);
+                       page_addr = kmap_atomic(srb->page, KM_BIO_SRC_IRQ);
+                       virt_addr = page_addr + srb->offset;
+
                        while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 
0x40) {
                                u8 byte = DC395x_read8(acb, 
TRM_S1040_SCSI_FIFO);
-                               *(srb->virt_addr)++ = byte;
+                               *(virt_addr)++ = byte;
                                if (debug_enabled(DBG_PIO))
                                        printk(" %02x", byte);
                                d_left_counter--;
@@ -2320,7 +2309,7 @@
                 /* Read the last byte ... */
                                if (srb->total_xfer_length > 0) {
                                        u8 byte = DC395x_read8(acb, 
TRM_S1040_SCSI_FIFO);
-                                       *(srb->virt_addr)++ = byte;
+                                       *(virt_addr)++ = byte;
                                        srb->total_xfer_length--;
                                        if (debug_enabled(DBG_PIO))
                                                printk(" %02x", byte);
@@ -2328,6 +2317,8 @@
 #endif
                                DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
                        }
+                       kunmap_atomic(page_addr, KM_BIO_SRC_IRQ);
+                       local_irq_restore(flags);
                        /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */
                        /*srb->total_xfer_length = 0; */
                        if (debug_enabled(DBG_PIO))
@@ -2485,22 +2476,25 @@
                                      SCMD_FIFO_IN);
                } else {        /* write */
                        int ln = srb->total_xfer_length;
+                       char *page_addr, *virt_addr;
+                       unsigned long flags;
+
+                       local_irq_save(flags);
+                       page_addr = kmap_atomic(srb->page, KM_BIO_SRC_IRQ);
+                       virt_addr = page_addr + srb->offset;
                        if (srb->dcb->sync_period & WIDE_SYNC)
                                DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
                                     CFG2_WIDEFIFO);
-                       dprintkdbg(DBG_PIO,
-                               "data_io_transfer: PIO %i bytes from %p:",
-                               srb->total_xfer_length, srb->virt_addr);
-
                        while (srb->total_xfer_length) {
                                if (debug_enabled(DBG_PIO))
-                                       printk(" %02x", (unsigned char) 
*(srb->virt_addr));
+                                       printk(" %02x", (unsigned char) 
*virt_addr);
 
                                DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 
-                                    *(srb->virt_addr)++);
-
+                                    *virt_addr++);
                                sg_subtract_one(srb);
                        }
+                       kunmap_atomic(page_addr, KM_BIO_SRC_IRQ);
+                       local_irq_restore(flags);
                        if (srb->dcb->sync_period & WIDE_SYNC) {
                                if (ln % 2) {
                                        DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 
0);
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to