aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c157
1 files changed, 93 insertions, 64 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 701a328f7beb..ede158d08d9d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -286,13 +286,12 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
286 int result; 286 int result;
287 287
288 if (sshdr) { 288 if (sshdr) {
289 sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); 289 sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
290 if (!sense) 290 if (!sense)
291 return DRIVER_ERROR << 24; 291 return DRIVER_ERROR << 24;
292 memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
293 } 292 }
294 result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, 293 result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
295 sense, timeout, retries, 0); 294 sense, timeout, retries, 0);
296 if (sshdr) 295 if (sshdr)
297 scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); 296 scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
298 297
@@ -1812,6 +1811,84 @@ void scsi_exit_queue(void)
1812 kmem_cache_destroy(sgp->slab); 1811 kmem_cache_destroy(sgp->slab);
1813 } 1812 }
1814} 1813}
1814
1815/**
1816 * scsi_mode_select - issue a mode select
1817 * @sdev: SCSI device to be queried
1818 * @pf: Page format bit (1 == standard, 0 == vendor specific)
1819 * @sp: Save page bit (0 == don't save, 1 == save)
1820 * @modepage: mode page being requested
1821 * @buffer: request buffer (may not be smaller than eight bytes)
1822 * @len: length of request buffer.
1823 * @timeout: command timeout
1824 * @retries: number of retries before failing
1825 * @data: returns a structure abstracting the mode header data
1826 * @sense: place to put sense data (or NULL if no sense to be collected).
1827 * must be SCSI_SENSE_BUFFERSIZE big.
1828 *
1829 * Returns zero if successful; negative error number or scsi
1830 * status on error
1831 *
1832 */
1833int
1834scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage,
1835 unsigned char *buffer, int len, int timeout, int retries,
1836 struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)
1837{
1838 unsigned char cmd[10];
1839 unsigned char *real_buffer;
1840 int ret;
1841
1842 memset(cmd, 0, sizeof(cmd));
1843 cmd[1] = (pf ? 0x10 : 0) | (sp ? 0x01 : 0);
1844
1845 if (sdev->use_10_for_ms) {
1846 if (len > 65535)
1847 return -EINVAL;
1848 real_buffer = kmalloc(8 + len, GFP_KERNEL);
1849 if (!real_buffer)
1850 return -ENOMEM;
1851 memcpy(real_buffer + 8, buffer, len);
1852 len += 8;
1853 real_buffer[0] = 0;
1854 real_buffer[1] = 0;
1855 real_buffer[2] = data->medium_type;
1856 real_buffer[3] = data->device_specific;
1857 real_buffer[4] = data->longlba ? 0x01 : 0;
1858 real_buffer[5] = 0;
1859 real_buffer[6] = data->block_descriptor_length >> 8;
1860 real_buffer[7] = data->block_descriptor_length;
1861
1862 cmd[0] = MODE_SELECT_10;
1863 cmd[7] = len >> 8;
1864 cmd[8] = len;
1865 } else {
1866 if (len > 255 || data->block_descriptor_length > 255 ||
1867 data->longlba)
1868 return -EINVAL;
1869
1870 real_buffer = kmalloc(4 + len, GFP_KERNEL);
1871 if (!real_buffer)
1872 return -ENOMEM;
1873 memcpy(real_buffer + 4, buffer, len);
1874 len += 4;
1875 real_buffer[0] = 0;
1876 real_buffer[1] = data->medium_type;
1877 real_buffer[2] = data->device_specific;
1878 real_buffer[3] = data->block_descriptor_length;
1879
1880
1881 cmd[0] = MODE_SELECT;
1882 cmd[4] = len;
1883 }
1884
1885 ret = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, real_buffer, len,
1886 sshdr, timeout, retries);
1887 kfree(real_buffer);
1888 return ret;
1889}
1890EXPORT_SYMBOL_GPL(scsi_mode_select);
1891
1815/** 1892/**
1816 * scsi_mode_sense - issue a mode sense, falling back from 10 to 1893 * scsi_mode_sense - issue a mode sense, falling back from 10 to
1817 * six bytes if necessary. 1894 * six bytes if necessary.
@@ -1833,7 +1910,8 @@ void scsi_exit_queue(void)
1833int 1910int
1834scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, 1911scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
1835 unsigned char *buffer, int len, int timeout, int retries, 1912 unsigned char *buffer, int len, int timeout, int retries,
1836 struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { 1913 struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)
1914{
1837 unsigned char cmd[12]; 1915 unsigned char cmd[12];
1838 int use_10_for_ms; 1916 int use_10_for_ms;
1839 int header_length; 1917 int header_length;
@@ -1893,8 +1971,16 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
1893 } 1971 }
1894 1972
1895 if(scsi_status_is_good(result)) { 1973 if(scsi_status_is_good(result)) {
1896 data->header_length = header_length; 1974 if (unlikely(buffer[0] == 0x86 && buffer[1] == 0x0b &&
1897 if(use_10_for_ms) { 1975 (modepage == 6 || modepage == 8))) {
1976 /* Initio breakage? */
1977 header_length = 0;
1978 data->length = 13;
1979 data->medium_type = 0;
1980 data->device_specific = 0;
1981 data->longlba = 0;
1982 data->block_descriptor_length = 0;
1983 } else if(use_10_for_ms) {
1898 data->length = buffer[0]*256 + buffer[1] + 2; 1984 data->length = buffer[0]*256 + buffer[1] + 2;
1899 data->medium_type = buffer[2]; 1985 data->medium_type = buffer[2];
1900 data->device_specific = buffer[3]; 1986 data->device_specific = buffer[3];
@@ -1907,6 +1993,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
1907 data->device_specific = buffer[2]; 1993 data->device_specific = buffer[2];
1908 data->block_descriptor_length = buffer[3]; 1994 data->block_descriptor_length = buffer[3];
1909 } 1995 }
1996 data->header_length = header_length;
1910 } 1997 }
1911 1998
1912 return result; 1999 return result;
@@ -2249,61 +2336,3 @@ scsi_target_unblock(struct device *dev)
2249 device_for_each_child(dev, NULL, target_unblock); 2336 device_for_each_child(dev, NULL, target_unblock);
2250} 2337}
2251EXPORT_SYMBOL_GPL(scsi_target_unblock); 2338EXPORT_SYMBOL_GPL(scsi_target_unblock);
2252
2253
2254struct work_queue_work {
2255 struct work_struct work;
2256 void (*fn)(void *);
2257 void *data;
2258};
2259
2260static void execute_in_process_context_work(void *data)
2261{
2262 void (*fn)(void *data);
2263 struct work_queue_work *wqw = data;
2264
2265 fn = wqw->fn;
2266 data = wqw->data;
2267
2268 kfree(wqw);
2269
2270 fn(data);
2271}
2272
2273/**
2274 * scsi_execute_in_process_context - reliably execute the routine with user context
2275 * @fn: the function to execute
2276 * @data: data to pass to the function
2277 *
2278 * Executes the function immediately if process context is available,
2279 * otherwise schedules the function for delayed execution.
2280 *
2281 * Returns: 0 - function was executed
2282 * 1 - function was scheduled for execution
2283 * <0 - error
2284 */
2285int scsi_execute_in_process_context(void (*fn)(void *data), void *data)
2286{
2287 struct work_queue_work *wqw;
2288
2289 if (!in_interrupt()) {
2290 fn(data);
2291 return 0;
2292 }
2293
2294 wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC);
2295
2296 if (unlikely(!wqw)) {
2297 printk(KERN_ERR "Failed to allocate memory\n");
2298 WARN_ON(1);
2299 return -ENOMEM;
2300 }
2301
2302 INIT_WORK(&wqw->work, execute_in_process_context_work, wqw);
2303 wqw->fn = fn;
2304 wqw->data = data;
2305 schedule_work(&wqw->work);
2306
2307 return 1;
2308}
2309EXPORT_SYMBOL_GPL(scsi_execute_in_process_context);