From: Greg Kroah-Hartman Date: Sun, 10 May 2015 12:32:40 +0000 (+0200) Subject: 3.10-stable patches X-Git-Tag: v3.19.8~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=eba451e22e5747a394c3027395f24a5415be9bf2;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: 3w-9xxx-fix-command-completion-race.patch 3w-sas-fix-command-completion-race.patch 3w-xxxx-fix-command-completion-race.patch usb-host-oxu210hp-use-new-usb_resume_timeout.patch --- diff --git a/queue-3.10/3w-9xxx-fix-command-completion-race.patch b/queue-3.10/3w-9xxx-fix-command-completion-race.patch new file mode 100644 index 00000000000..82dabd96191 --- /dev/null +++ b/queue-3.10/3w-9xxx-fix-command-completion-race.patch @@ -0,0 +1,157 @@ +From 118c855b5623f3e2e6204f02623d88c09e0c34de Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 23 Apr 2015 09:48:51 +0200 +Subject: 3w-9xxx: fix command completion race + +From: Christoph Hellwig + +commit 118c855b5623f3e2e6204f02623d88c09e0c34de upstream. + +The 3w-9xxx driver needs to tear down the dma mappings before returning +the command to the midlayer, as there is no guarantee the sglist and +count are valid after that point. Also remove the dma mapping helpers +which have another inherent race due to the request_id index. + +Signed-off-by: Christoph Hellwig +Acked-by: Adam Radford +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/3w-9xxx.c | 57 +++++++++++-------------------------------------- + drivers/scsi/3w-9xxx.h | 5 ---- + 2 files changed, 13 insertions(+), 49 deletions(-) + +--- a/drivers/scsi/3w-9xxx.c ++++ b/drivers/scsi/3w-9xxx.c +@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_ + static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); + static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); + static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); +-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id); + + /* Functions */ + +@@ -1352,11 +1351,11 @@ static irqreturn_t twa_interrupt(int irq + } + + /* Now complete the io */ ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- twa_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for valid status after each drain */ +@@ -1414,26 +1413,6 @@ static void twa_load_sgl(TW_Device_Exten + } + } /* End twa_load_sgl() */ + +-/* This function will perform a pci-dma mapping for a scatter gather list */ +-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- int use_sg; +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- use_sg = scsi_dma_map(cmd); +- if (!use_sg) +- return 0; +- else if (use_sg < 0) { +- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End twa_map_scsi_sg_data() */ +- + /* This function will poll for a response interrupt of a request */ + static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) + { +@@ -1612,9 +1591,11 @@ static int twa_reset_device_extension(TW + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { + if (tw_dev->srb[i]) { +- tw_dev->srb[i]->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- twa_unmap_scsi_data(tw_dev, i); ++ struct scsi_cmnd *cmd = tw_dev->srb[i]; ++ ++ cmd->result = (DID_RESET << 16); ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + } + } + } +@@ -1793,21 +1774,18 @@ static int twa_scsi_queue_lck(struct scs + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + switch (retval) { + case SCSI_MLQUEUE_HOST_BUSY: ++ scsi_dma_unmap(SCpnt); + twa_free_request_id(tw_dev, request_id); +- twa_unmap_scsi_data(tw_dev, request_id); + break; + case 1: +- tw_dev->state[request_id] = TW_S_COMPLETED; +- twa_free_request_id(tw_dev, request_id); +- twa_unmap_scsi_data(tw_dev, request_id); + SCpnt->result = (DID_ERROR << 16); ++ scsi_dma_unmap(SCpnt); + done(SCpnt); ++ tw_dev->state[request_id] = TW_S_COMPLETED; ++ twa_free_request_id(tw_dev, request_id); + retval = 0; + } + out: +@@ -1875,8 +1853,8 @@ static int twa_scsiop_execute_scsi(TW_De + command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); + command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); + } else { +- sg_count = twa_map_scsi_sg_data(tw_dev, request_id); +- if (sg_count == 0) ++ sg_count = scsi_dma_map(srb); ++ if (sg_count < 0) + goto out; + + scsi_for_each_sg(srb, sg, sg_count, i) { +@@ -1991,15 +1969,6 @@ static char *twa_string_lookup(twa_messa + return(table[index].text); + } /* End twa_string_lookup() */ + +-/* This function will perform a pci-dma unmap */ +-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End twa_unmap_scsi_data() */ +- + /* This function gets called when a disk is coming on-line */ + static int twa_slave_configure(struct scsi_device *sdev) + { +--- a/drivers/scsi/3w-9xxx.h ++++ b/drivers/scsi/3w-9xxx.h +@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[ + #define TW_CURRENT_DRIVER_BUILD 0 + #define TW_CURRENT_DRIVER_BRANCH 0 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SINGLE 1 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_9550SX_DRAIN_COMPLETED 0xFFFF + #define TW_SECTOR_SIZE 512 diff --git a/queue-3.10/3w-sas-fix-command-completion-race.patch b/queue-3.10/3w-sas-fix-command-completion-race.patch new file mode 100644 index 00000000000..eb92dc3e485 --- /dev/null +++ b/queue-3.10/3w-sas-fix-command-completion-race.patch @@ -0,0 +1,136 @@ +From 579d69bc1fd56d5af5761969aa529d1d1c188300 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 23 Apr 2015 09:48:49 +0200 +Subject: 3w-sas: fix command completion race + +From: Christoph Hellwig + +commit 579d69bc1fd56d5af5761969aa529d1d1c188300 upstream. + +The 3w-sas driver needs to tear down the dma mappings before returning +the command to the midlayer, as there is no guarantee the sglist and +count are valid after that point. Also remove the dma mapping helpers +which have another inherent race due to the request_id index. + +Signed-off-by: Christoph Hellwig +Reported-by: Torsten Luettgert +Tested-by: Bernd Kardatzki +Acked-by: Adam Radford +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/3w-sas.c | 50 ++++++++++---------------------------------------- + drivers/scsi/3w-sas.h | 4 ---- + 2 files changed, 10 insertions(+), 44 deletions(-) + +--- a/drivers/scsi/3w-sas.c ++++ b/drivers/scsi/3w-sas.c +@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_De + return 0; + } /* End twl_post_command_packet() */ + +-/* This function will perform a pci-dma mapping for a scatter gather list */ +-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- int use_sg; +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- use_sg = scsi_dma_map(cmd); +- if (!use_sg) +- return 0; +- else if (use_sg < 0) { +- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End twl_map_scsi_sg_data() */ +- + /* This function hands scsi cdb's to the firmware */ + static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg) + { +@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_De + if (!sglistarg) { + /* Map sglist from scsi layer to cmd packet */ + if (scsi_sg_count(srb)) { +- sg_count = twl_map_scsi_sg_data(tw_dev, request_id); +- if (sg_count == 0) ++ sg_count = scsi_dma_map(srb); ++ if (sg_count <= 0) + goto out; + + scsi_for_each_sg(srb, sg, sg_count, i) { +@@ -1116,15 +1096,6 @@ out: + return retval; + } /* End twl_initialize_device_extension() */ + +-/* This function will perform a pci-dma unmap */ +-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End twl_unmap_scsi_data() */ +- + /* This function will handle attention interrupts */ + static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev) + { +@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq + } + + /* Now complete the io */ ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twl_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- twl_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for another response interrupt */ +@@ -1414,10 +1385,12 @@ static int twl_reset_device_extension(TW + if ((tw_dev->state[i] != TW_S_FINISHED) && + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { +- if (tw_dev->srb[i]) { +- tw_dev->srb[i]->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- twl_unmap_scsi_data(tw_dev, i); ++ struct scsi_cmnd *cmd = tw_dev->srb[i]; ++ ++ if (cmd) { ++ cmd->result = (DID_RESET << 16); ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + } + } + } +@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scs + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + if (retval) { + tw_dev->state[request_id] = TW_S_COMPLETED; +--- a/drivers/scsi/3w-sas.h ++++ b/drivers/scsi/3w-sas.h +@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] = + #define TW_CURRENT_DRIVER_BUILD 0 + #define TW_CURRENT_DRIVER_BRANCH 0 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_SECTOR_SIZE 512 + #define TW_MAX_UNITS 32 diff --git a/queue-3.10/3w-xxxx-fix-command-completion-race.patch b/queue-3.10/3w-xxxx-fix-command-completion-race.patch new file mode 100644 index 00000000000..48999e249bc --- /dev/null +++ b/queue-3.10/3w-xxxx-fix-command-completion-race.patch @@ -0,0 +1,120 @@ +From 9cd9554615cba14f0877cc9972a6537ad2bdde61 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 23 Apr 2015 09:48:50 +0200 +Subject: 3w-xxxx: fix command completion race + +From: Christoph Hellwig + +commit 9cd9554615cba14f0877cc9972a6537ad2bdde61 upstream. + +The 3w-xxxx driver needs to tear down the dma mappings before returning +the command to the midlayer, as there is no guarantee the sglist and +count are valid after that point. Also remove the dma mapping helpers +which have another inherent race due to the request_id index. + +Signed-off-by: Christoph Hellwig +Acked-by: Adam Radford +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/3w-xxxx.c | 42 ++++++------------------------------------ + drivers/scsi/3w-xxxx.h | 5 ----- + 2 files changed, 6 insertions(+), 41 deletions(-) + +--- a/drivers/scsi/3w-xxxx.c ++++ b/drivers/scsi/3w-xxxx.c +@@ -1283,32 +1283,6 @@ static int tw_initialize_device_extensio + return 0; + } /* End tw_initialize_device_extension() */ + +-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +-{ +- int use_sg; +- +- dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); +- +- use_sg = scsi_dma_map(cmd); +- if (use_sg < 0) { +- printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End tw_map_scsi_sg_data() */ +- +-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +-{ +- dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End tw_unmap_scsi_data() */ +- + /* This function will reset a device extension */ + static int tw_reset_device_extension(TW_Device_Extension *tw_dev) + { +@@ -1331,8 +1305,8 @@ static int tw_reset_device_extension(TW_ + srb = tw_dev->srb[i]; + if (srb != NULL) { + srb->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); ++ scsi_dma_unmap(srb); ++ srb->scsi_done(srb); + } + } + } +@@ -1779,8 +1753,8 @@ static int tw_scsiop_read_write(TW_Devic + command_packet->byte8.io.lba = lba; + command_packet->byte6.block_count = num_sectors; + +- use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); +- if (!use_sg) ++ use_sg = scsi_dma_map(srb); ++ if (use_sg <= 0) + return 1; + + scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) { +@@ -1967,9 +1941,6 @@ static int tw_scsi_queue_lck(struct scsi + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + switch (*command) { + case READ_10: + case READ_6: +@@ -2196,12 +2167,11 @@ static irqreturn_t tw_interrupt(int irq, + + /* Now complete the io */ + if ((error != TW_ISR_DONT_COMPLETE)) { ++ scsi_dma_unmap(tw_dev->srb[request_id]); ++ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- +- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + } + } + +--- a/drivers/scsi/3w-xxxx.h ++++ b/drivers/scsi/3w-xxxx.h +@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] + #define TW_AEN_SMART_FAIL 0x000F + #define TW_AEN_SBUF_FAIL 0x0024 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SINGLE 1 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_ALIGNMENT_6000 64 /* 64 bytes */ + #define TW_ALIGNMENT_7000 4 /* 4 bytes */ diff --git a/queue-3.10/series b/queue-3.10/series index 4d625152f2e..04ca88ae395 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -7,3 +7,7 @@ alsa-hda-fix-mute-led-fixed-mode.patch serial-of-serial-remove-device_type-serial-registration.patch rbd-end-i-o-the-entire-obj_request-on-error.patch ext4-fix-data-corruption-caused-by-unwritten-and-delayed-extents.patch +3w-xxxx-fix-command-completion-race.patch +3w-9xxx-fix-command-completion-race.patch +3w-sas-fix-command-completion-race.patch +usb-host-oxu210hp-use-new-usb_resume_timeout.patch diff --git a/queue-3.10/usb-host-oxu210hp-use-new-usb_resume_timeout.patch b/queue-3.10/usb-host-oxu210hp-use-new-usb_resume_timeout.patch new file mode 100644 index 00000000000..5b471d94241 --- /dev/null +++ b/queue-3.10/usb-host-oxu210hp-use-new-usb_resume_timeout.patch @@ -0,0 +1,37 @@ +From 84c0d178eb9f3a3ae4d63dc97a440266cf17f7f5 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 13 Feb 2015 14:57:54 -0600 +Subject: usb: host: oxu210hp: use new USB_RESUME_TIMEOUT + +From: Felipe Balbi + +commit 84c0d178eb9f3a3ae4d63dc97a440266cf17f7f5 upstream. + +Make sure we're using the new macro, so our +resume signaling will always pass certification. + +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/oxu210hp-hcd.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/oxu210hp-hcd.c ++++ b/drivers/usb/host/oxu210hp-hcd.c +@@ -2497,11 +2497,12 @@ static irqreturn_t oxu210_hcd_irq(struct + || oxu->reset_done[i] != 0) + continue; + +- /* start 20 msec resume signaling from this port, +- * and make khubd collect PORT_STAT_C_SUSPEND to ++ /* start USB_RESUME_TIMEOUT resume signaling from this ++ * port, and make hub_wq collect PORT_STAT_C_SUSPEND to + * stop that signaling. + */ +- oxu->reset_done[i] = jiffies + msecs_to_jiffies(20); ++ oxu->reset_done[i] = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + oxu_dbg(oxu, "port %d remote wakeup\n", i + 1); + mod_timer(&hcd->rh_timer, oxu->reset_done[i]); + }