diff options
-rw-r--r-- | drivers/scsi/scsi_debug.c | 277 |
1 files changed, 133 insertions, 144 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 1b6a6d8e5d27..07103c399fe0 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -218,8 +218,6 @@ static DEFINE_RWLOCK(atomic_rw); | |||
218 | 218 | ||
219 | static char sdebug_proc_name[] = "scsi_debug"; | 219 | static char sdebug_proc_name[] = "scsi_debug"; |
220 | 220 | ||
221 | static int sdebug_driver_probe(struct device *); | ||
222 | static int sdebug_driver_remove(struct device *); | ||
223 | static struct bus_type pseudo_lld_bus; | 221 | static struct bus_type pseudo_lld_bus; |
224 | 222 | ||
225 | static struct device_driver sdebug_driverfs_driver = { | 223 | static struct device_driver sdebug_driverfs_driver = { |
@@ -235,18 +233,42 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, | |||
235 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, | 233 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, |
236 | 0, 0, 0x0, 0x0}; | 234 | 0, 0, 0x0, 0x0}; |
237 | 235 | ||
238 | static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev); | ||
239 | static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, | ||
240 | int asc, int asq); | ||
241 | static void stop_all_queued(void); | ||
242 | static int stop_queued_cmnd(struct scsi_cmnd * cmnd); | ||
243 | |||
244 | static int sdebug_add_adapter(void); | 236 | static int sdebug_add_adapter(void); |
245 | static void sdebug_remove_adapter(void); | 237 | static void sdebug_remove_adapter(void); |
246 | static void sdebug_max_tgts_luns(void); | ||
247 | 238 | ||
248 | static struct device pseudo_primary; | 239 | static void sdebug_max_tgts_luns(void) |
249 | static struct bus_type pseudo_lld_bus; | 240 | { |
241 | struct sdebug_host_info *sdbg_host; | ||
242 | struct Scsi_Host *hpnt; | ||
243 | |||
244 | spin_lock(&sdebug_host_list_lock); | ||
245 | list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { | ||
246 | hpnt = sdbg_host->shost; | ||
247 | if ((hpnt->this_id >= 0) && | ||
248 | (scsi_debug_num_tgts > hpnt->this_id)) | ||
249 | hpnt->max_id = scsi_debug_num_tgts + 1; | ||
250 | else | ||
251 | hpnt->max_id = scsi_debug_num_tgts; | ||
252 | /* scsi_debug_max_luns; */ | ||
253 | hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; | ||
254 | } | ||
255 | spin_unlock(&sdebug_host_list_lock); | ||
256 | } | ||
257 | |||
258 | static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, | ||
259 | int asc, int asq) | ||
260 | { | ||
261 | unsigned char *sbuff; | ||
262 | |||
263 | sbuff = devip->sense_buff; | ||
264 | memset(sbuff, 0, SDEBUG_SENSE_LEN); | ||
265 | |||
266 | scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); | ||
267 | |||
268 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
269 | printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " | ||
270 | "[0x%x,0x%x,0x%x]\n", key, asc, asq); | ||
271 | } | ||
250 | 272 | ||
251 | static void get_data_transfer_info(unsigned char *cmd, | 273 | static void get_data_transfer_info(unsigned char *cmd, |
252 | unsigned long long *lba, unsigned int *num) | 274 | unsigned long long *lba, unsigned int *num) |
@@ -1680,52 +1702,9 @@ static void timer_intr_handler(unsigned long indx) | |||
1680 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 1702 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
1681 | } | 1703 | } |
1682 | 1704 | ||
1683 | static int scsi_debug_slave_alloc(struct scsi_device * sdp) | ||
1684 | { | ||
1685 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
1686 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", | ||
1687 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | ||
1688 | set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags); | ||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | static int scsi_debug_slave_configure(struct scsi_device * sdp) | ||
1693 | { | ||
1694 | struct sdebug_dev_info * devip; | ||
1695 | |||
1696 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
1697 | printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", | ||
1698 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | ||
1699 | if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) | ||
1700 | sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; | ||
1701 | devip = devInfoReg(sdp); | ||
1702 | if (NULL == devip) | ||
1703 | return 1; /* no resources, will be marked offline */ | ||
1704 | sdp->hostdata = devip; | ||
1705 | if (sdp->host->cmd_per_lun) | ||
1706 | scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, | ||
1707 | sdp->host->cmd_per_lun); | ||
1708 | blk_queue_max_segment_size(sdp->request_queue, 256 * 1024); | ||
1709 | return 0; | ||
1710 | } | ||
1711 | |||
1712 | static void scsi_debug_slave_destroy(struct scsi_device * sdp) | ||
1713 | { | ||
1714 | struct sdebug_dev_info * devip = | ||
1715 | (struct sdebug_dev_info *)sdp->hostdata; | ||
1716 | 1705 | ||
1717 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1706 | static struct sdebug_dev_info * |
1718 | printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", | 1707 | sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) |
1719 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | ||
1720 | if (devip) { | ||
1721 | /* make this slot avaliable for re-use */ | ||
1722 | devip->used = 0; | ||
1723 | sdp->hostdata = NULL; | ||
1724 | } | ||
1725 | } | ||
1726 | |||
1727 | struct sdebug_dev_info *sdebug_device_create(struct sdebug_host_info *sdbg_host, | ||
1728 | gfp_t flags) | ||
1729 | { | 1708 | { |
1730 | struct sdebug_dev_info *devip; | 1709 | struct sdebug_dev_info *devip; |
1731 | 1710 | ||
@@ -1789,19 +1768,88 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | |||
1789 | return open_devip; | 1768 | return open_devip; |
1790 | } | 1769 | } |
1791 | 1770 | ||
1792 | static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, | 1771 | static int scsi_debug_slave_alloc(struct scsi_device *sdp) |
1793 | int asc, int asq) | ||
1794 | { | 1772 | { |
1795 | unsigned char *sbuff; | 1773 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
1774 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", | ||
1775 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | ||
1776 | set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags); | ||
1777 | return 0; | ||
1778 | } | ||
1796 | 1779 | ||
1797 | sbuff = devip->sense_buff; | 1780 | static int scsi_debug_slave_configure(struct scsi_device *sdp) |
1798 | memset(sbuff, 0, SDEBUG_SENSE_LEN); | 1781 | { |
1782 | struct sdebug_dev_info *devip; | ||
1799 | 1783 | ||
1800 | scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); | 1784 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
1785 | printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", | ||
1786 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | ||
1787 | if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) | ||
1788 | sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; | ||
1789 | devip = devInfoReg(sdp); | ||
1790 | if (NULL == devip) | ||
1791 | return 1; /* no resources, will be marked offline */ | ||
1792 | sdp->hostdata = devip; | ||
1793 | if (sdp->host->cmd_per_lun) | ||
1794 | scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, | ||
1795 | sdp->host->cmd_per_lun); | ||
1796 | blk_queue_max_segment_size(sdp->request_queue, 256 * 1024); | ||
1797 | return 0; | ||
1798 | } | ||
1799 | |||
1800 | static void scsi_debug_slave_destroy(struct scsi_device *sdp) | ||
1801 | { | ||
1802 | struct sdebug_dev_info *devip = | ||
1803 | (struct sdebug_dev_info *)sdp->hostdata; | ||
1801 | 1804 | ||
1802 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 1805 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
1803 | printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " | 1806 | printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", |
1804 | "[0x%x,0x%x,0x%x]\n", key, asc, asq); | 1807 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
1808 | if (devip) { | ||
1809 | /* make this slot avaliable for re-use */ | ||
1810 | devip->used = 0; | ||
1811 | sdp->hostdata = NULL; | ||
1812 | } | ||
1813 | } | ||
1814 | |||
1815 | /* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */ | ||
1816 | static int stop_queued_cmnd(struct scsi_cmnd *cmnd) | ||
1817 | { | ||
1818 | unsigned long iflags; | ||
1819 | int k; | ||
1820 | struct sdebug_queued_cmd *sqcp; | ||
1821 | |||
1822 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
1823 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { | ||
1824 | sqcp = &queued_arr[k]; | ||
1825 | if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) { | ||
1826 | del_timer_sync(&sqcp->cmnd_timer); | ||
1827 | sqcp->in_use = 0; | ||
1828 | sqcp->a_cmnd = NULL; | ||
1829 | break; | ||
1830 | } | ||
1831 | } | ||
1832 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
1833 | return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0; | ||
1834 | } | ||
1835 | |||
1836 | /* Deletes (stops) timers of all queued commands */ | ||
1837 | static void stop_all_queued(void) | ||
1838 | { | ||
1839 | unsigned long iflags; | ||
1840 | int k; | ||
1841 | struct sdebug_queued_cmd *sqcp; | ||
1842 | |||
1843 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
1844 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { | ||
1845 | sqcp = &queued_arr[k]; | ||
1846 | if (sqcp->in_use && sqcp->a_cmnd) { | ||
1847 | del_timer_sync(&sqcp->cmnd_timer); | ||
1848 | sqcp->in_use = 0; | ||
1849 | sqcp->a_cmnd = NULL; | ||
1850 | } | ||
1851 | } | ||
1852 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
1805 | } | 1853 | } |
1806 | 1854 | ||
1807 | static int scsi_debug_abort(struct scsi_cmnd * SCpnt) | 1855 | static int scsi_debug_abort(struct scsi_cmnd * SCpnt) |
@@ -1891,46 +1939,6 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) | |||
1891 | return SUCCESS; | 1939 | return SUCCESS; |
1892 | } | 1940 | } |
1893 | 1941 | ||
1894 | /* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */ | ||
1895 | static int stop_queued_cmnd(struct scsi_cmnd * cmnd) | ||
1896 | { | ||
1897 | unsigned long iflags; | ||
1898 | int k; | ||
1899 | struct sdebug_queued_cmd * sqcp; | ||
1900 | |||
1901 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
1902 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { | ||
1903 | sqcp = &queued_arr[k]; | ||
1904 | if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) { | ||
1905 | del_timer_sync(&sqcp->cmnd_timer); | ||
1906 | sqcp->in_use = 0; | ||
1907 | sqcp->a_cmnd = NULL; | ||
1908 | break; | ||
1909 | } | ||
1910 | } | ||
1911 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
1912 | return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0; | ||
1913 | } | ||
1914 | |||
1915 | /* Deletes (stops) timers of all queued commands */ | ||
1916 | static void stop_all_queued(void) | ||
1917 | { | ||
1918 | unsigned long iflags; | ||
1919 | int k; | ||
1920 | struct sdebug_queued_cmd * sqcp; | ||
1921 | |||
1922 | spin_lock_irqsave(&queued_arr_lock, iflags); | ||
1923 | for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { | ||
1924 | sqcp = &queued_arr[k]; | ||
1925 | if (sqcp->in_use && sqcp->a_cmnd) { | ||
1926 | del_timer_sync(&sqcp->cmnd_timer); | ||
1927 | sqcp->in_use = 0; | ||
1928 | sqcp->a_cmnd = NULL; | ||
1929 | } | ||
1930 | } | ||
1931 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | ||
1932 | } | ||
1933 | |||
1934 | /* Initializes timers in queued array */ | 1942 | /* Initializes timers in queued array */ |
1935 | static void __init init_all_queued(void) | 1943 | static void __init init_all_queued(void) |
1936 | { | 1944 | { |
@@ -2055,7 +2063,6 @@ static int schedule_resp(struct scsi_cmnd * cmnd, | |||
2055 | return 0; | 2063 | return 0; |
2056 | } | 2064 | } |
2057 | } | 2065 | } |
2058 | |||
2059 | /* Note: The following macros create attribute files in the | 2066 | /* Note: The following macros create attribute files in the |
2060 | /sys/module/scsi_debug/parameters directory. Unfortunately this | 2067 | /sys/module/scsi_debug/parameters directory. Unfortunately this |
2061 | driver is unaware of a change and cannot trigger auxiliary actions | 2068 | driver is unaware of a change and cannot trigger auxiliary actions |
@@ -2474,6 +2481,17 @@ static void do_remove_driverfs_files(void) | |||
2474 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); | 2481 | driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); |
2475 | } | 2482 | } |
2476 | 2483 | ||
2484 | static void pseudo_0_release(struct device *dev) | ||
2485 | { | ||
2486 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2487 | printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); | ||
2488 | } | ||
2489 | |||
2490 | static struct device pseudo_primary = { | ||
2491 | .bus_id = "pseudo_0", | ||
2492 | .release = pseudo_0_release, | ||
2493 | }; | ||
2494 | |||
2477 | static int __init scsi_debug_init(void) | 2495 | static int __init scsi_debug_init(void) |
2478 | { | 2496 | { |
2479 | unsigned long sz; | 2497 | unsigned long sz; |
@@ -2588,30 +2606,6 @@ static void __exit scsi_debug_exit(void) | |||
2588 | device_initcall(scsi_debug_init); | 2606 | device_initcall(scsi_debug_init); |
2589 | module_exit(scsi_debug_exit); | 2607 | module_exit(scsi_debug_exit); |
2590 | 2608 | ||
2591 | static void pseudo_0_release(struct device * dev) | ||
2592 | { | ||
2593 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2594 | printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n"); | ||
2595 | } | ||
2596 | |||
2597 | static struct device pseudo_primary = { | ||
2598 | .bus_id = "pseudo_0", | ||
2599 | .release = pseudo_0_release, | ||
2600 | }; | ||
2601 | |||
2602 | static int pseudo_lld_bus_match(struct device *dev, | ||
2603 | struct device_driver *dev_driver) | ||
2604 | { | ||
2605 | return 1; | ||
2606 | } | ||
2607 | |||
2608 | static struct bus_type pseudo_lld_bus = { | ||
2609 | .name = "pseudo", | ||
2610 | .match = pseudo_lld_bus_match, | ||
2611 | .probe = sdebug_driver_probe, | ||
2612 | .remove = sdebug_driver_remove, | ||
2613 | }; | ||
2614 | |||
2615 | static void sdebug_release_adapter(struct device * dev) | 2609 | static void sdebug_release_adapter(struct device * dev) |
2616 | { | 2610 | { |
2617 | struct sdebug_host_info *sdbg_host; | 2611 | struct sdebug_host_info *sdbg_host; |
@@ -3011,20 +3005,15 @@ static int sdebug_driver_remove(struct device * dev) | |||
3011 | return 0; | 3005 | return 0; |
3012 | } | 3006 | } |
3013 | 3007 | ||
3014 | static void sdebug_max_tgts_luns(void) | 3008 | static int pseudo_lld_bus_match(struct device *dev, |
3009 | struct device_driver *dev_driver) | ||
3015 | { | 3010 | { |
3016 | struct sdebug_host_info * sdbg_host; | 3011 | return 1; |
3017 | struct Scsi_Host *hpnt; | ||
3018 | |||
3019 | spin_lock(&sdebug_host_list_lock); | ||
3020 | list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { | ||
3021 | hpnt = sdbg_host->shost; | ||
3022 | if ((hpnt->this_id >= 0) && | ||
3023 | (scsi_debug_num_tgts > hpnt->this_id)) | ||
3024 | hpnt->max_id = scsi_debug_num_tgts + 1; | ||
3025 | else | ||
3026 | hpnt->max_id = scsi_debug_num_tgts; | ||
3027 | hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* scsi_debug_max_luns; */ | ||
3028 | } | ||
3029 | spin_unlock(&sdebug_host_list_lock); | ||
3030 | } | 3012 | } |
3013 | |||
3014 | static struct bus_type pseudo_lld_bus = { | ||
3015 | .name = "pseudo", | ||
3016 | .match = pseudo_lld_bus_match, | ||
3017 | .probe = sdebug_driver_probe, | ||
3018 | .remove = sdebug_driver_remove, | ||
3019 | }; | ||