Commit 576d6618 authored by James Bottomley's avatar James Bottomley

Make ncr53c8xx respect clustering

From: Joel Soete <soete.joel@tiscali.be>

This patch makes the ncr driver capable of accepting segments which
are larger than the block size.  It has been tested against IOMMU
merging on parisc.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent a7ed0dc0
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
*/ */
/* Name and version of the driver */ /* Name and version of the driver */
#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3e" #define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3f"
#define SCSI_NCR_DEBUG_FLAGS (0) #define SCSI_NCR_DEBUG_FLAGS (0)
...@@ -839,7 +839,7 @@ struct dsb { ...@@ -839,7 +839,7 @@ struct dsb {
struct scr_tblmove smsg ; struct scr_tblmove smsg ;
struct scr_tblmove cmd ; struct scr_tblmove cmd ;
struct scr_tblmove sense ; struct scr_tblmove sense ;
struct scr_tblmove data [MAX_SCATTER]; struct scr_tblmove data[MAX_SCATTER];
}; };
...@@ -3845,7 +3845,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) ...@@ -3845,7 +3845,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
direction = scsi_data_direction(cmd); direction = scsi_data_direction(cmd);
if (direction != SCSI_DATA_NONE) { if (direction != SCSI_DATA_NONE) {
segments = ncr_scatter (np, cp, cp->cmd); segments = ncr_scatter(np, cp, cp->cmd);
if (segments < 0) { if (segments < 0) {
ncr_free_ccb(np, cp); ncr_free_ccb(np, cp);
return(DID_ERROR); return(DID_ERROR);
...@@ -7575,44 +7575,57 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char * ...@@ -7575,44 +7575,57 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char *
** sizes to the data segment array. ** sizes to the data segment array.
*/ */
static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
{
struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1];
int segment;
cp->data_len = cmd->request_bufflen;
if (cmd->request_bufflen) {
dma_addr_t baddr = map_scsi_single_data(np, cmd);
if (baddr) {
ncr_build_sge(np, data, baddr, cmd->request_bufflen);
segment = 1;
} else {
segment = -2;
}
} else {
segment = 0;
}
return segment;
}
static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
{ {
struct scr_tblmove *data;
int segment = 0; int segment = 0;
int use_sg = (int) cmd->use_sg; int use_sg = (int) cmd->use_sg;
data = cp->phys.data;
cp->data_len = 0; cp->data_len = 0;
if (!use_sg) { if (!use_sg)
if (cmd->request_bufflen) { segment = ncr_scatter_no_sglist(np, cp, cmd);
u_long baddr = map_scsi_single_data(np, cmd); else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
struct scr_tblmove *data;
data = &data[MAX_SCATTER - 1]; if (use_sg > MAX_SCATTER) {
data[0].addr = cpu_to_scr(baddr); unmap_scsi_data(np, cmd);
data[0].size = cpu_to_scr(cmd->request_bufflen); return -1;
cp->data_len = cmd->request_bufflen;
segment = 1;
} }
}
else if (use_sg <= MAX_SCATTER) {
struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
use_sg = map_scsi_sg_data(np, cmd); data = &cp->phys.data[MAX_SCATTER - use_sg];
data = &data[MAX_SCATTER - use_sg];
while (segment < use_sg) { for (segment = 0; segment < use_sg; segment++) {
u_long baddr = scsi_sg_dma_address(&scatter[segment]); dma_addr_t baddr = sg_dma_address(&scatter[segment]);
unsigned int len = scsi_sg_dma_len(&scatter[segment]); unsigned int len = sg_dma_len(&scatter[segment]);
data[segment].addr = cpu_to_scr(baddr); ncr_build_sge(np, &data[segment], baddr, len);
data[segment].size = cpu_to_scr(len); cp->data_len += len;
cp->data_len += len;
++segment;
} }
} } else {
else { segment = -2;
return -1;
} }
return segment; return segment;
......
...@@ -48,6 +48,18 @@ typedef u_long vm_offset_t; ...@@ -48,6 +48,18 @@ typedef u_long vm_offset_t;
#include "sym53c8xx_defs.h" #include "sym53c8xx_defs.h"
/*
Build a scatter/gather entry.
see sym53c8xx_2/sym_hipd.h for more detailed sym_build_sge()
implementation ;)
*/
#define ncr_build_sge(np, data, badd, len) \
do { \
(data)->addr = cpu_to_scr(badd); \
(data)->size = cpu_to_scr(len); \
} while (0)
/*========================================================== /*==========================================================
** **
** Structures used by the detection routine to transmit ** Structures used by the detection routine to transmit
......
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