sg_ring: Gentler scsi merge
Subsystems (5)
cover sg_ring: Gentler scsi merge
OK, after wading through many scsi drivers, I decided to change tack and try to provide a transition path. This is in two stages:
1) These two patches. sg_ring used underneath, but if any driver asks for scsi_sglist() they get a 2.6.24-style chained sg. No other patches are necessary.
2) Once all chained-sg-needing scsi drivers change to use cmd->sg (ie. sg_ring) directly, and the chained sg patches can be reverted. scsi_sglist() and scsi_sg_count() then become:
/* You should only use these if you never need chained sgs */
static inline struct scatterlist *scsi_sglist(struct scsi_cmd *cmd)
{
BUG_ON(!list_empty(&cmd->sg->list));
return &cmd->sg->sg[0];
}
static unsigned int scsi_sg_count(struct scsi_cmd *cmd)
{
if (!cmd->sg)
return 0;
BUG_ON(!list_empty(&cmd->sg->list));
return cmd->sg->num;
}Thanks,
Rusty.
PATCH 1/3 scsi: Convert everyone to scsi_sglist and scsi_sg_count
This patch simply converts direct uses of ->use_sg and ->request_buffer to use the wrapper macros. This removes the assumption that the sg list is overloaded on request_buffer, and that there's an explicit use_sg field.
The ->request_buffer assumption is explicit in scsi_debug.c's paranoid checking, so that code had to be shuffled a little.
--- drivers/scsi/NCR5380.c | 6 +++--- drivers/scsi/NCR53C9x.c | 6 +++--- drivers/scsi/aha1542.c | 14 +++++++------- drivers/scsi/atari_NCR5380.c | 2 +- drivers/scsi/atp870u.c | 22 +++++++++++----------- drivers/scsi/eata_pio.c | 6 +++--- drivers/scsi/fd_mcs.c | 6 +++--- drivers/scsi/imm.c | 5 ++--- drivers/scsi/in2000.c | 6 +++--- drivers/scsi/libsrp.c | 12 ++++++------ drivers/scsi/pcmcia/nsp_cs.c | 8 ++++---- drivers/scsi/ppa.c | 4 ++-- drivers/scsi/qlogicpti.c | 12 ++++++------ drivers/scsi/scsi_debug.c | 14 +++++++------- drivers/scsi/seagate.c | 4 ++-- drivers/scsi/sr.c | 6 +++--- drivers/scsi/sun3_NCR5380.c | 6 +++--- drivers/scsi/sun3x_esp.c | 4 ++-- drivers/scsi/wd33c93.c | 6 +++--- 21 files changed, 77 insertions(+), 76 deletions(-)
drivers/scsi/NCR5380.c +3 -3
@@ -295,9 +295,9 @@ static __inline__ void initialize_SCp(Sc* various queues are valid. */ -if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg -1 ; +if (scsi_sg_count (cmd)) { + cmd->SCp.buffer =scsi_sglist (cmd); + cmd->SCp.buffers_residual =scsi_sg_count (cmd) -1 ; cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; }else {
drivers/scsi/NCR53C9x.c +3 -3
@@ -910,7 +910,7 @@ EXPORT_SYMBOL(esp_proc_info);static void esp_get_dmabufs (struct NCR_ESP *esp,Scsi_Cmnd *sp) { -if (sp->use_sg ==0 ) { +if (scsi_sg_count (sp) ==0 ) { sp->SCp.this_residual = sp->request_bufflen; sp->SCp.buffer = (struct scatterlist *) sp->request_buffer; sp->SCp.buffers_residual =0 ;
@@ -920,8 +920,8 @@ static void esp_get_dmabufs(struct NCR_E sp->SCp.ptr = (char *)virt_to_phys (sp->request_buffer); }else { - sp->SCp.buffer = (struct scatterlist *) sp->request_buffer; - sp->SCp.buffers_residual = sp->use_sg -1 ; + sp->SCp.buffer =scsi_sglist (sp->request_buffer); + sp->SCp.buffers_residual =scsi_sg_count (sp) -1 ; sp->SCp.this_residual = sp->SCp.buffer->length;if (esp->dma_mmu_get_scsi_sgl) esp->dma_mmu_get_scsi_sgl (esp, sp);
drivers/scsi/aha1542.c +7 -7
@@ -689,7 +689,7 @@ static int aha1542_queuecommand(Scsi_Cmnmemcpy (ccb[mbo].cdb, cmd, ccb[mbo].cdblen); -if (SCpnt->use_sg) { +if (scsi_sg_count (SCpnt)) {struct scatterlist *sg;struct chain *cptr;#ifdef DEBUG
@@ -704,12 +704,12 @@ static int aha1542_queuecommand(Scsi_CmnHOSTDATA (SCpnt->device->host)->SCint[mbo] =NULL ;return SCSI_MLQUEUE_HOST_BUSY ; } -scsi_for_each_sg (SCpnt, sg, SCpnt->use_sg, i) { -if (sg->length ==0 || SCpnt->use_sg >16 || +scsi_for_each_sg (SCpnt, sg,scsi_sg_count (SCpnt), i) { +if (sg->length ==0 ||scsi_sg_count (SCpnt) >16 || (((int ) sg->offset) &1 ) || (sg->length &1 )) {unsigned char *ptr; -printk (KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n" , SCpnt->use_sg, i); -scsi_for_each_sg (SCpnt, sg, SCpnt->use_sg, i) { +printk (KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n" ,scsi_sg_count (SCpnt), i); +scsi_for_each_sg (SCpnt, sg,scsi_sg_count (SCpnt), i) {printk (KERN_CRIT "%d: %p %d\n" , i,sg_virt (sg), sg->length); };
@@ -721,10 +721,10 @@ static int aha1542_queuecommand(Scsi_Cmn };any2scsi (cptr[i].dataptr,SCSI_SG_PA (sg));if (SCSI_SG_PA (sg) + sg->length -1 >ISA_DMA_THRESHOLD ) -BAD_SG_DMA (SCpnt, sg, SCpnt->use_sg, i); +BAD_SG_DMA (SCpnt, sg,scsi_sg_count (SCpnt), i);any2scsi (cptr[i].datalen, sg->length); }; -any2scsi (ccb[mbo].datalen, SCpnt->use_sg *sizeof (struct chain )); +any2scsi (ccb[mbo].datalen,scsi_sg_count (SCpnt) *sizeof (struct chain ));any2scsi (ccb[mbo].dataptr,SCSI_BUF_PA (cptr));#ifdef DEBUG printk ("cptr %x: " , cptr);
drivers/scsi/atari_NCR5380.c +1 -1
@@ -512,7 +512,7 @@ static inline void initialize_SCp(Scsi_C*/ if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer; + cmd->SCp.buffer =scsi_sglist (cmd->request_buffer); cmd->SCp.buffers_residual = cmd->use_sg -1 ; cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length;
drivers/scsi/atp870u.c +11 -11
@@ -471,10 +471,10 @@ go_42:/* * Complete the command */ -if (workreq->use_sg) { +if (scsi_sg_count (workreq)) {pci_unmap_sg (dev->pdev, - (struct scatterlist *)workreq->request_buffer, - workreq->use_sg, +scsi_sglist (workreq->request_buffer), +scsi_sg_count (workreq), workreq->sc_data_direction); }else if (workreq->request_bufflen && workreq->sc_data_direction !=DMA_NONE ) {
@@ -855,18 +855,18 @@ oktosend:/* * Figure out the transfer size */ -if (workreq->use_sg) { +if (scsi_sg_count (workreq)) {#ifdef ED_DBGP printk ("Using SGL\n" );#endif l =0 ; - sgpnt = (struct scatterlist *) workreq->request_buffer; - sg_count =pci_map_sg (dev->pdev, sgpnt, workreq->use_sg, + sgpnt =scsi_sglist (workreq); + sg_count =pci_map_sg (dev->pdev, sgpnt,scsi_sg_count (workreq), workreq->sc_data_direction); -for (i =0 ; i < workreq->use_sg; i++) { -if (sgpnt[i].length ==0 || workreq->use_sg >ATP870U_SCATTER ) { +for (i =0 ; i <scsi_sg_count (workreq); i++) { +if (sgpnt[i].length ==0 ||scsi_sg_count (workreq) >ATP870U_SCATTER ) {panic ("Foooooooood fight!" ); } l += sgpnt[i].length;
@@ -938,10 +938,10 @@ oktosend:* a linear chain. */ -if (workreq->use_sg) { - sgpnt = (struct scatterlist *) workreq->request_buffer; +if (scsi_sg_count (workreq)) { + sgpnt =scsi_sglist (workreq->request_buffer); i =0 ; -for (j =0 ; j < workreq->use_sg; j++) { +for (j =0 ; j <scsi_sg_count (workreq); j++) { bttl =sg_dma_address (&sgpnt[j]); l=sg_dma_len (&sgpnt[j]);#ifdef ED_DBGP
drivers/scsi/eata_pio.c +3 -3
@@ -402,14 +402,14 @@ static int eata_pio_queue(struct scsi_cm cp->cmd = cmd; cmd->host_scribble = (char *) &hd->ccb[y]; -if (cmd->use_sg ==0 ) { +if (scsi_sg_count (cmd) ==0 ) { cmd->SCp.buffers_residual =1 ; cmd->SCp.ptr = cmd->request_buffer; cmd->SCp.this_residual = cmd->request_bufflen; cmd->SCp.buffer =NULL ; }else { - cmd->SCp.buffer = cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg; + cmd->SCp.buffer =scsi_sglist (cmd); + cmd->SCp.buffers_residual =scsi_sg_count (cmd); cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; }
drivers/scsi/fd_mcs.c +3 -3
@@ -1107,11 +1107,11 @@ static int fd_mcs_queue(Scsi_Cmnd * SCpn/* Initialize static data */ -if (current_SC->use_sg) { - current_SC->SCp.buffer = (struct scatterlist *) current_SC->request_buffer; +if (scsi_sg_count (current_SC)) { + current_SC->SCp.buffer =scsi_sglist (current_SC->request_buffer); current_SC->SCp.ptr =sg_virt (current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - current_SC->SCp.buffers_residual = current_SC->use_sg -1 ; + current_SC->SCp.buffers_residual =scsi_sg_count (current_SC) -1 ; }else { current_SC->SCp.ptr = (char *) current_SC->request_buffer; current_SC->SCp.this_residual = current_SC->request_bufflen;
drivers/scsi/imm.c +2 -3
@@ -837,10 +837,9 @@ static int imm_engine(imm_struct *dev, s/* Phase 4 - Setup scatter/gather buffers */ case 4 : -if (cmd->use_sg) { +if (scsi_sg_count (cmd)) {/* if many buffers are available, start filling the first */ - cmd->SCp.buffer = - (struct scatterlist *) cmd->request_buffer; + cmd->SCp.buffer =scsi_sglist (cmd); cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); }else {
drivers/scsi/in2000.c +3 -3
@@ -369,9 +369,9 @@ static int in2000_queuecommand(Scsi_Cmnd* - SCp.phase records this command's SRCID_ER bit setting */ -if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg -1 ; +if (scsi_sg_count (cmd)) { + cmd->SCp.buffer =scsi_sglist (cmd->request_buffer); + cmd->SCp.buffers_residual =scsi_sg_count (cmd) -1 ; cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; }else {
drivers/scsi/libsrp.c +6 -6
@@ -192,15 +192,15 @@ static int srp_direct_data(struct scsi_cif (dma_map) { iue = (struct iu_entry *) sc->SCp.ptr; - sg = sc->request_buffer; + sg =scsi_sglist (sc);dprintk ("%p %u %u %d\n" , iue, sc->request_bufflen, md->len, sc->use_sg); - nsg =dma_map_sg (iue->target->dev, sg, sc->use_sg, + nsg =dma_map_sg (iue->target->dev, sg,scsi_sg_count (sc),DMA_BIDIRECTIONAL );if (!nsg) { -printk ("fail to map %p %d\n" , iue, sc->use_sg); +printk ("fail to map %p %d\n" , iue,scsi_sg_count (sc));return 0 ; } len =min (sc->request_bufflen, md->len);
@@ -229,7 +229,7 @@ static int srp_indirect_data(struct scsiif (dma_map || ext_desc) { iue = (struct iu_entry *) sc->SCp.ptr; - sg = sc->request_buffer; + sg =scsi_sglist (sc); dprintk("%p %u %u %d %d\n", iue, sc->request_bufflen, id->len,
@@ -268,9 +268,9 @@ static int srp_indirect_data(struct scsi rdma:if (dma_map) { - nsg =dma_map_sg (iue->target->dev, sg, sc->use_sg,DMA_BIDIRECTIONAL ); + nsg =dma_map_sg (iue->target->dev, sg,scsi_sg_count (sc),DMA_BIDIRECTIONAL );if (!nsg) { -eprintk ("fail to map %p %d\n" , iue, sc->use_sg); +eprintk ("fail to map %p %d\n" , iue,scsi_sg_count (sc)); err = -EIO ; goto free_mem; }
drivers/scsi/pcmcia/nsp_cs.c +4 -4
@@ -233,11 +233,11 @@ static int nsp_queuecommand(struct scsi_SCp.buffer : next buffer SCp.buffers_residual : left buffers in list SCp.phase : current state of the command */ -if (SCpnt->use_sg) { - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; +if (scsi_sg_count (SCpnt)) { + SCpnt->SCp.buffer =scsi_sglist (SCpnt); SCpnt->SCp.ptr =BUFFER_ADDR ; SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - SCpnt->SCp.buffers_residual = SCpnt->use_sg -1 ; + SCpnt->SCp.buffers_residual =scsi_sg_count (SCpnt) -1 ; }else { SCpnt->SCp.ptr = (char *) SCpnt->request_buffer; SCpnt->SCp.this_residual = SCpnt->request_bufflen;
@@ -911,7 +911,7 @@ static int nsp_nexus(struct scsi_cmnd *Snsp_index_write (base,SYNCREG , sync->SyncRegister);nsp_index_write (base,ACKWIDTH , sync->AckWidth); -if (SCpnt->use_sg ==0 || +if (scsi_sg_count (SCpnt) ==0 || SCpnt->resid %4 !=0 || SCpnt->resid <=PAGE_SIZE ) { data->TransferMode =MODE_IO8 ;
drivers/scsi/ppa.c +2 -2
@@ -750,9 +750,9 @@ static int ppa_engine(ppa_struct *dev, s cmd->SCp.phase++;case 4 :/* Phase 4 - Setup scatter/gather buffers */ -if (cmd->use_sg) { +if (scsi_sg_count (cmd)) {/* if many buffers are available, start filling the first */ - cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; + cmd->SCp.buffer =scsi_sglist (cmd); cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); }else {
drivers/scsi/qlogicpti.c +6 -6
@@ -871,11 +871,11 @@ static inline int load_cmd(struct scsi_cstruct scatterlist *sg, *s;int i, n; -if (Cmnd->use_sg) { +if (scsi_sg_count (Cmnd)) {int sg_count; - sg = (struct scatterlist *) Cmnd->request_buffer; - sg_count =sbus_map_sg (qpti->sdev, sg, Cmnd->use_sg, Cmnd->sc_data_direction); + sg =scsi_sglist (Cmnd); + sg_count =sbus_map_sg (qpti->sdev, sg,scsi_sg_count (Cmnd), Cmnd->sc_data_direction); ds = cmd->dataseg; cmd->segment_cnt = sg_count;
@@ -1159,10 +1159,10 @@ static struct scsi_cmnd *qlogicpti_intr_else Cmnd->result =DID_ERROR <<16 ; -if (Cmnd->use_sg) { +if (scsi_sg_count (Cmnd)) {sbus_unmap_sg (qpti->sdev, - (struct scatterlist *)Cmnd->request_buffer, - Cmnd->use_sg, +scsi_sglist (Cmnd->request_buffer), +scsi_sg_count (Cmnd), Cmnd->sc_data_direction); }else if (Cmnd->request_bufflen) { sbus_unmap_single(qpti->sdev,
drivers/scsi/scsi_debug.c +7 -7
@@ -605,12 +605,10 @@ static int fill_from_dev_buffer(struct sif (0 == scp->request_bufflen)return 0 ; -if (NULL == scp->request_buffer) -return (DID_ERROR <<16 );if (! ((scp->sc_data_direction ==DMA_BIDIRECTIONAL ) || (scp->sc_data_direction ==DMA_FROM_DEVICE )))return (DID_ERROR <<16 ); -if (0 == scp->use_sg) { +if (0 ==scsi_sg_count (scp)) { req_len = scp->request_bufflen; act_len = (req_len < arr_len) ? req_len : arr_len;memcpy (scp->request_buffer, arr, act_len);
@@ -620,9 +618,11 @@ static int fill_from_dev_buffer(struct s scp->resid = req_len - act_len;return 0 ; } +if (!scsi_sglist (scp)) +return (DID_ERROR <<16 ); active =1 ; req_len = act_len =0 ; -scsi_for_each_sg (scp, sg, scp->use_sg, k) { +scsi_for_each_sg (scp, sg,scsi_sg_count (scp), k) {if (active) { kaddr = (unsigned char *)kmap_atomic (sg_page (sg),KM_USER0 );
@@ -658,12 +658,12 @@ static int fetch_to_dev_buffer(struct scif (0 == scp->request_bufflen)return 0 ; -if (NULL == scp->request_buffer) +if (NULL ==scsi_sglist (scp))return -1 ;if (! ((scp->sc_data_direction ==DMA_BIDIRECTIONAL ) || (scp->sc_data_direction ==DMA_TO_DEVICE )))return -1 ; -if (0 == scp->use_sg) { +if (0 ==scsi_sg_count (scp)) { req_len = scp->request_bufflen; len = (req_len < max_arr_len) ? req_len : max_arr_len;memcpy (arr, scp->request_buffer, len);
@@ -671,7 +671,7 @@ static int fetch_to_dev_buffer(struct sc } sg =scsi_sglist (scp); req_len = fin =0 ; -for (k =0 ; k < scp->use_sg; ++k, sg =sg_next (sg)) { +for (k =0 ; k <scsi_sg_count (scp); ++k, sg =sg_next (sg)) { kaddr = (unsigned char *)kmap_atomic (sg_page (sg),KM_USER0 );if (NULL == kaddr)return -1 ;
drivers/scsi/seagate.c +2 -2
@@ -991,7 +991,7 @@ connect_loop:/* Establish current pointers. Take into account scatter / gather */ -if ((nobuffs = SCint->use_sg)) { +if ((nobuffs =scsi_sg_count (SCint))) {#if (DEBUG &DEBUG_SG ) {int i;
@@ -1004,7 +1004,7 @@ connect_loop: }#endif - buffer = (struct scatterlist *) SCint->request_buffer; + buffer =scsi_sglist (SCint->request_buffer); len = buffer->length; data =sg_virt (buffer); }else {
drivers/scsi/sr.c +3 -3
@@ -366,12 +366,12 @@ static int sr_prep_fn(struct request_que } { -struct scatterlist *sg = SCpnt->request_buffer; +struct scatterlist *sg =scsi_sglist (SCpnt);int i, size =0 ; -for (i =0 ; i < SCpnt->use_sg; i++) +for (i =0 ; i <scsi_sg_count (SCpnt); i++) size += sg[i].length; -if (size != SCpnt->request_bufflen && SCpnt->use_sg) { +if (size != SCpnt->request_bufflen &&scsi_sg_count (SCpnt)) {scmd_printk (KERN_ERR , SCpnt,"mismatch count %d, bytes %d\n" , size, SCpnt->request_bufflen);
drivers/scsi/sun3_NCR5380.c +3 -3
@@ -515,9 +515,9 @@ static __inline__ void initialize_SCp(st* various queues are valid. */ -if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg -1 ; +if (scsi_sg_count (cmd)) { + cmd->SCp.buffer =scsi_sglist (cmd); + cmd->SCp.buffers_residual =scsi_sg_count (cmd) -1 ; cmd->SCp.ptr = (char *)SGADDR (cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length;
drivers/scsi/sun3x_esp.c +2 -2
@@ -346,8 +346,8 @@ static void dma_mmu_release_scsi_one (ststatic void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp,Scsi_Cmnd *sp) { -int sz = sp->use_sg -1 ; -struct scatterlist *sg = (struct scatterlist *)sp->request_buffer; +int sz =scsi_sg_count (sp) -1 ; +struct scatterlist *sg =scsi_sglist (sp);while (sz >=0 ) {dvma_unmap ((char *)sg[sz].dma_address);
drivers/scsi/wd33c93.c +3 -3
@@ -407,9 +407,9 @@ wd33c93_queuecommand(struct scsi_cmnd *c* - SCp.phase records this command's SRCID_ER bit setting */ -if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg -1 ; +if (scsi_sgcount (cmd)) { + cmd->SCp.buffer =scsi_sg_list (cmd); + cmd->SCp.buffers_residual =scsi_sgcount (cmd) -1 ; cmd->SCp.ptr =sg_virt (cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; }else {
PATCH 2/3 usb_storage: usb_stor_bulk_transfer_sg cleanup
usb_stor_bulk_transfer_sg() assumes buf is a scatterlist array if use_sg is non-NULL. Change it to an explicit sg arg, instead, to allow the callers to change to scsi_sglist().
drivers/usb/storage/freecom.c +2 -2
@@ -133,7 +133,7 @@ freecom_readdata (struct scsi_cmnd *srb,/* Now transfer all of our blocks. */ US_DEBUGP ("Start of read\n" ); result =usb_stor_bulk_transfer_sg (us, ipipe, srb->request_buffer, - count, srb->use_sg, &srb->resid); + count,scsi_sglist (srb),scsi_sg_count (srb), &srb->resid);US_DEBUGP ("freecom_readdata done!\n" );if (result >USB_STOR_XFER_SHORT )
@@ -167,7 +167,7 @@ freecom_writedata (struct scsi_cmnd *srb/* Now transfer all of our blocks. */ US_DEBUGP ("Start of write\n" ); result =usb_stor_bulk_transfer_sg (us, opipe, srb->request_buffer, - count, srb->use_sg, &srb->resid); + count,scsi_sglist (srb),scsi_sg_count (srb), &srb->resid);US_DEBUGP ("freecom_writedata done!\n" );if (result >USB_STOR_XFER_SHORT )
drivers/usb/storage/sddr09.c +24 -18
146 lines not on this page · raw message
drivers/usb/storage/shuttle_usbat.c +28 -18
193 lines not on this page · raw message
drivers/usb/storage/transport.c +9 -5
@@ -468,7 +468,8 @@ static int usb_stor_bulk_transfer_sglist* scatter-gather or not, and acts appropriately. */ int usb_stor_bulk_transfer_sg (struct us_data * us,unsigned int pipe, -void *buf,unsigned int length_left,int use_sg,int *residual) +void *buf,unsigned int length_left, +struct scatterlist *sg,int use_sg,int *residual) {int result;unsigned int partial;
@@ -477,7 +478,7 @@ int usb_stor_bulk_transfer_sg(struct us_if (use_sg) {/* use the usb core scatter-gather primitives */ result =usb_stor_bulk_transfer_sglist (us, pipe, - (struct scatterlist *) buf, use_sg, + sg, use_sg, length_left, &partial); length_left -= partial; }else {
@@ -739,7 +740,8 @@ int usb_stor_CBI_transport(struct scsi_c us->recv_bulk_pipe : us->send_bulk_pipe; result =usb_stor_bulk_transfer_sg (us, pipe, srb->request_buffer, transfer_length, - srb->use_sg, &srb->resid); +scsi_sglist (srb),scsi_sg_count (srb), + &srb->resid);US_DEBUGP ("CBI data stage result is 0x%x\n" , result);/* if we stalled the data transfer it means command failed */
@@ -838,7 +840,8 @@ int usb_stor_CB_transport(struct scsi_cm us->recv_bulk_pipe : us->send_bulk_pipe; result =usb_stor_bulk_transfer_sg (us, pipe, srb->request_buffer, transfer_length, - srb->use_sg, &srb->resid); +scsi_sglist (srb),scsi_sg_count (srb), + &srb->resid);US_DEBUGP ("CB data stage result is 0x%x\n" , result);/* if we stalled the data transfer it means command failed */
@@ -957,7 +960,8 @@ int usb_stor_Bulk_transport(struct scsi_ us->recv_bulk_pipe : us->send_bulk_pipe; result =usb_stor_bulk_transfer_sg (us, pipe, srb->request_buffer, transfer_length, - srb->use_sg, &srb->resid); +scsi_sglist (srb),scsi_sg_count (srb), + &srb->resid);US_DEBUGP ("Bulk data transfer result 0x%x\n" , result);if (result ==USB_STOR_XFER_ERROR )return USB_STOR_TRANSPORT_ERROR ;
drivers/usb/storage/transport.h +2 -1
@@ -138,7 +138,8 @@ extern int usb_stor_bulk_transfer_buf(stextern int usb_stor_bulk_transfer_buf (struct us_data *us,unsigned int pipe,void *buf,unsigned int length,unsigned int *act_len);extern int usb_stor_bulk_transfer_sg (struct us_data *us,unsigned int pipe, -void *buf,unsigned int length,int use_sg,int *residual); +void *buf,unsigned int length,struct scatterlist *sg, +int use_sg,int *residual);extern int usb_stor_port_reset (struct us_data *us);#endif
PATCH 3/3 scsi: convert core to sg_ring
A 'struct sg_ring *sg' element is added to struct scsi_cmd, and the use_sg and __use_sg fields are removed. If this field is null, request_buffer point to the data (as was previously indicated by use_sg == 0).
To ease transition, scsi_sglist() is now a backwards-compat routine which chains the sg_ring entries so they can be iterated using sg_next(). Once all the drivers which actually want to use chained sgs are converted to sg_ring, the remaining drivers can revert to using simple sg arrays.
The backwards-compat conversion is placed under an (always-on) config option (CONFIG_SCSI_SG_CHAIN).
--- drivers/scsi/Kconfig | 6 + drivers/scsi/scsi_error.c | 15 +-- drivers/scsi/scsi_lib.c | 219 +++++++++++++++++++++----------------------- drivers/scsi/scsi_lib_dma.c | 27 ++--- drivers/scsi/scsi_tgt_lib.c | 17 +-- include/scsi/scsi_cmnd.h | 38 +++++-- include/scsi/scsi_eh.h | 6 - 7 files changed, 170 insertions(+), 158 deletions(-)
drivers/scsi/Kconfig +6 -0
@@ -29,6 +29,12 @@ config SCSI However, do not compile this as a module if your root file system (the one containing the directory /) is located on a SCSI device. + +config SCSI_SG_CHAIN + bool + default y + ---help--- + Support sg chaining for older SCSI drivers. config SCSI_DMA bool
drivers/scsi/scsi_error.c +8 -7
@@ -617,20 +617,21 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd ses->cmd_len = scmd->cmd_len;memcpy (ses->cmnd, scmd->cmnd,sizeof (scmd->cmnd)); ses->data_direction = scmd->sc_data_direction; + ses->sg = scmd->sg; ses->bufflen = scmd->request_bufflen; ses->buffer = scmd->request_buffer; - ses->use_sg = scmd->use_sg; ses->resid = scmd->resid; ses->result = scmd->result;if (sense_bytes) { scmd->request_bufflen =min_t (unsigned,sizeof (scmd->sense_buffer), sense_bytes); -sg_init_one (&ses->sense_sgl, scmd->sense_buffer, - scmd->request_bufflen); - scmd->request_buffer = &ses->sense_sgl; + +sg_ring_single (&ses->sense_sg.ring, scmd->sense_buffer, + scmd->request_bufflen); + scmd->sg = &ses->sense_sg.ring; + scmd->request_buffer =NULL ; scmd->sc_data_direction =DMA_FROM_DEVICE ; - scmd->use_sg =1 ;memset (scmd->cmnd,0 ,sizeof (scmd->cmnd)); scmd->cmnd[0 ] =REQUEST_SENSE ; scmd->cmnd[4 ] = scmd->request_bufflen;
@@ -639,7 +640,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd scmd->request_buffer =NULL ; scmd->request_bufflen =0 ; scmd->sc_data_direction =DMA_NONE ; - scmd->use_sg =0 ; + scmd->sg =NULL ;if (cmnd) {memset (scmd->cmnd,0 ,sizeof (scmd->cmnd));memcpy (scmd->cmnd, cmnd, cmnd_size);
@@ -678,7 +679,7 @@ void scsi_eh_restore_cmnd(struct scsi_cm scmd->sc_data_direction = ses->data_direction; scmd->request_bufflen = ses->bufflen; scmd->request_buffer = ses->buffer; - scmd->use_sg = ses->use_sg; + scmd->sg = ses->sg; scmd->resid = ses->resid; scmd->result = ses->result; }
drivers/scsi/scsi_lib.c +108 -111
338 lines not on this page · raw message
drivers/scsi/scsi_lib_dma.c +13 -14
@@ -5,6 +5,7 @@#include <linux/blkdev.h> #include <linux/device.h> #include <linux/kernel.h> +#include <linux/sg_ring.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h>
@@ -15,22 +16,21 @@* scsi_dma_map - perform DMA mapping against command's sg lists * @cmd: scsi command * -* Returns the number of sg lists actually used, zero if the sg lists -* is NULL, or -ENOMEM if the mapping failed. +* Returns -ENOMEM if the mapping failed, or the number of elements mapped +* (ie. sg_ring_num(cmd->sg)). */ int scsi_dma_map (struct scsi_cmnd *cmd) { -int nseg =0 ; +if (cmd->sg) { +struct device *dev = cmd->device->host->shost_gendev.parent; +int err; -if (scsi_sg_count (cmd)) { -struct device *dev = cmd->device->host->shost_gendev.parent; - - nseg =dma_map_sg (dev,scsi_sglist (cmd),scsi_sg_count (cmd), - cmd->sc_data_direction); -if (unlikely (!nseg)) -return -ENOMEM ; + err =dma_map_sg_ring (dev, cmd->sg, cmd->sc_data_direction); +if (err) +return err; +return sg_ring_num (cmd->sg); } -return nseg; +return 0 ; }EXPORT_SYMBOL (scsi_dma_map);
@@ -40,11 +40,10 @@ EXPORT_SYMBOL(scsi_dma_map);*/ void scsi_dma_unmap (struct scsi_cmnd *cmd) { -if (scsi_sg_count (cmd)) { +if (cmd->sg) {struct device *dev = cmd->device->host->shost_gendev.parent; -dma_unmap_sg (dev,scsi_sglist (cmd),scsi_sg_count (cmd), - cmd->sc_data_direction); +dma_unmap_sg_ring (dev, cmd->sg, cmd->sc_data_direction); } }EXPORT_SYMBOL (scsi_dma_unmap);
drivers/scsi/scsi_tgt_lib.c +7 -11
@@ -331,8 +331,8 @@ static void scsi_tgt_cmd_done(struct scsscsi_tgt_uspace_send_status (cmd, tcmd->itn_id, tcmd->tag); -if (cmd->request_buffer) -scsi_free_sgtable (cmd); +if (cmd->sg) +scsi_free_sgring (cmd);queue_work (scsi_tgtd, &tcmd->work); }
@@ -356,19 +356,15 @@ static int scsi_tgt_init_cmd(struct scsistatic int scsi_tgt_init_cmd (struct scsi_cmnd *cmd,gfp_t gfp_mask) {struct request *rq = cmd->request; -int count; - cmd->use_sg = rq->nr_phys_segments; - cmd->request_buffer =scsi_alloc_sgtable (cmd, gfp_mask); -if (!cmd->request_buffer) + cmd->sg =scsi_alloc_sgring (cmd, rq->nr_phys_segments, gfp_mask); +if (!cmd->sg)return -ENOMEM ; - + cmd->request_buffer =NULL ; cmd->request_bufflen = rq->data_len; -dprintk ("cmd %p cnt %d %lu\n" , cmd, cmd->use_sg,rq_data_dir (rq)); - count =blk_rq_map_sg (rq->q, rq, cmd->request_buffer); -BUG_ON (count > cmd->use_sg); - cmd->use_sg = count; +dprintk ("cmd %p cnt %d %lu\n" , cmd, rq->nr_phys_segments,rq_data_dir (rq)); +blk_rq_map_sg_ring (rq->q, rq, cmd->request_buffer);return 0 ; }
include/scsi/scsi_cmnd.h +25 -13
@@ -5,7 +5,7 @@#include <linux/list.h> #include <linux/types.h> #include <linux/timer.h> -#include <linux/scatterlist.h> +#include <linux/sg_ring.h> struct request ;struct scatterlist ;
@@ -17,8 +17,12 @@ struct scsi_pointer {struct scsi_pointer {char *ptr;/* data pointer */ int this_residual;/* left in this buffer */ +#ifdef CONFIG_SCSI_SG_CHAIN struct scatterlist *buffer;/* which buffer */ int buffers_residual;/* how many buffers left */ +#endif +struct sg_ring *sg;/* which buffer ring */ +int buffers_offset;/* how many buffers of this sg already used */ dma_addr_t dma_handle;
@@ -66,11 +70,8 @@ struct scsi_cmnd {unsigned request_bufflen;/* Actual request size */ struct timer_list eh_timeout;/* Used to time out the command. */ -void *request_buffer;/* Actual requested buffer */ - -/* These elements define the operation we ultimately want to perform */ -unsigned short use_sg;/* Number of pieces of scatter-gather */ -unsigned short __use_sg; +struct sg_ring *sg;/* if it's a scatter-gather, otherwise... */ +void *request_buffer;/* Actual requested buffer */ unsigned underflow;/* Return error if less than this amount is transferred */
@@ -130,14 +131,28 @@ extern void *scsi_kmap_atomic_sg(struct size_t *offset, size_t *len);extern void scsi_kunmap_atomic_sg (void *virt); -extern struct scatterlist *scsi_alloc_sgtable (struct scsi_cmnd *,gfp_t ); -extern void scsi_free_sgtable (struct scsi_cmnd *); +extern struct sg_ring *scsi_alloc_sgring (struct scsi_cmnd *,unsigned ,gfp_t ); +extern void scsi_free_sgring (struct scsi_cmnd *);extern int scsi_dma_map (struct scsi_cmnd *cmd);extern void scsi_dma_unmap (struct scsi_cmnd *cmd); -#define scsi_sg_count (cmd) ((cmd)->use_sg) -#define scsi_sglist (cmd) ((struct scatterlist *)(cmd)->request_buffer) +#ifdef CONFIG_SCSI_SG_CHAIN +/* Deprecated: use sg_ring_num(cmd->sg) */ +extern int scsi_sg_count (struct scsi_cmnd *cmd); + +/* Deprecated: this routine converts the sg_ring into an sg chain: +* modern drivers should use cmd->sg directly. */ +extern struct scatterlist *scsi_sglist (struct scsi_cmnd *cmd); + +/* Deprecated: the modern way is to use sg_ring_for_each(cmd->sg, +* sgring, i): sgring->sg[i] is the current element. Note that i does +* not always increase (it goes back to 0 when sgring is iterated). */ +#define scsi_for_each_sg (cmd, sg, nseg, __i) \ + for_each_sg(scsi_sglist(cmd), sg, nseg, __i) + +#endif /* CONFIG_SCSI_SG_CHAIN */ +#define scsi_bufflen (cmd) ((cmd)->request_bufflen)static inline void scsi_set_resid (struct scsi_cmnd *cmd,int resid)
@@ -150,7 +165,4 @@ static inline int scsi_get_resid(struct return cmd->resid; } -#define scsi_for_each_sg (cmd, sg, nseg, __i) \ - for_each_sg(scsi_sglist(cmd), sg, nseg, __i) -#endif /* _SCSI_SCSI_CMND_H */
include/scsi/scsi_eh.h +3 -3
@@ -1,7 +1,7 @@#ifndef _SCSI_SCSI_EH_H#define _SCSI_SCSI_EH_H -#include <linux/scatterlist.h> +#include <linux/sg_ring.h> #include <scsi/scsi_cmnd.h> struct scsi_device ;
@@ -75,10 +75,10 @@ struct scsi_eh_save {void *buffer;unsigned bufflen; -unsigned short use_sg; +struct sg_ring *sg;int resid; -struct scatterlist sense_sgl; +DECLARE_SG_RING (sense_sg,1 ); }; extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
Re: [PATCH 1/3] scsi: Convert everyone to scsi_sglist and scsi_sg_count
In reply to Rusty RussellQuoted 21 lines · Rusty Russell
This patch simply converts direct uses of ->use_sg and ->request_buffer to use the wrapper macros. This removes the assumption that the sg list is overloaded on
request_buffer, and that there's an explicituse_sgfield.The ->request_buffer assumption is explicit in scsi_debug.c's paranoid checking, so that code had to be shuffled a little.
Signed-off-by Rusty Russell <[email protected]>--- drivers/scsi/NCR5380.c | 6 +++--- drivers/scsi/NCR53C9x.c | 6 +++--- drivers/scsi/aha1542.c | 14 +++++++------- drivers/scsi/atari_NCR5380.c | 2 +- drivers/scsi/atp870u.c | 22 +++++++++++----------- drivers/scsi/eata_pio.c | 6 +++--- drivers/scsi/fd_mcs.c | 6 +++--- drivers/scsi/imm.c | 5 ++--- drivers/scsi/in2000.c | 6 +++--- drivers/scsi/libsrp.c | 12 ++++++------ drivers/scsi/pcmcia/nsp_cs.c | 8 ++++---- drivers/scsi/ppa.c | 4 ++--
Quoted 9 lines
drivers/scsi/qlogicpti.c | 12 ++++++------ drivers/scsi/scsi_debug.c | 14 +++++++------- drivers/scsi/seagate.c | 4 ++-- drivers/scsi/sr.c | 6 +++--- drivers/scsi/sun3_NCR5380.c | 6 +++--- drivers/scsi/sun3x_esp.c | 4 ++-- drivers/scsi/wd33c93.c | 6 +++--- 21 files changed, 77 insertions(+), 76 deletions(-)
All of these drivers are properly converted in current scsi-misc + scsi-pending. If you are really serious about changing scsi-layer you better work ontop of scsi git trees.
Also you can inspect -mm tree it has the scsi_data_buffer patches that does 4/5 what you want.
Boaz
Re: [PATCH 1/3] scsi: Convert everyone to scsi_sglist and scsi_sg_count
Quoted 1 line · On Thursday 03 January 2008 20:26:13 Boaz Harrosh wrote:
On Thu, Jan 03 2008 at 10:50 +0200, Rusty Russell <[email protected]>
Quoted 8 lines · wrote:
Quoted 4 lines
This patch simply converts direct uses of ->use_sg and ->request_buffer to use the wrapper macros. This removes the assumption that the sg list is overloaded on
request_buffer, and that there's an explicituse_sgfield.All of these drivers are properly converted in current scsi-misc + scsi-pending. If you are really serious about changing scsi-layer you better work ontop of scsi git trees.
Hi Boaz,
Well, I wouldn't say I'm serious about SCSI 8) but I am delighted to see
this being done. Have grabbed scsi-pending from git.kernel.org, thanks for the hint.
Quoted 2 lines
Also you can inspect -mm tree it has the
scsi_data_bufferpatches that does 4/5 what you want.
Remember, these scsi patches are a side-effect of trying to get my own
sg-using code sane. So this is exactly what I *don't* want: another "works for scsi" solution :(
I'll see where we can go from here...
Thanks,
Rusty.
Quoted 26 lines · Rusty Russell
OK, after wading through many scsi drivers, I decided to change tack and try to provide a transition path. This is in two stages:
1) These two patches.
sg_ringused underneath, but if any driver asks forscsi_sglist()they get a 2.6.24-style chained sg. No other patches are necessary.2) Once all chained-sg-needing scsi drivers change to use
cmd->sg(ie.sg_ring) directly, and the chained sg patches can be reverted.scsi_sglist()andscsi_sg_count()then become:/* You should only use these if you never need chained sgs */ static inline struct scatterlist *scsi_sglist(struct scsi_cmd *cmd) { BUG_ON(!list_empty(&cmd->sg->list)); return &cmd->sg->sg[0]; } static unsigned int scsi_sg_count(struct scsi_cmd *cmd) { if (!cmd->sg) return 0; BUG_ON(!list_empty(&cmd->sg->list)); return cmd->sg->num; }
Quoted 2 lines
Thanks,
Rusty.
Look in the mailing list archives for the scsi_sgtable patches. These did exactly what you do here. (OK 95% ;))
(only as a scsi subsystem not as a generic sg)
Boaz