diff options
Diffstat (limited to 'drivers')
291 files changed, 13461 insertions, 4252 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 48f446d3c671..283c089537bc 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -44,6 +44,8 @@ source "drivers/char/Kconfig" | |||
| 44 | 44 | ||
| 45 | source "drivers/i2c/Kconfig" | 45 | source "drivers/i2c/Kconfig" |
| 46 | 46 | ||
| 47 | source "drivers/spi/Kconfig" | ||
| 48 | |||
| 47 | source "drivers/w1/Kconfig" | 49 | source "drivers/w1/Kconfig" |
| 48 | 50 | ||
| 49 | source "drivers/hwmon/Kconfig" | 51 | source "drivers/hwmon/Kconfig" |
diff --git a/drivers/Makefile b/drivers/Makefile index 7fc3f0f08b29..7c45050ecd03 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -41,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/ | |||
| 41 | obj-$(CONFIG_IEEE1394) += ieee1394/ | 41 | obj-$(CONFIG_IEEE1394) += ieee1394/ |
| 42 | obj-y += cdrom/ | 42 | obj-y += cdrom/ |
| 43 | obj-$(CONFIG_MTD) += mtd/ | 43 | obj-$(CONFIG_MTD) += mtd/ |
| 44 | obj-$(CONFIG_SPI) += spi/ | ||
| 44 | obj-$(CONFIG_PCCARD) += pcmcia/ | 45 | obj-$(CONFIG_PCCARD) += pcmcia/ |
| 45 | obj-$(CONFIG_DIO) += dio/ | 46 | obj-$(CONFIG_DIO) += dio/ |
| 46 | obj-$(CONFIG_SBUS) += sbus/ | 47 | obj-$(CONFIG_SBUS) += sbus/ |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7e1a445955bc..3758b558d2b5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -153,7 +153,7 @@ static int acpi_ec_polling_mode = EC_POLLING; | |||
| 153 | Transaction Management | 153 | Transaction Management |
| 154 | -------------------------------------------------------------------------- */ | 154 | -------------------------------------------------------------------------- */ |
| 155 | 155 | ||
| 156 | static inline u32 acpi_ec_read_status(union acpi_ec *ec) | 156 | static u32 acpi_ec_read_status(union acpi_ec *ec) |
| 157 | { | 157 | { |
| 158 | u32 status = 0; | 158 | u32 status = 0; |
| 159 | 159 | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 2b905016664d..730a9ce0a14a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
| @@ -78,7 +78,13 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
| 78 | pr_debug("%s: Matched Device %s with Driver %s\n", | 78 | pr_debug("%s: Matched Device %s with Driver %s\n", |
| 79 | drv->bus->name, dev->bus_id, drv->name); | 79 | drv->bus->name, dev->bus_id, drv->name); |
| 80 | dev->driver = drv; | 80 | dev->driver = drv; |
| 81 | if (drv->probe) { | 81 | if (dev->bus->probe) { |
| 82 | ret = dev->bus->probe(dev); | ||
| 83 | if (ret) { | ||
| 84 | dev->driver = NULL; | ||
| 85 | goto ProbeFailed; | ||
| 86 | } | ||
| 87 | } else if (drv->probe) { | ||
| 82 | ret = drv->probe(dev); | 88 | ret = drv->probe(dev); |
| 83 | if (ret) { | 89 | if (ret) { |
| 84 | dev->driver = NULL; | 90 | dev->driver = NULL; |
| @@ -203,7 +209,9 @@ static void __device_release_driver(struct device * dev) | |||
| 203 | sysfs_remove_link(&dev->kobj, "driver"); | 209 | sysfs_remove_link(&dev->kobj, "driver"); |
| 204 | klist_remove(&dev->knode_driver); | 210 | klist_remove(&dev->knode_driver); |
| 205 | 211 | ||
| 206 | if (drv->remove) | 212 | if (dev->bus->remove) |
| 213 | dev->bus->remove(dev); | ||
| 214 | else if (drv->remove) | ||
| 207 | drv->remove(dev); | 215 | drv->remove(dev); |
| 208 | dev->driver = NULL; | 216 | dev->driver = NULL; |
| 209 | put_driver(drv); | 217 | put_driver(drv); |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 161f3a390d90..b400314e1c62 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
| @@ -171,6 +171,11 @@ static void klist_devices_put(struct klist_node *n) | |||
| 171 | */ | 171 | */ |
| 172 | int driver_register(struct device_driver * drv) | 172 | int driver_register(struct device_driver * drv) |
| 173 | { | 173 | { |
| 174 | if ((drv->bus->probe && drv->probe) || | ||
| 175 | (drv->bus->remove && drv->remove) || | ||
| 176 | (drv->bus->shutdown && drv->shutdown)) { | ||
| 177 | printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); | ||
| 178 | } | ||
| 174 | klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); | 179 | klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); |
| 175 | init_completion(&drv->unloaded); | 180 | init_completion(&drv->unloaded); |
| 176 | return bus_add_driver(drv); | 181 | return bus_add_driver(drv); |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 3d384e3d34de..e97e911ebf7a 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -48,7 +48,7 @@ struct firmware_priv { | |||
| 48 | struct timer_list timeout; | 48 | struct timer_list timeout; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | static inline void | 51 | static void |
| 52 | fw_load_abort(struct firmware_priv *fw_priv) | 52 | fw_load_abort(struct firmware_priv *fw_priv) |
| 53 | { | 53 | { |
| 54 | set_bit(FW_STATUS_ABORT, &fw_priv->status); | 54 | set_bit(FW_STATUS_ABORT, &fw_priv->status); |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0f81731bdfa8..461554a02517 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -327,7 +327,7 @@ EXPORT_SYMBOL_GPL(platform_device_register); | |||
| 327 | * @pdev: platform device we're unregistering | 327 | * @pdev: platform device we're unregistering |
| 328 | * | 328 | * |
| 329 | * Unregistration is done in 2 steps. Fisrt we release all resources | 329 | * Unregistration is done in 2 steps. Fisrt we release all resources |
| 330 | * and remove it from the sybsystem, then we drop reference count by | 330 | * and remove it from the subsystem, then we drop reference count by |
| 331 | * calling platform_device_put(). | 331 | * calling platform_device_put(). |
| 332 | */ | 332 | */ |
| 333 | void platform_device_unregister(struct platform_device * pdev) | 333 | void platform_device_unregister(struct platform_device * pdev) |
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index f50a08be424b..c2475f3134ea 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c | |||
| @@ -35,12 +35,15 @@ extern int sysdev_shutdown(void); | |||
| 35 | */ | 35 | */ |
| 36 | void device_shutdown(void) | 36 | void device_shutdown(void) |
| 37 | { | 37 | { |
| 38 | struct device * dev; | 38 | struct device * dev, *devn; |
| 39 | 39 | ||
| 40 | down_write(&devices_subsys.rwsem); | 40 | down_write(&devices_subsys.rwsem); |
| 41 | list_for_each_entry_reverse(dev, &devices_subsys.kset.list, | 41 | list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list, |
| 42 | kobj.entry) { | 42 | kobj.entry) { |
| 43 | if (dev->driver && dev->driver->shutdown) { | 43 | if (dev->bus && dev->bus->shutdown) { |
| 44 | dev_dbg(dev, "shutdown\n"); | ||
| 45 | dev->bus->shutdown(dev); | ||
| 46 | } else if (dev->driver && dev->driver->shutdown) { | ||
| 44 | dev_dbg(dev, "shutdown\n"); | 47 | dev_dbg(dev, "shutdown\n"); |
| 45 | dev->driver->shutdown(dev); | 48 | dev->driver->shutdown(dev); |
| 46 | } | 49 | } |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 864729046e22..5f6d1a5cce11 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -294,7 +294,7 @@ fail: | |||
| 294 | * This helper just factors out common code between do_lo_send_direct_write() | 294 | * This helper just factors out common code between do_lo_send_direct_write() |
| 295 | * and do_lo_send_write(). | 295 | * and do_lo_send_write(). |
| 296 | */ | 296 | */ |
| 297 | static inline int __do_lo_send_write(struct file *file, | 297 | static int __do_lo_send_write(struct file *file, |
| 298 | u8 __user *buf, const int len, loff_t pos) | 298 | u8 __user *buf, const int len, loff_t pos) |
| 299 | { | 299 | { |
| 300 | ssize_t bw; | 300 | ssize_t bw; |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 51b7a5c5b77a..93affeeef7bd 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -247,7 +247,7 @@ static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node) | |||
| 247 | return rb_entry(n, struct pkt_rb_node, rb_node); | 247 | return rb_entry(n, struct pkt_rb_node, rb_node); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | static inline void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) | 250 | static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) |
| 251 | { | 251 | { |
| 252 | rb_erase(&node->rb_node, &pd->bio_queue); | 252 | rb_erase(&node->rb_node, &pd->bio_queue); |
| 253 | mempool_free(node, pd->rb_pool); | 253 | mempool_free(node, pd->rb_pool); |
| @@ -315,7 +315,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod | |||
| 315 | /* | 315 | /* |
| 316 | * Add a bio to a single linked list defined by its head and tail pointers. | 316 | * Add a bio to a single linked list defined by its head and tail pointers. |
| 317 | */ | 317 | */ |
| 318 | static inline void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) | 318 | static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) |
| 319 | { | 319 | { |
| 320 | bio->bi_next = NULL; | 320 | bio->bi_next = NULL; |
| 321 | if (*list_tail) { | 321 | if (*list_tail) { |
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 8fddfdfd0fbd..7bd4ef904115 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c | |||
| @@ -494,7 +494,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char | |||
| 494 | } | 494 | } |
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | static inline void bcsp_complete_rx_pkt(struct hci_uart *hu) | 497 | static void bcsp_complete_rx_pkt(struct hci_uart *hu) |
| 498 | { | 498 | { |
| 499 | struct bcsp_struct *bcsp = hu->priv; | 499 | struct bcsp_struct *bcsp = hu->priv; |
| 500 | int pass_up; | 500 | int pass_up; |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 667a21c72edb..7ac365b5d9ec 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
| @@ -129,7 +129,6 @@ static struct serial_state rs_table[1]; | |||
| 129 | * memory if large numbers of serial ports are open. | 129 | * memory if large numbers of serial ports are open. |
| 130 | */ | 130 | */ |
| 131 | static unsigned char *tmp_buf; | 131 | static unsigned char *tmp_buf; |
| 132 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 133 | 132 | ||
| 134 | #include <asm/uaccess.h> | 133 | #include <asm/uaccess.h> |
| 135 | 134 | ||
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c index caeecc2c36da..a080cdd6081e 100644 --- a/drivers/char/drm/r128_state.c +++ b/drivers/char/drm/r128_state.c | |||
| @@ -220,7 +220,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv) | |||
| 220 | ADVANCE_RING(); | 220 | ADVANCE_RING(); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv) | 223 | static void r128_emit_state(drm_r128_private_t * dev_priv) |
| 224 | { | 224 | { |
| 225 | drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; | 225 | drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; |
| 226 | unsigned int dirty = sarea_priv->dirty; | 226 | unsigned int dirty = sarea_priv->dirty; |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index e469f641c728..dd5dc8fa490d 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
| @@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int); | |||
| 160 | * memory if large numbers of serial ports are open. | 160 | * memory if large numbers of serial ports are open. |
| 161 | */ | 161 | */ |
| 162 | static unsigned char *tmp_buf; | 162 | static unsigned char *tmp_buf; |
| 163 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 164 | 163 | ||
| 165 | static inline int serial_paranoia_check(struct esp_struct *info, | 164 | static inline int serial_paranoia_check(struct esp_struct *info, |
| 166 | char *name, const char *routine) | 165 | char *name, const char *routine) |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 204a7302a4a9..e38a5f0e07bb 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #define DEBUG | 34 | #define DEBUG |
| 35 | 35 | ||
| 36 | static char * tmp_buf; | 36 | static char * tmp_buf; |
| 37 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 38 | 37 | ||
| 39 | static int gs_debug; | 38 | static int gs_debug; |
| 40 | 39 | ||
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 050e70ee5920..119e629656b7 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
| @@ -82,7 +82,6 @@ | |||
| 82 | static struct riscom_board * IRQ_to_board[16]; | 82 | static struct riscom_board * IRQ_to_board[16]; |
| 83 | static struct tty_driver *riscom_driver; | 83 | static struct tty_driver *riscom_driver; |
| 84 | static unsigned char * tmp_buf; | 84 | static unsigned char * tmp_buf; |
| 85 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 86 | 85 | ||
| 87 | static unsigned long baud_table[] = { | 86 | static unsigned long baud_table[] = { |
| 88 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 87 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index f36342ae8e7e..037c940ac71b 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
| @@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = { | |||
| 129 | * memory if large numbers of serial ports are open. | 129 | * memory if large numbers of serial ports are open. |
| 130 | */ | 130 | */ |
| 131 | static unsigned char *tmp_buf = 0; | 131 | static unsigned char *tmp_buf = 0; |
| 132 | DECLARE_MUTEX(tmp_buf_sem); | ||
| 133 | 132 | ||
| 134 | /* | 133 | /* |
| 135 | * This is used to look up the divisor speeds and the timeouts | 134 | * This is used to look up the divisor speeds and the timeouts |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 0a574bdbce36..5343e9fc6ab7 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
| @@ -184,7 +184,6 @@ static int sx_poll = HZ; | |||
| 184 | 184 | ||
| 185 | static struct tty_driver *specialix_driver; | 185 | static struct tty_driver *specialix_driver; |
| 186 | static unsigned char * tmp_buf; | 186 | static unsigned char * tmp_buf; |
| 187 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 188 | 187 | ||
| 189 | static unsigned long baud_table[] = { | 188 | static unsigned long baud_table[] = { |
| 190 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 189 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
| @@ -2556,8 +2555,6 @@ static int __init specialix_init_module(void) | |||
| 2556 | 2555 | ||
| 2557 | func_enter(); | 2556 | func_enter(); |
| 2558 | 2557 | ||
| 2559 | init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */ | ||
| 2560 | |||
| 2561 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { | 2558 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { |
| 2562 | for(i = 0; i < SX_NBOARD; i++) { | 2559 | for(i = 0; i < SX_NBOARD; i++) { |
| 2563 | sx_board[i].base = iobase[i]; | 2560 | sx_board[i].base = iobase[i]; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 9f1b466c4f84..ede688a4e141 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
| @@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void) | |||
| 951 | * memory if large numbers of serial ports are open. | 951 | * memory if large numbers of serial ports are open. |
| 952 | */ | 952 | */ |
| 953 | static unsigned char *tmp_buf; | 953 | static unsigned char *tmp_buf; |
| 954 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 955 | 954 | ||
| 956 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, | 955 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, |
| 957 | char *name, const char *routine) | 956 | char *name, const char *routine) |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index a6544790af60..c0dfcf273f0a 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
| @@ -395,12 +395,38 @@ config MACHZ_WDT | |||
| 395 | To compile this driver as a module, choose M here: the | 395 | To compile this driver as a module, choose M here: the |
| 396 | module will be called machzwd. | 396 | module will be called machzwd. |
| 397 | 397 | ||
| 398 | config SBC_EPX_C3_WATCHDOG | ||
| 399 | tristate "Winsystems SBC EPX-C3 watchdog" | ||
| 400 | depends on WATCHDOG && X86 | ||
| 401 | ---help--- | ||
| 402 | This is the driver for the built-in watchdog timer on the EPX-C3 | ||
| 403 | Single-board computer made by Winsystems, Inc. | ||
| 404 | |||
| 405 | *Note*: This hardware watchdog is not probeable and thus there | ||
| 406 | is no way to know if writing to its IO address will corrupt | ||
| 407 | your system or have any real effect. The only way to be sure | ||
| 408 | that this driver does what you want is to make sure you | ||
| 409 | are runnning it on an EPX-C3 from Winsystems with the watchdog | ||
| 410 | timer at IO address 0x1ee and 0x1ef. It will write to both those | ||
| 411 | IO ports. Basically, the assumption is made that if you compile | ||
| 412 | this driver into your kernel and/or load it as a module, that you | ||
| 413 | know what you are doing and that you are in fact running on an | ||
| 414 | EPX-C3 board! | ||
| 415 | |||
| 416 | To compile this driver as a module, choose M here: the | ||
| 417 | module will be called sbc_epx_c3. | ||
| 418 | |||
| 419 | |||
| 398 | # PowerPC Architecture | 420 | # PowerPC Architecture |
| 399 | 421 | ||
| 400 | config 8xx_WDT | 422 | config 8xx_WDT |
| 401 | tristate "MPC8xx Watchdog Timer" | 423 | tristate "MPC8xx Watchdog Timer" |
| 402 | depends on WATCHDOG && 8xx | 424 | depends on WATCHDOG && 8xx |
| 403 | 425 | ||
| 426 | config 83xx_WDT | ||
| 427 | tristate "MPC83xx Watchdog Timer" | ||
| 428 | depends on WATCHDOG && PPC_83xx | ||
| 429 | |||
| 404 | config MV64X60_WDT | 430 | config MV64X60_WDT |
| 405 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" | 431 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" |
| 406 | depends on WATCHDOG && MV64X60 | 432 | depends on WATCHDOG && MV64X60 |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index cfd0a3987710..36c0b282b8ba 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
| @@ -52,9 +52,11 @@ obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o | |||
| 52 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o | 52 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o |
| 53 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o | 53 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o |
| 54 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o | 54 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o |
| 55 | obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o | ||
| 55 | 56 | ||
| 56 | # PowerPC Architecture | 57 | # PowerPC Architecture |
| 57 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 58 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
| 59 | obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o | ||
| 58 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o | 60 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o |
| 59 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | 61 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o |
| 60 | 62 | ||
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c new file mode 100644 index 000000000000..5d6f5061603a --- /dev/null +++ b/drivers/char/watchdog/mpc83xx_wdt.c | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | /* | ||
| 2 | * mpc83xx_wdt.c - MPC83xx watchdog userspace interface | ||
| 3 | * | ||
| 4 | * Authors: Dave Updegraff <dave@cray.org> | ||
| 5 | * Kumar Gala <galak@kernel.crashing.org> | ||
| 6 | * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> | ||
| 7 | * ..and from sc520_wdt | ||
| 8 | * | ||
| 9 | * Note: it appears that you can only actually ENABLE or DISABLE the thing | ||
| 10 | * once after POR. Once enabled, you cannot disable, and vice versa. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/config.h> | ||
| 19 | #include <linux/fs.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/miscdevice.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/watchdog.h> | ||
| 26 | #include <asm/io.h> | ||
| 27 | #include <asm/uaccess.h> | ||
| 28 | |||
| 29 | struct mpc83xx_wdt { | ||
| 30 | __be32 res0; | ||
| 31 | __be32 swcrr; /* System watchdog control register */ | ||
| 32 | #define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ | ||
| 33 | #define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ | ||
| 34 | #define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ | ||
| 35 | #define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ | ||
| 36 | __be32 swcnr; /* System watchdog count register */ | ||
| 37 | u8 res1[2]; | ||
| 38 | __be16 swsrr; /* System watchdog service register */ | ||
| 39 | u8 res2[0xF0]; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static struct mpc83xx_wdt __iomem *wd_base; | ||
| 43 | |||
| 44 | static u16 timeout = 0xffff; | ||
| 45 | module_param(timeout, ushort, 0); | ||
| 46 | MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535"); | ||
| 47 | |||
| 48 | static int reset = 1; | ||
| 49 | module_param(reset, bool, 0); | ||
| 50 | MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset"); | ||
| 51 | |||
| 52 | /* | ||
| 53 | * We always prescale, but if someone really doesn't want to they can set this | ||
| 54 | * to 0 | ||
| 55 | */ | ||
| 56 | static int prescale = 1; | ||
| 57 | static unsigned int timeout_sec; | ||
| 58 | |||
| 59 | static unsigned long wdt_is_open; | ||
| 60 | static spinlock_t wdt_spinlock; | ||
| 61 | |||
| 62 | static void mpc83xx_wdt_keepalive(void) | ||
| 63 | { | ||
| 64 | /* Ping the WDT */ | ||
| 65 | spin_lock(&wdt_spinlock); | ||
| 66 | out_be16(&wd_base->swsrr, 0x556c); | ||
| 67 | out_be16(&wd_base->swsrr, 0xaa39); | ||
| 68 | spin_unlock(&wdt_spinlock); | ||
| 69 | } | ||
| 70 | |||
| 71 | static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf, | ||
| 72 | size_t count, loff_t *ppos) | ||
| 73 | { | ||
| 74 | if (count) | ||
| 75 | mpc83xx_wdt_keepalive(); | ||
| 76 | return count; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int mpc83xx_wdt_open(struct inode *inode, struct file *file) | ||
| 80 | { | ||
| 81 | u32 tmp = SWCRR_SWEN; | ||
| 82 | if (test_and_set_bit(0, &wdt_is_open)) | ||
| 83 | return -EBUSY; | ||
| 84 | |||
| 85 | /* Once we start the watchdog we can't stop it */ | ||
| 86 | __module_get(THIS_MODULE); | ||
| 87 | |||
| 88 | /* Good, fire up the show */ | ||
| 89 | if (prescale) | ||
| 90 | tmp |= SWCRR_SWPR; | ||
| 91 | if (reset) | ||
| 92 | tmp |= SWCRR_SWRI; | ||
| 93 | |||
| 94 | tmp |= timeout << 16; | ||
| 95 | |||
| 96 | out_be32(&wd_base->swcrr, tmp); | ||
| 97 | |||
| 98 | return nonseekable_open(inode, file); | ||
| 99 | } | ||
| 100 | |||
| 101 | static int mpc83xx_wdt_release(struct inode *inode, struct file *file) | ||
| 102 | { | ||
| 103 | printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n"); | ||
| 104 | mpc83xx_wdt_keepalive(); | ||
| 105 | clear_bit(0, &wdt_is_open); | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, | ||
| 110 | unsigned int cmd, unsigned long arg) | ||
| 111 | { | ||
| 112 | void __user *argp = (void __user *)arg; | ||
| 113 | int __user *p = argp; | ||
| 114 | static struct watchdog_info ident = { | ||
| 115 | .options = WDIOF_KEEPALIVEPING, | ||
| 116 | .firmware_version = 1, | ||
| 117 | .identity = "MPC83xx", | ||
| 118 | }; | ||
| 119 | |||
| 120 | switch (cmd) { | ||
| 121 | case WDIOC_GETSUPPORT: | ||
| 122 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
| 123 | case WDIOC_KEEPALIVE: | ||
| 124 | mpc83xx_wdt_keepalive(); | ||
| 125 | return 0; | ||
| 126 | case WDIOC_GETTIMEOUT: | ||
| 127 | return put_user(timeout_sec, p); | ||
| 128 | default: | ||
| 129 | return -ENOIOCTLCMD; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | static struct file_operations mpc83xx_wdt_fops = { | ||
| 134 | .owner = THIS_MODULE, | ||
| 135 | .llseek = no_llseek, | ||
| 136 | .write = mpc83xx_wdt_write, | ||
| 137 | .ioctl = mpc83xx_wdt_ioctl, | ||
| 138 | .open = mpc83xx_wdt_open, | ||
| 139 | .release = mpc83xx_wdt_release, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static struct miscdevice mpc83xx_wdt_miscdev = { | ||
| 143 | .minor = WATCHDOG_MINOR, | ||
| 144 | .name = "watchdog", | ||
| 145 | .fops = &mpc83xx_wdt_fops, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static int __devinit mpc83xx_wdt_probe(struct platform_device *dev) | ||
| 149 | { | ||
| 150 | struct resource *r; | ||
| 151 | int ret; | ||
| 152 | unsigned int *freq = dev->dev.platform_data; | ||
| 153 | |||
| 154 | /* get a pointer to the register memory */ | ||
| 155 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
| 156 | |||
| 157 | if (!r) { | ||
| 158 | ret = -ENODEV; | ||
| 159 | goto err_out; | ||
| 160 | } | ||
| 161 | |||
| 162 | wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt)); | ||
| 163 | |||
| 164 | if (wd_base == NULL) { | ||
| 165 | ret = -ENOMEM; | ||
| 166 | goto err_out; | ||
| 167 | } | ||
| 168 | |||
| 169 | ret = misc_register(&mpc83xx_wdt_miscdev); | ||
| 170 | if (ret) { | ||
| 171 | printk(KERN_ERR "cannot register miscdev on minor=%d " | ||
| 172 | "(err=%d)\n", | ||
| 173 | WATCHDOG_MINOR, ret); | ||
| 174 | goto err_unmap; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* Calculate the timeout in seconds */ | ||
| 178 | if (prescale) | ||
| 179 | timeout_sec = (timeout * 0x10000) / (*freq); | ||
| 180 | else | ||
| 181 | timeout_sec = timeout / (*freq); | ||
| 182 | |||
| 183 | printk(KERN_INFO "WDT driver for MPC83xx initialized. " | ||
| 184 | "mode:%s timeout=%d (%d seconds)\n", | ||
| 185 | reset ? "reset":"interrupt", timeout, timeout_sec); | ||
| 186 | |||
| 187 | spin_lock_init(&wdt_spinlock); | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | |||
| 191 | err_unmap: | ||
| 192 | iounmap(wd_base); | ||
| 193 | err_out: | ||
| 194 | return ret; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int __devexit mpc83xx_wdt_remove(struct platform_device *dev) | ||
| 198 | { | ||
| 199 | misc_deregister(&mpc83xx_wdt_miscdev); | ||
| 200 | iounmap(wd_base); | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static struct platform_driver mpc83xx_wdt_driver = { | ||
| 206 | .probe = mpc83xx_wdt_probe, | ||
| 207 | .remove = __devexit_p(mpc83xx_wdt_remove), | ||
| 208 | .driver = { | ||
| 209 | .name = "mpc83xx_wdt", | ||
| 210 | }, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int __init mpc83xx_wdt_init(void) | ||
| 214 | { | ||
| 215 | return platform_driver_register(&mpc83xx_wdt_driver); | ||
| 216 | } | ||
| 217 | |||
| 218 | static void __exit mpc83xx_wdt_exit(void) | ||
| 219 | { | ||
| 220 | platform_driver_unregister(&mpc83xx_wdt_driver); | ||
| 221 | } | ||
| 222 | |||
| 223 | module_init(mpc83xx_wdt_init); | ||
| 224 | module_exit(mpc83xx_wdt_exit); | ||
| 225 | |||
| 226 | MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); | ||
| 227 | MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor"); | ||
| 228 | MODULE_LICENSE("GPL"); | ||
| 229 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c new file mode 100644 index 000000000000..951764614ebf --- /dev/null +++ b/drivers/char/watchdog/sbc_epx_c3.c | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | /* | ||
| 2 | * SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3 | ||
| 3 | * single board computer | ||
| 4 | * | ||
| 5 | * (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, All Rights | ||
| 6 | * Reserved. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License | ||
| 10 | * as published by the Free Software Foundation; either version | ||
| 11 | * 2 of the License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * based on softdog.c by Alan Cox <alan@redhat.com> | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/moduleparam.h> | ||
| 18 | #include <linux/config.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/fs.h> | ||
| 22 | #include <linux/mm.h> | ||
| 23 | #include <linux/miscdevice.h> | ||
| 24 | #include <linux/watchdog.h> | ||
| 25 | #include <linux/notifier.h> | ||
| 26 | #include <linux/reboot.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <asm/uaccess.h> | ||
| 29 | #include <asm/io.h> | ||
| 30 | |||
| 31 | #define PFX "epx_c3: " | ||
| 32 | static int epx_c3_alive; | ||
| 33 | |||
| 34 | #define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */ | ||
| 35 | |||
| 36 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
| 37 | module_param(nowayout, int, 0); | ||
| 38 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
| 39 | |||
| 40 | #define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */ | ||
| 41 | #define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */ | ||
| 42 | |||
| 43 | static void epx_c3_start(void) | ||
| 44 | { | ||
| 45 | outb(1, EPXC3_WATCHDOG_CTL_REG); | ||
| 46 | } | ||
| 47 | |||
| 48 | static void epx_c3_stop(void) | ||
| 49 | { | ||
| 50 | |||
| 51 | outb(0, EPXC3_WATCHDOG_CTL_REG); | ||
| 52 | |||
| 53 | printk(KERN_INFO PFX "Stopped watchdog timer.\n"); | ||
| 54 | } | ||
| 55 | |||
| 56 | static void epx_c3_pet(void) | ||
| 57 | { | ||
| 58 | outb(1, EPXC3_WATCHDOG_PET_REG); | ||
| 59 | } | ||
| 60 | |||
| 61 | /* | ||
| 62 | * Allow only one person to hold it open | ||
| 63 | */ | ||
| 64 | static int epx_c3_open(struct inode *inode, struct file *file) | ||
| 65 | { | ||
| 66 | if (epx_c3_alive) | ||
| 67 | return -EBUSY; | ||
| 68 | |||
| 69 | if (nowayout) | ||
| 70 | __module_get(THIS_MODULE); | ||
| 71 | |||
| 72 | /* Activate timer */ | ||
| 73 | epx_c3_start(); | ||
| 74 | epx_c3_pet(); | ||
| 75 | |||
| 76 | epx_c3_alive = 1; | ||
| 77 | printk(KERN_INFO "Started watchdog timer.\n"); | ||
| 78 | |||
| 79 | return nonseekable_open(inode, file); | ||
| 80 | } | ||
| 81 | |||
| 82 | static int epx_c3_release(struct inode *inode, struct file *file) | ||
| 83 | { | ||
| 84 | /* Shut off the timer. | ||
| 85 | * Lock it in if it's a module and we defined ...NOWAYOUT */ | ||
| 86 | if (!nowayout) | ||
| 87 | epx_c3_stop(); /* Turn the WDT off */ | ||
| 88 | |||
| 89 | epx_c3_alive = 0; | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static ssize_t epx_c3_write(struct file *file, const char *data, | ||
| 95 | size_t len, loff_t *ppos) | ||
| 96 | { | ||
| 97 | /* Refresh the timer. */ | ||
| 98 | if (len) | ||
| 99 | epx_c3_pet(); | ||
| 100 | return len; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int epx_c3_ioctl(struct inode *inode, struct file *file, | ||
| 104 | unsigned int cmd, unsigned long arg) | ||
| 105 | { | ||
| 106 | int options, retval = -EINVAL; | ||
| 107 | static struct watchdog_info ident = { | ||
| 108 | .options = WDIOF_KEEPALIVEPING | | ||
| 109 | WDIOF_MAGICCLOSE, | ||
| 110 | .firmware_version = 0, | ||
| 111 | .identity = "Winsystems EPX-C3 H/W Watchdog", | ||
| 112 | }; | ||
| 113 | |||
| 114 | switch (cmd) { | ||
| 115 | case WDIOC_GETSUPPORT: | ||
| 116 | if (copy_to_user((struct watchdog_info *)arg, | ||
| 117 | &ident, sizeof(ident))) | ||
| 118 | return -EFAULT; | ||
| 119 | return 0; | ||
| 120 | case WDIOC_GETSTATUS: | ||
| 121 | case WDIOC_GETBOOTSTATUS: | ||
| 122 | return put_user(0,(int *)arg); | ||
| 123 | case WDIOC_KEEPALIVE: | ||
| 124 | epx_c3_pet(); | ||
| 125 | return 0; | ||
| 126 | case WDIOC_GETTIMEOUT: | ||
| 127 | return put_user(WATCHDOG_TIMEOUT,(int *)arg); | ||
| 128 | case WDIOC_SETOPTIONS: { | ||
| 129 | if (get_user(options, (int *)arg)) | ||
| 130 | return -EFAULT; | ||
| 131 | |||
| 132 | if (options & WDIOS_DISABLECARD) { | ||
| 133 | epx_c3_stop(); | ||
| 134 | retval = 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | if (options & WDIOS_ENABLECARD) { | ||
| 138 | epx_c3_start(); | ||
| 139 | retval = 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | return retval; | ||
| 143 | } | ||
| 144 | default: | ||
| 145 | return -ENOIOCTLCMD; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code, | ||
| 150 | void *unused) | ||
| 151 | { | ||
| 152 | if (code == SYS_DOWN || code == SYS_HALT) | ||
| 153 | epx_c3_stop(); /* Turn the WDT off */ | ||
| 154 | |||
| 155 | return NOTIFY_DONE; | ||
| 156 | } | ||
| 157 | |||
| 158 | static struct file_operations epx_c3_fops = { | ||
| 159 | .owner = THIS_MODULE, | ||
| 160 | .llseek = no_llseek, | ||
| 161 | .write = epx_c3_write, | ||
| 162 | .ioctl = epx_c3_ioctl, | ||
| 163 | .open = epx_c3_open, | ||
| 164 | .release = epx_c3_release, | ||
| 165 | }; | ||
| 166 | |||
| 167 | static struct miscdevice epx_c3_miscdev = { | ||
| 168 | .minor = WATCHDOG_MINOR, | ||
| 169 | .name = "watchdog", | ||
| 170 | .fops = &epx_c3_fops, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static struct notifier_block epx_c3_notifier = { | ||
| 174 | .notifier_call = epx_c3_notify_sys, | ||
| 175 | }; | ||
| 176 | |||
| 177 | static const char banner[] __initdata = | ||
| 178 | KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n"; | ||
| 179 | |||
| 180 | static int __init watchdog_init(void) | ||
| 181 | { | ||
| 182 | int ret; | ||
| 183 | |||
| 184 | ret = register_reboot_notifier(&epx_c3_notifier); | ||
| 185 | if (ret) { | ||
| 186 | printk(KERN_ERR PFX "cannot register reboot notifier " | ||
| 187 | "(err=%d)\n", ret); | ||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | ret = misc_register(&epx_c3_miscdev); | ||
| 192 | if (ret) { | ||
| 193 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d " | ||
| 194 | "(err=%d)\n", WATCHDOG_MINOR, ret); | ||
| 195 | unregister_reboot_notifier(&epx_c3_notifier); | ||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | |||
| 199 | printk(banner); | ||
| 200 | |||
| 201 | return 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | static void __exit watchdog_exit(void) | ||
| 205 | { | ||
| 206 | misc_deregister(&epx_c3_miscdev); | ||
| 207 | unregister_reboot_notifier(&epx_c3_notifier); | ||
| 208 | } | ||
| 209 | |||
| 210 | module_init(watchdog_init); | ||
| 211 | module_exit(watchdog_exit); | ||
| 212 | |||
| 213 | MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>"); | ||
| 214 | MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!"); | ||
| 215 | MODULE_LICENSE("GPL"); | ||
| 216 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a9163d02983a..277a843a87a6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -41,7 +41,6 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); | |||
| 41 | /* internal prototypes */ | 41 | /* internal prototypes */ |
| 42 | static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); | 42 | static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); |
| 43 | static void handle_update(void *data); | 43 | static void handle_update(void *data); |
| 44 | static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci); | ||
| 45 | 44 | ||
| 46 | /** | 45 | /** |
| 47 | * Two notifier lists: the "policy" list is involved in the | 46 | * Two notifier lists: the "policy" list is involved in the |
| @@ -127,7 +126,7 @@ static unsigned int debug_ratelimit = 1; | |||
| 127 | static unsigned int disable_ratelimit = 1; | 126 | static unsigned int disable_ratelimit = 1; |
| 128 | static DEFINE_SPINLOCK(disable_ratelimit_lock); | 127 | static DEFINE_SPINLOCK(disable_ratelimit_lock); |
| 129 | 128 | ||
| 130 | static inline void cpufreq_debug_enable_ratelimit(void) | 129 | static void cpufreq_debug_enable_ratelimit(void) |
| 131 | { | 130 | { |
| 132 | unsigned long flags; | 131 | unsigned long flags; |
| 133 | 132 | ||
| @@ -137,7 +136,7 @@ static inline void cpufreq_debug_enable_ratelimit(void) | |||
| 137 | spin_unlock_irqrestore(&disable_ratelimit_lock, flags); | 136 | spin_unlock_irqrestore(&disable_ratelimit_lock, flags); |
| 138 | } | 137 | } |
| 139 | 138 | ||
| 140 | static inline void cpufreq_debug_disable_ratelimit(void) | 139 | static void cpufreq_debug_disable_ratelimit(void) |
| 141 | { | 140 | { |
| 142 | unsigned long flags; | 141 | unsigned long flags; |
| 143 | 142 | ||
| @@ -206,7 +205,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; } | |||
| 206 | static unsigned long l_p_j_ref; | 205 | static unsigned long l_p_j_ref; |
| 207 | static unsigned int l_p_j_ref_freq; | 206 | static unsigned int l_p_j_ref_freq; |
| 208 | 207 | ||
| 209 | static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) | 208 | static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) |
| 210 | { | 209 | { |
| 211 | if (ci->flags & CPUFREQ_CONST_LOOPS) | 210 | if (ci->flags & CPUFREQ_CONST_LOOPS) |
| 212 | return; | 211 | return; |
diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c index ffe6f44ac76f..ca8e69d2f64d 100644 --- a/drivers/dio/dio-driver.c +++ b/drivers/dio/dio-driver.c | |||
| @@ -83,7 +83,6 @@ int dio_register_driver(struct dio_driver *drv) | |||
| 83 | /* initialize common driver fields */ | 83 | /* initialize common driver fields */ |
| 84 | drv->driver.name = drv->name; | 84 | drv->driver.name = drv->name; |
| 85 | drv->driver.bus = &dio_bus_type; | 85 | drv->driver.bus = &dio_bus_type; |
| 86 | drv->driver.probe = dio_device_probe; | ||
| 87 | 86 | ||
| 88 | /* register with core */ | 87 | /* register with core */ |
| 89 | count = driver_register(&drv->driver); | 88 | count = driver_register(&drv->driver); |
| @@ -145,7 +144,8 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv) | |||
| 145 | 144 | ||
| 146 | struct bus_type dio_bus_type = { | 145 | struct bus_type dio_bus_type = { |
| 147 | .name = "dio", | 146 | .name = "dio", |
| 148 | .match = dio_bus_match | 147 | .match = dio_bus_match, |
| 148 | .probe = dio_device_probe, | ||
| 149 | }; | 149 | }; |
| 150 | 150 | ||
| 151 | 151 | ||
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index dfedb777d8c9..fdb8b042e64d 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
| @@ -49,7 +49,7 @@ | |||
| 49 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | 49 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
| 50 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | 50 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
| 51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
| 52 | MODULE_VERSION("3.1"); | 52 | MODULE_VERSION("3.2"); |
| 53 | 53 | ||
| 54 | #define BIOS_SCAN_LIMIT 0xffffffff | 54 | #define BIOS_SCAN_LIMIT 0xffffffff |
| 55 | #define MAX_IMAGE_LENGTH 16 | 55 | #define MAX_IMAGE_LENGTH 16 |
| @@ -564,12 +564,10 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, | |||
| 564 | 564 | ||
| 565 | static void callbackfn_rbu(const struct firmware *fw, void *context) | 565 | static void callbackfn_rbu(const struct firmware *fw, void *context) |
| 566 | { | 566 | { |
| 567 | int rc = 0; | 567 | rbu_data.entry_created = 0; |
| 568 | 568 | ||
| 569 | if (!fw || !fw->size) { | 569 | if (!fw || !fw->size) |
| 570 | rbu_data.entry_created = 0; | ||
| 571 | return; | 570 | return; |
| 572 | } | ||
| 573 | 571 | ||
| 574 | spin_lock(&rbu_data.lock); | 572 | spin_lock(&rbu_data.lock); |
| 575 | if (!strcmp(image_type, "mono")) { | 573 | if (!strcmp(image_type, "mono")) { |
| @@ -592,15 +590,6 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
| 592 | } else | 590 | } else |
| 593 | pr_debug("invalid image type specified.\n"); | 591 | pr_debug("invalid image type specified.\n"); |
| 594 | spin_unlock(&rbu_data.lock); | 592 | spin_unlock(&rbu_data.lock); |
| 595 | |||
| 596 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | ||
| 597 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); | ||
| 598 | if (rc) | ||
| 599 | printk(KERN_ERR | ||
| 600 | "dell_rbu:%s request_firmware_nowait failed" | ||
| 601 | " %d\n", __FUNCTION__, rc); | ||
| 602 | else | ||
| 603 | rbu_data.entry_created = 1; | ||
| 604 | } | 593 | } |
| 605 | 594 | ||
| 606 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | 595 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, |
| @@ -735,14 +724,7 @@ static int __init dcdrbu_init(void) | |||
| 735 | sysfs_create_bin_file(&rbu_device->dev.kobj, | 724 | sysfs_create_bin_file(&rbu_device->dev.kobj, |
| 736 | &rbu_packet_size_attr); | 725 | &rbu_packet_size_attr); |
| 737 | 726 | ||
| 738 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 727 | rbu_data.entry_created = 0; |
| 739 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); | ||
| 740 | if (rc) | ||
| 741 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" | ||
| 742 | " failed %d\n", __FUNCTION__, rc); | ||
| 743 | else | ||
| 744 | rbu_data.entry_created = 1; | ||
| 745 | |||
| 746 | return rc; | 728 | return rc; |
| 747 | 729 | ||
| 748 | } | 730 | } |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 52b77477df57..0ce58b506046 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev) | |||
| 63 | return rc; | 63 | return rc; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | struct bus_type i2c_bus_type = { | ||
| 67 | .name = "i2c", | ||
| 68 | .match = i2c_device_match, | ||
| 69 | .suspend = i2c_bus_suspend, | ||
| 70 | .resume = i2c_bus_resume, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static int i2c_device_probe(struct device *dev) | 66 | static int i2c_device_probe(struct device *dev) |
| 74 | { | 67 | { |
| 75 | return -ENODEV; | 68 | return -ENODEV; |
| @@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev) | |||
| 80 | return 0; | 73 | return 0; |
| 81 | } | 74 | } |
| 82 | 75 | ||
| 76 | struct bus_type i2c_bus_type = { | ||
| 77 | .name = "i2c", | ||
| 78 | .match = i2c_device_match, | ||
| 79 | .probe = i2c_device_probe, | ||
| 80 | .remove = i2c_device_remove, | ||
| 81 | .suspend = i2c_bus_suspend, | ||
| 82 | .resume = i2c_bus_resume, | ||
| 83 | }; | ||
| 84 | |||
| 83 | void i2c_adapter_dev_release(struct device *dev) | 85 | void i2c_adapter_dev_release(struct device *dev) |
| 84 | { | 86 | { |
| 85 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); | 87 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); |
| @@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = { | |||
| 90 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
| 91 | .name = "i2c_adapter", | 93 | .name = "i2c_adapter", |
| 92 | .bus = &i2c_bus_type, | 94 | .bus = &i2c_bus_type, |
| 93 | .probe = i2c_device_probe, | ||
| 94 | .remove = i2c_device_remove, | ||
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | static void i2c_adapter_class_dev_release(struct class_device *dev) | 97 | static void i2c_adapter_class_dev_release(struct class_device *dev) |
| @@ -294,8 +294,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
| 294 | /* add the driver to the list of i2c drivers in the driver core */ | 294 | /* add the driver to the list of i2c drivers in the driver core */ |
| 295 | driver->driver.owner = owner; | 295 | driver->driver.owner = owner; |
| 296 | driver->driver.bus = &i2c_bus_type; | 296 | driver->driver.bus = &i2c_bus_type; |
| 297 | driver->driver.probe = i2c_device_probe; | ||
| 298 | driver->driver.remove = i2c_device_remove; | ||
| 299 | 297 | ||
| 300 | res = driver_register(&driver->driver); | 298 | res = driver_register(&driver->driver); |
| 301 | if (res) | 299 | if (res) |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 9b2ebd219ad0..3325660f7248 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, | |||
| 980 | * and attempt to recover if there are problems. Returns 0 if everything's | 980 | * and attempt to recover if there are problems. Returns 0 if everything's |
| 981 | * ok; nonzero if the request has been terminated. | 981 | * ok; nonzero if the request has been terminated. |
| 982 | */ | 982 | */ |
| 983 | static inline | 983 | static |
| 984 | int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) | 984 | int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) |
| 985 | { | 985 | { |
| 986 | if (ireason == 2) | 986 | if (ireason == 2) |
| @@ -1539,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) | |||
| 1539 | /* | 1539 | /* |
| 1540 | * Write handling | 1540 | * Write handling |
| 1541 | */ | 1541 | */ |
| 1542 | static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) | 1542 | static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) |
| 1543 | { | 1543 | { |
| 1544 | /* Two notes about IDE interrupt reason here - 0 means that | 1544 | /* Two notes about IDE interrupt reason here - 0 means that |
| 1545 | * the drive wants to receive data from us, 2 means that | 1545 | * the drive wants to receive data from us, 2 means that |
| @@ -3256,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) | |||
| 3256 | } | 3256 | } |
| 3257 | #endif | 3257 | #endif |
| 3258 | 3258 | ||
| 3259 | static int ide_cd_remove(struct device *dev) | 3259 | static void ide_cd_remove(ide_drive_t *drive) |
| 3260 | { | 3260 | { |
| 3261 | ide_drive_t *drive = to_ide_device(dev); | ||
| 3262 | struct cdrom_info *info = drive->driver_data; | 3261 | struct cdrom_info *info = drive->driver_data; |
| 3263 | 3262 | ||
| 3264 | ide_unregister_subdriver(drive, info->driver); | 3263 | ide_unregister_subdriver(drive, info->driver); |
| @@ -3266,8 +3265,6 @@ static int ide_cd_remove(struct device *dev) | |||
| 3266 | del_gendisk(info->disk); | 3265 | del_gendisk(info->disk); |
| 3267 | 3266 | ||
| 3268 | ide_cd_put(info); | 3267 | ide_cd_put(info); |
| 3269 | |||
| 3270 | return 0; | ||
| 3271 | } | 3268 | } |
| 3272 | 3269 | ||
| 3273 | static void ide_cd_release(struct kref *kref) | 3270 | static void ide_cd_release(struct kref *kref) |
| @@ -3291,7 +3288,7 @@ static void ide_cd_release(struct kref *kref) | |||
| 3291 | kfree(info); | 3288 | kfree(info); |
| 3292 | } | 3289 | } |
| 3293 | 3290 | ||
| 3294 | static int ide_cd_probe(struct device *); | 3291 | static int ide_cd_probe(ide_drive_t *); |
| 3295 | 3292 | ||
| 3296 | #ifdef CONFIG_PROC_FS | 3293 | #ifdef CONFIG_PROC_FS |
| 3297 | static int proc_idecd_read_capacity | 3294 | static int proc_idecd_read_capacity |
| @@ -3317,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = { | |||
| 3317 | .owner = THIS_MODULE, | 3314 | .owner = THIS_MODULE, |
| 3318 | .name = "ide-cdrom", | 3315 | .name = "ide-cdrom", |
| 3319 | .bus = &ide_bus_type, | 3316 | .bus = &ide_bus_type, |
| 3320 | .probe = ide_cd_probe, | ||
| 3321 | .remove = ide_cd_remove, | ||
| 3322 | }, | 3317 | }, |
| 3318 | .probe = ide_cd_probe, | ||
| 3319 | .remove = ide_cd_remove, | ||
| 3323 | .version = IDECD_VERSION, | 3320 | .version = IDECD_VERSION, |
| 3324 | .media = ide_cdrom, | 3321 | .media = ide_cdrom, |
| 3325 | .supports_dsc_overlap = 1, | 3322 | .supports_dsc_overlap = 1, |
| @@ -3413,9 +3410,8 @@ static char *ignore = NULL; | |||
| 3413 | module_param(ignore, charp, 0400); | 3410 | module_param(ignore, charp, 0400); |
| 3414 | MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); | 3411 | MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); |
| 3415 | 3412 | ||
| 3416 | static int ide_cd_probe(struct device *dev) | 3413 | static int ide_cd_probe(ide_drive_t *drive) |
| 3417 | { | 3414 | { |
| 3418 | ide_drive_t *drive = to_ide_device(dev); | ||
| 3419 | struct cdrom_info *info; | 3415 | struct cdrom_info *info; |
| 3420 | struct gendisk *g; | 3416 | struct gendisk *g; |
| 3421 | struct request_sense sense; | 3417 | struct request_sense sense; |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index cab362ea0336..ca25f9e3d0f4 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) | |||
| 477 | && id->lba_capacity_2; | 477 | && id->lba_capacity_2; |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | static inline void idedisk_check_hpa(ide_drive_t *drive) | 480 | static void idedisk_check_hpa(ide_drive_t *drive) |
| 481 | { | 481 | { |
| 482 | unsigned long long capacity, set_max; | 482 | unsigned long long capacity, set_max; |
| 483 | int lba48 = idedisk_supports_lba48(drive->id); | 483 | int lba48 = idedisk_supports_lba48(drive->id); |
| @@ -997,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t *drive) | |||
| 997 | printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); | 997 | printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); |
| 998 | } | 998 | } |
| 999 | 999 | ||
| 1000 | static int ide_disk_remove(struct device *dev) | 1000 | static void ide_disk_remove(ide_drive_t *drive) |
| 1001 | { | 1001 | { |
| 1002 | ide_drive_t *drive = to_ide_device(dev); | ||
| 1003 | struct ide_disk_obj *idkp = drive->driver_data; | 1002 | struct ide_disk_obj *idkp = drive->driver_data; |
| 1004 | struct gendisk *g = idkp->disk; | 1003 | struct gendisk *g = idkp->disk; |
| 1005 | 1004 | ||
| @@ -1010,8 +1009,6 @@ static int ide_disk_remove(struct device *dev) | |||
| 1010 | ide_cacheflush_p(drive); | 1009 | ide_cacheflush_p(drive); |
| 1011 | 1010 | ||
| 1012 | ide_disk_put(idkp); | 1011 | ide_disk_put(idkp); |
| 1013 | |||
| 1014 | return 0; | ||
| 1015 | } | 1012 | } |
| 1016 | 1013 | ||
| 1017 | static void ide_disk_release(struct kref *kref) | 1014 | static void ide_disk_release(struct kref *kref) |
| @@ -1027,12 +1024,10 @@ static void ide_disk_release(struct kref *kref) | |||
| 1027 | kfree(idkp); | 1024 | kfree(idkp); |
| 1028 | } | 1025 | } |
| 1029 | 1026 | ||
| 1030 | static int ide_disk_probe(struct device *dev); | 1027 | static int ide_disk_probe(ide_drive_t *drive); |
| 1031 | 1028 | ||
| 1032 | static void ide_device_shutdown(struct device *dev) | 1029 | static void ide_device_shutdown(ide_drive_t *drive) |
| 1033 | { | 1030 | { |
| 1034 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); | ||
| 1035 | |||
| 1036 | #ifdef CONFIG_ALPHA | 1031 | #ifdef CONFIG_ALPHA |
| 1037 | /* On Alpha, halt(8) doesn't actually turn the machine off, | 1032 | /* On Alpha, halt(8) doesn't actually turn the machine off, |
| 1038 | it puts you into the sort of firmware monitor. Typically, | 1033 | it puts you into the sort of firmware monitor. Typically, |
| @@ -1054,7 +1049,7 @@ static void ide_device_shutdown(struct device *dev) | |||
| 1054 | } | 1049 | } |
| 1055 | 1050 | ||
| 1056 | printk("Shutdown: %s\n", drive->name); | 1051 | printk("Shutdown: %s\n", drive->name); |
| 1057 | dev->bus->suspend(dev, PMSG_SUSPEND); | 1052 | drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); |
| 1058 | } | 1053 | } |
| 1059 | 1054 | ||
| 1060 | static ide_driver_t idedisk_driver = { | 1055 | static ide_driver_t idedisk_driver = { |
| @@ -1062,10 +1057,10 @@ static ide_driver_t idedisk_driver = { | |||
| 1062 | .owner = THIS_MODULE, | 1057 | .owner = THIS_MODULE, |
| 1063 | .name = "ide-disk", | 1058 | .name = "ide-disk", |
| 1064 | .bus = &ide_bus_type, | 1059 | .bus = &ide_bus_type, |
| 1065 | .probe = ide_disk_probe, | ||
| 1066 | .remove = ide_disk_remove, | ||
| 1067 | .shutdown = ide_device_shutdown, | ||
| 1068 | }, | 1060 | }, |
| 1061 | .probe = ide_disk_probe, | ||
| 1062 | .remove = ide_disk_remove, | ||
| 1063 | .shutdown = ide_device_shutdown, | ||
| 1069 | .version = IDEDISK_VERSION, | 1064 | .version = IDEDISK_VERSION, |
| 1070 | .media = ide_disk, | 1065 | .media = ide_disk, |
| 1071 | .supports_dsc_overlap = 0, | 1066 | .supports_dsc_overlap = 0, |
| @@ -1182,9 +1177,8 @@ static struct block_device_operations idedisk_ops = { | |||
| 1182 | 1177 | ||
| 1183 | MODULE_DESCRIPTION("ATA DISK Driver"); | 1178 | MODULE_DESCRIPTION("ATA DISK Driver"); |
| 1184 | 1179 | ||
| 1185 | static int ide_disk_probe(struct device *dev) | 1180 | static int ide_disk_probe(ide_drive_t *drive) |
| 1186 | { | 1181 | { |
| 1187 | ide_drive_t *drive = to_ide_device(dev); | ||
| 1188 | struct ide_disk_obj *idkp; | 1182 | struct ide_disk_obj *idkp; |
| 1189 | struct gendisk *g; | 1183 | struct gendisk *g; |
| 1190 | 1184 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 5945f551aaaa..1f8db9ac05d1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
| @@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) | |||
| 1871 | idefloppy_add_settings(drive); | 1871 | idefloppy_add_settings(drive); |
| 1872 | } | 1872 | } |
| 1873 | 1873 | ||
| 1874 | static int ide_floppy_remove(struct device *dev) | 1874 | static void ide_floppy_remove(ide_drive_t *drive) |
| 1875 | { | 1875 | { |
| 1876 | ide_drive_t *drive = to_ide_device(dev); | ||
| 1877 | idefloppy_floppy_t *floppy = drive->driver_data; | 1876 | idefloppy_floppy_t *floppy = drive->driver_data; |
| 1878 | struct gendisk *g = floppy->disk; | 1877 | struct gendisk *g = floppy->disk; |
| 1879 | 1878 | ||
| @@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev) | |||
| 1882 | del_gendisk(g); | 1881 | del_gendisk(g); |
| 1883 | 1882 | ||
| 1884 | ide_floppy_put(floppy); | 1883 | ide_floppy_put(floppy); |
| 1885 | |||
| 1886 | return 0; | ||
| 1887 | } | 1884 | } |
| 1888 | 1885 | ||
| 1889 | static void ide_floppy_release(struct kref *kref) | 1886 | static void ide_floppy_release(struct kref *kref) |
| @@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = { | |||
| 1922 | 1919 | ||
| 1923 | #endif /* CONFIG_PROC_FS */ | 1920 | #endif /* CONFIG_PROC_FS */ |
| 1924 | 1921 | ||
| 1925 | static int ide_floppy_probe(struct device *); | 1922 | static int ide_floppy_probe(ide_drive_t *); |
| 1926 | 1923 | ||
| 1927 | static ide_driver_t idefloppy_driver = { | 1924 | static ide_driver_t idefloppy_driver = { |
| 1928 | .gen_driver = { | 1925 | .gen_driver = { |
| 1929 | .owner = THIS_MODULE, | 1926 | .owner = THIS_MODULE, |
| 1930 | .name = "ide-floppy", | 1927 | .name = "ide-floppy", |
| 1931 | .bus = &ide_bus_type, | 1928 | .bus = &ide_bus_type, |
| 1932 | .probe = ide_floppy_probe, | ||
| 1933 | .remove = ide_floppy_remove, | ||
| 1934 | }, | 1929 | }, |
| 1930 | .probe = ide_floppy_probe, | ||
| 1931 | .remove = ide_floppy_remove, | ||
| 1935 | .version = IDEFLOPPY_VERSION, | 1932 | .version = IDEFLOPPY_VERSION, |
| 1936 | .media = ide_floppy, | 1933 | .media = ide_floppy, |
| 1937 | .supports_dsc_overlap = 0, | 1934 | .supports_dsc_overlap = 0, |
| @@ -2136,9 +2133,8 @@ static struct block_device_operations idefloppy_ops = { | |||
| 2136 | .revalidate_disk= idefloppy_revalidate_disk | 2133 | .revalidate_disk= idefloppy_revalidate_disk |
| 2137 | }; | 2134 | }; |
| 2138 | 2135 | ||
| 2139 | static int ide_floppy_probe(struct device *dev) | 2136 | static int ide_floppy_probe(ide_drive_t *drive) |
| 2140 | { | 2137 | { |
| 2141 | ide_drive_t *drive = to_ide_device(dev); | ||
| 2142 | idefloppy_floppy_t *floppy; | 2138 | idefloppy_floppy_t *floppy; |
| 2143 | struct gendisk *g; | 2139 | struct gendisk *g; |
| 2144 | 2140 | ||
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index fab9b2b02504..0101d0def7c5 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
| @@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) | |||
| 4682 | idetape_add_settings(drive); | 4682 | idetape_add_settings(drive); |
| 4683 | } | 4683 | } |
| 4684 | 4684 | ||
| 4685 | static int ide_tape_remove(struct device *dev) | 4685 | static void ide_tape_remove(ide_drive_t *drive) |
| 4686 | { | 4686 | { |
| 4687 | ide_drive_t *drive = to_ide_device(dev); | ||
| 4688 | idetape_tape_t *tape = drive->driver_data; | 4687 | idetape_tape_t *tape = drive->driver_data; |
| 4689 | 4688 | ||
| 4690 | ide_unregister_subdriver(drive, tape->driver); | 4689 | ide_unregister_subdriver(drive, tape->driver); |
| @@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev) | |||
| 4692 | ide_unregister_region(tape->disk); | 4691 | ide_unregister_region(tape->disk); |
| 4693 | 4692 | ||
| 4694 | ide_tape_put(tape); | 4693 | ide_tape_put(tape); |
| 4695 | |||
| 4696 | return 0; | ||
| 4697 | } | 4694 | } |
| 4698 | 4695 | ||
| 4699 | static void ide_tape_release(struct kref *kref) | 4696 | static void ide_tape_release(struct kref *kref) |
| @@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = { | |||
| 4745 | 4742 | ||
| 4746 | #endif | 4743 | #endif |
| 4747 | 4744 | ||
| 4748 | static int ide_tape_probe(struct device *); | 4745 | static int ide_tape_probe(ide_drive_t *); |
| 4749 | 4746 | ||
| 4750 | static ide_driver_t idetape_driver = { | 4747 | static ide_driver_t idetape_driver = { |
| 4751 | .gen_driver = { | 4748 | .gen_driver = { |
| 4752 | .owner = THIS_MODULE, | 4749 | .owner = THIS_MODULE, |
| 4753 | .name = "ide-tape", | 4750 | .name = "ide-tape", |
| 4754 | .bus = &ide_bus_type, | 4751 | .bus = &ide_bus_type, |
| 4755 | .probe = ide_tape_probe, | ||
| 4756 | .remove = ide_tape_remove, | ||
| 4757 | }, | 4752 | }, |
| 4753 | .probe = ide_tape_probe, | ||
| 4754 | .remove = ide_tape_remove, | ||
| 4758 | .version = IDETAPE_VERSION, | 4755 | .version = IDETAPE_VERSION, |
| 4759 | .media = ide_tape, | 4756 | .media = ide_tape, |
| 4760 | .supports_dsc_overlap = 1, | 4757 | .supports_dsc_overlap = 1, |
| @@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = { | |||
| 4825 | .ioctl = idetape_ioctl, | 4822 | .ioctl = idetape_ioctl, |
| 4826 | }; | 4823 | }; |
| 4827 | 4824 | ||
| 4828 | static int ide_tape_probe(struct device *dev) | 4825 | static int ide_tape_probe(ide_drive_t *drive) |
| 4829 | { | 4826 | { |
| 4830 | ide_drive_t *drive = to_ide_device(dev); | ||
| 4831 | idetape_tape_t *tape; | 4827 | idetape_tape_t *tape; |
| 4832 | struct gendisk *g; | 4828 | struct gendisk *g; |
| 4833 | int minor; | 4829 | int minor; |
| @@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device *dev) | |||
| 4883 | idetape_setup(drive, tape, minor); | 4879 | idetape_setup(drive, tape, minor); |
| 4884 | 4880 | ||
| 4885 | class_device_create(idetape_sysfs_class, NULL, | 4881 | class_device_create(idetape_sysfs_class, NULL, |
| 4886 | MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name); | 4882 | MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name); |
| 4887 | class_device_create(idetape_sysfs_class, NULL, | 4883 | class_device_create(idetape_sysfs_class, NULL, |
| 4888 | MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name); | 4884 | MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name); |
| 4889 | 4885 | ||
| 4890 | devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), | 4886 | devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), |
| 4891 | S_IFCHR | S_IRUGO | S_IWUGO, | 4887 | S_IFCHR | S_IRUGO | S_IWUGO, |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 62ebefd6394a..9834dce4e20f 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
| @@ -308,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) | |||
| 308 | ide_pio_sector(drive, write); | 308 | ide_pio_sector(drive, write); |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, | 311 | static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, |
| 312 | unsigned int write) | 312 | unsigned int write) |
| 313 | { | 313 | { |
| 314 | if (rq->bio) /* fs request */ | 314 | if (rq->bio) /* fs request */ |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ec5a4cb173b0..afeb02bbb722 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
| @@ -1949,10 +1949,41 @@ static int ide_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1949 | return 0; | 1949 | return 0; |
| 1950 | } | 1950 | } |
| 1951 | 1951 | ||
| 1952 | static int generic_ide_probe(struct device *dev) | ||
| 1953 | { | ||
| 1954 | ide_drive_t *drive = to_ide_device(dev); | ||
| 1955 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
| 1956 | |||
| 1957 | return drv->probe ? drv->probe(drive) : -ENODEV; | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | static int generic_ide_remove(struct device *dev) | ||
| 1961 | { | ||
| 1962 | ide_drive_t *drive = to_ide_device(dev); | ||
| 1963 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
| 1964 | |||
| 1965 | if (drv->remove) | ||
| 1966 | drv->remove(drive); | ||
| 1967 | |||
| 1968 | return 0; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | static void generic_ide_shutdown(struct device *dev) | ||
| 1972 | { | ||
| 1973 | ide_drive_t *drive = to_ide_device(dev); | ||
| 1974 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
| 1975 | |||
| 1976 | if (dev->driver && drv->shutdown) | ||
| 1977 | drv->shutdown(drive); | ||
| 1978 | } | ||
| 1979 | |||
| 1952 | struct bus_type ide_bus_type = { | 1980 | struct bus_type ide_bus_type = { |
| 1953 | .name = "ide", | 1981 | .name = "ide", |
| 1954 | .match = ide_bus_match, | 1982 | .match = ide_bus_match, |
| 1955 | .uevent = ide_uevent, | 1983 | .uevent = ide_uevent, |
| 1984 | .probe = generic_ide_probe, | ||
| 1985 | .remove = generic_ide_remove, | ||
| 1986 | .shutdown = generic_ide_shutdown, | ||
| 1956 | .dev_attrs = ide_dev_attrs, | 1987 | .dev_attrs = ide_dev_attrs, |
| 1957 | .suspend = generic_ide_suspend, | 1988 | .suspend = generic_ide_suspend, |
| 1958 | .resume = generic_ide_resume, | 1989 | .resume = generic_ide_resume, |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 3a611fe5497e..2514de3480d8 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
| @@ -856,7 +856,7 @@ static void cm_format_req(struct cm_req_msg *req_msg, | |||
| 856 | param->private_data_len); | 856 | param->private_data_len); |
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | static inline int cm_validate_req_param(struct ib_cm_req_param *param) | 859 | static int cm_validate_req_param(struct ib_cm_req_param *param) |
| 860 | { | 860 | { |
| 861 | /* peer-to-peer not supported */ | 861 | /* peer-to-peer not supported */ |
| 862 | if (param->peer_to_peer) | 862 | if (param->peer_to_peer) |
| @@ -1005,7 +1005,7 @@ static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid, | |||
| 1005 | (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn)))); | 1005 | (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn)))); |
| 1006 | } | 1006 | } |
| 1007 | 1007 | ||
| 1008 | static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg, | 1008 | static void cm_format_paths_from_req(struct cm_req_msg *req_msg, |
| 1009 | struct ib_sa_path_rec *primary_path, | 1009 | struct ib_sa_path_rec *primary_path, |
| 1010 | struct ib_sa_path_rec *alt_path) | 1010 | struct ib_sa_path_rec *alt_path) |
| 1011 | { | 1011 | { |
| @@ -3163,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id, | |||
| 3163 | } | 3163 | } |
| 3164 | EXPORT_SYMBOL(ib_cm_init_qp_attr); | 3164 | EXPORT_SYMBOL(ib_cm_init_qp_attr); |
| 3165 | 3165 | ||
| 3166 | static __be64 cm_get_ca_guid(struct ib_device *device) | ||
| 3167 | { | ||
| 3168 | struct ib_device_attr *device_attr; | ||
| 3169 | __be64 guid; | ||
| 3170 | int ret; | ||
| 3171 | |||
| 3172 | device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); | ||
| 3173 | if (!device_attr) | ||
| 3174 | return 0; | ||
| 3175 | |||
| 3176 | ret = ib_query_device(device, device_attr); | ||
| 3177 | guid = ret ? 0 : device_attr->node_guid; | ||
| 3178 | kfree(device_attr); | ||
| 3179 | return guid; | ||
| 3180 | } | ||
| 3181 | |||
| 3182 | static void cm_add_one(struct ib_device *device) | 3166 | static void cm_add_one(struct ib_device *device) |
| 3183 | { | 3167 | { |
| 3184 | struct cm_device *cm_dev; | 3168 | struct cm_device *cm_dev; |
| @@ -3200,9 +3184,7 @@ static void cm_add_one(struct ib_device *device) | |||
| 3200 | return; | 3184 | return; |
| 3201 | 3185 | ||
| 3202 | cm_dev->device = device; | 3186 | cm_dev->device = device; |
| 3203 | cm_dev->ca_guid = cm_get_ca_guid(device); | 3187 | cm_dev->ca_guid = device->node_guid; |
| 3204 | if (!cm_dev->ca_guid) | ||
| 3205 | goto error1; | ||
| 3206 | 3188 | ||
| 3207 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); | 3189 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); |
| 3208 | for (i = 1; i <= device->phys_port_cnt; i++) { | 3190 | for (i = 1; i <= device->phys_port_cnt; i++) { |
| @@ -3217,11 +3199,11 @@ static void cm_add_one(struct ib_device *device) | |||
| 3217 | cm_recv_handler, | 3199 | cm_recv_handler, |
| 3218 | port); | 3200 | port); |
| 3219 | if (IS_ERR(port->mad_agent)) | 3201 | if (IS_ERR(port->mad_agent)) |
| 3220 | goto error2; | 3202 | goto error1; |
| 3221 | 3203 | ||
| 3222 | ret = ib_modify_port(device, i, 0, &port_modify); | 3204 | ret = ib_modify_port(device, i, 0, &port_modify); |
| 3223 | if (ret) | 3205 | if (ret) |
| 3224 | goto error3; | 3206 | goto error2; |
| 3225 | } | 3207 | } |
| 3226 | ib_set_client_data(device, &cm_client, cm_dev); | 3208 | ib_set_client_data(device, &cm_client, cm_dev); |
| 3227 | 3209 | ||
| @@ -3230,9 +3212,9 @@ static void cm_add_one(struct ib_device *device) | |||
| 3230 | write_unlock_irqrestore(&cm.device_lock, flags); | 3212 | write_unlock_irqrestore(&cm.device_lock, flags); |
| 3231 | return; | 3213 | return; |
| 3232 | 3214 | ||
| 3233 | error3: | ||
| 3234 | ib_unregister_mad_agent(port->mad_agent); | ||
| 3235 | error2: | 3215 | error2: |
| 3216 | ib_unregister_mad_agent(port->mad_agent); | ||
| 3217 | error1: | ||
| 3236 | port_modify.set_port_cap_mask = 0; | 3218 | port_modify.set_port_cap_mask = 0; |
| 3237 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; | 3219 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; |
| 3238 | while (--i) { | 3220 | while (--i) { |
| @@ -3240,7 +3222,6 @@ error2: | |||
| 3240 | ib_modify_port(device, port->port_num, 0, &port_modify); | 3222 | ib_modify_port(device, port->port_num, 0, &port_modify); |
| 3241 | ib_unregister_mad_agent(port->mad_agent); | 3223 | ib_unregister_mad_agent(port->mad_agent); |
| 3242 | } | 3224 | } |
| 3243 | error1: | ||
| 3244 | kfree(cm_dev); | 3225 | kfree(cm_dev); |
| 3245 | } | 3226 | } |
| 3246 | 3227 | ||
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index e169e798354b..b2f3cb91d9bc 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
| @@ -38,8 +38,7 @@ | |||
| 38 | #include <linux/errno.h> | 38 | #include <linux/errno.h> |
| 39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
| 40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
| 41 | 41 | #include <linux/mutex.h> | |
| 42 | #include <asm/semaphore.h> | ||
| 43 | 42 | ||
| 44 | #include "core_priv.h" | 43 | #include "core_priv.h" |
| 45 | 44 | ||
| @@ -57,13 +56,13 @@ static LIST_HEAD(device_list); | |||
| 57 | static LIST_HEAD(client_list); | 56 | static LIST_HEAD(client_list); |
| 58 | 57 | ||
| 59 | /* | 58 | /* |
| 60 | * device_sem protects access to both device_list and client_list. | 59 | * device_mutex protects access to both device_list and client_list. |
| 61 | * There's no real point to using multiple locks or something fancier | 60 | * There's no real point to using multiple locks or something fancier |
| 62 | * like an rwsem: we always access both lists, and we're always | 61 | * like an rwsem: we always access both lists, and we're always |
| 63 | * modifying one list or the other list. In any case this is not a | 62 | * modifying one list or the other list. In any case this is not a |
| 64 | * hot path so there's no point in trying to optimize. | 63 | * hot path so there's no point in trying to optimize. |
| 65 | */ | 64 | */ |
| 66 | static DECLARE_MUTEX(device_sem); | 65 | static DEFINE_MUTEX(device_mutex); |
| 67 | 66 | ||
| 68 | static int ib_device_check_mandatory(struct ib_device *device) | 67 | static int ib_device_check_mandatory(struct ib_device *device) |
| 69 | { | 68 | { |
| @@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device) | |||
| 221 | { | 220 | { |
| 222 | int ret; | 221 | int ret; |
| 223 | 222 | ||
| 224 | down(&device_sem); | 223 | mutex_lock(&device_mutex); |
| 225 | 224 | ||
| 226 | if (strchr(device->name, '%')) { | 225 | if (strchr(device->name, '%')) { |
| 227 | ret = alloc_name(device->name); | 226 | ret = alloc_name(device->name); |
| @@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device) | |||
| 259 | } | 258 | } |
| 260 | 259 | ||
| 261 | out: | 260 | out: |
| 262 | up(&device_sem); | 261 | mutex_unlock(&device_mutex); |
| 263 | return ret; | 262 | return ret; |
| 264 | } | 263 | } |
| 265 | EXPORT_SYMBOL(ib_register_device); | 264 | EXPORT_SYMBOL(ib_register_device); |
| @@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device) | |||
| 276 | struct ib_client_data *context, *tmp; | 275 | struct ib_client_data *context, *tmp; |
| 277 | unsigned long flags; | 276 | unsigned long flags; |
| 278 | 277 | ||
| 279 | down(&device_sem); | 278 | mutex_lock(&device_mutex); |
| 280 | 279 | ||
| 281 | list_for_each_entry_reverse(client, &client_list, list) | 280 | list_for_each_entry_reverse(client, &client_list, list) |
| 282 | if (client->remove) | 281 | if (client->remove) |
| @@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device) | |||
| 284 | 283 | ||
| 285 | list_del(&device->core_list); | 284 | list_del(&device->core_list); |
| 286 | 285 | ||
| 287 | up(&device_sem); | 286 | mutex_unlock(&device_mutex); |
| 288 | 287 | ||
| 289 | spin_lock_irqsave(&device->client_data_lock, flags); | 288 | spin_lock_irqsave(&device->client_data_lock, flags); |
| 290 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) | 289 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) |
| @@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client) | |||
| 312 | { | 311 | { |
| 313 | struct ib_device *device; | 312 | struct ib_device *device; |
| 314 | 313 | ||
| 315 | down(&device_sem); | 314 | mutex_lock(&device_mutex); |
| 316 | 315 | ||
| 317 | list_add_tail(&client->list, &client_list); | 316 | list_add_tail(&client->list, &client_list); |
| 318 | list_for_each_entry(device, &device_list, core_list) | 317 | list_for_each_entry(device, &device_list, core_list) |
| 319 | if (client->add && !add_client_context(device, client)) | 318 | if (client->add && !add_client_context(device, client)) |
| 320 | client->add(device); | 319 | client->add(device); |
| 321 | 320 | ||
| 322 | up(&device_sem); | 321 | mutex_unlock(&device_mutex); |
| 323 | 322 | ||
| 324 | return 0; | 323 | return 0; |
| 325 | } | 324 | } |
| @@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client) | |||
| 339 | struct ib_device *device; | 338 | struct ib_device *device; |
| 340 | unsigned long flags; | 339 | unsigned long flags; |
| 341 | 340 | ||
| 342 | down(&device_sem); | 341 | mutex_lock(&device_mutex); |
| 343 | 342 | ||
| 344 | list_for_each_entry(device, &device_list, core_list) { | 343 | list_for_each_entry(device, &device_list, core_list) { |
| 345 | if (client->remove) | 344 | if (client->remove) |
| @@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client) | |||
| 355 | } | 354 | } |
| 356 | list_del(&client->list); | 355 | list_del(&client->list); |
| 357 | 356 | ||
| 358 | up(&device_sem); | 357 | mutex_unlock(&device_mutex); |
| 359 | } | 358 | } |
| 360 | EXPORT_SYMBOL(ib_unregister_client); | 359 | EXPORT_SYMBOL(ib_unregister_client); |
| 361 | 360 | ||
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 1f1743c5c9a3..5982d687a000 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
| @@ -445,13 +445,7 @@ static int ib_device_uevent(struct class_device *cdev, char **envp, | |||
| 445 | return -ENOMEM; | 445 | return -ENOMEM; |
| 446 | 446 | ||
| 447 | /* | 447 | /* |
| 448 | * It might be nice to pass the node GUID with the event, but | 448 | * It would be nice to pass the node GUID with the event... |
| 449 | * right now the only way to get it is to query the device | ||
| 450 | * provider, and this can crash during device removal because | ||
| 451 | * we are will be running after driver removal has started. | ||
| 452 | * We could add a node_guid field to struct ib_device, or we | ||
| 453 | * could just let userspace read the node GUID from sysfs when | ||
| 454 | * devices are added. | ||
| 455 | */ | 449 | */ |
| 456 | 450 | ||
| 457 | envp[i] = NULL; | 451 | envp[i] = NULL; |
| @@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf) | |||
| 623 | static ssize_t show_node_guid(struct class_device *cdev, char *buf) | 617 | static ssize_t show_node_guid(struct class_device *cdev, char *buf) |
| 624 | { | 618 | { |
| 625 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); | 619 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); |
| 626 | struct ib_device_attr attr; | ||
| 627 | ssize_t ret; | ||
| 628 | 620 | ||
| 629 | if (!ibdev_is_alive(dev)) | 621 | if (!ibdev_is_alive(dev)) |
| 630 | return -ENODEV; | 622 | return -ENODEV; |
| 631 | 623 | ||
| 632 | ret = ib_query_device(dev, &attr); | ||
| 633 | if (ret) | ||
| 634 | return ret; | ||
| 635 | |||
| 636 | return sprintf(buf, "%04x:%04x:%04x:%04x\n", | 624 | return sprintf(buf, "%04x:%04x:%04x:%04x\n", |
| 637 | be16_to_cpu(((__be16 *) &attr.node_guid)[0]), | 625 | be16_to_cpu(((__be16 *) &dev->node_guid)[0]), |
| 638 | be16_to_cpu(((__be16 *) &attr.node_guid)[1]), | 626 | be16_to_cpu(((__be16 *) &dev->node_guid)[1]), |
| 639 | be16_to_cpu(((__be16 *) &attr.node_guid)[2]), | 627 | be16_to_cpu(((__be16 *) &dev->node_guid)[2]), |
| 640 | be16_to_cpu(((__be16 *) &attr.node_guid)[3])); | 628 | be16_to_cpu(((__be16 *) &dev->node_guid)[3])); |
| 641 | } | 629 | } |
| 642 | 630 | ||
| 643 | static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); | 631 | static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 6e15787d1de1..e95c4293a496 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/mount.h> | 42 | #include <linux/mount.h> |
| 43 | #include <linux/cdev.h> | 43 | #include <linux/cdev.h> |
| 44 | #include <linux/idr.h> | 44 | #include <linux/idr.h> |
| 45 | #include <linux/mutex.h> | ||
| 45 | 46 | ||
| 46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
| 47 | 48 | ||
| @@ -113,7 +114,7 @@ static struct ib_client ucm_client = { | |||
| 113 | .remove = ib_ucm_remove_one | 114 | .remove = ib_ucm_remove_one |
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 116 | static DECLARE_MUTEX(ctx_id_mutex); | 117 | static DEFINE_MUTEX(ctx_id_mutex); |
| 117 | static DEFINE_IDR(ctx_id_table); | 118 | static DEFINE_IDR(ctx_id_table); |
| 118 | static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); | 119 | static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); |
| 119 | 120 | ||
| @@ -121,7 +122,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | |||
| 121 | { | 122 | { |
| 122 | struct ib_ucm_context *ctx; | 123 | struct ib_ucm_context *ctx; |
| 123 | 124 | ||
| 124 | down(&ctx_id_mutex); | 125 | mutex_lock(&ctx_id_mutex); |
| 125 | ctx = idr_find(&ctx_id_table, id); | 126 | ctx = idr_find(&ctx_id_table, id); |
| 126 | if (!ctx) | 127 | if (!ctx) |
| 127 | ctx = ERR_PTR(-ENOENT); | 128 | ctx = ERR_PTR(-ENOENT); |
| @@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | |||
| 129 | ctx = ERR_PTR(-EINVAL); | 130 | ctx = ERR_PTR(-EINVAL); |
| 130 | else | 131 | else |
| 131 | atomic_inc(&ctx->ref); | 132 | atomic_inc(&ctx->ref); |
| 132 | up(&ctx_id_mutex); | 133 | mutex_unlock(&ctx_id_mutex); |
| 133 | 134 | ||
| 134 | return ctx; | 135 | return ctx; |
| 135 | } | 136 | } |
| @@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | |||
| 186 | if (!result) | 187 | if (!result) |
| 187 | goto error; | 188 | goto error; |
| 188 | 189 | ||
| 189 | down(&ctx_id_mutex); | 190 | mutex_lock(&ctx_id_mutex); |
| 190 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); | 191 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); |
| 191 | up(&ctx_id_mutex); | 192 | mutex_unlock(&ctx_id_mutex); |
| 192 | } while (result == -EAGAIN); | 193 | } while (result == -EAGAIN); |
| 193 | 194 | ||
| 194 | if (result) | 195 | if (result) |
| @@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, | |||
| 550 | err2: | 551 | err2: |
| 551 | ib_destroy_cm_id(ctx->cm_id); | 552 | ib_destroy_cm_id(ctx->cm_id); |
| 552 | err1: | 553 | err1: |
| 553 | down(&ctx_id_mutex); | 554 | mutex_lock(&ctx_id_mutex); |
| 554 | idr_remove(&ctx_id_table, ctx->id); | 555 | idr_remove(&ctx_id_table, ctx->id); |
| 555 | up(&ctx_id_mutex); | 556 | mutex_unlock(&ctx_id_mutex); |
| 556 | kfree(ctx); | 557 | kfree(ctx); |
| 557 | return result; | 558 | return result; |
| 558 | } | 559 | } |
| @@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
| 572 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 573 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
| 573 | return -EFAULT; | 574 | return -EFAULT; |
| 574 | 575 | ||
| 575 | down(&ctx_id_mutex); | 576 | mutex_lock(&ctx_id_mutex); |
| 576 | ctx = idr_find(&ctx_id_table, cmd.id); | 577 | ctx = idr_find(&ctx_id_table, cmd.id); |
| 577 | if (!ctx) | 578 | if (!ctx) |
| 578 | ctx = ERR_PTR(-ENOENT); | 579 | ctx = ERR_PTR(-ENOENT); |
| @@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
| 580 | ctx = ERR_PTR(-EINVAL); | 581 | ctx = ERR_PTR(-EINVAL); |
| 581 | else | 582 | else |
| 582 | idr_remove(&ctx_id_table, ctx->id); | 583 | idr_remove(&ctx_id_table, ctx->id); |
| 583 | up(&ctx_id_mutex); | 584 | mutex_unlock(&ctx_id_mutex); |
| 584 | 585 | ||
| 585 | if (IS_ERR(ctx)) | 586 | if (IS_ERR(ctx)) |
| 586 | return PTR_ERR(ctx); | 587 | return PTR_ERR(ctx); |
| @@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) | |||
| 1280 | struct ib_ucm_context, file_list); | 1281 | struct ib_ucm_context, file_list); |
| 1281 | up(&file->mutex); | 1282 | up(&file->mutex); |
| 1282 | 1283 | ||
| 1283 | down(&ctx_id_mutex); | 1284 | mutex_lock(&ctx_id_mutex); |
| 1284 | idr_remove(&ctx_id_table, ctx->id); | 1285 | idr_remove(&ctx_id_table, ctx->id); |
| 1285 | up(&ctx_id_mutex); | 1286 | mutex_unlock(&ctx_id_mutex); |
| 1286 | 1287 | ||
| 1287 | ib_destroy_cm_id(ctx->cm_id); | 1288 | ib_destroy_cm_id(ctx->cm_id); |
| 1288 | ib_ucm_cleanup_events(ctx); | 1289 | ib_ucm_cleanup_events(ctx); |
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 7114e3fbab00..f7eecbc6af6c 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | 41 | ||
| 42 | #include <linux/kref.h> | 42 | #include <linux/kref.h> |
| 43 | #include <linux/idr.h> | 43 | #include <linux/idr.h> |
| 44 | #include <linux/mutex.h> | ||
| 44 | 45 | ||
| 45 | #include <rdma/ib_verbs.h> | 46 | #include <rdma/ib_verbs.h> |
| 46 | #include <rdma/ib_user_verbs.h> | 47 | #include <rdma/ib_user_verbs.h> |
| @@ -88,7 +89,7 @@ struct ib_uverbs_event_file { | |||
| 88 | 89 | ||
| 89 | struct ib_uverbs_file { | 90 | struct ib_uverbs_file { |
| 90 | struct kref ref; | 91 | struct kref ref; |
| 91 | struct semaphore mutex; | 92 | struct mutex mutex; |
| 92 | struct ib_uverbs_device *device; | 93 | struct ib_uverbs_device *device; |
| 93 | struct ib_ucontext *ucontext; | 94 | struct ib_ucontext *ucontext; |
| 94 | struct ib_event_handler event_handler; | 95 | struct ib_event_handler event_handler; |
| @@ -131,7 +132,7 @@ struct ib_ucq_object { | |||
| 131 | u32 async_events_reported; | 132 | u32 async_events_reported; |
| 132 | }; | 133 | }; |
| 133 | 134 | ||
| 134 | extern struct semaphore ib_uverbs_idr_mutex; | 135 | extern struct mutex ib_uverbs_idr_mutex; |
| 135 | extern struct idr ib_uverbs_pd_idr; | 136 | extern struct idr ib_uverbs_pd_idr; |
| 136 | extern struct idr ib_uverbs_mr_idr; | 137 | extern struct idr ib_uverbs_mr_idr; |
| 137 | extern struct idr ib_uverbs_mw_idr; | 138 | extern struct idr ib_uverbs_mw_idr; |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a02c5a05c984..407b6284d7d5 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
| @@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
| 67 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 67 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 68 | return -EFAULT; | 68 | return -EFAULT; |
| 69 | 69 | ||
| 70 | down(&file->mutex); | 70 | mutex_lock(&file->mutex); |
| 71 | 71 | ||
| 72 | if (file->ucontext) { | 72 | if (file->ucontext) { |
| 73 | ret = -EINVAL; | 73 | ret = -EINVAL; |
| @@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
| 119 | 119 | ||
| 120 | fd_install(resp.async_fd, filp); | 120 | fd_install(resp.async_fd, filp); |
| 121 | 121 | ||
| 122 | up(&file->mutex); | 122 | mutex_unlock(&file->mutex); |
| 123 | 123 | ||
| 124 | return in_len; | 124 | return in_len; |
| 125 | 125 | ||
| @@ -131,7 +131,7 @@ err_free: | |||
| 131 | ibdev->dealloc_ucontext(ucontext); | 131 | ibdev->dealloc_ucontext(ucontext); |
| 132 | 132 | ||
| 133 | err: | 133 | err: |
| 134 | up(&file->mutex); | 134 | mutex_unlock(&file->mutex); |
| 135 | return ret; | 135 | return ret; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| @@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, | |||
| 157 | memset(&resp, 0, sizeof resp); | 157 | memset(&resp, 0, sizeof resp); |
| 158 | 158 | ||
| 159 | resp.fw_ver = attr.fw_ver; | 159 | resp.fw_ver = attr.fw_ver; |
| 160 | resp.node_guid = attr.node_guid; | 160 | resp.node_guid = file->device->ib_dev->node_guid; |
| 161 | resp.sys_image_guid = attr.sys_image_guid; | 161 | resp.sys_image_guid = attr.sys_image_guid; |
| 162 | resp.max_mr_size = attr.max_mr_size; | 162 | resp.max_mr_size = attr.max_mr_size; |
| 163 | resp.page_size_cap = attr.page_size_cap; | 163 | resp.page_size_cap = attr.page_size_cap; |
| @@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, | |||
| 290 | pd->uobject = uobj; | 290 | pd->uobject = uobj; |
| 291 | atomic_set(&pd->usecnt, 0); | 291 | atomic_set(&pd->usecnt, 0); |
| 292 | 292 | ||
| 293 | down(&ib_uverbs_idr_mutex); | 293 | mutex_lock(&ib_uverbs_idr_mutex); |
| 294 | 294 | ||
| 295 | retry: | 295 | retry: |
| 296 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { | 296 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { |
| @@ -314,11 +314,11 @@ retry: | |||
| 314 | goto err_idr; | 314 | goto err_idr; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | down(&file->mutex); | 317 | mutex_lock(&file->mutex); |
| 318 | list_add_tail(&uobj->list, &file->ucontext->pd_list); | 318 | list_add_tail(&uobj->list, &file->ucontext->pd_list); |
| 319 | up(&file->mutex); | 319 | mutex_unlock(&file->mutex); |
| 320 | 320 | ||
| 321 | up(&ib_uverbs_idr_mutex); | 321 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 322 | 322 | ||
| 323 | return in_len; | 323 | return in_len; |
| 324 | 324 | ||
| @@ -326,7 +326,7 @@ err_idr: | |||
| 326 | idr_remove(&ib_uverbs_pd_idr, uobj->id); | 326 | idr_remove(&ib_uverbs_pd_idr, uobj->id); |
| 327 | 327 | ||
| 328 | err_up: | 328 | err_up: |
| 329 | up(&ib_uverbs_idr_mutex); | 329 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 330 | ib_dealloc_pd(pd); | 330 | ib_dealloc_pd(pd); |
| 331 | 331 | ||
| 332 | err: | 332 | err: |
| @@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, | |||
| 346 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 346 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 347 | return -EFAULT; | 347 | return -EFAULT; |
| 348 | 348 | ||
| 349 | down(&ib_uverbs_idr_mutex); | 349 | mutex_lock(&ib_uverbs_idr_mutex); |
| 350 | 350 | ||
| 351 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 351 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
| 352 | if (!pd || pd->uobject->context != file->ucontext) | 352 | if (!pd || pd->uobject->context != file->ucontext) |
| @@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, | |||
| 360 | 360 | ||
| 361 | idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); | 361 | idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); |
| 362 | 362 | ||
| 363 | down(&file->mutex); | 363 | mutex_lock(&file->mutex); |
| 364 | list_del(&uobj->list); | 364 | list_del(&uobj->list); |
| 365 | up(&file->mutex); | 365 | mutex_unlock(&file->mutex); |
| 366 | 366 | ||
| 367 | kfree(uobj); | 367 | kfree(uobj); |
| 368 | 368 | ||
| 369 | out: | 369 | out: |
| 370 | up(&ib_uverbs_idr_mutex); | 370 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 371 | 371 | ||
| 372 | return ret ? ret : in_len; | 372 | return ret ? ret : in_len; |
| 373 | } | 373 | } |
| @@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, | |||
| 426 | 426 | ||
| 427 | obj->umem.virt_base = cmd.hca_va; | 427 | obj->umem.virt_base = cmd.hca_va; |
| 428 | 428 | ||
| 429 | down(&ib_uverbs_idr_mutex); | 429 | mutex_lock(&ib_uverbs_idr_mutex); |
| 430 | 430 | ||
| 431 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 431 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
| 432 | if (!pd || pd->uobject->context != file->ucontext) { | 432 | if (!pd || pd->uobject->context != file->ucontext) { |
| @@ -476,11 +476,11 @@ retry: | |||
| 476 | goto err_idr; | 476 | goto err_idr; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | down(&file->mutex); | 479 | mutex_lock(&file->mutex); |
| 480 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); | 480 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); |
| 481 | up(&file->mutex); | 481 | mutex_unlock(&file->mutex); |
| 482 | 482 | ||
| 483 | up(&ib_uverbs_idr_mutex); | 483 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 484 | 484 | ||
| 485 | return in_len; | 485 | return in_len; |
| 486 | 486 | ||
| @@ -492,7 +492,7 @@ err_unreg: | |||
| 492 | atomic_dec(&pd->usecnt); | 492 | atomic_dec(&pd->usecnt); |
| 493 | 493 | ||
| 494 | err_up: | 494 | err_up: |
| 495 | up(&ib_uverbs_idr_mutex); | 495 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 496 | 496 | ||
| 497 | ib_umem_release(file->device->ib_dev, &obj->umem); | 497 | ib_umem_release(file->device->ib_dev, &obj->umem); |
| 498 | 498 | ||
| @@ -513,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | |||
| 513 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 513 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 514 | return -EFAULT; | 514 | return -EFAULT; |
| 515 | 515 | ||
| 516 | down(&ib_uverbs_idr_mutex); | 516 | mutex_lock(&ib_uverbs_idr_mutex); |
| 517 | 517 | ||
| 518 | mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); | 518 | mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); |
| 519 | if (!mr || mr->uobject->context != file->ucontext) | 519 | if (!mr || mr->uobject->context != file->ucontext) |
| @@ -527,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | |||
| 527 | 527 | ||
| 528 | idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); | 528 | idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); |
| 529 | 529 | ||
| 530 | down(&file->mutex); | 530 | mutex_lock(&file->mutex); |
| 531 | list_del(&memobj->uobject.list); | 531 | list_del(&memobj->uobject.list); |
| 532 | up(&file->mutex); | 532 | mutex_unlock(&file->mutex); |
| 533 | 533 | ||
| 534 | ib_umem_release(file->device->ib_dev, &memobj->umem); | 534 | ib_umem_release(file->device->ib_dev, &memobj->umem); |
| 535 | kfree(memobj); | 535 | kfree(memobj); |
| 536 | 536 | ||
| 537 | out: | 537 | out: |
| 538 | up(&ib_uverbs_idr_mutex); | 538 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 539 | 539 | ||
| 540 | return ret ? ret : in_len; | 540 | return ret ? ret : in_len; |
| 541 | } | 541 | } |
| @@ -628,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
| 628 | cq->cq_context = ev_file; | 628 | cq->cq_context = ev_file; |
| 629 | atomic_set(&cq->usecnt, 0); | 629 | atomic_set(&cq->usecnt, 0); |
| 630 | 630 | ||
| 631 | down(&ib_uverbs_idr_mutex); | 631 | mutex_lock(&ib_uverbs_idr_mutex); |
| 632 | 632 | ||
| 633 | retry: | 633 | retry: |
| 634 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { | 634 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { |
| @@ -653,11 +653,11 @@ retry: | |||
| 653 | goto err_idr; | 653 | goto err_idr; |
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | down(&file->mutex); | 656 | mutex_lock(&file->mutex); |
| 657 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); | 657 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); |
| 658 | up(&file->mutex); | 658 | mutex_unlock(&file->mutex); |
| 659 | 659 | ||
| 660 | up(&ib_uverbs_idr_mutex); | 660 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 661 | 661 | ||
| 662 | return in_len; | 662 | return in_len; |
| 663 | 663 | ||
| @@ -665,7 +665,7 @@ err_idr: | |||
| 665 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); | 665 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); |
| 666 | 666 | ||
| 667 | err_up: | 667 | err_up: |
| 668 | up(&ib_uverbs_idr_mutex); | 668 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 669 | ib_destroy_cq(cq); | 669 | ib_destroy_cq(cq); |
| 670 | 670 | ||
| 671 | err: | 671 | err: |
| @@ -701,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
| 701 | goto out_wc; | 701 | goto out_wc; |
| 702 | } | 702 | } |
| 703 | 703 | ||
| 704 | down(&ib_uverbs_idr_mutex); | 704 | mutex_lock(&ib_uverbs_idr_mutex); |
| 705 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 705 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
| 706 | if (!cq || cq->uobject->context != file->ucontext) { | 706 | if (!cq || cq->uobject->context != file->ucontext) { |
| 707 | ret = -EINVAL; | 707 | ret = -EINVAL; |
| @@ -731,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
| 731 | ret = -EFAULT; | 731 | ret = -EFAULT; |
| 732 | 732 | ||
| 733 | out: | 733 | out: |
| 734 | up(&ib_uverbs_idr_mutex); | 734 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 735 | kfree(resp); | 735 | kfree(resp); |
| 736 | 736 | ||
| 737 | out_wc: | 737 | out_wc: |
| @@ -750,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, | |||
| 750 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 750 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 751 | return -EFAULT; | 751 | return -EFAULT; |
| 752 | 752 | ||
| 753 | down(&ib_uverbs_idr_mutex); | 753 | mutex_lock(&ib_uverbs_idr_mutex); |
| 754 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 754 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
| 755 | if (cq && cq->uobject->context == file->ucontext) { | 755 | if (cq && cq->uobject->context == file->ucontext) { |
| 756 | ib_req_notify_cq(cq, cmd.solicited_only ? | 756 | ib_req_notify_cq(cq, cmd.solicited_only ? |
| 757 | IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); | 757 | IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); |
| 758 | ret = in_len; | 758 | ret = in_len; |
| 759 | } | 759 | } |
| 760 | up(&ib_uverbs_idr_mutex); | 760 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 761 | 761 | ||
| 762 | return ret; | 762 | return ret; |
| 763 | } | 763 | } |
| @@ -779,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
| 779 | 779 | ||
| 780 | memset(&resp, 0, sizeof resp); | 780 | memset(&resp, 0, sizeof resp); |
| 781 | 781 | ||
| 782 | down(&ib_uverbs_idr_mutex); | 782 | mutex_lock(&ib_uverbs_idr_mutex); |
| 783 | 783 | ||
| 784 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 784 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
| 785 | if (!cq || cq->uobject->context != file->ucontext) | 785 | if (!cq || cq->uobject->context != file->ucontext) |
| @@ -795,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
| 795 | 795 | ||
| 796 | idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); | 796 | idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); |
| 797 | 797 | ||
| 798 | down(&file->mutex); | 798 | mutex_lock(&file->mutex); |
| 799 | list_del(&uobj->uobject.list); | 799 | list_del(&uobj->uobject.list); |
| 800 | up(&file->mutex); | 800 | mutex_unlock(&file->mutex); |
| 801 | 801 | ||
| 802 | ib_uverbs_release_ucq(file, ev_file, uobj); | 802 | ib_uverbs_release_ucq(file, ev_file, uobj); |
| 803 | 803 | ||
| @@ -811,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
| 811 | ret = -EFAULT; | 811 | ret = -EFAULT; |
| 812 | 812 | ||
| 813 | out: | 813 | out: |
| 814 | up(&ib_uverbs_idr_mutex); | 814 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 815 | 815 | ||
| 816 | return ret ? ret : in_len; | 816 | return ret ? ret : in_len; |
| 817 | } | 817 | } |
| @@ -845,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
| 845 | if (!uobj) | 845 | if (!uobj) |
| 846 | return -ENOMEM; | 846 | return -ENOMEM; |
| 847 | 847 | ||
| 848 | down(&ib_uverbs_idr_mutex); | 848 | mutex_lock(&ib_uverbs_idr_mutex); |
| 849 | 849 | ||
| 850 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 850 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
| 851 | scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); | 851 | scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); |
| @@ -930,11 +930,11 @@ retry: | |||
| 930 | goto err_idr; | 930 | goto err_idr; |
| 931 | } | 931 | } |
| 932 | 932 | ||
| 933 | down(&file->mutex); | 933 | mutex_lock(&file->mutex); |
| 934 | list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); | 934 | list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); |
| 935 | up(&file->mutex); | 935 | mutex_unlock(&file->mutex); |
| 936 | 936 | ||
| 937 | up(&ib_uverbs_idr_mutex); | 937 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 938 | 938 | ||
| 939 | return in_len; | 939 | return in_len; |
| 940 | 940 | ||
| @@ -950,7 +950,7 @@ err_destroy: | |||
| 950 | atomic_dec(&attr.srq->usecnt); | 950 | atomic_dec(&attr.srq->usecnt); |
| 951 | 951 | ||
| 952 | err_up: | 952 | err_up: |
| 953 | up(&ib_uverbs_idr_mutex); | 953 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 954 | 954 | ||
| 955 | kfree(uobj); | 955 | kfree(uobj); |
| 956 | return ret; | 956 | return ret; |
| @@ -972,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
| 972 | if (!attr) | 972 | if (!attr) |
| 973 | return -ENOMEM; | 973 | return -ENOMEM; |
| 974 | 974 | ||
| 975 | down(&ib_uverbs_idr_mutex); | 975 | mutex_lock(&ib_uverbs_idr_mutex); |
| 976 | 976 | ||
| 977 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 977 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 978 | if (!qp || qp->uobject->context != file->ucontext) { | 978 | if (!qp || qp->uobject->context != file->ucontext) { |
| @@ -1033,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
| 1033 | ret = in_len; | 1033 | ret = in_len; |
| 1034 | 1034 | ||
| 1035 | out: | 1035 | out: |
| 1036 | up(&ib_uverbs_idr_mutex); | 1036 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1037 | kfree(attr); | 1037 | kfree(attr); |
| 1038 | 1038 | ||
| 1039 | return ret; | 1039 | return ret; |
| @@ -1054,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
| 1054 | 1054 | ||
| 1055 | memset(&resp, 0, sizeof resp); | 1055 | memset(&resp, 0, sizeof resp); |
| 1056 | 1056 | ||
| 1057 | down(&ib_uverbs_idr_mutex); | 1057 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1058 | 1058 | ||
| 1059 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1059 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 1060 | if (!qp || qp->uobject->context != file->ucontext) | 1060 | if (!qp || qp->uobject->context != file->ucontext) |
| @@ -1073,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
| 1073 | 1073 | ||
| 1074 | idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); | 1074 | idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 1075 | 1075 | ||
| 1076 | down(&file->mutex); | 1076 | mutex_lock(&file->mutex); |
| 1077 | list_del(&uobj->uevent.uobject.list); | 1077 | list_del(&uobj->uevent.uobject.list); |
| 1078 | up(&file->mutex); | 1078 | mutex_unlock(&file->mutex); |
| 1079 | 1079 | ||
| 1080 | ib_uverbs_release_uevent(file, &uobj->uevent); | 1080 | ib_uverbs_release_uevent(file, &uobj->uevent); |
| 1081 | 1081 | ||
| @@ -1088,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
| 1088 | ret = -EFAULT; | 1088 | ret = -EFAULT; |
| 1089 | 1089 | ||
| 1090 | out: | 1090 | out: |
| 1091 | up(&ib_uverbs_idr_mutex); | 1091 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1092 | 1092 | ||
| 1093 | return ret ? ret : in_len; | 1093 | return ret ? ret : in_len; |
| 1094 | } | 1094 | } |
| @@ -1119,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
| 1119 | if (!user_wr) | 1119 | if (!user_wr) |
| 1120 | return -ENOMEM; | 1120 | return -ENOMEM; |
| 1121 | 1121 | ||
| 1122 | down(&ib_uverbs_idr_mutex); | 1122 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1123 | 1123 | ||
| 1124 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1124 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 1125 | if (!qp || qp->uobject->context != file->ucontext) | 1125 | if (!qp || qp->uobject->context != file->ucontext) |
| @@ -1224,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
| 1224 | ret = -EFAULT; | 1224 | ret = -EFAULT; |
| 1225 | 1225 | ||
| 1226 | out: | 1226 | out: |
| 1227 | up(&ib_uverbs_idr_mutex); | 1227 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1228 | 1228 | ||
| 1229 | while (wr) { | 1229 | while (wr) { |
| 1230 | next = wr->next; | 1230 | next = wr->next; |
| @@ -1341,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, | |||
| 1341 | if (IS_ERR(wr)) | 1341 | if (IS_ERR(wr)) |
| 1342 | return PTR_ERR(wr); | 1342 | return PTR_ERR(wr); |
| 1343 | 1343 | ||
| 1344 | down(&ib_uverbs_idr_mutex); | 1344 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1345 | 1345 | ||
| 1346 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1346 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 1347 | if (!qp || qp->uobject->context != file->ucontext) | 1347 | if (!qp || qp->uobject->context != file->ucontext) |
| @@ -1362,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, | |||
| 1362 | ret = -EFAULT; | 1362 | ret = -EFAULT; |
| 1363 | 1363 | ||
| 1364 | out: | 1364 | out: |
| 1365 | up(&ib_uverbs_idr_mutex); | 1365 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1366 | 1366 | ||
| 1367 | while (wr) { | 1367 | while (wr) { |
| 1368 | next = wr->next; | 1368 | next = wr->next; |
| @@ -1392,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, | |||
| 1392 | if (IS_ERR(wr)) | 1392 | if (IS_ERR(wr)) |
| 1393 | return PTR_ERR(wr); | 1393 | return PTR_ERR(wr); |
| 1394 | 1394 | ||
| 1395 | down(&ib_uverbs_idr_mutex); | 1395 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1396 | 1396 | ||
| 1397 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); | 1397 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); |
| 1398 | if (!srq || srq->uobject->context != file->ucontext) | 1398 | if (!srq || srq->uobject->context != file->ucontext) |
| @@ -1413,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, | |||
| 1413 | ret = -EFAULT; | 1413 | ret = -EFAULT; |
| 1414 | 1414 | ||
| 1415 | out: | 1415 | out: |
| 1416 | up(&ib_uverbs_idr_mutex); | 1416 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1417 | 1417 | ||
| 1418 | while (wr) { | 1418 | while (wr) { |
| 1419 | next = wr->next; | 1419 | next = wr->next; |
| @@ -1446,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
| 1446 | if (!uobj) | 1446 | if (!uobj) |
| 1447 | return -ENOMEM; | 1447 | return -ENOMEM; |
| 1448 | 1448 | ||
| 1449 | down(&ib_uverbs_idr_mutex); | 1449 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1450 | 1450 | ||
| 1451 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 1451 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
| 1452 | if (!pd || pd->uobject->context != file->ucontext) { | 1452 | if (!pd || pd->uobject->context != file->ucontext) { |
| @@ -1498,11 +1498,11 @@ retry: | |||
| 1498 | goto err_idr; | 1498 | goto err_idr; |
| 1499 | } | 1499 | } |
| 1500 | 1500 | ||
| 1501 | down(&file->mutex); | 1501 | mutex_lock(&file->mutex); |
| 1502 | list_add_tail(&uobj->list, &file->ucontext->ah_list); | 1502 | list_add_tail(&uobj->list, &file->ucontext->ah_list); |
| 1503 | up(&file->mutex); | 1503 | mutex_unlock(&file->mutex); |
| 1504 | 1504 | ||
| 1505 | up(&ib_uverbs_idr_mutex); | 1505 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1506 | 1506 | ||
| 1507 | return in_len; | 1507 | return in_len; |
| 1508 | 1508 | ||
| @@ -1513,7 +1513,7 @@ err_destroy: | |||
| 1513 | ib_destroy_ah(ah); | 1513 | ib_destroy_ah(ah); |
| 1514 | 1514 | ||
| 1515 | err_up: | 1515 | err_up: |
| 1516 | up(&ib_uverbs_idr_mutex); | 1516 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1517 | 1517 | ||
| 1518 | kfree(uobj); | 1518 | kfree(uobj); |
| 1519 | return ret; | 1519 | return ret; |
| @@ -1530,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, | |||
| 1530 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1530 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 1531 | return -EFAULT; | 1531 | return -EFAULT; |
| 1532 | 1532 | ||
| 1533 | down(&ib_uverbs_idr_mutex); | 1533 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1534 | 1534 | ||
| 1535 | ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); | 1535 | ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); |
| 1536 | if (!ah || ah->uobject->context != file->ucontext) | 1536 | if (!ah || ah->uobject->context != file->ucontext) |
| @@ -1544,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, | |||
| 1544 | 1544 | ||
| 1545 | idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); | 1545 | idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); |
| 1546 | 1546 | ||
| 1547 | down(&file->mutex); | 1547 | mutex_lock(&file->mutex); |
| 1548 | list_del(&uobj->list); | 1548 | list_del(&uobj->list); |
| 1549 | up(&file->mutex); | 1549 | mutex_unlock(&file->mutex); |
| 1550 | 1550 | ||
| 1551 | kfree(uobj); | 1551 | kfree(uobj); |
| 1552 | 1552 | ||
| 1553 | out: | 1553 | out: |
| 1554 | up(&ib_uverbs_idr_mutex); | 1554 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1555 | 1555 | ||
| 1556 | return ret ? ret : in_len; | 1556 | return ret ? ret : in_len; |
| 1557 | } | 1557 | } |
| @@ -1569,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, | |||
| 1569 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1569 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 1570 | return -EFAULT; | 1570 | return -EFAULT; |
| 1571 | 1571 | ||
| 1572 | down(&ib_uverbs_idr_mutex); | 1572 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1573 | 1573 | ||
| 1574 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1574 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 1575 | if (!qp || qp->uobject->context != file->ucontext) | 1575 | if (!qp || qp->uobject->context != file->ucontext) |
| @@ -1602,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, | |||
| 1602 | kfree(mcast); | 1602 | kfree(mcast); |
| 1603 | 1603 | ||
| 1604 | out: | 1604 | out: |
| 1605 | up(&ib_uverbs_idr_mutex); | 1605 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1606 | 1606 | ||
| 1607 | return ret ? ret : in_len; | 1607 | return ret ? ret : in_len; |
| 1608 | } | 1608 | } |
| @@ -1620,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, | |||
| 1620 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1620 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 1621 | return -EFAULT; | 1621 | return -EFAULT; |
| 1622 | 1622 | ||
| 1623 | down(&ib_uverbs_idr_mutex); | 1623 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1624 | 1624 | ||
| 1625 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1625 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
| 1626 | if (!qp || qp->uobject->context != file->ucontext) | 1626 | if (!qp || qp->uobject->context != file->ucontext) |
| @@ -1641,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, | |||
| 1641 | } | 1641 | } |
| 1642 | 1642 | ||
| 1643 | out: | 1643 | out: |
| 1644 | up(&ib_uverbs_idr_mutex); | 1644 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1645 | 1645 | ||
| 1646 | return ret ? ret : in_len; | 1646 | return ret ? ret : in_len; |
| 1647 | } | 1647 | } |
| @@ -1673,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, | |||
| 1673 | if (!uobj) | 1673 | if (!uobj) |
| 1674 | return -ENOMEM; | 1674 | return -ENOMEM; |
| 1675 | 1675 | ||
| 1676 | down(&ib_uverbs_idr_mutex); | 1676 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1677 | 1677 | ||
| 1678 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 1678 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
| 1679 | 1679 | ||
| @@ -1730,11 +1730,11 @@ retry: | |||
| 1730 | goto err_idr; | 1730 | goto err_idr; |
| 1731 | } | 1731 | } |
| 1732 | 1732 | ||
| 1733 | down(&file->mutex); | 1733 | mutex_lock(&file->mutex); |
| 1734 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); | 1734 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); |
| 1735 | up(&file->mutex); | 1735 | mutex_unlock(&file->mutex); |
| 1736 | 1736 | ||
| 1737 | up(&ib_uverbs_idr_mutex); | 1737 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1738 | 1738 | ||
| 1739 | return in_len; | 1739 | return in_len; |
| 1740 | 1740 | ||
| @@ -1746,7 +1746,7 @@ err_destroy: | |||
| 1746 | atomic_dec(&pd->usecnt); | 1746 | atomic_dec(&pd->usecnt); |
| 1747 | 1747 | ||
| 1748 | err_up: | 1748 | err_up: |
| 1749 | up(&ib_uverbs_idr_mutex); | 1749 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1750 | 1750 | ||
| 1751 | kfree(uobj); | 1751 | kfree(uobj); |
| 1752 | return ret; | 1752 | return ret; |
| @@ -1764,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
| 1764 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1764 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 1765 | return -EFAULT; | 1765 | return -EFAULT; |
| 1766 | 1766 | ||
| 1767 | down(&ib_uverbs_idr_mutex); | 1767 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1768 | 1768 | ||
| 1769 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); | 1769 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); |
| 1770 | if (!srq || srq->uobject->context != file->ucontext) { | 1770 | if (!srq || srq->uobject->context != file->ucontext) { |
| @@ -1778,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
| 1778 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); | 1778 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); |
| 1779 | 1779 | ||
| 1780 | out: | 1780 | out: |
| 1781 | up(&ib_uverbs_idr_mutex); | 1781 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1782 | 1782 | ||
| 1783 | return ret ? ret : in_len; | 1783 | return ret ? ret : in_len; |
| 1784 | } | 1784 | } |
| @@ -1796,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
| 1796 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1796 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
| 1797 | return -EFAULT; | 1797 | return -EFAULT; |
| 1798 | 1798 | ||
| 1799 | down(&ib_uverbs_idr_mutex); | 1799 | mutex_lock(&ib_uverbs_idr_mutex); |
| 1800 | 1800 | ||
| 1801 | memset(&resp, 0, sizeof resp); | 1801 | memset(&resp, 0, sizeof resp); |
| 1802 | 1802 | ||
| @@ -1812,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
| 1812 | 1812 | ||
| 1813 | idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); | 1813 | idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); |
| 1814 | 1814 | ||
| 1815 | down(&file->mutex); | 1815 | mutex_lock(&file->mutex); |
| 1816 | list_del(&uobj->uobject.list); | 1816 | list_del(&uobj->uobject.list); |
| 1817 | up(&file->mutex); | 1817 | mutex_unlock(&file->mutex); |
| 1818 | 1818 | ||
| 1819 | ib_uverbs_release_uevent(file, uobj); | 1819 | ib_uverbs_release_uevent(file, uobj); |
| 1820 | 1820 | ||
| @@ -1827,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
| 1827 | ret = -EFAULT; | 1827 | ret = -EFAULT; |
| 1828 | 1828 | ||
| 1829 | out: | 1829 | out: |
| 1830 | up(&ib_uverbs_idr_mutex); | 1830 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 1831 | 1831 | ||
| 1832 | return ret ? ret : in_len; | 1832 | return ret ? ret : in_len; |
| 1833 | } | 1833 | } |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 81737bd6faea..96ea79b63df7 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
| @@ -66,7 +66,7 @@ enum { | |||
| 66 | 66 | ||
| 67 | static struct class *uverbs_class; | 67 | static struct class *uverbs_class; |
| 68 | 68 | ||
| 69 | DECLARE_MUTEX(ib_uverbs_idr_mutex); | 69 | DEFINE_MUTEX(ib_uverbs_idr_mutex); |
| 70 | DEFINE_IDR(ib_uverbs_pd_idr); | 70 | DEFINE_IDR(ib_uverbs_pd_idr); |
| 71 | DEFINE_IDR(ib_uverbs_mr_idr); | 71 | DEFINE_IDR(ib_uverbs_mr_idr); |
| 72 | DEFINE_IDR(ib_uverbs_mw_idr); | 72 | DEFINE_IDR(ib_uverbs_mw_idr); |
| @@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
| 180 | if (!context) | 180 | if (!context) |
| 181 | return 0; | 181 | return 0; |
| 182 | 182 | ||
| 183 | down(&ib_uverbs_idr_mutex); | 183 | mutex_lock(&ib_uverbs_idr_mutex); |
| 184 | 184 | ||
| 185 | list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { | 185 | list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { |
| 186 | struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); | 186 | struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); |
| @@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
| 250 | kfree(uobj); | 250 | kfree(uobj); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | up(&ib_uverbs_idr_mutex); | 253 | mutex_unlock(&ib_uverbs_idr_mutex); |
| 254 | 254 | ||
| 255 | return context->device->dealloc_ucontext(context); | 255 | return context->device->dealloc_ucontext(context); |
| 256 | } | 256 | } |
| @@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) | |||
| 653 | file->ucontext = NULL; | 653 | file->ucontext = NULL; |
| 654 | file->async_file = NULL; | 654 | file->async_file = NULL; |
| 655 | kref_init(&file->ref); | 655 | kref_init(&file->ref); |
| 656 | init_MUTEX(&file->mutex); | 656 | mutex_init(&file->mutex); |
| 657 | 657 | ||
| 658 | filp->private_data = file; | 658 | filp->private_data = file; |
| 659 | 659 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 22fdc446f25c..a14eed08a0fc 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
| @@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) | |||
| 163 | return 0; | 163 | return 0; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | int mthca_ah_grh_present(struct mthca_ah *ah) | ||
| 167 | { | ||
| 168 | return !!(ah->av->g_slid & 0x80); | ||
| 169 | } | ||
| 170 | |||
| 166 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | 171 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, |
| 167 | struct ib_ud_header *header) | 172 | struct ib_ud_header *header) |
| 168 | { | 173 | { |
| @@ -172,8 +177,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | |||
| 172 | header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; | 177 | header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; |
| 173 | header->lrh.destination_lid = ah->av->dlid; | 178 | header->lrh.destination_lid = ah->av->dlid; |
| 174 | header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); | 179 | header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); |
| 175 | if (ah->av->g_slid & 0x80) { | 180 | if (mthca_ah_grh_present(ah)) { |
| 176 | header->grh_present = 1; | ||
| 177 | header->grh.traffic_class = | 181 | header->grh.traffic_class = |
| 178 | (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; | 182 | (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; |
| 179 | header->grh.flow_label = | 183 | header->grh.flow_label = |
| @@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | |||
| 184 | &header->grh.source_gid); | 188 | &header->grh.source_gid); |
| 185 | memcpy(header->grh.destination_gid.raw, | 189 | memcpy(header->grh.destination_gid.raw, |
| 186 | ah->av->dgid, 16); | 190 | ah->av->dgid, 16); |
| 187 | } else { | ||
| 188 | header->grh_present = 0; | ||
| 189 | } | 191 | } |
| 190 | 192 | ||
| 191 | return 0; | 193 | return 0; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 22ac72bc20c3..be1791be627b 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
| @@ -606,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | |||
| 606 | err = -EINVAL; | 606 | err = -EINVAL; |
| 607 | goto out; | 607 | goto out; |
| 608 | } | 608 | } |
| 609 | for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { | 609 | for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) { |
| 610 | if (virt != -1) { | 610 | if (virt != -1) { |
| 611 | pages[nent * 2] = cpu_to_be64(virt); | 611 | pages[nent * 2] = cpu_to_be64(virt); |
| 612 | virt += 1 << lg; | 612 | virt += 1 << lg; |
| @@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | |||
| 727 | * system pages needed. | 727 | * system pages needed. |
| 728 | */ | 728 | */ |
| 729 | dev->fw.arbel.fw_pages = | 729 | dev->fw.arbel.fw_pages = |
| 730 | (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> | 730 | ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >> |
| 731 | (PAGE_SHIFT - 12); | 731 | (PAGE_SHIFT - 12); |
| 732 | 732 | ||
| 733 | mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", | 733 | mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", |
| 734 | (unsigned long long) dev->fw.arbel.clr_int_base, | 734 | (unsigned long long) dev->fw.arbel.clr_int_base, |
| @@ -1445,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, | |||
| 1445 | * pages needed. | 1445 | * pages needed. |
| 1446 | */ | 1446 | */ |
| 1447 | *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); | 1447 | *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); |
| 1448 | *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12); | ||
| 1448 | 1449 | ||
| 1449 | return 0; | 1450 | return 0; |
| 1450 | } | 1451 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 795b379260bf..a104ab041ea3 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
| @@ -520,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev, | |||
| 520 | int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); | 520 | int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); |
| 521 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | 521 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, |
| 522 | struct ib_ud_header *header); | 522 | struct ib_ud_header *header); |
| 523 | int mthca_ah_grh_present(struct mthca_ah *ah); | ||
| 523 | 524 | ||
| 524 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | 525 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); |
| 525 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | 526 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index e8a948f087c0..2eabb27804cd 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | enum { | 45 | enum { |
| 46 | MTHCA_NUM_ASYNC_EQE = 0x80, | 46 | MTHCA_NUM_ASYNC_EQE = 0x80, |
| 47 | MTHCA_NUM_CMD_EQE = 0x80, | 47 | MTHCA_NUM_CMD_EQE = 0x80, |
| 48 | MTHCA_NUM_SPARE_EQE = 0x80, | ||
| 48 | MTHCA_EQ_ENTRY_SIZE = 0x20 | 49 | MTHCA_EQ_ENTRY_SIZE = 0x20 |
| 49 | }; | 50 | }; |
| 50 | 51 | ||
| @@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
| 277 | { | 278 | { |
| 278 | struct mthca_eqe *eqe; | 279 | struct mthca_eqe *eqe; |
| 279 | int disarm_cqn; | 280 | int disarm_cqn; |
| 280 | int eqes_found = 0; | 281 | int eqes_found = 0; |
| 282 | int set_ci = 0; | ||
| 281 | 283 | ||
| 282 | while ((eqe = next_eqe_sw(eq))) { | 284 | while ((eqe = next_eqe_sw(eq))) { |
| 283 | int set_ci = 0; | ||
| 284 | |||
| 285 | /* | 285 | /* |
| 286 | * Make sure we read EQ entry contents after we've | 286 | * Make sure we read EQ entry contents after we've |
| 287 | * checked the ownership bit. | 287 | * checked the ownership bit. |
| @@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
| 345 | be16_to_cpu(eqe->event.cmd.token), | 345 | be16_to_cpu(eqe->event.cmd.token), |
| 346 | eqe->event.cmd.status, | 346 | eqe->event.cmd.status, |
| 347 | be64_to_cpu(eqe->event.cmd.out_param)); | 347 | be64_to_cpu(eqe->event.cmd.out_param)); |
| 348 | /* | ||
| 349 | * cmd_event() may add more commands. | ||
| 350 | * The card will think the queue has overflowed if | ||
| 351 | * we don't tell it we've been processing events. | ||
| 352 | */ | ||
| 353 | set_ci = 1; | ||
| 354 | break; | 348 | break; |
| 355 | 349 | ||
| 356 | case MTHCA_EVENT_TYPE_PORT_CHANGE: | 350 | case MTHCA_EVENT_TYPE_PORT_CHANGE: |
| @@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
| 385 | set_eqe_hw(eqe); | 379 | set_eqe_hw(eqe); |
| 386 | ++eq->cons_index; | 380 | ++eq->cons_index; |
| 387 | eqes_found = 1; | 381 | eqes_found = 1; |
| 382 | ++set_ci; | ||
| 388 | 383 | ||
| 389 | if (unlikely(set_ci)) { | 384 | /* |
| 385 | * The HCA will think the queue has overflowed if we | ||
| 386 | * don't tell it we've been processing events. We | ||
| 387 | * create our EQs with MTHCA_NUM_SPARE_EQE extra | ||
| 388 | * entries, so we must update our consumer index at | ||
| 389 | * least that often. | ||
| 390 | */ | ||
| 391 | if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) { | ||
| 390 | /* | 392 | /* |
| 391 | * Conditional on hca_type is OK here because | 393 | * Conditional on hca_type is OK here because |
| 392 | * this is a rare case, not the fast path. | 394 | * this is a rare case, not the fast path. |
| @@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) | |||
| 862 | intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? | 864 | intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? |
| 863 | 128 : dev->eq_table.inta_pin; | 865 | 128 : dev->eq_table.inta_pin; |
| 864 | 866 | ||
| 865 | err = mthca_create_eq(dev, dev->limits.num_cqs, | 867 | err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE, |
| 866 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, | 868 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, |
| 867 | &dev->eq_table.eq[MTHCA_EQ_COMP]); | 869 | &dev->eq_table.eq[MTHCA_EQ_COMP]); |
| 868 | if (err) | 870 | if (err) |
| 869 | goto err_out_unmap; | 871 | goto err_out_unmap; |
| 870 | 872 | ||
| 871 | err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE, | 873 | err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE, |
| 872 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, | 874 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, |
| 873 | &dev->eq_table.eq[MTHCA_EQ_ASYNC]); | 875 | &dev->eq_table.eq[MTHCA_EQ_ASYNC]); |
| 874 | if (err) | 876 | if (err) |
| 875 | goto err_out_comp; | 877 | goto err_out_comp; |
| 876 | 878 | ||
| 877 | err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE, | 879 | err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE, |
| 878 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, | 880 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, |
| 879 | &dev->eq_table.eq[MTHCA_EQ_CMD]); | 881 | &dev->eq_table.eq[MTHCA_EQ_CMD]); |
| 880 | if (err) | 882 | if (err) |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 4cc7e2846df1..484a7e6b7f8c 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 34 | * SOFTWARE. | 34 | * SOFTWARE. |
| 35 | * | 35 | * |
| 36 | * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $ | 36 | * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $ |
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | #include <rdma/ib_smi.h> | 39 | #include <rdma/ib_smi.h> |
| @@ -45,6 +45,14 @@ | |||
| 45 | #include "mthca_user.h" | 45 | #include "mthca_user.h" |
| 46 | #include "mthca_memfree.h" | 46 | #include "mthca_memfree.h" |
| 47 | 47 | ||
| 48 | static void init_query_mad(struct ib_smp *mad) | ||
| 49 | { | ||
| 50 | mad->base_version = 1; | ||
| 51 | mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | ||
| 52 | mad->class_version = 1; | ||
| 53 | mad->method = IB_MGMT_METHOD_GET; | ||
| 54 | } | ||
| 55 | |||
| 48 | static int mthca_query_device(struct ib_device *ibdev, | 56 | static int mthca_query_device(struct ib_device *ibdev, |
| 49 | struct ib_device_attr *props) | 57 | struct ib_device_attr *props) |
| 50 | { | 58 | { |
| @@ -55,7 +63,7 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
| 55 | 63 | ||
| 56 | u8 status; | 64 | u8 status; |
| 57 | 65 | ||
| 58 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 66 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
| 59 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 67 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
| 60 | if (!in_mad || !out_mad) | 68 | if (!in_mad || !out_mad) |
| 61 | goto out; | 69 | goto out; |
| @@ -64,12 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
| 64 | 72 | ||
| 65 | props->fw_ver = mdev->fw_ver; | 73 | props->fw_ver = mdev->fw_ver; |
| 66 | 74 | ||
| 67 | memset(in_mad, 0, sizeof *in_mad); | 75 | init_query_mad(in_mad); |
| 68 | in_mad->base_version = 1; | 76 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; |
| 69 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | ||
| 70 | in_mad->class_version = 1; | ||
| 71 | in_mad->method = IB_MGMT_METHOD_GET; | ||
| 72 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
| 73 | 77 | ||
| 74 | err = mthca_MAD_IFC(mdev, 1, 1, | 78 | err = mthca_MAD_IFC(mdev, 1, 1, |
| 75 | 1, NULL, NULL, in_mad, out_mad, | 79 | 1, NULL, NULL, in_mad, out_mad, |
| @@ -87,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
| 87 | props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); | 91 | props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); |
| 88 | props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); | 92 | props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); |
| 89 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); | 93 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); |
| 90 | memcpy(&props->node_guid, out_mad->data + 12, 8); | ||
| 91 | 94 | ||
| 92 | props->max_mr_size = ~0ull; | 95 | props->max_mr_size = ~0ull; |
| 93 | props->page_size_cap = mdev->limits.page_size_cap; | 96 | props->page_size_cap = mdev->limits.page_size_cap; |
| @@ -128,20 +131,16 @@ static int mthca_query_port(struct ib_device *ibdev, | |||
| 128 | int err = -ENOMEM; | 131 | int err = -ENOMEM; |
| 129 | u8 status; | 132 | u8 status; |
| 130 | 133 | ||
| 131 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 134 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
| 132 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 135 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
| 133 | if (!in_mad || !out_mad) | 136 | if (!in_mad || !out_mad) |
| 134 | goto out; | 137 | goto out; |
| 135 | 138 | ||
| 136 | memset(props, 0, sizeof *props); | 139 | memset(props, 0, sizeof *props); |
| 137 | 140 | ||
| 138 | memset(in_mad, 0, sizeof *in_mad); | 141 | init_query_mad(in_mad); |
| 139 | in_mad->base_version = 1; | 142 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
| 140 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 143 | in_mad->attr_mod = cpu_to_be32(port); |
| 141 | in_mad->class_version = 1; | ||
| 142 | in_mad->method = IB_MGMT_METHOD_GET; | ||
| 143 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
| 144 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 145 | 144 | ||
| 146 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 145 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
| 147 | port, NULL, NULL, in_mad, out_mad, | 146 | port, NULL, NULL, in_mad, out_mad, |
| @@ -220,18 +219,14 @@ static int mthca_query_pkey(struct ib_device *ibdev, | |||
| 220 | int err = -ENOMEM; | 219 | int err = -ENOMEM; |
| 221 | u8 status; | 220 | u8 status; |
| 222 | 221 | ||
| 223 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 222 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
| 224 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 223 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
| 225 | if (!in_mad || !out_mad) | 224 | if (!in_mad || !out_mad) |
| 226 | goto out; | 225 | goto out; |
| 227 | 226 | ||
| 228 | memset(in_mad, 0, sizeof *in_mad); | 227 | init_query_mad(in_mad); |
| 229 | in_mad->base_version = 1; | 228 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; |
| 230 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 229 | in_mad->attr_mod = cpu_to_be32(index / 32); |
| 231 | in_mad->class_version = 1; | ||
| 232 | in_mad->method = IB_MGMT_METHOD_GET; | ||
| 233 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | ||
| 234 | in_mad->attr_mod = cpu_to_be32(index / 32); | ||
| 235 | 230 | ||
| 236 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 231 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
| 237 | port, NULL, NULL, in_mad, out_mad, | 232 | port, NULL, NULL, in_mad, out_mad, |
| @@ -259,18 +254,14 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
| 259 | int err = -ENOMEM; | 254 | int err = -ENOMEM; |
| 260 | u8 status; | 255 | u8 status; |
| 261 | 256 | ||
| 262 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 257 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
| 263 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 258 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
| 264 | if (!in_mad || !out_mad) | 259 | if (!in_mad || !out_mad) |
| 265 | goto out; | 260 | goto out; |
| 266 | 261 | ||
| 267 | memset(in_mad, 0, sizeof *in_mad); | 262 | init_query_mad(in_mad); |
| 268 | in_mad->base_version = 1; | 263 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
| 269 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 264 | in_mad->attr_mod = cpu_to_be32(port); |
| 270 | in_mad->class_version = 1; | ||
| 271 | in_mad->method = IB_MGMT_METHOD_GET; | ||
| 272 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
| 273 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 274 | 265 | ||
| 275 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 266 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
| 276 | port, NULL, NULL, in_mad, out_mad, | 267 | port, NULL, NULL, in_mad, out_mad, |
| @@ -284,13 +275,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
| 284 | 275 | ||
| 285 | memcpy(gid->raw, out_mad->data + 8, 8); | 276 | memcpy(gid->raw, out_mad->data + 8, 8); |
| 286 | 277 | ||
| 287 | memset(in_mad, 0, sizeof *in_mad); | 278 | init_query_mad(in_mad); |
| 288 | in_mad->base_version = 1; | 279 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; |
| 289 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 280 | in_mad->attr_mod = cpu_to_be32(index / 8); |
| 290 | in_mad->class_version = 1; | ||
| 291 | in_mad->method = IB_MGMT_METHOD_GET; | ||
| 292 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | ||
| 293 | in_mad->attr_mod = cpu_to_be32(index / 8); | ||
| 294 | 281 | ||
| 295 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 282 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
| 296 | port, NULL, NULL, in_mad, out_mad, | 283 | port, NULL, NULL, in_mad, out_mad, |
| @@ -458,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd, | |||
| 458 | if (pd->uobject) { | 445 | if (pd->uobject) { |
| 459 | context = to_mucontext(pd->uobject->context); | 446 | context = to_mucontext(pd->uobject->context); |
| 460 | 447 | ||
| 461 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 448 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { |
| 462 | return ERR_PTR(-EFAULT); | 449 | err = -EFAULT; |
| 450 | goto err_free; | ||
| 451 | } | ||
| 463 | 452 | ||
| 464 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | 453 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, |
| 465 | context->db_tab, ucmd.db_index, | 454 | context->db_tab, ucmd.db_index, |
| @@ -535,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, | |||
| 535 | if (pd->uobject) { | 524 | if (pd->uobject) { |
| 536 | context = to_mucontext(pd->uobject->context); | 525 | context = to_mucontext(pd->uobject->context); |
| 537 | 526 | ||
| 538 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 527 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { |
| 528 | kfree(qp); | ||
| 539 | return ERR_PTR(-EFAULT); | 529 | return ERR_PTR(-EFAULT); |
| 530 | } | ||
| 540 | 531 | ||
| 541 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | 532 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, |
| 542 | context->db_tab, | 533 | context->db_tab, |
| @@ -783,24 +774,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, | |||
| 783 | if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) | 774 | if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) |
| 784 | return ERR_PTR(-EINVAL); | 775 | return ERR_PTR(-EINVAL); |
| 785 | 776 | ||
| 786 | if (num_phys_buf > 1 && | ||
| 787 | ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) | ||
| 788 | return ERR_PTR(-EINVAL); | ||
| 789 | |||
| 790 | mask = 0; | 777 | mask = 0; |
| 791 | total_size = 0; | 778 | total_size = 0; |
| 792 | for (i = 0; i < num_phys_buf; ++i) { | 779 | for (i = 0; i < num_phys_buf; ++i) { |
| 793 | if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) | 780 | if (i != 0) |
| 794 | return ERR_PTR(-EINVAL); | 781 | mask |= buffer_list[i].addr; |
| 795 | if (i != 0 && i != num_phys_buf - 1 && | 782 | if (i != num_phys_buf - 1) |
| 796 | (buffer_list[i].size & ~PAGE_MASK)) | 783 | mask |= buffer_list[i].addr + buffer_list[i].size; |
| 797 | return ERR_PTR(-EINVAL); | ||
| 798 | 784 | ||
| 799 | total_size += buffer_list[i].size; | 785 | total_size += buffer_list[i].size; |
| 800 | if (i > 0) | ||
| 801 | mask |= buffer_list[i].addr; | ||
| 802 | } | 786 | } |
| 803 | 787 | ||
| 788 | if (mask & ~PAGE_MASK) | ||
| 789 | return ERR_PTR(-EINVAL); | ||
| 790 | |||
| 804 | /* Find largest page shift we can use to cover buffers */ | 791 | /* Find largest page shift we can use to cover buffers */ |
| 805 | for (shift = PAGE_SHIFT; shift < 31; ++shift) | 792 | for (shift = PAGE_SHIFT; shift < 31; ++shift) |
| 806 | if (num_phys_buf > 1) { | 793 | if (num_phys_buf > 1) { |
| @@ -1070,11 +1057,48 @@ static struct class_device_attribute *mthca_class_attributes[] = { | |||
| 1070 | &class_device_attr_board_id | 1057 | &class_device_attr_board_id |
| 1071 | }; | 1058 | }; |
| 1072 | 1059 | ||
| 1060 | static int mthca_init_node_data(struct mthca_dev *dev) | ||
| 1061 | { | ||
| 1062 | struct ib_smp *in_mad = NULL; | ||
| 1063 | struct ib_smp *out_mad = NULL; | ||
| 1064 | int err = -ENOMEM; | ||
| 1065 | u8 status; | ||
| 1066 | |||
| 1067 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | ||
| 1068 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | ||
| 1069 | if (!in_mad || !out_mad) | ||
| 1070 | goto out; | ||
| 1071 | |||
| 1072 | init_query_mad(in_mad); | ||
| 1073 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
| 1074 | |||
| 1075 | err = mthca_MAD_IFC(dev, 1, 1, | ||
| 1076 | 1, NULL, NULL, in_mad, out_mad, | ||
| 1077 | &status); | ||
| 1078 | if (err) | ||
| 1079 | goto out; | ||
| 1080 | if (status) { | ||
| 1081 | err = -EINVAL; | ||
| 1082 | goto out; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); | ||
| 1086 | |||
| 1087 | out: | ||
| 1088 | kfree(in_mad); | ||
| 1089 | kfree(out_mad); | ||
| 1090 | return err; | ||
| 1091 | } | ||
| 1092 | |||
| 1073 | int mthca_register_device(struct mthca_dev *dev) | 1093 | int mthca_register_device(struct mthca_dev *dev) |
| 1074 | { | 1094 | { |
| 1075 | int ret; | 1095 | int ret; |
| 1076 | int i; | 1096 | int i; |
| 1077 | 1097 | ||
| 1098 | ret = mthca_init_node_data(dev); | ||
| 1099 | if (ret) | ||
| 1100 | return ret; | ||
| 1101 | |||
| 1078 | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); | 1102 | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); |
| 1079 | dev->ib_dev.owner = THIS_MODULE; | 1103 | dev->ib_dev.owner = THIS_MODULE; |
| 1080 | 1104 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 564b6d51c394..fba608ed7df2 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
| @@ -1434,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp, | |||
| 1434 | u16 pkey; | 1434 | u16 pkey; |
| 1435 | 1435 | ||
| 1436 | ib_ud_header_init(256, /* assume a MAD */ | 1436 | ib_ud_header_init(256, /* assume a MAD */ |
| 1437 | sqp->ud_header.grh_present, | 1437 | mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), |
| 1438 | &sqp->ud_header); | 1438 | &sqp->ud_header); |
| 1439 | 1439 | ||
| 1440 | err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); | 1440 | err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9923a15a9996..e0a5412b7e68 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
| @@ -45,11 +45,11 @@ | |||
| 45 | #include <linux/config.h> | 45 | #include <linux/config.h> |
| 46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
| 47 | #include <linux/if_infiniband.h> | 47 | #include <linux/if_infiniband.h> |
| 48 | #include <linux/mutex.h> | ||
| 48 | 49 | ||
| 49 | #include <net/neighbour.h> | 50 | #include <net/neighbour.h> |
| 50 | 51 | ||
| 51 | #include <asm/atomic.h> | 52 | #include <asm/atomic.h> |
| 52 | #include <asm/semaphore.h> | ||
| 53 | 53 | ||
| 54 | #include <rdma/ib_verbs.h> | 54 | #include <rdma/ib_verbs.h> |
| 55 | #include <rdma/ib_pack.h> | 55 | #include <rdma/ib_pack.h> |
| @@ -123,8 +123,8 @@ struct ipoib_dev_priv { | |||
| 123 | 123 | ||
| 124 | unsigned long flags; | 124 | unsigned long flags; |
| 125 | 125 | ||
| 126 | struct semaphore mcast_mutex; | 126 | struct mutex mcast_mutex; |
| 127 | struct semaphore vlan_mutex; | 127 | struct mutex vlan_mutex; |
| 128 | 128 | ||
| 129 | struct rb_root path_tree; | 129 | struct rb_root path_tree; |
| 130 | struct list_head path_list; | 130 | struct list_head path_list; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 23885801b6d2..86bcdd72a107 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level, | |||
| 52 | 52 | ||
| 53 | #define IPOIB_OP_RECV (1ul << 31) | 53 | #define IPOIB_OP_RECV (1ul << 31) |
| 54 | 54 | ||
| 55 | static DECLARE_MUTEX(pkey_sem); | 55 | static DEFINE_MUTEX(pkey_mutex); |
| 56 | 56 | ||
| 57 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, | 57 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, |
| 58 | struct ib_pd *pd, struct ib_ah_attr *attr) | 58 | struct ib_pd *pd, struct ib_ah_attr *attr) |
| @@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev) | |||
| 445 | 445 | ||
| 446 | /* Shutdown the P_Key thread if still active */ | 446 | /* Shutdown the P_Key thread if still active */ |
| 447 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { | 447 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { |
| 448 | down(&pkey_sem); | 448 | mutex_lock(&pkey_mutex); |
| 449 | set_bit(IPOIB_PKEY_STOP, &priv->flags); | 449 | set_bit(IPOIB_PKEY_STOP, &priv->flags); |
| 450 | cancel_delayed_work(&priv->pkey_task); | 450 | cancel_delayed_work(&priv->pkey_task); |
| 451 | up(&pkey_sem); | 451 | mutex_unlock(&pkey_mutex); |
| 452 | flush_workqueue(ipoib_workqueue); | 452 | flush_workqueue(ipoib_workqueue); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | ipoib_mcast_stop_thread(dev, 1); | 455 | ipoib_mcast_stop_thread(dev, 1); |
| 456 | |||
| 457 | /* | ||
| 458 | * Flush the multicast groups first so we stop any multicast joins. The | ||
| 459 | * completion thread may have already died and we may deadlock waiting | ||
| 460 | * for the completion thread to finish some multicast joins. | ||
| 461 | */ | ||
| 462 | ipoib_mcast_dev_flush(dev); | 456 | ipoib_mcast_dev_flush(dev); |
| 463 | 457 | ||
| 464 | /* Delete broadcast and local addresses since they will be recreated */ | ||
| 465 | ipoib_mcast_dev_down(dev); | ||
| 466 | |||
| 467 | ipoib_flush_paths(dev); | 458 | ipoib_flush_paths(dev); |
| 468 | 459 | ||
| 469 | return 0; | 460 | return 0; |
| @@ -608,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev) | |||
| 608 | if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) | 599 | if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) |
| 609 | ipoib_ib_dev_up(dev); | 600 | ipoib_ib_dev_up(dev); |
| 610 | 601 | ||
| 611 | down(&priv->vlan_mutex); | 602 | mutex_lock(&priv->vlan_mutex); |
| 612 | 603 | ||
| 613 | /* Flush any child interfaces too */ | 604 | /* Flush any child interfaces too */ |
| 614 | list_for_each_entry(cpriv, &priv->child_intfs, list) | 605 | list_for_each_entry(cpriv, &priv->child_intfs, list) |
| 615 | ipoib_ib_dev_flush(&cpriv->dev); | 606 | ipoib_ib_dev_flush(&cpriv->dev); |
| 616 | 607 | ||
| 617 | up(&priv->vlan_mutex); | 608 | mutex_unlock(&priv->vlan_mutex); |
| 618 | } | 609 | } |
| 619 | 610 | ||
| 620 | void ipoib_ib_dev_cleanup(struct net_device *dev) | 611 | void ipoib_ib_dev_cleanup(struct net_device *dev) |
| @@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) | |||
| 624 | ipoib_dbg(priv, "cleaning up ib_dev\n"); | 615 | ipoib_dbg(priv, "cleaning up ib_dev\n"); |
| 625 | 616 | ||
| 626 | ipoib_mcast_stop_thread(dev, 1); | 617 | ipoib_mcast_stop_thread(dev, 1); |
| 627 | 618 | ipoib_mcast_dev_flush(dev); | |
| 628 | /* Delete the broadcast address and the local address */ | ||
| 629 | ipoib_mcast_dev_down(dev); | ||
| 630 | 619 | ||
| 631 | ipoib_transport_dev_cleanup(dev); | 620 | ipoib_transport_dev_cleanup(dev); |
| 632 | } | 621 | } |
| @@ -662,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr) | |||
| 662 | if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) | 651 | if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) |
| 663 | ipoib_open(dev); | 652 | ipoib_open(dev); |
| 664 | else { | 653 | else { |
| 665 | down(&pkey_sem); | 654 | mutex_lock(&pkey_mutex); |
| 666 | if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) | 655 | if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) |
| 667 | queue_delayed_work(ipoib_workqueue, | 656 | queue_delayed_work(ipoib_workqueue, |
| 668 | &priv->pkey_task, | 657 | &priv->pkey_task, |
| 669 | HZ); | 658 | HZ); |
| 670 | up(&pkey_sem); | 659 | mutex_unlock(&pkey_mutex); |
| 671 | } | 660 | } |
| 672 | } | 661 | } |
| 673 | 662 | ||
| @@ -681,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev) | |||
| 681 | 670 | ||
| 682 | /* P_Key value not assigned yet - start polling */ | 671 | /* P_Key value not assigned yet - start polling */ |
| 683 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { | 672 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { |
| 684 | down(&pkey_sem); | 673 | mutex_lock(&pkey_mutex); |
| 685 | clear_bit(IPOIB_PKEY_STOP, &priv->flags); | 674 | clear_bit(IPOIB_PKEY_STOP, &priv->flags); |
| 686 | queue_delayed_work(ipoib_workqueue, | 675 | queue_delayed_work(ipoib_workqueue, |
| 687 | &priv->pkey_task, | 676 | &priv->pkey_task, |
| 688 | HZ); | 677 | HZ); |
| 689 | up(&pkey_sem); | 678 | mutex_unlock(&pkey_mutex); |
| 690 | return 1; | 679 | return 1; |
| 691 | } | 680 | } |
| 692 | 681 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 780009c7eaa6..fd3f5c862a5d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -105,7 +105,7 @@ int ipoib_open(struct net_device *dev) | |||
| 105 | struct ipoib_dev_priv *cpriv; | 105 | struct ipoib_dev_priv *cpriv; |
| 106 | 106 | ||
| 107 | /* Bring up any child interfaces too */ | 107 | /* Bring up any child interfaces too */ |
| 108 | down(&priv->vlan_mutex); | 108 | mutex_lock(&priv->vlan_mutex); |
| 109 | list_for_each_entry(cpriv, &priv->child_intfs, list) { | 109 | list_for_each_entry(cpriv, &priv->child_intfs, list) { |
| 110 | int flags; | 110 | int flags; |
| 111 | 111 | ||
| @@ -115,7 +115,7 @@ int ipoib_open(struct net_device *dev) | |||
| 115 | 115 | ||
| 116 | dev_change_flags(cpriv->dev, flags | IFF_UP); | 116 | dev_change_flags(cpriv->dev, flags | IFF_UP); |
| 117 | } | 117 | } |
| 118 | up(&priv->vlan_mutex); | 118 | mutex_unlock(&priv->vlan_mutex); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | netif_start_queue(dev); | 121 | netif_start_queue(dev); |
| @@ -140,7 +140,7 @@ static int ipoib_stop(struct net_device *dev) | |||
| 140 | struct ipoib_dev_priv *cpriv; | 140 | struct ipoib_dev_priv *cpriv; |
| 141 | 141 | ||
| 142 | /* Bring down any child interfaces too */ | 142 | /* Bring down any child interfaces too */ |
| 143 | down(&priv->vlan_mutex); | 143 | mutex_lock(&priv->vlan_mutex); |
| 144 | list_for_each_entry(cpriv, &priv->child_intfs, list) { | 144 | list_for_each_entry(cpriv, &priv->child_intfs, list) { |
| 145 | int flags; | 145 | int flags; |
| 146 | 146 | ||
| @@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev) | |||
| 150 | 150 | ||
| 151 | dev_change_flags(cpriv->dev, flags & ~IFF_UP); | 151 | dev_change_flags(cpriv->dev, flags & ~IFF_UP); |
| 152 | } | 152 | } |
| 153 | up(&priv->vlan_mutex); | 153 | mutex_unlock(&priv->vlan_mutex); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | return 0; | 156 | return 0; |
| @@ -892,8 +892,8 @@ static void ipoib_setup(struct net_device *dev) | |||
| 892 | spin_lock_init(&priv->lock); | 892 | spin_lock_init(&priv->lock); |
| 893 | spin_lock_init(&priv->tx_lock); | 893 | spin_lock_init(&priv->tx_lock); |
| 894 | 894 | ||
| 895 | init_MUTEX(&priv->mcast_mutex); | 895 | mutex_init(&priv->mcast_mutex); |
| 896 | init_MUTEX(&priv->vlan_mutex); | 896 | mutex_init(&priv->vlan_mutex); |
| 897 | 897 | ||
| 898 | INIT_LIST_HEAD(&priv->path_list); | 898 | INIT_LIST_HEAD(&priv->path_list); |
| 899 | INIT_LIST_HEAD(&priv->child_intfs); | 899 | INIT_LIST_HEAD(&priv->child_intfs); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ed0c2ead8bc1..98039da0caf0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -55,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level, | |||
| 55 | "Enable multicast debug tracing if > 0"); | 55 | "Enable multicast debug tracing if > 0"); |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | static DECLARE_MUTEX(mcast_mutex); | 58 | static DEFINE_MUTEX(mcast_mutex); |
| 59 | 59 | ||
| 60 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ | 60 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ |
| 61 | struct ipoib_mcast { | 61 | struct ipoib_mcast { |
| @@ -97,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
| 97 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 97 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 98 | struct ipoib_neigh *neigh, *tmp; | 98 | struct ipoib_neigh *neigh, *tmp; |
| 99 | unsigned long flags; | 99 | unsigned long flags; |
| 100 | LIST_HEAD(ah_list); | ||
| 101 | struct ipoib_ah *ah, *tah; | ||
| 102 | 100 | ||
| 103 | ipoib_dbg_mcast(netdev_priv(dev), | 101 | ipoib_dbg_mcast(netdev_priv(dev), |
| 104 | "deleting multicast group " IPOIB_GID_FMT "\n", | 102 | "deleting multicast group " IPOIB_GID_FMT "\n", |
| @@ -107,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
| 107 | spin_lock_irqsave(&priv->lock, flags); | 105 | spin_lock_irqsave(&priv->lock, flags); |
| 108 | 106 | ||
| 109 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { | 107 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { |
| 108 | /* | ||
| 109 | * It's safe to call ipoib_put_ah() inside priv->lock | ||
| 110 | * here, because we know that mcast->ah will always | ||
| 111 | * hold one more reference, so ipoib_put_ah() will | ||
| 112 | * never do more than decrement the ref count. | ||
| 113 | */ | ||
| 110 | if (neigh->ah) | 114 | if (neigh->ah) |
| 111 | list_add_tail(&neigh->ah->list, &ah_list); | 115 | ipoib_put_ah(neigh->ah); |
| 112 | *to_ipoib_neigh(neigh->neighbour) = NULL; | 116 | *to_ipoib_neigh(neigh->neighbour) = NULL; |
| 113 | neigh->neighbour->ops->destructor = NULL; | 117 | neigh->neighbour->ops->destructor = NULL; |
| 114 | kfree(neigh); | 118 | kfree(neigh); |
| @@ -116,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
| 116 | 120 | ||
| 117 | spin_unlock_irqrestore(&priv->lock, flags); | 121 | spin_unlock_irqrestore(&priv->lock, flags); |
| 118 | 122 | ||
| 119 | list_for_each_entry_safe(ah, tah, &ah_list, list) | ||
| 120 | ipoib_put_ah(ah); | ||
| 121 | |||
| 122 | if (mcast->ah) | 123 | if (mcast->ah) |
| 123 | ipoib_put_ah(mcast->ah); | 124 | ipoib_put_ah(mcast->ah); |
| 124 | 125 | ||
| @@ -384,10 +385,10 @@ static void ipoib_mcast_join_complete(int status, | |||
| 384 | 385 | ||
| 385 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { | 386 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { |
| 386 | mcast->backoff = 1; | 387 | mcast->backoff = 1; |
| 387 | down(&mcast_mutex); | 388 | mutex_lock(&mcast_mutex); |
| 388 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 389 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
| 389 | queue_work(ipoib_workqueue, &priv->mcast_task); | 390 | queue_work(ipoib_workqueue, &priv->mcast_task); |
| 390 | up(&mcast_mutex); | 391 | mutex_unlock(&mcast_mutex); |
| 391 | complete(&mcast->done); | 392 | complete(&mcast->done); |
| 392 | return; | 393 | return; |
| 393 | } | 394 | } |
| @@ -417,7 +418,7 @@ static void ipoib_mcast_join_complete(int status, | |||
| 417 | 418 | ||
| 418 | mcast->query = NULL; | 419 | mcast->query = NULL; |
| 419 | 420 | ||
| 420 | down(&mcast_mutex); | 421 | mutex_lock(&mcast_mutex); |
| 421 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { | 422 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { |
| 422 | if (status == -ETIMEDOUT) | 423 | if (status == -ETIMEDOUT) |
| 423 | queue_work(ipoib_workqueue, &priv->mcast_task); | 424 | queue_work(ipoib_workqueue, &priv->mcast_task); |
| @@ -426,7 +427,7 @@ static void ipoib_mcast_join_complete(int status, | |||
| 426 | mcast->backoff * HZ); | 427 | mcast->backoff * HZ); |
| 427 | } else | 428 | } else |
| 428 | complete(&mcast->done); | 429 | complete(&mcast->done); |
| 429 | up(&mcast_mutex); | 430 | mutex_unlock(&mcast_mutex); |
| 430 | 431 | ||
| 431 | return; | 432 | return; |
| 432 | } | 433 | } |
| @@ -481,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, | |||
| 481 | if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) | 482 | if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) |
| 482 | mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; | 483 | mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; |
| 483 | 484 | ||
| 484 | down(&mcast_mutex); | 485 | mutex_lock(&mcast_mutex); |
| 485 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 486 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
| 486 | queue_delayed_work(ipoib_workqueue, | 487 | queue_delayed_work(ipoib_workqueue, |
| 487 | &priv->mcast_task, | 488 | &priv->mcast_task, |
| 488 | mcast->backoff * HZ); | 489 | mcast->backoff * HZ); |
| 489 | up(&mcast_mutex); | 490 | mutex_unlock(&mcast_mutex); |
| 490 | } else | 491 | } else |
| 491 | mcast->query_id = ret; | 492 | mcast->query_id = ret; |
| 492 | } | 493 | } |
| @@ -519,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr) | |||
| 519 | priv->broadcast = ipoib_mcast_alloc(dev, 1); | 520 | priv->broadcast = ipoib_mcast_alloc(dev, 1); |
| 520 | if (!priv->broadcast) { | 521 | if (!priv->broadcast) { |
| 521 | ipoib_warn(priv, "failed to allocate broadcast group\n"); | 522 | ipoib_warn(priv, "failed to allocate broadcast group\n"); |
| 522 | down(&mcast_mutex); | 523 | mutex_lock(&mcast_mutex); |
| 523 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 524 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
| 524 | queue_delayed_work(ipoib_workqueue, | 525 | queue_delayed_work(ipoib_workqueue, |
| 525 | &priv->mcast_task, HZ); | 526 | &priv->mcast_task, HZ); |
| 526 | up(&mcast_mutex); | 527 | mutex_unlock(&mcast_mutex); |
| 527 | return; | 528 | return; |
| 528 | } | 529 | } |
| 529 | 530 | ||
| @@ -579,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
| 579 | 580 | ||
| 580 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); | 581 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); |
| 581 | 582 | ||
| 582 | down(&mcast_mutex); | 583 | mutex_lock(&mcast_mutex); |
| 583 | if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) | 584 | if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) |
| 584 | queue_work(ipoib_workqueue, &priv->mcast_task); | 585 | queue_work(ipoib_workqueue, &priv->mcast_task); |
| 585 | up(&mcast_mutex); | 586 | mutex_unlock(&mcast_mutex); |
| 586 | 587 | ||
| 587 | return 0; | 588 | return 0; |
| 588 | } | 589 | } |
| @@ -594,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |||
| 594 | 595 | ||
| 595 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); | 596 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); |
| 596 | 597 | ||
| 597 | down(&mcast_mutex); | 598 | mutex_lock(&mcast_mutex); |
| 598 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); | 599 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); |
| 599 | cancel_delayed_work(&priv->mcast_task); | 600 | cancel_delayed_work(&priv->mcast_task); |
| 600 | up(&mcast_mutex); | 601 | mutex_unlock(&mcast_mutex); |
| 601 | 602 | ||
| 602 | if (flush) | 603 | if (flush) |
| 603 | flush_workqueue(ipoib_workqueue); | 604 | flush_workqueue(ipoib_workqueue); |
| @@ -741,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
| 741 | { | 742 | { |
| 742 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 743 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 743 | LIST_HEAD(remove_list); | 744 | LIST_HEAD(remove_list); |
| 744 | struct ipoib_mcast *mcast, *tmcast, *nmcast; | 745 | struct ipoib_mcast *mcast, *tmcast; |
| 745 | unsigned long flags; | 746 | unsigned long flags; |
| 746 | 747 | ||
| 747 | ipoib_dbg_mcast(priv, "flushing multicast list\n"); | 748 | ipoib_dbg_mcast(priv, "flushing multicast list\n"); |
| 748 | 749 | ||
| 749 | spin_lock_irqsave(&priv->lock, flags); | 750 | spin_lock_irqsave(&priv->lock, flags); |
| 750 | list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { | ||
| 751 | nmcast = ipoib_mcast_alloc(dev, 0); | ||
| 752 | if (nmcast) { | ||
| 753 | nmcast->flags = | ||
| 754 | mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY); | ||
| 755 | 751 | ||
| 756 | nmcast->mcmember.mgid = mcast->mcmember.mgid; | 752 | list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { |
| 757 | 753 | list_del(&mcast->list); | |
| 758 | /* Add the new group in before the to-be-destroyed group */ | 754 | rb_erase(&mcast->rb_node, &priv->multicast_tree); |
| 759 | list_add_tail(&nmcast->list, &mcast->list); | 755 | list_add_tail(&mcast->list, &remove_list); |
| 760 | list_del_init(&mcast->list); | ||
| 761 | |||
| 762 | rb_replace_node(&mcast->rb_node, &nmcast->rb_node, | ||
| 763 | &priv->multicast_tree); | ||
| 764 | |||
| 765 | list_add_tail(&mcast->list, &remove_list); | ||
| 766 | } else { | ||
| 767 | ipoib_warn(priv, "could not reallocate multicast group " | ||
| 768 | IPOIB_GID_FMT "\n", | ||
| 769 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
| 770 | } | ||
| 771 | } | 756 | } |
| 772 | 757 | ||
| 773 | if (priv->broadcast) { | 758 | if (priv->broadcast) { |
| 774 | nmcast = ipoib_mcast_alloc(dev, 0); | 759 | rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); |
| 775 | if (nmcast) { | 760 | list_add_tail(&priv->broadcast->list, &remove_list); |
| 776 | nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid; | 761 | priv->broadcast = NULL; |
| 777 | |||
| 778 | rb_replace_node(&priv->broadcast->rb_node, | ||
| 779 | &nmcast->rb_node, | ||
| 780 | &priv->multicast_tree); | ||
| 781 | |||
| 782 | list_add_tail(&priv->broadcast->list, &remove_list); | ||
| 783 | } | ||
| 784 | |||
| 785 | priv->broadcast = nmcast; | ||
| 786 | } | 762 | } |
| 787 | 763 | ||
| 788 | spin_unlock_irqrestore(&priv->lock, flags); | 764 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -793,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
| 793 | } | 769 | } |
| 794 | } | 770 | } |
| 795 | 771 | ||
| 796 | void ipoib_mcast_dev_down(struct net_device *dev) | ||
| 797 | { | ||
| 798 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
| 799 | unsigned long flags; | ||
| 800 | |||
| 801 | /* Delete broadcast since it will be recreated */ | ||
| 802 | if (priv->broadcast) { | ||
| 803 | ipoib_dbg_mcast(priv, "deleting broadcast group\n"); | ||
| 804 | |||
| 805 | spin_lock_irqsave(&priv->lock, flags); | ||
| 806 | rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); | ||
| 807 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 808 | ipoib_mcast_leave(dev, priv->broadcast); | ||
| 809 | ipoib_mcast_free(priv->broadcast); | ||
| 810 | priv->broadcast = NULL; | ||
| 811 | } | ||
| 812 | } | ||
| 813 | |||
| 814 | void ipoib_mcast_restart_task(void *dev_ptr) | 772 | void ipoib_mcast_restart_task(void *dev_ptr) |
| 815 | { | 773 | { |
| 816 | struct net_device *dev = dev_ptr; | 774 | struct net_device *dev = dev_ptr; |
| @@ -824,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
| 824 | 782 | ||
| 825 | ipoib_mcast_stop_thread(dev, 0); | 783 | ipoib_mcast_stop_thread(dev, 0); |
| 826 | 784 | ||
| 827 | spin_lock_irqsave(&priv->lock, flags); | 785 | spin_lock_irqsave(&dev->xmit_lock, flags); |
| 786 | spin_lock(&priv->lock); | ||
| 828 | 787 | ||
| 829 | /* | 788 | /* |
| 830 | * Unfortunately, the networking core only gives us a list of all of | 789 | * Unfortunately, the networking core only gives us a list of all of |
| @@ -896,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
| 896 | list_add_tail(&mcast->list, &remove_list); | 855 | list_add_tail(&mcast->list, &remove_list); |
| 897 | } | 856 | } |
| 898 | } | 857 | } |
| 899 | spin_unlock_irqrestore(&priv->lock, flags); | 858 | |
| 859 | spin_unlock(&priv->lock); | ||
| 860 | spin_unlock_irqrestore(&dev->xmit_lock, flags); | ||
| 900 | 861 | ||
| 901 | /* We have to cancel outside of the spinlock */ | 862 | /* We have to cancel outside of the spinlock */ |
| 902 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { | 863 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index e829e10400e3..faaf10e5fc7b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c | |||
| @@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid) | |||
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | /* attach QP to multicast group */ | 67 | /* attach QP to multicast group */ |
| 68 | down(&priv->mcast_mutex); | 68 | mutex_lock(&priv->mcast_mutex); |
| 69 | ret = ib_attach_mcast(priv->qp, mgid, mlid); | 69 | ret = ib_attach_mcast(priv->qp, mgid, mlid); |
| 70 | up(&priv->mcast_mutex); | 70 | mutex_unlock(&priv->mcast_mutex); |
| 71 | if (ret) | 71 | if (ret) |
| 72 | ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); | 72 | ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); |
| 73 | 73 | ||
| @@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid) | |||
| 81 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 81 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 82 | int ret; | 82 | int ret; |
| 83 | 83 | ||
| 84 | down(&priv->mcast_mutex); | 84 | mutex_lock(&priv->mcast_mutex); |
| 85 | ret = ib_detach_mcast(priv->qp, mgid, mlid); | 85 | ret = ib_detach_mcast(priv->qp, mgid, mlid); |
| 86 | up(&priv->mcast_mutex); | 86 | mutex_unlock(&priv->mcast_mutex); |
| 87 | if (ret) | 87 | if (ret) |
| 88 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); | 88 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); |
| 89 | 89 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index d280b341a37f..4ca175553f9f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
| @@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
| 63 | 63 | ||
| 64 | ppriv = netdev_priv(pdev); | 64 | ppriv = netdev_priv(pdev); |
| 65 | 65 | ||
| 66 | down(&ppriv->vlan_mutex); | 66 | mutex_lock(&ppriv->vlan_mutex); |
| 67 | 67 | ||
| 68 | /* | 68 | /* |
| 69 | * First ensure this isn't a duplicate. We check the parent device and | 69 | * First ensure this isn't a duplicate. We check the parent device and |
| @@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
| 124 | 124 | ||
| 125 | list_add_tail(&priv->list, &ppriv->child_intfs); | 125 | list_add_tail(&priv->list, &ppriv->child_intfs); |
| 126 | 126 | ||
| 127 | up(&ppriv->vlan_mutex); | 127 | mutex_unlock(&ppriv->vlan_mutex); |
| 128 | 128 | ||
| 129 | return 0; | 129 | return 0; |
| 130 | 130 | ||
| @@ -139,7 +139,7 @@ device_init_failed: | |||
| 139 | free_netdev(priv->dev); | 139 | free_netdev(priv->dev); |
| 140 | 140 | ||
| 141 | err: | 141 | err: |
| 142 | up(&ppriv->vlan_mutex); | 142 | mutex_unlock(&ppriv->vlan_mutex); |
| 143 | return result; | 143 | return result; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
| 153 | 153 | ||
| 154 | ppriv = netdev_priv(pdev); | 154 | ppriv = netdev_priv(pdev); |
| 155 | 155 | ||
| 156 | down(&ppriv->vlan_mutex); | 156 | mutex_lock(&ppriv->vlan_mutex); |
| 157 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { | 157 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { |
| 158 | if (priv->pkey == pkey) { | 158 | if (priv->pkey == pkey) { |
| 159 | unregister_netdev(priv->dev); | 159 | unregister_netdev(priv->dev); |
| @@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
| 167 | break; | 167 | break; |
| 168 | } | 168 | } |
| 169 | } | 169 | } |
| 170 | up(&ppriv->vlan_mutex); | 170 | mutex_unlock(&ppriv->vlan_mutex); |
| 171 | 171 | ||
| 172 | return ret; | 172 | return ret; |
| 173 | } | 173 | } |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index dd488d3cffa9..31207e664148 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
| @@ -1516,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf) | |||
| 1516 | 1516 | ||
| 1517 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); | 1517 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); |
| 1518 | 1518 | ||
| 1519 | static struct srp_host *srp_add_port(struct ib_device *device, | 1519 | static struct srp_host *srp_add_port(struct ib_device *device, u8 port) |
| 1520 | __be64 node_guid, u8 port) | ||
| 1521 | { | 1520 | { |
| 1522 | struct srp_host *host; | 1521 | struct srp_host *host; |
| 1523 | 1522 | ||
| @@ -1532,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, | |||
| 1532 | host->port = port; | 1531 | host->port = port; |
| 1533 | 1532 | ||
| 1534 | host->initiator_port_id[7] = port; | 1533 | host->initiator_port_id[7] = port; |
| 1535 | memcpy(host->initiator_port_id + 8, &node_guid, 8); | 1534 | memcpy(host->initiator_port_id + 8, &device->node_guid, 8); |
| 1536 | 1535 | ||
| 1537 | host->pd = ib_alloc_pd(device); | 1536 | host->pd = ib_alloc_pd(device); |
| 1538 | if (IS_ERR(host->pd)) | 1537 | if (IS_ERR(host->pd)) |
| @@ -1580,22 +1579,11 @@ static void srp_add_one(struct ib_device *device) | |||
| 1580 | { | 1579 | { |
| 1581 | struct list_head *dev_list; | 1580 | struct list_head *dev_list; |
| 1582 | struct srp_host *host; | 1581 | struct srp_host *host; |
| 1583 | struct ib_device_attr *dev_attr; | ||
| 1584 | int s, e, p; | 1582 | int s, e, p; |
| 1585 | 1583 | ||
| 1586 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); | ||
| 1587 | if (!dev_attr) | ||
| 1588 | return; | ||
| 1589 | |||
| 1590 | if (ib_query_device(device, dev_attr)) { | ||
| 1591 | printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n", | ||
| 1592 | device->name); | ||
| 1593 | goto out; | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); | 1584 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); |
| 1597 | if (!dev_list) | 1585 | if (!dev_list) |
| 1598 | goto out; | 1586 | return; |
| 1599 | 1587 | ||
| 1600 | INIT_LIST_HEAD(dev_list); | 1588 | INIT_LIST_HEAD(dev_list); |
| 1601 | 1589 | ||
| @@ -1608,15 +1596,12 @@ static void srp_add_one(struct ib_device *device) | |||
| 1608 | } | 1596 | } |
| 1609 | 1597 | ||
| 1610 | for (p = s; p <= e; ++p) { | 1598 | for (p = s; p <= e; ++p) { |
| 1611 | host = srp_add_port(device, dev_attr->node_guid, p); | 1599 | host = srp_add_port(device, p); |
| 1612 | if (host) | 1600 | if (host) |
| 1613 | list_add_tail(&host->list, dev_list); | 1601 | list_add_tail(&host->list, dev_list); |
| 1614 | } | 1602 | } |
| 1615 | 1603 | ||
| 1616 | ib_set_client_data(device, &srp_client, dev_list); | 1604 | ib_set_client_data(device, &srp_client, dev_list); |
| 1617 | |||
| 1618 | out: | ||
| 1619 | kfree(dev_attr); | ||
| 1620 | } | 1605 | } |
| 1621 | 1606 | ||
| 1622 | static void srp_remove_one(struct ib_device *device) | 1607 | static void srp_remove_one(struct ib_device *device) |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index caac6d63d46f..b765a155c008 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
| @@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem); | |||
| 50 | 50 | ||
| 51 | static LIST_HEAD(gameport_list); | 51 | static LIST_HEAD(gameport_list); |
| 52 | 52 | ||
| 53 | static struct bus_type gameport_bus = { | 53 | static struct bus_type gameport_bus; |
| 54 | .name = "gameport", | ||
| 55 | }; | ||
| 56 | 54 | ||
| 57 | static void gameport_add_port(struct gameport *gameport); | 55 | static void gameport_add_port(struct gameport *gameport); |
| 58 | static void gameport_destroy_port(struct gameport *gameport); | 56 | static void gameport_destroy_port(struct gameport *gameport); |
| @@ -703,11 +701,15 @@ static int gameport_driver_remove(struct device *dev) | |||
| 703 | return 0; | 701 | return 0; |
| 704 | } | 702 | } |
| 705 | 703 | ||
| 704 | static struct bus_type gameport_bus = { | ||
| 705 | .name = "gameport", | ||
| 706 | .probe = gameport_driver_probe, | ||
| 707 | .remove = gameport_driver_remove, | ||
| 708 | }; | ||
| 709 | |||
| 706 | void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) | 710 | void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) |
| 707 | { | 711 | { |
| 708 | drv->driver.bus = &gameport_bus; | 712 | drv->driver.bus = &gameport_bus; |
| 709 | drv->driver.probe = gameport_driver_probe; | ||
| 710 | drv->driver.remove = gameport_driver_remove; | ||
| 711 | gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); | 713 | gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); |
| 712 | } | 714 | } |
| 713 | 715 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index fe33ff334e27..4fe3da3c667a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -528,40 +528,56 @@ INPUT_DEV_STRING_ATTR_SHOW(name); | |||
| 528 | INPUT_DEV_STRING_ATTR_SHOW(phys); | 528 | INPUT_DEV_STRING_ATTR_SHOW(phys); |
| 529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); | 529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); |
| 530 | 530 | ||
| 531 | static int print_modalias_bits(char *buf, char prefix, unsigned long *arr, | 531 | static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr, |
| 532 | unsigned int min, unsigned int max) | 532 | unsigned int min, unsigned int max) |
| 533 | { | 533 | { |
| 534 | int len, i; | 534 | int len, i; |
| 535 | 535 | ||
| 536 | len = sprintf(buf, "%c", prefix); | 536 | len = snprintf(buf, size, "%c", prefix); |
| 537 | for (i = min; i < max; i++) | 537 | for (i = min; i < max; i++) |
| 538 | if (arr[LONG(i)] & BIT(i)) | 538 | if (arr[LONG(i)] & BIT(i)) |
| 539 | len += sprintf(buf+len, "%X,", i); | 539 | len += snprintf(buf + len, size - len, "%X,", i); |
| 540 | return len; | 540 | return len; |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | 543 | static int print_modalias(char *buf, int size, struct input_dev *id) |
| 544 | { | 544 | { |
| 545 | struct input_dev *id = to_input_dev(dev); | 545 | int len; |
| 546 | ssize_t len = 0; | ||
| 547 | 546 | ||
| 548 | len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-", | 547 | len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-", |
| 549 | id->id.bustype, | 548 | id->id.bustype, |
| 550 | id->id.vendor, | 549 | id->id.vendor, |
| 551 | id->id.product, | 550 | id->id.product, |
| 552 | id->id.version); | 551 | id->id.version); |
| 553 | 552 | ||
| 554 | len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX); | 553 | len += print_modalias_bits(buf + len, size - len, 'e', id->evbit, |
| 555 | len += print_modalias_bits(buf+len, 'k', id->keybit, | 554 | 0, EV_MAX); |
| 555 | len += print_modalias_bits(buf + len, size - len, 'k', id->keybit, | ||
| 556 | KEY_MIN_INTERESTING, KEY_MAX); | 556 | KEY_MIN_INTERESTING, KEY_MAX); |
| 557 | len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX); | 557 | len += print_modalias_bits(buf + len, size - len, 'r', id->relbit, |
| 558 | len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX); | 558 | 0, REL_MAX); |
| 559 | len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX); | 559 | len += print_modalias_bits(buf + len, size - len, 'a', id->absbit, |
| 560 | len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX); | 560 | 0, ABS_MAX); |
| 561 | len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX); | 561 | len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit, |
| 562 | len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX); | 562 | 0, MSC_MAX); |
| 563 | len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX); | 563 | len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit, |
| 564 | len += sprintf(buf+len, "\n"); | 564 | 0, LED_MAX); |
| 565 | len += print_modalias_bits(buf + len, size - len, 's', id->sndbit, | ||
| 566 | 0, SND_MAX); | ||
| 567 | len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit, | ||
| 568 | 0, FF_MAX); | ||
| 569 | len += print_modalias_bits(buf + len, size - len, 'w', id->swbit, | ||
| 570 | 0, SW_MAX); | ||
| 571 | return len; | ||
| 572 | } | ||
| 573 | |||
| 574 | static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | ||
| 575 | { | ||
| 576 | struct input_dev *id = to_input_dev(dev); | ||
| 577 | ssize_t len; | ||
| 578 | |||
| 579 | len = print_modalias(buf, PAGE_SIZE, id); | ||
| 580 | len += snprintf(buf + len, PAGE_SIZE-len, "\n"); | ||
| 565 | return len; | 581 | return len; |
| 566 | } | 582 | } |
| 567 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | 583 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); |
| @@ -728,8 +744,11 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, | |||
| 728 | if (test_bit(EV_SW, dev->evbit)) | 744 | if (test_bit(EV_SW, dev->evbit)) |
| 729 | INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); | 745 | INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); |
| 730 | 746 | ||
| 731 | envp[i] = NULL; | 747 | envp[i++] = buffer + len; |
| 748 | len += snprintf(buffer + len, buffer_size - len, "MODALIAS="); | ||
| 749 | len += print_modalias(buffer + len, buffer_size - len, dev) + 1; | ||
| 732 | 750 | ||
| 751 | envp[i] = NULL; | ||
| 733 | return 0; | 752 | return 0; |
| 734 | } | 753 | } |
| 735 | 754 | ||
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 24474335dfd1..2141501e9f2e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) | |||
| 348 | return 0; | 348 | return 0; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | /* | ||
| 352 | * alps_poll() - poll the touchpad for current motion packet. | ||
| 353 | * Used in resync. | ||
| 354 | */ | ||
| 355 | static int alps_poll(struct psmouse *psmouse) | ||
| 356 | { | ||
| 357 | struct alps_data *priv = psmouse->private; | ||
| 358 | unsigned char buf[6]; | ||
| 359 | int poll_failed; | ||
| 360 | |||
| 361 | if (priv->i->flags & ALPS_PASS) | ||
| 362 | alps_passthrough_mode(psmouse, 1); | ||
| 363 | |||
| 364 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | ||
| 365 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | ||
| 366 | |||
| 367 | if (priv->i->flags & ALPS_PASS) | ||
| 368 | alps_passthrough_mode(psmouse, 0); | ||
| 369 | |||
| 370 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | ||
| 371 | return -1; | ||
| 372 | |||
| 373 | if ((psmouse->badbyte & 0xc8) == 0x08) { | ||
| 374 | /* | ||
| 375 | * Poll the track stick ... | ||
| 376 | */ | ||
| 377 | if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) | ||
| 378 | return -1; | ||
| 379 | } | ||
| 380 | |||
| 381 | memcpy(psmouse->packet, buf, sizeof(buf)); | ||
| 382 | return 0; | ||
| 383 | } | ||
| 384 | |||
| 351 | static int alps_reconnect(struct psmouse *psmouse) | 385 | static int alps_reconnect(struct psmouse *psmouse) |
| 352 | { | 386 | { |
| 353 | struct alps_data *priv = psmouse->private; | 387 | struct alps_data *priv = psmouse->private; |
| @@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse) | |||
| 451 | input_register_device(priv->dev2); | 485 | input_register_device(priv->dev2); |
| 452 | 486 | ||
| 453 | psmouse->protocol_handler = alps_process_byte; | 487 | psmouse->protocol_handler = alps_process_byte; |
| 488 | psmouse->poll = alps_poll; | ||
| 454 | psmouse->disconnect = alps_disconnect; | 489 | psmouse->disconnect = alps_disconnect; |
| 455 | psmouse->reconnect = alps_reconnect; | 490 | psmouse->reconnect = alps_reconnect; |
| 456 | psmouse->pktsize = 6; | 491 | psmouse->pktsize = 6; |
| 457 | 492 | ||
| 493 | /* We are having trouble resyncing ALPS touchpads so disable it for now */ | ||
| 494 | psmouse->resync_time = 0; | ||
| 495 | |||
| 458 | return 0; | 496 | return 0; |
| 459 | 497 | ||
| 460 | init_fail: | 498 | init_fail: |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 025a71de5404..c88520d3d13c 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
| @@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
| 117 | if (psmouse_sliced_command(psmouse, command)) | 117 | if (psmouse_sliced_command(psmouse, command)) |
| 118 | return -1; | 118 | return -1; |
| 119 | 119 | ||
| 120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) | 120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300)) |
| 121 | return -1; | 121 | return -1; |
| 122 | 122 | ||
| 123 | return 0; | 123 | return 0; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 4d5ecc04c5b6..7665fd9ce559 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1; | |||
| 54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); | 54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); |
| 55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); | 55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); |
| 56 | 56 | ||
| 57 | static unsigned int psmouse_resetafter; | 57 | static unsigned int psmouse_resetafter = 5; |
| 58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
| 59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
| 60 | 60 | ||
| 61 | static unsigned int psmouse_resync_time = 5; | ||
| 62 | module_param_named(resync_time, psmouse_resync_time, uint, 0644); | ||
| 63 | MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); | ||
| 64 | |||
| 61 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, | 65 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, |
| 62 | NULL, | 66 | NULL, |
| 63 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); | 67 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); |
| @@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, | |||
| 70 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, | 74 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, |
| 71 | (void *) offsetof(struct psmouse, resetafter), | 75 | (void *) offsetof(struct psmouse, resetafter), |
| 72 | psmouse_show_int_attr, psmouse_set_int_attr); | 76 | psmouse_show_int_attr, psmouse_set_int_attr); |
| 77 | PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO, | ||
| 78 | (void *) offsetof(struct psmouse, resync_time), | ||
| 79 | psmouse_show_int_attr, psmouse_set_int_attr); | ||
| 73 | 80 | ||
| 74 | static struct attribute *psmouse_attributes[] = { | 81 | static struct attribute *psmouse_attributes[] = { |
| 75 | &psmouse_attr_protocol.dattr.attr, | 82 | &psmouse_attr_protocol.dattr.attr, |
| 76 | &psmouse_attr_rate.dattr.attr, | 83 | &psmouse_attr_rate.dattr.attr, |
| 77 | &psmouse_attr_resolution.dattr.attr, | 84 | &psmouse_attr_resolution.dattr.attr, |
| 78 | &psmouse_attr_resetafter.dattr.attr, | 85 | &psmouse_attr_resetafter.dattr.attr, |
| 86 | &psmouse_attr_resync_time.dattr.attr, | ||
| 79 | NULL | 87 | NULL |
| 80 | }; | 88 | }; |
| 81 | 89 | ||
| @@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate="); | |||
| 98 | */ | 106 | */ |
| 99 | static DECLARE_MUTEX(psmouse_sem); | 107 | static DECLARE_MUTEX(psmouse_sem); |
| 100 | 108 | ||
| 109 | static struct workqueue_struct *kpsmoused_wq; | ||
| 110 | |||
| 101 | struct psmouse_protocol { | 111 | struct psmouse_protocol { |
| 102 | enum psmouse_type type; | 112 | enum psmouse_type type; |
| 103 | char *name; | 113 | char *name; |
| @@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg | |||
| 178 | } | 188 | } |
| 179 | 189 | ||
| 180 | /* | 190 | /* |
| 181 | * psmouse_interrupt() handles incoming characters, either gathering them into | 191 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
| 182 | * packets or passing them to the command routine as command output. | 192 | */ |
| 193 | |||
| 194 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
| 195 | { | ||
| 196 | psmouse->state = new_state; | ||
| 197 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
| 198 | psmouse->ps2dev.flags = 0; | ||
| 199 | psmouse->last = jiffies; | ||
| 200 | } | ||
| 201 | |||
| 202 | |||
| 203 | /* | ||
| 204 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
| 205 | * counters while holding serio lock so fighting with interrupt handler | ||
| 206 | * is not a concern. | ||
| 207 | */ | ||
| 208 | |||
| 209 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
| 210 | { | ||
| 211 | serio_pause_rx(psmouse->ps2dev.serio); | ||
| 212 | __psmouse_set_state(psmouse, new_state); | ||
| 213 | serio_continue_rx(psmouse->ps2dev.serio); | ||
| 214 | } | ||
| 215 | |||
| 216 | /* | ||
| 217 | * psmouse_handle_byte() processes one byte of the input data stream | ||
| 218 | * by calling corresponding protocol handler. | ||
| 219 | */ | ||
| 220 | |||
| 221 | static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
| 222 | { | ||
| 223 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs); | ||
| 224 | |||
| 225 | switch (rc) { | ||
| 226 | case PSMOUSE_BAD_DATA: | ||
| 227 | if (psmouse->state == PSMOUSE_ACTIVATED) { | ||
| 228 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
| 229 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
| 230 | if (++psmouse->out_of_sync == psmouse->resetafter) { | ||
| 231 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
| 232 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | ||
| 233 | serio_reconnect(psmouse->ps2dev.serio); | ||
| 234 | return -1; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | psmouse->pktcnt = 0; | ||
| 238 | break; | ||
| 239 | |||
| 240 | case PSMOUSE_FULL_PACKET: | ||
| 241 | psmouse->pktcnt = 0; | ||
| 242 | if (psmouse->out_of_sync) { | ||
| 243 | psmouse->out_of_sync = 0; | ||
| 244 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
| 245 | psmouse->name, psmouse->phys); | ||
| 246 | } | ||
| 247 | break; | ||
| 248 | |||
| 249 | case PSMOUSE_GOOD_DATA: | ||
| 250 | break; | ||
| 251 | } | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* | ||
| 256 | * psmouse_interrupt() handles incoming characters, either passing them | ||
| 257 | * for normal processing or gathering them as command response. | ||
| 183 | */ | 258 | */ |
| 184 | 259 | ||
| 185 | static irqreturn_t psmouse_interrupt(struct serio *serio, | 260 | static irqreturn_t psmouse_interrupt(struct serio *serio, |
| 186 | unsigned char data, unsigned int flags, struct pt_regs *regs) | 261 | unsigned char data, unsigned int flags, struct pt_regs *regs) |
| 187 | { | 262 | { |
| 188 | struct psmouse *psmouse = serio_get_drvdata(serio); | 263 | struct psmouse *psmouse = serio_get_drvdata(serio); |
| 189 | psmouse_ret_t rc; | ||
| 190 | 264 | ||
| 191 | if (psmouse->state == PSMOUSE_IGNORE) | 265 | if (psmouse->state == PSMOUSE_IGNORE) |
| 192 | goto out; | 266 | goto out; |
| @@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
| 208 | if (ps2_handle_response(&psmouse->ps2dev, data)) | 282 | if (ps2_handle_response(&psmouse->ps2dev, data)) |
| 209 | goto out; | 283 | goto out; |
| 210 | 284 | ||
| 211 | if (psmouse->state == PSMOUSE_INITIALIZING) | 285 | if (psmouse->state <= PSMOUSE_RESYNCING) |
| 212 | goto out; | 286 | goto out; |
| 213 | 287 | ||
| 214 | if (psmouse->state == PSMOUSE_ACTIVATED && | 288 | if (psmouse->state == PSMOUSE_ACTIVATED && |
| 215 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { | 289 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { |
| 216 | printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", | 290 | printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", |
| 217 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 291 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
| 218 | psmouse->pktcnt = 0; | 292 | psmouse->badbyte = psmouse->packet[0]; |
| 293 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
| 294 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
| 295 | goto out; | ||
| 219 | } | 296 | } |
| 220 | 297 | ||
| 221 | psmouse->last = jiffies; | ||
| 222 | psmouse->packet[psmouse->pktcnt++] = data; | 298 | psmouse->packet[psmouse->pktcnt++] = data; |
| 223 | 299 | /* | |
| 224 | if (psmouse->packet[0] == PSMOUSE_RET_BAT) { | 300 | * Check if this is a new device announcement (0xAA 0x00) |
| 301 | */ | ||
| 302 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { | ||
| 225 | if (psmouse->pktcnt == 1) | 303 | if (psmouse->pktcnt == 1) |
| 226 | goto out; | 304 | goto out; |
| 227 | 305 | ||
| 228 | if (psmouse->pktcnt == 2) { | 306 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { |
| 229 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 307 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
| 230 | psmouse->state = PSMOUSE_IGNORE; | 308 | serio_reconnect(serio); |
| 231 | serio_reconnect(serio); | 309 | goto out; |
| 232 | goto out; | ||
| 233 | } | ||
| 234 | if (psmouse->type == PSMOUSE_SYNAPTICS) { | ||
| 235 | /* neither 0xAA nor 0x00 are valid first bytes | ||
| 236 | * for a packet in absolute mode | ||
| 237 | */ | ||
| 238 | psmouse->pktcnt = 0; | ||
| 239 | goto out; | ||
| 240 | } | ||
| 241 | } | 310 | } |
| 242 | } | 311 | /* |
| 243 | 312 | * Not a new device, try processing first byte normally | |
| 244 | rc = psmouse->protocol_handler(psmouse, regs); | 313 | */ |
| 314 | psmouse->pktcnt = 1; | ||
| 315 | if (psmouse_handle_byte(psmouse, regs)) | ||
| 316 | goto out; | ||
| 245 | 317 | ||
| 246 | switch (rc) { | 318 | psmouse->packet[psmouse->pktcnt++] = data; |
| 247 | case PSMOUSE_BAD_DATA: | 319 | } |
| 248 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
| 249 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
| 250 | psmouse->pktcnt = 0; | ||
| 251 | 320 | ||
| 252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 321 | /* |
| 253 | psmouse->state = PSMOUSE_IGNORE; | 322 | * See if we need to force resync because mouse was idle for too long |
| 254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 323 | */ |
| 255 | serio_reconnect(psmouse->ps2dev.serio); | 324 | if (psmouse->state == PSMOUSE_ACTIVATED && |
| 256 | } | 325 | psmouse->pktcnt == 1 && psmouse->resync_time && |
| 257 | break; | 326 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
| 327 | psmouse->badbyte = psmouse->packet[0]; | ||
| 328 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
| 329 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
| 330 | goto out; | ||
| 331 | } | ||
| 258 | 332 | ||
| 259 | case PSMOUSE_FULL_PACKET: | 333 | psmouse->last = jiffies; |
| 260 | psmouse->pktcnt = 0; | 334 | psmouse_handle_byte(psmouse, regs); |
| 261 | if (psmouse->out_of_sync) { | ||
| 262 | psmouse->out_of_sync = 0; | ||
| 263 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
| 264 | psmouse->name, psmouse->phys); | ||
| 265 | } | ||
| 266 | break; | ||
| 267 | 335 | ||
| 268 | case PSMOUSE_GOOD_DATA: | 336 | out: |
| 269 | break; | ||
| 270 | } | ||
| 271 | out: | ||
| 272 | return IRQ_HANDLED; | 337 | return IRQ_HANDLED; |
| 273 | } | 338 | } |
| 274 | 339 | ||
| @@ -752,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
| 752 | } | 817 | } |
| 753 | 818 | ||
| 754 | /* | 819 | /* |
| 755 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
| 756 | * counters while holding serio lock so fighting with interrupt handler | ||
| 757 | * is not a concern. | ||
| 758 | */ | ||
| 759 | |||
| 760 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
| 761 | { | ||
| 762 | serio_pause_rx(psmouse->ps2dev.serio); | ||
| 763 | psmouse->state = new_state; | ||
| 764 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
| 765 | psmouse->ps2dev.flags = 0; | ||
| 766 | serio_continue_rx(psmouse->ps2dev.serio); | ||
| 767 | } | ||
| 768 | |||
| 769 | /* | ||
| 770 | * psmouse_activate() enables the mouse so that we get motion reports from it. | 820 | * psmouse_activate() enables the mouse so that we get motion reports from it. |
| 771 | */ | 821 | */ |
| 772 | 822 | ||
| @@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse) | |||
| 794 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 844 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| 795 | } | 845 | } |
| 796 | 846 | ||
| 847 | /* | ||
| 848 | * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. | ||
| 849 | */ | ||
| 850 | |||
| 851 | static int psmouse_poll(struct psmouse *psmouse) | ||
| 852 | { | ||
| 853 | return ps2_command(&psmouse->ps2dev, psmouse->packet, | ||
| 854 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); | ||
| 855 | } | ||
| 856 | |||
| 857 | |||
| 858 | /* | ||
| 859 | * psmouse_resync() attempts to re-validate current protocol. | ||
| 860 | */ | ||
| 861 | |||
| 862 | static void psmouse_resync(void *p) | ||
| 863 | { | ||
| 864 | struct psmouse *psmouse = p, *parent = NULL; | ||
| 865 | struct serio *serio = psmouse->ps2dev.serio; | ||
| 866 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | ||
| 867 | int failed = 0, enabled = 0; | ||
| 868 | int i; | ||
| 869 | |||
| 870 | down(&psmouse_sem); | ||
| 871 | |||
| 872 | if (psmouse->state != PSMOUSE_RESYNCING) | ||
| 873 | goto out; | ||
| 874 | |||
| 875 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
| 876 | parent = serio_get_drvdata(serio->parent); | ||
| 877 | psmouse_deactivate(parent); | ||
| 878 | } | ||
| 879 | |||
| 880 | /* | ||
| 881 | * Some mice don't ACK commands sent while they are in the middle of | ||
| 882 | * transmitting motion packet. To avoid delay we use ps2_sendbyte() | ||
| 883 | * instead of ps2_command() which would wait for 200ms for an ACK | ||
| 884 | * that may never come. | ||
| 885 | * As an additional quirk ALPS touchpads may not only forget to ACK | ||
| 886 | * disable command but will stop reporting taps, so if we see that | ||
| 887 | * mouse at least once ACKs disable we will do full reconnect if ACK | ||
| 888 | * is missing. | ||
| 889 | */ | ||
| 890 | psmouse->num_resyncs++; | ||
| 891 | |||
| 892 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | ||
| 893 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | ||
| 894 | failed = 1; | ||
| 895 | } else | ||
| 896 | psmouse->acks_disable_command = 1; | ||
| 897 | |||
| 898 | /* | ||
| 899 | * Poll the mouse. If it was reset the packet will be shorter than | ||
| 900 | * psmouse->pktsize and ps2_command will fail. We do not expect and | ||
| 901 | * do not handle scenario when mouse "upgrades" its protocol while | ||
| 902 | * disconnected since it would require additional delay. If we ever | ||
| 903 | * see a mouse that does it we'll adjust the code. | ||
| 904 | */ | ||
| 905 | if (!failed) { | ||
| 906 | if (psmouse->poll(psmouse)) | ||
| 907 | failed = 1; | ||
| 908 | else { | ||
| 909 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
| 910 | for (i = 0; i < psmouse->pktsize; i++) { | ||
| 911 | psmouse->pktcnt++; | ||
| 912 | rc = psmouse->protocol_handler(psmouse, NULL); | ||
| 913 | if (rc != PSMOUSE_GOOD_DATA) | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | if (rc != PSMOUSE_FULL_PACKET) | ||
| 917 | failed = 1; | ||
| 918 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
| 919 | } | ||
| 920 | } | ||
| 921 | /* | ||
| 922 | * Now try to enable mouse. We try to do that even if poll failed and also | ||
| 923 | * repeat our attempts 5 times, otherwise we may be left out with disabled | ||
| 924 | * mouse. | ||
| 925 | */ | ||
| 926 | for (i = 0; i < 5; i++) { | ||
| 927 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | ||
| 928 | enabled = 1; | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | msleep(200); | ||
| 932 | } | ||
| 933 | |||
| 934 | if (!enabled) { | ||
| 935 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | ||
| 936 | psmouse->ps2dev.serio->phys); | ||
| 937 | failed = 1; | ||
| 938 | } | ||
| 939 | |||
| 940 | if (failed) { | ||
| 941 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
| 942 | printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); | ||
| 943 | serio_reconnect(serio); | ||
| 944 | } else | ||
| 945 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
| 946 | |||
| 947 | if (parent) | ||
| 948 | psmouse_activate(parent); | ||
| 949 | out: | ||
| 950 | up(&psmouse_sem); | ||
| 951 | } | ||
| 797 | 952 | ||
| 798 | /* | 953 | /* |
| 799 | * psmouse_cleanup() resets the mouse into power-on state. | 954 | * psmouse_cleanup() resets the mouse into power-on state. |
| @@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio) | |||
| 822 | 977 | ||
| 823 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 978 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| 824 | 979 | ||
| 980 | /* make sure we don't have a resync in progress */ | ||
| 981 | up(&psmouse_sem); | ||
| 982 | flush_workqueue(kpsmoused_wq); | ||
| 983 | down(&psmouse_sem); | ||
| 984 | |||
| 825 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 985 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
| 826 | parent = serio_get_drvdata(serio->parent); | 986 | parent = serio_get_drvdata(serio->parent); |
| 827 | psmouse_deactivate(parent); | 987 | psmouse_deactivate(parent); |
| @@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
| 859 | 1019 | ||
| 860 | psmouse->set_rate = psmouse_set_rate; | 1020 | psmouse->set_rate = psmouse_set_rate; |
| 861 | psmouse->set_resolution = psmouse_set_resolution; | 1021 | psmouse->set_resolution = psmouse_set_resolution; |
| 1022 | psmouse->poll = psmouse_poll; | ||
| 862 | psmouse->protocol_handler = psmouse_process_byte; | 1023 | psmouse->protocol_handler = psmouse_process_byte; |
| 863 | psmouse->pktsize = 3; | 1024 | psmouse->pktsize = 3; |
| 864 | 1025 | ||
| @@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
| 874 | else | 1035 | else |
| 875 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1036 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); |
| 876 | 1037 | ||
| 1038 | /* | ||
| 1039 | * If mouse's packet size is 3 there is no point in polling the | ||
| 1040 | * device in hopes to detect protocol reset - we won't get less | ||
| 1041 | * than 3 bytes response anyhow. | ||
| 1042 | */ | ||
| 1043 | if (psmouse->pktsize == 3) | ||
| 1044 | psmouse->resync_time = 0; | ||
| 1045 | |||
| 1046 | /* | ||
| 1047 | * Some smart KVMs fake response to POLL command returning just | ||
| 1048 | * 3 bytes and messing up our resync logic, so if initial poll | ||
| 1049 | * fails we won't try polling the device anymore. Hopefully | ||
| 1050 | * such KVM will maintain initially selected protocol. | ||
| 1051 | */ | ||
| 1052 | if (psmouse->resync_time && psmouse->poll(psmouse)) | ||
| 1053 | psmouse->resync_time = 0; | ||
| 1054 | |||
| 877 | sprintf(psmouse->devname, "%s %s %s", | 1055 | sprintf(psmouse->devname, "%s %s %s", |
| 878 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1056 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); |
| 879 | 1057 | ||
| @@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 914 | goto out; | 1092 | goto out; |
| 915 | 1093 | ||
| 916 | ps2_init(&psmouse->ps2dev, serio); | 1094 | ps2_init(&psmouse->ps2dev, serio); |
| 1095 | INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); | ||
| 917 | psmouse->dev = input_dev; | 1096 | psmouse->dev = input_dev; |
| 918 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 1097 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
| 919 | 1098 | ||
| @@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 934 | psmouse->rate = psmouse_rate; | 1113 | psmouse->rate = psmouse_rate; |
| 935 | psmouse->resolution = psmouse_resolution; | 1114 | psmouse->resolution = psmouse_resolution; |
| 936 | psmouse->resetafter = psmouse_resetafter; | 1115 | psmouse->resetafter = psmouse_resetafter; |
| 1116 | psmouse->resync_time = parent ? 0 : psmouse_resync_time; | ||
| 937 | psmouse->smartscroll = psmouse_smartscroll; | 1117 | psmouse->smartscroll = psmouse_smartscroll; |
| 938 | 1118 | ||
| 939 | psmouse_switch_protocol(psmouse, NULL); | 1119 | psmouse_switch_protocol(psmouse, NULL); |
| @@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | |||
| 1278 | 1458 | ||
| 1279 | static int __init psmouse_init(void) | 1459 | static int __init psmouse_init(void) |
| 1280 | { | 1460 | { |
| 1461 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | ||
| 1462 | if (!kpsmoused_wq) { | ||
| 1463 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); | ||
| 1464 | return -ENOMEM; | ||
| 1465 | } | ||
| 1466 | |||
| 1281 | serio_register_driver(&psmouse_drv); | 1467 | serio_register_driver(&psmouse_drv); |
| 1468 | |||
| 1282 | return 0; | 1469 | return 0; |
| 1283 | } | 1470 | } |
| 1284 | 1471 | ||
| 1285 | static void __exit psmouse_exit(void) | 1472 | static void __exit psmouse_exit(void) |
| 1286 | { | 1473 | { |
| 1287 | serio_unregister_driver(&psmouse_drv); | 1474 | serio_unregister_driver(&psmouse_drv); |
| 1475 | destroy_workqueue(kpsmoused_wq); | ||
| 1288 | } | 1476 | } |
| 1289 | 1477 | ||
| 1290 | module_init(psmouse_init); | 1478 | module_init(psmouse_init); |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 7c4192bd1279..4d9107fba6a1 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #define PSMOUSE_CMD_GETINFO 0x03e9 | 7 | #define PSMOUSE_CMD_GETINFO 0x03e9 |
| 8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea | 8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea |
| 9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 | 9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 |
| 10 | #define PSMOUSE_CMD_POLL 0x03eb | 10 | #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ |
| 11 | #define PSMOUSE_CMD_GETID 0x02f2 | 11 | #define PSMOUSE_CMD_GETID 0x02f2 |
| 12 | #define PSMOUSE_CMD_SETRATE 0x10f3 | 12 | #define PSMOUSE_CMD_SETRATE 0x10f3 |
| 13 | #define PSMOUSE_CMD_ENABLE 0x00f4 | 13 | #define PSMOUSE_CMD_ENABLE 0x00f4 |
| @@ -23,6 +23,7 @@ | |||
| 23 | enum psmouse_state { | 23 | enum psmouse_state { |
| 24 | PSMOUSE_IGNORE, | 24 | PSMOUSE_IGNORE, |
| 25 | PSMOUSE_INITIALIZING, | 25 | PSMOUSE_INITIALIZING, |
| 26 | PSMOUSE_RESYNCING, | ||
| 26 | PSMOUSE_CMD_MODE, | 27 | PSMOUSE_CMD_MODE, |
| 27 | PSMOUSE_ACTIVATED, | 28 | PSMOUSE_ACTIVATED, |
| 28 | }; | 29 | }; |
| @@ -38,15 +39,19 @@ struct psmouse { | |||
| 38 | void *private; | 39 | void *private; |
| 39 | struct input_dev *dev; | 40 | struct input_dev *dev; |
| 40 | struct ps2dev ps2dev; | 41 | struct ps2dev ps2dev; |
| 42 | struct work_struct resync_work; | ||
| 41 | char *vendor; | 43 | char *vendor; |
| 42 | char *name; | 44 | char *name; |
| 43 | unsigned char packet[8]; | 45 | unsigned char packet[8]; |
| 46 | unsigned char badbyte; | ||
| 44 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
| 45 | unsigned char pktsize; | 48 | unsigned char pktsize; |
| 46 | unsigned char type; | 49 | unsigned char type; |
| 50 | unsigned char acks_disable_command; | ||
| 47 | unsigned int model; | 51 | unsigned int model; |
| 48 | unsigned long last; | 52 | unsigned long last; |
| 49 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync; |
| 54 | unsigned long num_resyncs; | ||
| 50 | enum psmouse_state state; | 55 | enum psmouse_state state; |
| 51 | char devname[64]; | 56 | char devname[64]; |
| 52 | char phys[32]; | 57 | char phys[32]; |
| @@ -54,6 +59,7 @@ struct psmouse { | |||
| 54 | unsigned int rate; | 59 | unsigned int rate; |
| 55 | unsigned int resolution; | 60 | unsigned int resolution; |
| 56 | unsigned int resetafter; | 61 | unsigned int resetafter; |
| 62 | unsigned int resync_time; | ||
| 57 | unsigned int smartscroll; /* Logitech only */ | 63 | unsigned int smartscroll; /* Logitech only */ |
| 58 | 64 | ||
| 59 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); |
| @@ -62,6 +68,7 @@ struct psmouse { | |||
| 62 | 68 | ||
| 63 | int (*reconnect)(struct psmouse *psmouse); | 69 | int (*reconnect)(struct psmouse *psmouse); |
| 64 | void (*disconnect)(struct psmouse *psmouse); | 70 | void (*disconnect)(struct psmouse *psmouse); |
| 71 | int (*poll)(struct psmouse *psmouse); | ||
| 65 | 72 | ||
| 66 | void (*pt_activate)(struct psmouse *psmouse); | 73 | void (*pt_activate)(struct psmouse *psmouse); |
| 67 | void (*pt_deactivate)(struct psmouse *psmouse); | 74 | void (*pt_deactivate)(struct psmouse *psmouse); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 97cdfd6acaca..2051bec2c394 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 652 | psmouse->disconnect = synaptics_disconnect; | 652 | psmouse->disconnect = synaptics_disconnect; |
| 653 | psmouse->reconnect = synaptics_reconnect; | 653 | psmouse->reconnect = synaptics_reconnect; |
| 654 | psmouse->pktsize = 6; | 654 | psmouse->pktsize = 6; |
| 655 | /* Synaptics can usually stay in sync without extra help */ | ||
| 656 | psmouse->resync_time = 0; | ||
| 655 | 657 | ||
| 656 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) | 658 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
| 657 | synaptics_pt_create(psmouse); | 659 | synaptics_pt_create(psmouse); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2d2f9fb3aded..a4c6f3522723 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
| @@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), | 173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), |
| 174 | }, | 174 | }, |
| 175 | }, | 175 | }, |
| 176 | { | ||
| 177 | .ident = "Sony Vaio FS-115b", | ||
| 178 | .matches = { | ||
| 179 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 180 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), | ||
| 181 | }, | ||
| 182 | }, | ||
| 176 | { } | 183 | { } |
| 177 | }; | 184 | }; |
| 178 | 185 | ||
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 8e530cc970e1..2f76813c3a64 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
| @@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem); | |||
| 59 | 59 | ||
| 60 | static LIST_HEAD(serio_list); | 60 | static LIST_HEAD(serio_list); |
| 61 | 61 | ||
| 62 | static struct bus_type serio_bus = { | 62 | static struct bus_type serio_bus; |
| 63 | .name = "serio", | ||
| 64 | }; | ||
| 65 | 63 | ||
| 66 | static void serio_add_port(struct serio *serio); | 64 | static void serio_add_port(struct serio *serio); |
| 67 | static void serio_destroy_port(struct serio *serio); | 65 | static void serio_destroy_port(struct serio *serio); |
| @@ -750,11 +748,15 @@ static int serio_driver_remove(struct device *dev) | |||
| 750 | return 0; | 748 | return 0; |
| 751 | } | 749 | } |
| 752 | 750 | ||
| 751 | static struct bus_type serio_bus = { | ||
| 752 | .name = "serio", | ||
| 753 | .probe = serio_driver_probe, | ||
| 754 | .remove = serio_driver_remove, | ||
| 755 | }; | ||
| 756 | |||
| 753 | void __serio_register_driver(struct serio_driver *drv, struct module *owner) | 757 | void __serio_register_driver(struct serio_driver *drv, struct module *owner) |
| 754 | { | 758 | { |
| 755 | drv->driver.bus = &serio_bus; | 759 | drv->driver.bus = &serio_bus; |
| 756 | drv->driver.probe = serio_driver_probe; | ||
| 757 | drv->driver.remove = serio_driver_remove; | ||
| 758 | 760 | ||
| 759 | serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); | 761 | serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); |
| 760 | } | 762 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 21d55ed4b88a..2c674023a6ac 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN | |||
| 11 | 11 | ||
| 12 | if INPUT_TOUCHSCREEN | 12 | if INPUT_TOUCHSCREEN |
| 13 | 13 | ||
| 14 | config TOUCHSCREEN_ADS7846 | ||
| 15 | tristate "ADS 7846 based touchscreens" | ||
| 16 | depends on SPI_MASTER | ||
| 17 | help | ||
| 18 | Say Y here if you have a touchscreen interface using the | ||
| 19 | ADS7846 controller, and your board-specific initialization | ||
| 20 | code includes that in its table of SPI devices. | ||
| 21 | |||
| 22 | If unsure, say N (but it's safe to say "Y"). | ||
| 23 | |||
| 24 | To compile this driver as a module, choose M here: the | ||
| 25 | module will be called ads7846. | ||
| 26 | |||
| 14 | config TOUCHSCREEN_BITSY | 27 | config TOUCHSCREEN_BITSY |
| 15 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" | 28 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" |
| 16 | depends on SA1100_BITSY | 29 | depends on SA1100_BITSY |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 6842869c9a26..5e5557c43121 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | ||
| 7 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 8 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
| 8 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 9 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
| 9 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 10 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c new file mode 100644 index 000000000000..dd8c6a9ffc76 --- /dev/null +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -0,0 +1,625 @@ | |||
| 1 | /* | ||
| 2 | * ADS7846 based touchscreen and sensor driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 David Brownell | ||
| 5 | * | ||
| 6 | * Using code from: | ||
| 7 | * - corgi_ts.c | ||
| 8 | * Copyright (C) 2004-2005 Richard Purdie | ||
| 9 | * - omap_ts.[hc], ads7846.h, ts_osk.c | ||
| 10 | * Copyright (C) 2002 MontaVista Software | ||
| 11 | * Copyright (C) 2004 Texas Instruments | ||
| 12 | * Copyright (C) 2005 Dirk Behme | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify | ||
| 15 | * it under the terms of the GNU General Public License version 2 as | ||
| 16 | * published by the Free Software Foundation. | ||
| 17 | */ | ||
| 18 | #include <linux/device.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/input.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/spi/spi.h> | ||
| 25 | #include <linux/spi/ads7846.h> | ||
| 26 | |||
| 27 | #ifdef CONFIG_ARM | ||
| 28 | #include <asm/mach-types.h> | ||
| 29 | #ifdef CONFIG_ARCH_OMAP | ||
| 30 | #include <asm/arch/gpio.h> | ||
| 31 | #endif | ||
| 32 | |||
| 33 | #else | ||
| 34 | #define set_irq_type(irq,type) do{}while(0) | ||
| 35 | #endif | ||
| 36 | |||
| 37 | |||
| 38 | /* | ||
| 39 | * This code has been lightly tested on an ads7846. | ||
| 40 | * Support for ads7843 and ads7845 has only been stubbed in. | ||
| 41 | * | ||
| 42 | * Not yet done: investigate the values reported. Are x/y/pressure | ||
| 43 | * event values sane enough for X11? How accurate are the temperature | ||
| 44 | * and voltage readings? (System-specific calibration should support | ||
| 45 | * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) | ||
| 46 | * | ||
| 47 | * app note sbaa036 talks in more detail about accurate sampling... | ||
| 48 | * that ought to help in situations like LCDs inducing noise (which | ||
| 49 | * can also be helped by using synch signals) and more generally. | ||
| 50 | */ | ||
| 51 | |||
| 52 | #define TS_POLL_PERIOD msecs_to_jiffies(10) | ||
| 53 | |||
| 54 | struct ts_event { | ||
| 55 | /* For portability, we can't read 12 bit values using SPI (which | ||
| 56 | * would make the controller deliver them as native byteorder u16 | ||
| 57 | * with msbs zeroed). Instead, we read them as two 8-byte values, | ||
| 58 | * which need byteswapping then range adjustment. | ||
| 59 | */ | ||
| 60 | __be16 x; | ||
| 61 | __be16 y; | ||
| 62 | __be16 z1, z2; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct ads7846 { | ||
| 66 | struct input_dev input; | ||
| 67 | char phys[32]; | ||
| 68 | |||
| 69 | struct spi_device *spi; | ||
| 70 | u16 model; | ||
| 71 | u16 vref_delay_usecs; | ||
| 72 | u16 x_plate_ohms; | ||
| 73 | |||
| 74 | struct ts_event tc; | ||
| 75 | |||
| 76 | struct spi_transfer xfer[8]; | ||
| 77 | struct spi_message msg; | ||
| 78 | |||
| 79 | spinlock_t lock; | ||
| 80 | struct timer_list timer; /* P: lock */ | ||
| 81 | unsigned pendown:1; /* P: lock */ | ||
| 82 | unsigned pending:1; /* P: lock */ | ||
| 83 | // FIXME remove "irq_disabled" | ||
| 84 | unsigned irq_disabled:1; /* P: lock */ | ||
| 85 | }; | ||
| 86 | |||
| 87 | /* leave chip selected when we're done, for quicker re-select? */ | ||
| 88 | #if 0 | ||
| 89 | #define CS_CHANGE(xfer) ((xfer).cs_change = 1) | ||
| 90 | #else | ||
| 91 | #define CS_CHANGE(xfer) ((xfer).cs_change = 0) | ||
| 92 | #endif | ||
| 93 | |||
| 94 | /*--------------------------------------------------------------------------*/ | ||
| 95 | |||
| 96 | /* The ADS7846 has touchscreen and other sensors. | ||
| 97 | * Earlier ads784x chips are somewhat compatible. | ||
| 98 | */ | ||
| 99 | #define ADS_START (1 << 7) | ||
| 100 | #define ADS_A2A1A0_d_y (1 << 4) /* differential */ | ||
| 101 | #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ | ||
| 102 | #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ | ||
| 103 | #define ADS_A2A1A0_d_x (5 << 4) /* differential */ | ||
| 104 | #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ | ||
| 105 | #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ | ||
| 106 | #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ | ||
| 107 | #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ | ||
| 108 | #define ADS_8_BIT (1 << 3) | ||
| 109 | #define ADS_12_BIT (0 << 3) | ||
| 110 | #define ADS_SER (1 << 2) /* non-differential */ | ||
| 111 | #define ADS_DFR (0 << 2) /* differential */ | ||
| 112 | #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ | ||
| 113 | #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ | ||
| 114 | #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ | ||
| 115 | #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ | ||
| 116 | |||
| 117 | #define MAX_12BIT ((1<<12)-1) | ||
| 118 | |||
| 119 | /* leave ADC powered up (disables penirq) between differential samples */ | ||
| 120 | #define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ | ||
| 121 | | ADS_12_BIT | ADS_DFR) | ||
| 122 | |||
| 123 | static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON; | ||
| 124 | static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON; | ||
| 125 | static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON; | ||
| 126 | static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */ | ||
| 127 | |||
| 128 | /* single-ended samples need to first power up reference voltage; | ||
| 129 | * we leave both ADC and VREF powered | ||
| 130 | */ | ||
| 131 | #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ | ||
| 132 | | ADS_12_BIT | ADS_SER) | ||
| 133 | |||
| 134 | static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON; | ||
| 135 | static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN; | ||
| 136 | |||
| 137 | /*--------------------------------------------------------------------------*/ | ||
| 138 | |||
| 139 | /* | ||
| 140 | * Non-touchscreen sensors only use single-ended conversions. | ||
| 141 | */ | ||
| 142 | |||
| 143 | struct ser_req { | ||
| 144 | u8 command; | ||
| 145 | u16 scratch; | ||
| 146 | __be16 sample; | ||
| 147 | struct spi_message msg; | ||
| 148 | struct spi_transfer xfer[6]; | ||
| 149 | }; | ||
| 150 | |||
| 151 | static int ads7846_read12_ser(struct device *dev, unsigned command) | ||
| 152 | { | ||
| 153 | struct spi_device *spi = to_spi_device(dev); | ||
| 154 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
| 155 | struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); | ||
| 156 | int status; | ||
| 157 | int sample; | ||
| 158 | int i; | ||
| 159 | |||
| 160 | if (!req) | ||
| 161 | return -ENOMEM; | ||
| 162 | |||
| 163 | INIT_LIST_HEAD(&req->msg.transfers); | ||
| 164 | |||
| 165 | /* activate reference, so it has time to settle; */ | ||
| 166 | req->xfer[0].tx_buf = &ref_on; | ||
| 167 | req->xfer[0].len = 1; | ||
| 168 | req->xfer[1].rx_buf = &req->scratch; | ||
| 169 | req->xfer[1].len = 2; | ||
| 170 | |||
| 171 | /* | ||
| 172 | * for external VREF, 0 usec (and assume it's always on); | ||
| 173 | * for 1uF, use 800 usec; | ||
| 174 | * no cap, 100 usec. | ||
| 175 | */ | ||
| 176 | req->xfer[1].delay_usecs = ts->vref_delay_usecs; | ||
| 177 | |||
| 178 | /* take sample */ | ||
| 179 | req->command = (u8) command; | ||
| 180 | req->xfer[2].tx_buf = &req->command; | ||
| 181 | req->xfer[2].len = 1; | ||
| 182 | req->xfer[3].rx_buf = &req->sample; | ||
| 183 | req->xfer[3].len = 2; | ||
| 184 | |||
| 185 | /* REVISIT: take a few more samples, and compare ... */ | ||
| 186 | |||
| 187 | /* turn off reference */ | ||
| 188 | req->xfer[4].tx_buf = &ref_off; | ||
| 189 | req->xfer[4].len = 1; | ||
| 190 | req->xfer[5].rx_buf = &req->scratch; | ||
| 191 | req->xfer[5].len = 2; | ||
| 192 | |||
| 193 | CS_CHANGE(req->xfer[5]); | ||
| 194 | |||
| 195 | /* group all the transfers together, so we can't interfere with | ||
| 196 | * reading touchscreen state; disable penirq while sampling | ||
| 197 | */ | ||
| 198 | for (i = 0; i < 6; i++) | ||
| 199 | spi_message_add_tail(&req->xfer[i], &req->msg); | ||
| 200 | |||
| 201 | disable_irq(spi->irq); | ||
| 202 | status = spi_sync(spi, &req->msg); | ||
| 203 | enable_irq(spi->irq); | ||
| 204 | |||
| 205 | if (req->msg.status) | ||
| 206 | status = req->msg.status; | ||
| 207 | sample = be16_to_cpu(req->sample); | ||
| 208 | sample = sample >> 4; | ||
| 209 | kfree(req); | ||
| 210 | |||
| 211 | return status ? status : sample; | ||
| 212 | } | ||
| 213 | |||
| 214 | #define SHOW(name) static ssize_t \ | ||
| 215 | name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 216 | { \ | ||
| 217 | ssize_t v = ads7846_read12_ser(dev, \ | ||
| 218 | READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ | ||
| 219 | if (v < 0) \ | ||
| 220 | return v; \ | ||
| 221 | return sprintf(buf, "%u\n", (unsigned) v); \ | ||
| 222 | } \ | ||
| 223 | static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); | ||
| 224 | |||
| 225 | SHOW(temp0) | ||
| 226 | SHOW(temp1) | ||
| 227 | SHOW(vaux) | ||
| 228 | SHOW(vbatt) | ||
| 229 | |||
| 230 | /*--------------------------------------------------------------------------*/ | ||
| 231 | |||
| 232 | /* | ||
| 233 | * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, | ||
| 234 | * to retrieve touchscreen status. | ||
| 235 | * | ||
| 236 | * The SPI transfer completion callback does the real work. It reports | ||
| 237 | * touchscreen events and reactivates the timer (or IRQ) as appropriate. | ||
| 238 | */ | ||
| 239 | |||
| 240 | static void ads7846_rx(void *ads) | ||
| 241 | { | ||
| 242 | struct ads7846 *ts = ads; | ||
| 243 | unsigned Rt; | ||
| 244 | unsigned sync = 0; | ||
| 245 | u16 x, y, z1, z2; | ||
| 246 | unsigned long flags; | ||
| 247 | |||
| 248 | /* adjust: 12 bit samples (left aligned), built from | ||
| 249 | * two 8 bit values writen msb-first. | ||
| 250 | */ | ||
| 251 | x = be16_to_cpu(ts->tc.x) >> 4; | ||
| 252 | y = be16_to_cpu(ts->tc.y) >> 4; | ||
| 253 | z1 = be16_to_cpu(ts->tc.z1) >> 4; | ||
| 254 | z2 = be16_to_cpu(ts->tc.z2) >> 4; | ||
| 255 | |||
| 256 | /* range filtering */ | ||
| 257 | if (x == MAX_12BIT) | ||
| 258 | x = 0; | ||
| 259 | |||
| 260 | if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | ||
| 261 | /* compute touch pressure resistance using equation #2 */ | ||
| 262 | Rt = z2; | ||
| 263 | Rt -= z1; | ||
| 264 | Rt *= x; | ||
| 265 | Rt *= ts->x_plate_ohms; | ||
| 266 | Rt /= z1; | ||
| 267 | Rt = (Rt + 2047) >> 12; | ||
| 268 | } else | ||
| 269 | Rt = 0; | ||
| 270 | |||
| 271 | /* NOTE: "pendown" is inferred from pressure; we don't rely on | ||
| 272 | * being able to check nPENIRQ status, or "friendly" trigger modes | ||
| 273 | * (both-edges is much better than just-falling or low-level). | ||
| 274 | * | ||
| 275 | * REVISIT: some boards may require reading nPENIRQ; it's | ||
| 276 | * needed on 7843. and 7845 reads pressure differently... | ||
| 277 | * | ||
| 278 | * REVISIT: the touchscreen might not be connected; this code | ||
| 279 | * won't notice that, even if nPENIRQ never fires ... | ||
| 280 | */ | ||
| 281 | if (!ts->pendown && Rt != 0) { | ||
| 282 | input_report_key(&ts->input, BTN_TOUCH, 1); | ||
| 283 | sync = 1; | ||
| 284 | } else if (ts->pendown && Rt == 0) { | ||
| 285 | input_report_key(&ts->input, BTN_TOUCH, 0); | ||
| 286 | sync = 1; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (Rt) { | ||
| 290 | input_report_abs(&ts->input, ABS_X, x); | ||
| 291 | input_report_abs(&ts->input, ABS_Y, y); | ||
| 292 | input_report_abs(&ts->input, ABS_PRESSURE, Rt); | ||
| 293 | sync = 1; | ||
| 294 | } | ||
| 295 | if (sync) | ||
| 296 | input_sync(&ts->input); | ||
| 297 | |||
| 298 | #ifdef VERBOSE | ||
| 299 | if (Rt || ts->pendown) | ||
| 300 | pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, | ||
| 301 | x, y, Rt, Rt ? "" : " UP"); | ||
| 302 | #endif | ||
| 303 | |||
| 304 | /* don't retrigger while we're suspended */ | ||
| 305 | spin_lock_irqsave(&ts->lock, flags); | ||
| 306 | |||
| 307 | ts->pendown = (Rt != 0); | ||
| 308 | ts->pending = 0; | ||
| 309 | |||
| 310 | if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | ||
| 311 | if (ts->pendown) | ||
| 312 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | ||
| 313 | else if (ts->irq_disabled) { | ||
| 314 | ts->irq_disabled = 0; | ||
| 315 | enable_irq(ts->spi->irq); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 320 | } | ||
| 321 | |||
| 322 | static void ads7846_timer(unsigned long handle) | ||
| 323 | { | ||
| 324 | struct ads7846 *ts = (void *)handle; | ||
| 325 | int status = 0; | ||
| 326 | unsigned long flags; | ||
| 327 | |||
| 328 | spin_lock_irqsave(&ts->lock, flags); | ||
| 329 | if (!ts->pending) { | ||
| 330 | ts->pending = 1; | ||
| 331 | if (!ts->irq_disabled) { | ||
| 332 | ts->irq_disabled = 1; | ||
| 333 | disable_irq(ts->spi->irq); | ||
| 334 | } | ||
| 335 | status = spi_async(ts->spi, &ts->msg); | ||
| 336 | if (status) | ||
| 337 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | ||
| 338 | status); | ||
| 339 | } | ||
| 340 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 341 | } | ||
| 342 | |||
| 343 | static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) | ||
| 344 | { | ||
| 345 | ads7846_timer((unsigned long) handle); | ||
| 346 | return IRQ_HANDLED; | ||
| 347 | } | ||
| 348 | |||
| 349 | /*--------------------------------------------------------------------------*/ | ||
| 350 | |||
| 351 | static int | ||
| 352 | ads7846_suspend(struct spi_device *spi, pm_message_t message) | ||
| 353 | { | ||
| 354 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
| 355 | unsigned long flags; | ||
| 356 | |||
| 357 | spin_lock_irqsave(&ts->lock, flags); | ||
| 358 | |||
| 359 | spi->dev.power.power_state = message; | ||
| 360 | |||
| 361 | /* are we waiting for IRQ, or polling? */ | ||
| 362 | if (!ts->pendown) { | ||
| 363 | if (!ts->irq_disabled) { | ||
| 364 | ts->irq_disabled = 1; | ||
| 365 | disable_irq(ts->spi->irq); | ||
| 366 | } | ||
| 367 | } else { | ||
| 368 | /* polling; force a final SPI completion; | ||
| 369 | * that will clean things up neatly | ||
| 370 | */ | ||
| 371 | if (!ts->pending) | ||
| 372 | mod_timer(&ts->timer, jiffies); | ||
| 373 | |||
| 374 | while (ts->pendown || ts->pending) { | ||
| 375 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 376 | udelay(10); | ||
| 377 | spin_lock_irqsave(&ts->lock, flags); | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | /* we know the chip's in lowpower mode since we always | ||
| 382 | * leave it that way after every request | ||
| 383 | */ | ||
| 384 | |||
| 385 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int ads7846_resume(struct spi_device *spi) | ||
| 390 | { | ||
| 391 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
| 392 | |||
| 393 | ts->irq_disabled = 0; | ||
| 394 | enable_irq(ts->spi->irq); | ||
| 395 | spi->dev.power.power_state = PMSG_ON; | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int __devinit ads7846_probe(struct spi_device *spi) | ||
| 400 | { | ||
| 401 | struct ads7846 *ts; | ||
| 402 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | ||
| 403 | struct spi_transfer *x; | ||
| 404 | int i; | ||
| 405 | |||
| 406 | if (!spi->irq) { | ||
| 407 | dev_dbg(&spi->dev, "no IRQ?\n"); | ||
| 408 | return -ENODEV; | ||
| 409 | } | ||
| 410 | |||
| 411 | if (!pdata) { | ||
| 412 | dev_dbg(&spi->dev, "no platform data?\n"); | ||
| 413 | return -ENODEV; | ||
| 414 | } | ||
| 415 | |||
| 416 | /* don't exceed max specified sample rate */ | ||
| 417 | if (spi->max_speed_hz > (125000 * 16)) { | ||
| 418 | dev_dbg(&spi->dev, "f(sample) %d KHz?\n", | ||
| 419 | (spi->max_speed_hz/16)/1000); | ||
| 420 | return -EINVAL; | ||
| 421 | } | ||
| 422 | |||
| 423 | /* We'd set the wordsize to 12 bits ... except that some controllers | ||
| 424 | * will then treat the 8 bit command words as 12 bits (and drop the | ||
| 425 | * four MSBs of the 12 bit result). Result: inputs must be shifted | ||
| 426 | * to discard the four garbage LSBs. | ||
| 427 | */ | ||
| 428 | |||
| 429 | if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) | ||
| 430 | return -ENOMEM; | ||
| 431 | |||
| 432 | dev_set_drvdata(&spi->dev, ts); | ||
| 433 | |||
| 434 | ts->spi = spi; | ||
| 435 | spi->dev.power.power_state = PMSG_ON; | ||
| 436 | |||
| 437 | init_timer(&ts->timer); | ||
| 438 | ts->timer.data = (unsigned long) ts; | ||
| 439 | ts->timer.function = ads7846_timer; | ||
| 440 | |||
| 441 | ts->model = pdata->model ? : 7846; | ||
| 442 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | ||
| 443 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | ||
| 444 | |||
| 445 | init_input_dev(&ts->input); | ||
| 446 | |||
| 447 | ts->input.dev = &spi->dev; | ||
| 448 | ts->input.name = "ADS784x Touchscreen"; | ||
| 449 | snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id); | ||
| 450 | ts->input.phys = ts->phys; | ||
| 451 | |||
| 452 | ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
| 453 | ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
| 454 | input_set_abs_params(&ts->input, ABS_X, | ||
| 455 | pdata->x_min ? : 0, | ||
| 456 | pdata->x_max ? : MAX_12BIT, | ||
| 457 | 0, 0); | ||
| 458 | input_set_abs_params(&ts->input, ABS_Y, | ||
| 459 | pdata->y_min ? : 0, | ||
| 460 | pdata->y_max ? : MAX_12BIT, | ||
| 461 | 0, 0); | ||
| 462 | input_set_abs_params(&ts->input, ABS_PRESSURE, | ||
| 463 | pdata->pressure_min, pdata->pressure_max, 0, 0); | ||
| 464 | |||
| 465 | input_register_device(&ts->input); | ||
| 466 | |||
| 467 | /* set up the transfers to read touchscreen state; this assumes we | ||
| 468 | * use formula #2 for pressure, not #3. | ||
| 469 | */ | ||
| 470 | x = ts->xfer; | ||
| 471 | |||
| 472 | /* y- still on; turn on only y+ (and ADC) */ | ||
| 473 | x->tx_buf = &read_y; | ||
| 474 | x->len = 1; | ||
| 475 | x++; | ||
| 476 | x->rx_buf = &ts->tc.y; | ||
| 477 | x->len = 2; | ||
| 478 | x++; | ||
| 479 | |||
| 480 | /* turn y+ off, x- on; we'll use formula #2 */ | ||
| 481 | if (ts->model == 7846) { | ||
| 482 | x->tx_buf = &read_z1; | ||
| 483 | x->len = 1; | ||
| 484 | x++; | ||
| 485 | x->rx_buf = &ts->tc.z1; | ||
| 486 | x->len = 2; | ||
| 487 | x++; | ||
| 488 | |||
| 489 | x->tx_buf = &read_z2; | ||
| 490 | x->len = 1; | ||
| 491 | x++; | ||
| 492 | x->rx_buf = &ts->tc.z2; | ||
| 493 | x->len = 2; | ||
| 494 | x++; | ||
| 495 | } | ||
| 496 | |||
| 497 | /* turn y- off, x+ on, then leave in lowpower */ | ||
| 498 | x->tx_buf = &read_x; | ||
| 499 | x->len = 1; | ||
| 500 | x++; | ||
| 501 | x->rx_buf = &ts->tc.x; | ||
| 502 | x->len = 2; | ||
| 503 | x++; | ||
| 504 | |||
| 505 | CS_CHANGE(x[-1]); | ||
| 506 | |||
| 507 | for (i = 0; i < x - ts->xfer; i++) | ||
| 508 | spi_message_add_tail(&ts->xfer[i], &ts->msg); | ||
| 509 | ts->msg.complete = ads7846_rx; | ||
| 510 | ts->msg.context = ts; | ||
| 511 | |||
| 512 | if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, | ||
| 513 | spi->dev.bus_id, ts)) { | ||
| 514 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | ||
| 515 | input_unregister_device(&ts->input); | ||
| 516 | kfree(ts); | ||
| 517 | return -EBUSY; | ||
| 518 | } | ||
| 519 | set_irq_type(spi->irq, IRQT_FALLING); | ||
| 520 | |||
| 521 | dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); | ||
| 522 | |||
| 523 | /* take a first sample, leaving nPENIRQ active; avoid | ||
| 524 | * the touchscreen, in case it's not connected. | ||
| 525 | */ | ||
| 526 | (void) ads7846_read12_ser(&spi->dev, | ||
| 527 | READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); | ||
| 528 | |||
| 529 | /* ads7843/7845 don't have temperature sensors, and | ||
| 530 | * use the other sensors a bit differently too | ||
| 531 | */ | ||
| 532 | if (ts->model == 7846) { | ||
| 533 | device_create_file(&spi->dev, &dev_attr_temp0); | ||
| 534 | device_create_file(&spi->dev, &dev_attr_temp1); | ||
| 535 | } | ||
| 536 | if (ts->model != 7845) | ||
| 537 | device_create_file(&spi->dev, &dev_attr_vbatt); | ||
| 538 | device_create_file(&spi->dev, &dev_attr_vaux); | ||
| 539 | |||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | |||
| 543 | static int __devexit ads7846_remove(struct spi_device *spi) | ||
| 544 | { | ||
| 545 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
| 546 | |||
| 547 | ads7846_suspend(spi, PMSG_SUSPEND); | ||
| 548 | free_irq(ts->spi->irq, ts); | ||
| 549 | if (ts->irq_disabled) | ||
| 550 | enable_irq(ts->spi->irq); | ||
| 551 | |||
| 552 | if (ts->model == 7846) { | ||
| 553 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
| 554 | device_remove_file(&spi->dev, &dev_attr_temp1); | ||
| 555 | } | ||
| 556 | if (ts->model != 7845) | ||
| 557 | device_remove_file(&spi->dev, &dev_attr_vbatt); | ||
| 558 | device_remove_file(&spi->dev, &dev_attr_vaux); | ||
| 559 | |||
| 560 | input_unregister_device(&ts->input); | ||
| 561 | kfree(ts); | ||
| 562 | |||
| 563 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | static struct spi_driver ads7846_driver = { | ||
| 568 | .driver = { | ||
| 569 | .name = "ads7846", | ||
| 570 | .bus = &spi_bus_type, | ||
| 571 | .owner = THIS_MODULE, | ||
| 572 | }, | ||
| 573 | .probe = ads7846_probe, | ||
| 574 | .remove = __devexit_p(ads7846_remove), | ||
| 575 | .suspend = ads7846_suspend, | ||
| 576 | .resume = ads7846_resume, | ||
| 577 | }; | ||
| 578 | |||
| 579 | static int __init ads7846_init(void) | ||
| 580 | { | ||
| 581 | /* grr, board-specific init should stay out of drivers!! */ | ||
| 582 | |||
| 583 | #ifdef CONFIG_ARCH_OMAP | ||
| 584 | if (machine_is_omap_osk()) { | ||
| 585 | /* GPIO4 = PENIRQ; GPIO6 = BUSY */ | ||
| 586 | omap_request_gpio(4); | ||
| 587 | omap_set_gpio_direction(4, 1); | ||
| 588 | omap_request_gpio(6); | ||
| 589 | omap_set_gpio_direction(6, 1); | ||
| 590 | } | ||
| 591 | // also TI 1510 Innovator, bitbanging through FPGA | ||
| 592 | // also Nokia 770 | ||
| 593 | // also Palm Tungsten T2 | ||
| 594 | #endif | ||
| 595 | |||
| 596 | // PXA: | ||
| 597 | // also Dell Axim X50 | ||
| 598 | // also HP iPaq H191x/H192x/H415x/H435x | ||
| 599 | // also Intel Lubbock (additional to UCB1400; as temperature sensor) | ||
| 600 | // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) | ||
| 601 | |||
| 602 | // Atmel at91sam9261-EK uses ads7843 | ||
| 603 | |||
| 604 | // also various AMD Au1x00 devel boards | ||
| 605 | |||
| 606 | return spi_register_driver(&ads7846_driver); | ||
| 607 | } | ||
| 608 | module_init(ads7846_init); | ||
| 609 | |||
| 610 | static void __exit ads7846_exit(void) | ||
| 611 | { | ||
| 612 | spi_unregister_driver(&ads7846_driver); | ||
| 613 | |||
| 614 | #ifdef CONFIG_ARCH_OMAP | ||
| 615 | if (machine_is_omap_osk()) { | ||
| 616 | omap_free_gpio(4); | ||
| 617 | omap_free_gpio(6); | ||
| 618 | } | ||
| 619 | #endif | ||
| 620 | |||
| 621 | } | ||
| 622 | module_exit(ads7846_exit); | ||
| 623 | |||
| 624 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); | ||
| 625 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 5d8ee7368f7b..4abe5ff10e72 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c | |||
| @@ -358,7 +358,7 @@ hdlc_fill_fifo(struct BCState *bcs) | |||
| 358 | } | 358 | } |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | static inline void | 361 | static void |
| 362 | HDLC_irq(struct BCState *bcs, u_int stat) { | 362 | HDLC_irq(struct BCState *bcs, u_int stat) { |
| 363 | int len; | 363 | int len; |
| 364 | struct sk_buff *skb; | 364 | struct sk_buff *skb; |
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index b62d6b30b72b..b0ff1cc97d7c 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c | |||
| @@ -476,7 +476,7 @@ Memhscx_fill_fifo(struct BCState *bcs) | |||
| 476 | } | 476 | } |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | static inline void | 479 | static void |
| 480 | Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) | 480 | Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) |
| 481 | { | 481 | { |
| 482 | u_char r; | 482 | u_char r; |
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c index 5fe9d42d03a3..7b1ad5e4ecda 100644 --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c | |||
| @@ -119,7 +119,7 @@ hscx_fill_fifo(struct BCState *bcs) | |||
| 119 | } | 119 | } |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static inline void | 122 | static void |
| 123 | hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) | 123 | hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) |
| 124 | { | 124 | { |
| 125 | u_char r; | 125 | u_char r; |
| @@ -221,7 +221,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) | |||
| 221 | } | 221 | } |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static inline void | 224 | static void |
| 225 | hscx_int_main(struct IsdnCardState *cs, u_char val) | 225 | hscx_int_main(struct IsdnCardState *cs, u_char val) |
| 226 | { | 226 | { |
| 227 | 227 | ||
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c index 08563400e4fd..1f201af15a0f 100644 --- a/drivers/isdn/hisax/jade_irq.c +++ b/drivers/isdn/hisax/jade_irq.c | |||
| @@ -110,7 +110,7 @@ jade_fill_fifo(struct BCState *bcs) | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | 112 | ||
| 113 | static inline void | 113 | static void |
| 114 | jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) | 114 | jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) |
| 115 | { | 115 | { |
| 116 | u_char r; | 116 | u_char r; |
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index cf6a6f2248ac..314fc0830d90 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
| 18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/ioport.h> | ||
| 20 | 21 | ||
| 21 | struct preg { | 22 | struct preg { |
| 22 | unsigned char r; | 23 | unsigned char r; |
| @@ -88,24 +89,26 @@ int macio_probe(void) | |||
| 88 | int macio_init(void) | 89 | int macio_init(void) |
| 89 | { | 90 | { |
| 90 | struct device_node *adbs; | 91 | struct device_node *adbs; |
| 92 | struct resource r; | ||
| 91 | 93 | ||
| 92 | adbs = find_compatible_devices("adb", "chrp,adb0"); | 94 | adbs = find_compatible_devices("adb", "chrp,adb0"); |
| 93 | if (adbs == 0) | 95 | if (adbs == 0) |
| 94 | return -ENXIO; | 96 | return -ENXIO; |
| 95 | 97 | ||
| 96 | #if 0 | 98 | #if 0 |
| 97 | { int i; | 99 | { int i = 0; |
| 98 | 100 | ||
| 99 | printk("macio_adb_init: node = %p, addrs =", adbs->node); | 101 | printk("macio_adb_init: node = %p, addrs =", adbs->node); |
| 100 | for (i = 0; i < adbs->n_addrs; ++i) | 102 | while(!of_address_to_resource(adbs, i, &r)) |
| 101 | printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); | 103 | printk(" %x(%x)", r.start, r.end - r.start); |
| 102 | printk(", intrs ="); | 104 | printk(", intrs ="); |
| 103 | for (i = 0; i < adbs->n_intrs; ++i) | 105 | for (i = 0; i < adbs->n_intrs; ++i) |
| 104 | printk(" %x", adbs->intrs[i].line); | 106 | printk(" %x", adbs->intrs[i].line); |
| 105 | printk("\n"); } | 107 | printk("\n"); } |
| 106 | #endif | 108 | #endif |
| 107 | 109 | if (of_address_to_resource(adbs, 0, &r)) | |
| 108 | adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); | 110 | return -ENXIO; |
| 111 | adb = ioremap(r.start, sizeof(struct adb_regs)); | ||
| 109 | 112 | ||
| 110 | out_8(&adb->ctrl.r, 0); | 113 | out_8(&adb->ctrl.r, 0); |
| 111 | out_8(&adb->intr.r, 0); | 114 | out_8(&adb->intr.r, 0); |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 2a545ceb523b..ed6d3174d660 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
| @@ -211,6 +211,9 @@ struct bus_type macio_bus_type = { | |||
| 211 | .name = "macio", | 211 | .name = "macio", |
| 212 | .match = macio_bus_match, | 212 | .match = macio_bus_match, |
| 213 | .uevent = macio_uevent, | 213 | .uevent = macio_uevent, |
| 214 | .probe = macio_device_probe, | ||
| 215 | .remove = macio_device_remove, | ||
| 216 | .shutdown = macio_device_shutdown, | ||
| 214 | .suspend = macio_device_suspend, | 217 | .suspend = macio_device_suspend, |
| 215 | .resume = macio_device_resume, | 218 | .resume = macio_device_resume, |
| 216 | .dev_attrs = macio_dev_attrs, | 219 | .dev_attrs = macio_dev_attrs, |
| @@ -528,9 +531,6 @@ int macio_register_driver(struct macio_driver *drv) | |||
| 528 | /* initialize common driver fields */ | 531 | /* initialize common driver fields */ |
| 529 | drv->driver.name = drv->name; | 532 | drv->driver.name = drv->name; |
| 530 | drv->driver.bus = &macio_bus_type; | 533 | drv->driver.bus = &macio_bus_type; |
| 531 | drv->driver.probe = macio_device_probe; | ||
| 532 | drv->driver.remove = macio_device_remove; | ||
| 533 | drv->driver.shutdown = macio_device_shutdown; | ||
| 534 | 534 | ||
| 535 | /* register with core */ | 535 | /* register with core */ |
| 536 | count = driver_register(&drv->driver); | 536 | count = driver_register(&drv->driver); |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 76a189ceb529..eae4473eadde 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -200,7 +200,7 @@ out: | |||
| 200 | /* if page is completely empty, put it back on the free list, or dealloc it */ | 200 | /* if page is completely empty, put it back on the free list, or dealloc it */ |
| 201 | /* if page was hijacked, unmark the flag so it might get alloced next time */ | 201 | /* if page was hijacked, unmark the flag so it might get alloced next time */ |
| 202 | /* Note: lock should be held when calling this */ | 202 | /* Note: lock should be held when calling this */ |
| 203 | static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) | 203 | static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) |
| 204 | { | 204 | { |
| 205 | char *ptr; | 205 | char *ptr; |
| 206 | 206 | ||
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a601a427885c..e7a650f9ca07 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { | |||
| 228 | }; | 228 | }; |
| 229 | 229 | ||
| 230 | 230 | ||
| 231 | static inline int | 231 | static int |
| 232 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, | 232 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, |
| 233 | struct scatterlist *in, unsigned int length, | 233 | struct scatterlist *in, unsigned int length, |
| 234 | int write, sector_t sector) | 234 | int write, sector_t sector) |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 561bda5011e0..1235135b384b 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
| @@ -598,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) | |||
| 598 | /* | 598 | /* |
| 599 | * Always use UUID for lookups if it's present, otherwise use name or dev. | 599 | * Always use UUID for lookups if it's present, otherwise use name or dev. |
| 600 | */ | 600 | */ |
| 601 | static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) | 601 | static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) |
| 602 | { | 602 | { |
| 603 | if (*param->uuid) | 603 | if (*param->uuid) |
| 604 | return __get_uuid_cell(param->uuid); | 604 | return __get_uuid_cell(param->uuid); |
| @@ -608,7 +608,7 @@ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) | |||
| 608 | return dm_get_mdptr(huge_decode_dev(param->dev)); | 608 | return dm_get_mdptr(huge_decode_dev(param->dev)); |
| 609 | } | 609 | } |
| 610 | 610 | ||
| 611 | static inline struct mapped_device *find_device(struct dm_ioctl *param) | 611 | static struct mapped_device *find_device(struct dm_ioctl *param) |
| 612 | { | 612 | { |
| 613 | struct hash_cell *hc; | 613 | struct hash_cell *hc; |
| 614 | struct mapped_device *md = NULL; | 614 | struct mapped_device *md = NULL; |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 4b9dd8fb1e5c..87727d84dbba 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -691,7 +691,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context) | |||
| 691 | /* | 691 | /* |
| 692 | * Dispatches the copy operation to kcopyd. | 692 | * Dispatches the copy operation to kcopyd. |
| 693 | */ | 693 | */ |
| 694 | static inline void start_copy(struct pending_exception *pe) | 694 | static void start_copy(struct pending_exception *pe) |
| 695 | { | 695 | { |
| 696 | struct dm_snapshot *s = pe->snap; | 696 | struct dm_snapshot *s = pe->snap; |
| 697 | struct io_region src, dest; | 697 | struct io_region src, dest; |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 097d1e540090..8c16359f8b01 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -293,7 +293,7 @@ struct dm_table *dm_get_table(struct mapped_device *md) | |||
| 293 | * Decrements the number of outstanding ios that a bio has been | 293 | * Decrements the number of outstanding ios that a bio has been |
| 294 | * cloned into, completing the original io if necc. | 294 | * cloned into, completing the original io if necc. |
| 295 | */ | 295 | */ |
| 296 | static inline void dec_pending(struct dm_io *io, int error) | 296 | static void dec_pending(struct dm_io *io, int error) |
| 297 | { | 297 | { |
| 298 | if (error) | 298 | if (error) |
| 299 | io->error = error; | 299 | io->error = error; |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a06ff91f27e2..d39f584cd8b3 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) | |||
| 176 | } | 176 | } |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static inline void free_r1bio(r1bio_t *r1_bio) | 179 | static void free_r1bio(r1bio_t *r1_bio) |
| 180 | { | 180 | { |
| 181 | conf_t *conf = mddev_to_conf(r1_bio->mddev); | 181 | conf_t *conf = mddev_to_conf(r1_bio->mddev); |
| 182 | 182 | ||
| @@ -190,7 +190,7 @@ static inline void free_r1bio(r1bio_t *r1_bio) | |||
| 190 | mempool_free(r1_bio, conf->r1bio_pool); | 190 | mempool_free(r1_bio, conf->r1bio_pool); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static inline void put_buf(r1bio_t *r1_bio) | 193 | static void put_buf(r1bio_t *r1_bio) |
| 194 | { | 194 | { |
| 195 | conf_t *conf = mddev_to_conf(r1_bio->mddev); | 195 | conf_t *conf = mddev_to_conf(r1_bio->mddev); |
| 196 | int i; | 196 | int i; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9e658e519a27..9130d051b474 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) | |||
| 176 | } | 176 | } |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static inline void free_r10bio(r10bio_t *r10_bio) | 179 | static void free_r10bio(r10bio_t *r10_bio) |
| 180 | { | 180 | { |
| 181 | conf_t *conf = mddev_to_conf(r10_bio->mddev); | 181 | conf_t *conf = mddev_to_conf(r10_bio->mddev); |
| 182 | 182 | ||
| @@ -190,7 +190,7 @@ static inline void free_r10bio(r10bio_t *r10_bio) | |||
| 190 | mempool_free(r10_bio, conf->r10bio_pool); | 190 | mempool_free(r10_bio, conf->r10bio_pool); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static inline void put_buf(r10bio_t *r10_bio) | 193 | static void put_buf(r10bio_t *r10_bio) |
| 194 | { | 194 | { |
| 195 | conf_t *conf = mddev_to_conf(r10_bio->mddev); | 195 | conf_t *conf = mddev_to_conf(r10_bio->mddev); |
| 196 | 196 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 54f4a9847e38..25976bfb6f9c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -69,7 +69,7 @@ | |||
| 69 | 69 | ||
| 70 | static void print_raid5_conf (raid5_conf_t *conf); | 70 | static void print_raid5_conf (raid5_conf_t *conf); |
| 71 | 71 | ||
| 72 | static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) | 72 | static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) |
| 73 | { | 73 | { |
| 74 | if (atomic_dec_and_test(&sh->count)) { | 74 | if (atomic_dec_and_test(&sh->count)) { |
| 75 | if (!list_empty(&sh->lru)) | 75 | if (!list_empty(&sh->lru)) |
| @@ -118,7 +118,7 @@ static inline void remove_hash(struct stripe_head *sh) | |||
| 118 | hlist_del_init(&sh->hash); | 118 | hlist_del_init(&sh->hash); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) | 121 | static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) |
| 122 | { | 122 | { |
| 123 | struct hlist_head *hp = stripe_hash(conf, sh->sector); | 123 | struct hlist_head *hp = stripe_hash(conf, sh->sector); |
| 124 | 124 | ||
| @@ -178,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num) | |||
| 178 | 178 | ||
| 179 | static void raid5_build_block (struct stripe_head *sh, int i); | 179 | static void raid5_build_block (struct stripe_head *sh, int i); |
| 180 | 180 | ||
| 181 | static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | 181 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) |
| 182 | { | 182 | { |
| 183 | raid5_conf_t *conf = sh->raid_conf; | 183 | raid5_conf_t *conf = sh->raid_conf; |
| 184 | int disks = conf->raid_disks, i; | 184 | int disks = conf->raid_disks, i; |
| @@ -1415,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh) | |||
| 1415 | } | 1415 | } |
| 1416 | } | 1416 | } |
| 1417 | 1417 | ||
| 1418 | static inline void raid5_activate_delayed(raid5_conf_t *conf) | 1418 | static void raid5_activate_delayed(raid5_conf_t *conf) |
| 1419 | { | 1419 | { |
| 1420 | if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { | 1420 | if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { |
| 1421 | while (!list_empty(&conf->delayed_list)) { | 1421 | while (!list_empty(&conf->delayed_list)) { |
| @@ -1431,7 +1431,7 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf) | |||
| 1431 | } | 1431 | } |
| 1432 | } | 1432 | } |
| 1433 | 1433 | ||
| 1434 | static inline void activate_bit_delay(raid5_conf_t *conf) | 1434 | static void activate_bit_delay(raid5_conf_t *conf) |
| 1435 | { | 1435 | { |
| 1436 | /* device_lock is held */ | 1436 | /* device_lock is held */ |
| 1437 | struct list_head head; | 1437 | struct list_head head; |
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 8c823d686a60..f618a53b98be 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
| @@ -88,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks) | |||
| 88 | 88 | ||
| 89 | static void print_raid6_conf (raid6_conf_t *conf); | 89 | static void print_raid6_conf (raid6_conf_t *conf); |
| 90 | 90 | ||
| 91 | static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) | 91 | static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) |
| 92 | { | 92 | { |
| 93 | if (atomic_dec_and_test(&sh->count)) { | 93 | if (atomic_dec_and_test(&sh->count)) { |
| 94 | if (!list_empty(&sh->lru)) | 94 | if (!list_empty(&sh->lru)) |
| @@ -197,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num) | |||
| 197 | 197 | ||
| 198 | static void raid6_build_block (struct stripe_head *sh, int i); | 198 | static void raid6_build_block (struct stripe_head *sh, int i); |
| 199 | 199 | ||
| 200 | static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | 200 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) |
| 201 | { | 201 | { |
| 202 | raid6_conf_t *conf = sh->raid_conf; | 202 | raid6_conf_t *conf = sh->raid_conf; |
| 203 | int disks = conf->raid_disks, i; | 203 | int disks = conf->raid_disks, i; |
| @@ -1577,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) | |||
| 1577 | } | 1577 | } |
| 1578 | } | 1578 | } |
| 1579 | 1579 | ||
| 1580 | static inline void raid6_activate_delayed(raid6_conf_t *conf) | 1580 | static void raid6_activate_delayed(raid6_conf_t *conf) |
| 1581 | { | 1581 | { |
| 1582 | if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { | 1582 | if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { |
| 1583 | while (!list_empty(&conf->delayed_list)) { | 1583 | while (!list_empty(&conf->delayed_list)) { |
| @@ -1593,7 +1593,7 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf) | |||
| 1593 | } | 1593 | } |
| 1594 | } | 1594 | } |
| 1595 | 1595 | ||
| 1596 | static inline void activate_bit_delay(raid6_conf_t *conf) | 1596 | static void activate_bit_delay(raid6_conf_t *conf) |
| 1597 | { | 1597 | { |
| 1598 | /* device_lock is held */ | 1598 | /* device_lock is held */ |
| 1599 | struct list_head head; | 1599 | struct list_head head; |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index f65f64b00ff3..44fcbe77c8f9 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
| @@ -779,9 +779,8 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) | |||
| 779 | return 0; | 779 | return 0; |
| 780 | } | 780 | } |
| 781 | 781 | ||
| 782 | static int dvb_bt8xx_probe(struct device *dev) | 782 | static int dvb_bt8xx_probe(struct bttv_sub_device *sub) |
| 783 | { | 783 | { |
| 784 | struct bttv_sub_device *sub = to_bttv_sub_dev(dev); | ||
| 785 | struct dvb_bt8xx_card *card; | 784 | struct dvb_bt8xx_card *card; |
| 786 | struct pci_dev* bttv_pci_dev; | 785 | struct pci_dev* bttv_pci_dev; |
| 787 | int ret; | 786 | int ret; |
| @@ -890,13 +889,13 @@ static int dvb_bt8xx_probe(struct device *dev) | |||
| 890 | return ret; | 889 | return ret; |
| 891 | } | 890 | } |
| 892 | 891 | ||
| 893 | dev_set_drvdata(dev, card); | 892 | dev_set_drvdata(&sub->dev, card); |
| 894 | return 0; | 893 | return 0; |
| 895 | } | 894 | } |
| 896 | 895 | ||
| 897 | static int dvb_bt8xx_remove(struct device *dev) | 896 | static int dvb_bt8xx_remove(struct bttv_sub_device *sub) |
| 898 | { | 897 | { |
| 899 | struct dvb_bt8xx_card *card = dev_get_drvdata(dev); | 898 | struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev); |
| 900 | 899 | ||
| 901 | dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); | 900 | dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); |
| 902 | 901 | ||
| @@ -919,14 +918,14 @@ static int dvb_bt8xx_remove(struct device *dev) | |||
| 919 | static struct bttv_sub_driver driver = { | 918 | static struct bttv_sub_driver driver = { |
| 920 | .drv = { | 919 | .drv = { |
| 921 | .name = "dvb-bt8xx", | 920 | .name = "dvb-bt8xx", |
| 922 | .probe = dvb_bt8xx_probe, | ||
| 923 | .remove = dvb_bt8xx_remove, | ||
| 924 | /* FIXME: | ||
| 925 | * .shutdown = dvb_bt8xx_shutdown, | ||
| 926 | * .suspend = dvb_bt8xx_suspend, | ||
| 927 | * .resume = dvb_bt8xx_resume, | ||
| 928 | */ | ||
| 929 | }, | 921 | }, |
| 922 | .probe = dvb_bt8xx_probe, | ||
| 923 | .remove = dvb_bt8xx_remove, | ||
| 924 | /* FIXME: | ||
| 925 | * .shutdown = dvb_bt8xx_shutdown, | ||
| 926 | * .suspend = dvb_bt8xx_suspend, | ||
| 927 | * .resume = dvb_bt8xx_resume, | ||
| 928 | */ | ||
| 930 | }; | 929 | }; |
| 931 | 930 | ||
| 932 | static int __init dvb_bt8xx_init(void) | 931 | static int __init dvb_bt8xx_init(void) |
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index d64accc17b0e..c4d5e2b70c28 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c | |||
| @@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) | |||
| 47 | return 0; | 47 | return 0; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static int bttv_sub_probe(struct device *dev) | ||
| 51 | { | ||
| 52 | struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); | ||
| 53 | struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); | ||
| 54 | |||
| 55 | return sub->probe ? sub->probe(sdev) : -ENODEV; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int bttv_sub_remove(struct device *dev) | ||
| 59 | { | ||
| 60 | struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); | ||
| 61 | struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); | ||
| 62 | |||
| 63 | if (sub->remove) | ||
| 64 | sub->remove(sdev); | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 50 | struct bus_type bttv_sub_bus_type = { | 68 | struct bus_type bttv_sub_bus_type = { |
| 51 | .name = "bttv-sub", | 69 | .name = "bttv-sub", |
| 52 | .match = &bttv_sub_bus_match, | 70 | .match = &bttv_sub_bus_match, |
| 71 | .probe = bttv_sub_probe, | ||
| 72 | .remove = bttv_sub_remove, | ||
| 53 | }; | 73 | }; |
| 54 | EXPORT_SYMBOL(bttv_sub_bus_type); | 74 | EXPORT_SYMBOL(bttv_sub_bus_type); |
| 55 | 75 | ||
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index e370d74f2a1b..9908c8e0c951 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
| @@ -365,6 +365,8 @@ struct bttv_sub_device { | |||
| 365 | struct bttv_sub_driver { | 365 | struct bttv_sub_driver { |
| 366 | struct device_driver drv; | 366 | struct device_driver drv; |
| 367 | char wanted[BUS_ID_SIZE]; | 367 | char wanted[BUS_ID_SIZE]; |
| 368 | int (*probe)(struct bttv_sub_device *sub); | ||
| 369 | void (*remove)(struct bttv_sub_device *sub); | ||
| 368 | void (*gpio_irq)(struct bttv_sub_device *sub); | 370 | void (*gpio_irq)(struct bttv_sub_device *sub); |
| 369 | }; | 371 | }; |
| 370 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) | 372 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) |
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index e86b522938fd..9094fa9f2ecb 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
| @@ -93,7 +93,7 @@ struct tvp5150 { | |||
| 93 | int sat; | 93 | int sat; |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | static inline int tvp5150_read(struct i2c_client *c, unsigned char addr) | 96 | static int tvp5150_read(struct i2c_client *c, unsigned char addr) |
| 97 | { | 97 | { |
| 98 | unsigned char buffer[1]; | 98 | unsigned char buffer[1]; |
| 99 | int rc; | 99 | int rc; |
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 1883d22cffeb..e67cf15e9c39 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig | |||
| @@ -23,6 +23,7 @@ config FUSION_FC | |||
| 23 | tristate "Fusion MPT ScsiHost drivers for FC" | 23 | tristate "Fusion MPT ScsiHost drivers for FC" |
| 24 | depends on PCI && SCSI | 24 | depends on PCI && SCSI |
| 25 | select FUSION | 25 | select FUSION |
| 26 | select SCSI_FC_ATTRS | ||
| 26 | ---help--- | 27 | ---help--- |
| 27 | SCSI HOST support for a Fiber Channel host adapters. | 28 | SCSI HOST support for a Fiber Channel host adapters. |
| 28 | 29 | ||
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index b61e3d175070..02cdc840a06b 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI Message independent structures and definitions | 6 | * Title: MPI Message independent structures and definitions |
| 7 | * Creation Date: July 27, 2000 | 7 | * Creation Date: July 27, 2000 |
| 8 | * | 8 | * |
| 9 | * mpi.h Version: 01.05.08 | 9 | * mpi.h Version: 01.05.10 |
| 10 | * | 10 | * |
| 11 | * Version History | 11 | * Version History |
| 12 | * --------------- | 12 | * --------------- |
| @@ -74,6 +74,8 @@ | |||
| 74 | * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and | 74 | * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and |
| 75 | * TargetAssistExtended requests. | 75 | * TargetAssistExtended requests. |
| 76 | * Added EEDP IOCStatus codes. | 76 | * Added EEDP IOCStatus codes. |
| 77 | * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. | ||
| 78 | * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. | ||
| 77 | * -------------------------------------------------------------------------- | 79 | * -------------------------------------------------------------------------- |
| 78 | */ | 80 | */ |
| 79 | 81 | ||
| @@ -104,7 +106,7 @@ | |||
| 104 | /* Note: The major versions of 0xe0 through 0xff are reserved */ | 106 | /* Note: The major versions of 0xe0 through 0xff are reserved */ |
| 105 | 107 | ||
| 106 | /* versioning for this MPI header set */ | 108 | /* versioning for this MPI header set */ |
| 107 | #define MPI_HEADER_VERSION_UNIT (0x0A) | 109 | #define MPI_HEADER_VERSION_UNIT (0x0C) |
| 108 | #define MPI_HEADER_VERSION_DEV (0x00) | 110 | #define MPI_HEADER_VERSION_DEV (0x00) |
| 109 | #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) | 111 | #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) |
| 110 | #define MPI_HEADER_VERSION_UNIT_SHIFT (8) | 112 | #define MPI_HEADER_VERSION_UNIT_SHIFT (8) |
| @@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY | |||
| 711 | #define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) | 713 | #define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) |
| 712 | #define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) | 714 | #define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) |
| 713 | #define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) | 715 | #define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) |
| 716 | #define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) | ||
| 717 | #define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) | ||
| 714 | 718 | ||
| 715 | /****************************************************************************/ | 719 | /****************************************************************************/ |
| 716 | /* Additional FCP target values (obsolete) */ | 720 | /* Additional FCP target values (obsolete) */ |
| @@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY | |||
| 745 | #define MPI_IOCSTATUS_LAN_CANCELED (0x0087) | 749 | #define MPI_IOCSTATUS_LAN_CANCELED (0x0087) |
| 746 | 750 | ||
| 747 | /****************************************************************************/ | 751 | /****************************************************************************/ |
| 748 | /* Serial Attached SCSI values */ | 752 | /* Serial Attached SCSI values */ |
| 749 | /****************************************************************************/ | 753 | /****************************************************************************/ |
| 750 | 754 | ||
| 751 | #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) | 755 | #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) |
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index d8339896f734..b1becec27e1b 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI Config message, structures, and Pages | 6 | * Title: MPI Config message, structures, and Pages |
| 7 | * Creation Date: July 27, 2000 | 7 | * Creation Date: July 27, 2000 |
| 8 | * | 8 | * |
| 9 | * mpi_cnfg.h Version: 01.05.09 | 9 | * mpi_cnfg.h Version: 01.05.11 |
| 10 | * | 10 | * |
| 11 | * Version History | 11 | * Version History |
| 12 | * --------------- | 12 | * --------------- |
| @@ -249,6 +249,23 @@ | |||
| 249 | * Added OwnerDevHandle and Flags field to SAS PHY Page 0. | 249 | * Added OwnerDevHandle and Flags field to SAS PHY Page 0. |
| 250 | * Added IOC GPIO Flags define to SAS Enclosure Page 0. | 250 | * Added IOC GPIO Flags define to SAS Enclosure Page 0. |
| 251 | * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. | 251 | * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. |
| 252 | * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from | ||
| 253 | * Manufacturing Page 4. | ||
| 254 | * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit. | ||
| 255 | * Added NumDevsPerEnclosure field to SAS IO Unit page 2. | ||
| 256 | * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP | ||
| 257 | * define. | ||
| 258 | * Added EnclosureHandle field to SAS Expander page 0. | ||
| 259 | * Removed redundant NumTableEntriesProg field from SAS | ||
| 260 | * Expander Page 1. | ||
| 261 | * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for | ||
| 262 | * SAS1078. | ||
| 263 | * Added more defines for Manufacturing Page 4 Flags field. | ||
| 264 | * Added more defines for IOCSettings and added | ||
| 265 | * ExpanderSpinup field to Bios Page 1. | ||
| 266 | * Added postpone SATA Init bit to SAS IO Unit Page 1 | ||
| 267 | * ControlFlags. | ||
| 268 | * Changed LogEntry format for Log Page 0. | ||
| 252 | * -------------------------------------------------------------------------- | 269 | * -------------------------------------------------------------------------- |
| 253 | */ | 270 | */ |
| 254 | 271 | ||
| @@ -494,7 +511,7 @@ typedef struct _MSG_CONFIG_REPLY | |||
| 494 | #define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) | 511 | #define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) |
| 495 | #define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) | 512 | #define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) |
| 496 | #define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) | 513 | #define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) |
| 497 | #define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646) | 514 | #define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646) |
| 498 | /* SCSI */ | 515 | /* SCSI */ |
| 499 | #define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) | 516 | #define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) |
| 500 | #define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) | 517 | #define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) |
| @@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY | |||
| 510 | #define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A) | 527 | #define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A) |
| 511 | #define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054) | 528 | #define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054) |
| 512 | #define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058) | 529 | #define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058) |
| 513 | #define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060) | 530 | #define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062) |
| 514 | 531 | ||
| 515 | 532 | ||
| 516 | typedef struct _CONFIG_PAGE_MANUFACTURING_0 | 533 | typedef struct _CONFIG_PAGE_MANUFACTURING_0 |
| @@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 | |||
| 602 | U32 IMVolumeSettings; /* 50h */ | 619 | U32 IMVolumeSettings; /* 50h */ |
| 603 | U32 Reserved3; /* 54h */ | 620 | U32 Reserved3; /* 54h */ |
| 604 | U32 Reserved4; /* 58h */ | 621 | U32 Reserved4; /* 58h */ |
| 605 | U8 ISDataScrubRate; /* 5Ch */ | 622 | U32 Reserved5; /* 5Ch */ |
| 606 | U8 ISResyncRate; /* 5Dh */ | ||
| 607 | U16 Reserved5; /* 5Eh */ | ||
| 608 | U8 IMEDataScrubRate; /* 60h */ | 623 | U8 IMEDataScrubRate; /* 60h */ |
| 609 | U8 IMEResyncRate; /* 61h */ | 624 | U8 IMEResyncRate; /* 61h */ |
| 610 | U16 Reserved6; /* 62h */ | 625 | U16 Reserved6; /* 62h */ |
| @@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 | |||
| 616 | } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, | 631 | } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, |
| 617 | ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; | 632 | ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; |
| 618 | 633 | ||
| 619 | #define MPI_MANUFACTURING4_PAGEVERSION (0x02) | 634 | #define MPI_MANUFACTURING4_PAGEVERSION (0x03) |
| 620 | 635 | ||
| 621 | /* defines for the Flags field */ | 636 | /* defines for the Flags field */ |
| 637 | #define MPI_MANPAGE4_IME_DISABLE (0x20) | ||
| 638 | #define MPI_MANPAGE4_IM_DISABLE (0x10) | ||
| 639 | #define MPI_MANPAGE4_IS_DISABLE (0x08) | ||
| 640 | #define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04) | ||
| 641 | #define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02) | ||
| 622 | #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) | 642 | #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) |
| 623 | 643 | ||
| 624 | 644 | ||
| @@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1 | |||
| 669 | } CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, | 689 | } CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, |
| 670 | IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; | 690 | IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; |
| 671 | 691 | ||
| 672 | #define MPI_IOUNITPAGE1_PAGEVERSION (0x01) | 692 | #define MPI_IOUNITPAGE1_PAGEVERSION (0x02) |
| 673 | 693 | ||
| 674 | /* IO Unit Page 1 Flags defines */ | 694 | /* IO Unit Page 1 Flags defines */ |
| 675 | #define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) | 695 | #define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) |
| @@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1 | |||
| 681 | #define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) | 701 | #define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) |
| 682 | #define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) | 702 | #define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) |
| 683 | #define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) | 703 | #define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) |
| 684 | 704 | #define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200) | |
| 685 | 705 | ||
| 686 | typedef struct _MPI_ADAPTER_INFO | 706 | typedef struct _MPI_ADAPTER_INFO |
| 687 | { | 707 | { |
| @@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1 | |||
| 968 | U32 Reserved1; /* 0Ch */ | 988 | U32 Reserved1; /* 0Ch */ |
| 969 | U32 DeviceSettings; /* 10h */ | 989 | U32 DeviceSettings; /* 10h */ |
| 970 | U16 NumberOfDevices; /* 14h */ | 990 | U16 NumberOfDevices; /* 14h */ |
| 971 | U16 Reserved2; /* 16h */ | 991 | U8 ExpanderSpinup; /* 16h */ |
| 992 | U8 Reserved2; /* 17h */ | ||
| 972 | U16 IOTimeoutBlockDevicesNonRM; /* 18h */ | 993 | U16 IOTimeoutBlockDevicesNonRM; /* 18h */ |
| 973 | U16 IOTimeoutSequential; /* 1Ah */ | 994 | U16 IOTimeoutSequential; /* 1Ah */ |
| 974 | U16 IOTimeoutOther; /* 1Ch */ | 995 | U16 IOTimeoutOther; /* 1Ch */ |
| @@ -976,7 +997,7 @@ typedef struct _CONFIG_PAGE_BIOS_1 | |||
| 976 | } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, | 997 | } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, |
| 977 | BIOSPage1_t, MPI_POINTER pBIOSPage1_t; | 998 | BIOSPage1_t, MPI_POINTER pBIOSPage1_t; |
| 978 | 999 | ||
| 979 | #define MPI_BIOSPAGE1_PAGEVERSION (0x02) | 1000 | #define MPI_BIOSPAGE1_PAGEVERSION (0x03) |
| 980 | 1001 | ||
| 981 | /* values for the BiosOptions field */ | 1002 | /* values for the BiosOptions field */ |
| 982 | #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) | 1003 | #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) |
| @@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1 | |||
| 985 | #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) | 1006 | #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) |
| 986 | 1007 | ||
| 987 | /* values for the IOCSettings field */ | 1008 | /* values for the IOCSettings field */ |
| 1009 | #define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000) | ||
| 1010 | #define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24) | ||
| 1011 | |||
| 988 | #define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000) | 1012 | #define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000) |
| 989 | #define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20) | 1013 | #define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20) |
| 1014 | |||
| 1015 | #define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000) | ||
| 1016 | #define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000) | ||
| 1017 | |||
| 990 | #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) | 1018 | #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) |
| 991 | #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) | 1019 | #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) |
| 992 | #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) | 1020 | #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) |
| @@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1 | |||
| 1016 | #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) | 1044 | #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) |
| 1017 | #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) | 1045 | #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) |
| 1018 | 1046 | ||
| 1047 | /* defines for the ExpanderSpinup field */ | ||
| 1048 | #define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0) | ||
| 1049 | #define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4) | ||
| 1050 | #define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F) | ||
| 1051 | |||
| 1019 | typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER | 1052 | typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER |
| 1020 | { | 1053 | { |
| 1021 | U32 Reserved1; /* 00h */ | 1054 | U32 Reserved1; /* 00h */ |
| @@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0 | |||
| 1233 | 1266 | ||
| 1234 | #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8) | 1267 | #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8) |
| 1235 | #define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \ | 1268 | #define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \ |
| 1236 | ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \ | 1269 | ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \ |
| 1237 | >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \ | 1270 | >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \ |
| 1238 | ) | 1271 | ) |
| 1239 | #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) | 1272 | #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) |
| 1240 | #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16) | 1273 | #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16) |
| 1241 | #define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \ | 1274 | #define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \ |
| 1242 | ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \ | 1275 | ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \ |
| 1243 | >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ | 1276 | >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ |
| 1244 | ) | 1277 | ) |
| 1245 | #define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000) | 1278 | #define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000) |
| @@ -2370,47 +2403,48 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 | |||
| 2370 | } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, | 2403 | } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, |
| 2371 | SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; | 2404 | SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; |
| 2372 | 2405 | ||
| 2373 | #define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04) | 2406 | #define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05) |
| 2374 | 2407 | ||
| 2375 | /* values for SAS IO Unit Page 1 ControlFlags */ | 2408 | /* values for SAS IO Unit Page 1 ControlFlags */ |
| 2376 | #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) | 2409 | #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) |
| 2377 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) | 2410 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) |
| 2378 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) | 2411 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) |
| 2379 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) | 2412 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) |
| 2380 | #define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) | 2413 | #define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) |
| 2381 | 2414 | ||
| 2382 | #define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) | 2415 | #define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) |
| 2383 | #define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) | 2416 | #define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) |
| 2384 | #define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) | 2417 | #define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) |
| 2385 | #define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) | 2418 | #define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) |
| 2386 | #define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) | 2419 | #define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) |
| 2387 | 2420 | ||
| 2388 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) | 2421 | #define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (0x0100) |
| 2389 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) | 2422 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) |
| 2390 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) | 2423 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) |
| 2391 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) | 2424 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) |
| 2392 | #define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) | 2425 | #define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) |
| 2393 | #define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) | 2426 | #define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) |
| 2394 | #define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) | 2427 | #define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) |
| 2395 | #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) | 2428 | #define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) |
| 2429 | #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) | ||
| 2396 | 2430 | ||
| 2397 | /* values for SAS IO Unit Page 1 PortFlags */ | 2431 | /* values for SAS IO Unit Page 1 PortFlags */ |
| 2398 | #define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) | 2432 | #define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) |
| 2399 | #define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) | 2433 | #define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) |
| 2400 | #define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) | 2434 | #define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) |
| 2401 | 2435 | ||
| 2402 | /* values for SAS IO Unit Page 0 PhyFlags */ | 2436 | /* values for SAS IO Unit Page 0 PhyFlags */ |
| 2403 | #define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) | 2437 | #define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) |
| 2404 | #define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) | 2438 | #define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) |
| 2405 | #define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) | 2439 | #define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) |
| 2406 | 2440 | ||
| 2407 | /* values for SAS IO Unit Page 0 MaxMinLinkRate */ | 2441 | /* values for SAS IO Unit Page 0 MaxMinLinkRate */ |
| 2408 | #define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) | 2442 | #define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) |
| 2409 | #define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) | 2443 | #define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) |
| 2410 | #define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) | 2444 | #define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) |
| 2411 | #define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) | 2445 | #define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) |
| 2412 | #define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) | 2446 | #define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) |
| 2413 | #define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) | 2447 | #define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) |
| 2414 | 2448 | ||
| 2415 | /* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ | 2449 | /* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ |
| 2416 | 2450 | ||
| @@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 | |||
| 2418 | typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 | 2452 | typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 |
| 2419 | { | 2453 | { |
| 2420 | CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ | 2454 | CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ |
| 2421 | U32 Reserved1; /* 08h */ | 2455 | U8 NumDevsPerEnclosure; /* 08h */ |
| 2456 | U8 Reserved1; /* 09h */ | ||
| 2457 | U16 Reserved2; /* 0Ah */ | ||
| 2422 | U16 MaxPersistentIDs; /* 0Ch */ | 2458 | U16 MaxPersistentIDs; /* 0Ch */ |
| 2423 | U16 NumPersistentIDsUsed; /* 0Eh */ | 2459 | U16 NumPersistentIDsUsed; /* 0Eh */ |
| 2424 | U8 Status; /* 10h */ | 2460 | U8 Status; /* 10h */ |
| 2425 | U8 Flags; /* 11h */ | 2461 | U8 Flags; /* 11h */ |
| 2426 | U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */ | 2462 | U16 MaxNumPhysicalMappedIDs;/* 12h */ |
| 2427 | } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, | 2463 | } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, |
| 2428 | SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; | 2464 | SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; |
| 2429 | 2465 | ||
| 2430 | #define MPI_SASIOUNITPAGE2_PAGEVERSION (0x04) | 2466 | #define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05) |
| 2431 | 2467 | ||
| 2432 | /* values for SAS IO Unit Page 2 Status field */ | 2468 | /* values for SAS IO Unit Page 2 Status field */ |
| 2433 | #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) | 2469 | #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) |
| @@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 | |||
| 2441 | #define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00) | 2477 | #define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00) |
| 2442 | #define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01) | 2478 | #define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01) |
| 2443 | #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) | 2479 | #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) |
| 2480 | #define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07) | ||
| 2444 | 2481 | ||
| 2445 | #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) | 2482 | #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) |
| 2446 | #define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20) | 2483 | #define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20) |
| @@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 | |||
| 2473 | CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ | 2510 | CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ |
| 2474 | U8 PhysicalPort; /* 08h */ | 2511 | U8 PhysicalPort; /* 08h */ |
| 2475 | U8 Reserved1; /* 09h */ | 2512 | U8 Reserved1; /* 09h */ |
| 2476 | U16 Reserved2; /* 0Ah */ | 2513 | U16 EnclosureHandle; /* 0Ah */ |
| 2477 | U64 SASAddress; /* 0Ch */ | 2514 | U64 SASAddress; /* 0Ch */ |
| 2478 | U32 DiscoveryStatus; /* 14h */ | 2515 | U32 DiscoveryStatus; /* 14h */ |
| 2479 | U16 DevHandle; /* 18h */ | 2516 | U16 DevHandle; /* 18h */ |
| @@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 | |||
| 2487 | } CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, | 2524 | } CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, |
| 2488 | SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; | 2525 | SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; |
| 2489 | 2526 | ||
| 2490 | #define MPI_SASEXPANDER0_PAGEVERSION (0x02) | 2527 | #define MPI_SASEXPANDER0_PAGEVERSION (0x03) |
| 2491 | 2528 | ||
| 2492 | /* values for SAS Expander Page 0 DiscoveryStatus field */ | 2529 | /* values for SAS Expander Page 0 DiscoveryStatus field */ |
| 2493 | #define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) | 2530 | #define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) |
| @@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1 | |||
| 2527 | U8 NegotiatedLinkRate; /* 1Fh */ | 2564 | U8 NegotiatedLinkRate; /* 1Fh */ |
| 2528 | U8 PhyIdentifier; /* 20h */ | 2565 | U8 PhyIdentifier; /* 20h */ |
| 2529 | U8 AttachedPhyIdentifier; /* 21h */ | 2566 | U8 AttachedPhyIdentifier; /* 21h */ |
| 2530 | U8 NumTableEntriesProg; /* 22h */ | 2567 | U8 Reserved3; /* 22h */ |
| 2531 | U8 DiscoveryInfo; /* 23h */ | 2568 | U8 DiscoveryInfo; /* 23h */ |
| 2532 | U32 Reserved3; /* 24h */ | 2569 | U32 Reserved4; /* 24h */ |
| 2533 | } CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1, | 2570 | } CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1, |
| 2534 | SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t; | 2571 | SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t; |
| 2535 | 2572 | ||
| @@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0 | |||
| 2766 | #define MPI_LOG_0_NUM_LOG_ENTRIES (1) | 2803 | #define MPI_LOG_0_NUM_LOG_ENTRIES (1) |
| 2767 | #endif | 2804 | #endif |
| 2768 | 2805 | ||
| 2769 | #define MPI_LOG_0_LOG_DATA_LENGTH (20) | 2806 | #define MPI_LOG_0_LOG_DATA_LENGTH (0x1C) |
| 2770 | 2807 | ||
| 2771 | typedef struct _MPI_LOG_0_ENTRY | 2808 | typedef struct _MPI_LOG_0_ENTRY |
| 2772 | { | 2809 | { |
| 2773 | U64 WWID; /* 00h */ | 2810 | U32 TimeStamp; /* 00h */ |
| 2774 | U32 TimeStamp; /* 08h */ | 2811 | U32 Reserved1; /* 04h */ |
| 2775 | U32 Reserved1; /* 0Ch */ | 2812 | U16 LogSequence; /* 08h */ |
| 2776 | U16 LogSequence; /* 10h */ | 2813 | U16 LogEntryQualifier; /* 0Ah */ |
| 2777 | U16 LogEntryQualifier; /* 12h */ | 2814 | U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */ |
| 2778 | U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */ | ||
| 2779 | } MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY, | 2815 | } MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY, |
| 2780 | MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t; | 2816 | MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t; |
| 2781 | 2817 | ||
| @@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0 | |||
| 2794 | } CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0, | 2830 | } CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0, |
| 2795 | LogPage0_t, MPI_POINTER pLogPage0_t; | 2831 | LogPage0_t, MPI_POINTER pLogPage0_t; |
| 2796 | 2832 | ||
| 2797 | #define MPI_LOG_0_PAGEVERSION (0x00) | 2833 | #define MPI_LOG_0_PAGEVERSION (0x01) |
| 2798 | 2834 | ||
| 2799 | 2835 | ||
| 2800 | #endif | 2836 | #endif |
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index 1a30ef16adb4..4a5f8dd1d766 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt | |||
| @@ -6,25 +6,25 @@ | |||
| 6 | Copyright (c) 2000-2005 LSI Logic Corporation. | 6 | Copyright (c) 2000-2005 LSI Logic Corporation. |
| 7 | 7 | ||
| 8 | --------------------------------------- | 8 | --------------------------------------- |
| 9 | Header Set Release Version: 01.05.10 | 9 | Header Set Release Version: 01.05.12 |
| 10 | Header Set Release Date: 03-11-05 | 10 | Header Set Release Date: 08-30-05 |
| 11 | --------------------------------------- | 11 | --------------------------------------- |
| 12 | 12 | ||
| 13 | Filename Current version Prior version | 13 | Filename Current version Prior version |
| 14 | ---------- --------------- ------------- | 14 | ---------- --------------- ------------- |
| 15 | mpi.h 01.05.08 01.05.07 | 15 | mpi.h 01.05.10 01.05.09 |
| 16 | mpi_ioc.h 01.05.09 01.05.08 | 16 | mpi_ioc.h 01.05.10 01.05.09 |
| 17 | mpi_cnfg.h 01.05.09 01.05.08 | 17 | mpi_cnfg.h 01.05.11 01.05.10 |
| 18 | mpi_init.h 01.05.05 01.05.04 | 18 | mpi_init.h 01.05.06 01.05.06 |
| 19 | mpi_targ.h 01.05.05 01.05.04 | 19 | mpi_targ.h 01.05.05 01.05.05 |
| 20 | mpi_fc.h 01.05.01 01.05.01 | 20 | mpi_fc.h 01.05.01 01.05.01 |
| 21 | mpi_lan.h 01.05.01 01.05.01 | 21 | mpi_lan.h 01.05.01 01.05.01 |
| 22 | mpi_raid.h 01.05.02 01.05.02 | 22 | mpi_raid.h 01.05.02 01.05.02 |
| 23 | mpi_tool.h 01.05.03 01.05.03 | 23 | mpi_tool.h 01.05.03 01.05.03 |
| 24 | mpi_inb.h 01.05.01 01.05.01 | 24 | mpi_inb.h 01.05.01 01.05.01 |
| 25 | mpi_sas.h 01.05.01 01.05.01 | 25 | mpi_sas.h 01.05.02 01.05.01 |
| 26 | mpi_type.h 01.05.01 01.05.01 | 26 | mpi_type.h 01.05.02 01.05.01 |
| 27 | mpi_history.txt 01.05.09 01.05.09 | 27 | mpi_history.txt 01.05.12 01.05.11 |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | * Date Version Description | 30 | * Date Version Description |
| @@ -91,6 +91,8 @@ mpi.h | |||
| 91 | * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and | 91 | * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and |
| 92 | * TargetAssistExtended requests. | 92 | * TargetAssistExtended requests. |
| 93 | * Added EEDP IOCStatus codes. | 93 | * Added EEDP IOCStatus codes. |
| 94 | * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. | ||
| 95 | * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. | ||
| 94 | * -------------------------------------------------------------------------- | 96 | * -------------------------------------------------------------------------- |
| 95 | 97 | ||
| 96 | mpi_ioc.h | 98 | mpi_ioc.h |
| @@ -164,6 +166,10 @@ mpi_ioc.h | |||
| 164 | * Removed IOCFacts Reply EEDP Capability bit. | 166 | * Removed IOCFacts Reply EEDP Capability bit. |
| 165 | * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. | 167 | * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. |
| 166 | * Added Max SATA Targets to SAS Discovery Error event. | 168 | * Added Max SATA Targets to SAS Discovery Error event. |
| 169 | * 08-30-05 01.05.10 Added 4 new events and their event data structures. | ||
| 170 | * Added new ReasonCode value for SAS Device Status Change | ||
| 171 | * event. | ||
| 172 | * Added new family code for FC949E. | ||
| 167 | * -------------------------------------------------------------------------- | 173 | * -------------------------------------------------------------------------- |
| 168 | 174 | ||
| 169 | mpi_cnfg.h | 175 | mpi_cnfg.h |
| @@ -402,6 +408,23 @@ mpi_cnfg.h | |||
| 402 | * Added OwnerDevHandle and Flags field to SAS PHY Page 0. | 408 | * Added OwnerDevHandle and Flags field to SAS PHY Page 0. |
| 403 | * Added IOC GPIO Flags define to SAS Enclosure Page 0. | 409 | * Added IOC GPIO Flags define to SAS Enclosure Page 0. |
| 404 | * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. | 410 | * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. |
| 411 | * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from | ||
| 412 | * Manufacturing Page 4. | ||
| 413 | * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit. | ||
| 414 | * Added NumDevsPerEnclosure field to SAS IO Unit page 2. | ||
| 415 | * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP | ||
| 416 | * define. | ||
| 417 | * Added EnclosureHandle field to SAS Expander page 0. | ||
| 418 | * Removed redundant NumTableEntriesProg field from SAS | ||
| 419 | * Expander Page 1. | ||
| 420 | * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for | ||
| 421 | * SAS1078. | ||
| 422 | * Added more defines for Manufacturing Page 4 Flags field. | ||
| 423 | * Added more defines for IOCSettings and added | ||
| 424 | * ExpanderSpinup field to Bios Page 1. | ||
| 425 | * Added postpone SATA Init bit to SAS IO Unit Page 1 | ||
| 426 | * ControlFlags. | ||
| 427 | * Changed LogEntry format for Log Page 0. | ||
| 405 | * -------------------------------------------------------------------------- | 428 | * -------------------------------------------------------------------------- |
| 406 | 429 | ||
| 407 | mpi_init.h | 430 | mpi_init.h |
| @@ -442,6 +465,8 @@ mpi_init.h | |||
| 442 | * addressing. | 465 | * addressing. |
| 443 | * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. | 466 | * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. |
| 444 | * Added four new defines for SEP SlotStatus. | 467 | * Added four new defines for SEP SlotStatus. |
| 468 | * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them | ||
| 469 | * unique in the first 32 characters. | ||
| 445 | * -------------------------------------------------------------------------- | 470 | * -------------------------------------------------------------------------- |
| 446 | 471 | ||
| 447 | mpi_targ.h | 472 | mpi_targ.h |
| @@ -582,6 +607,9 @@ mpi_inb.h | |||
| 582 | 607 | ||
| 583 | mpi_sas.h | 608 | mpi_sas.h |
| 584 | * 08-19-04 01.05.01 Original release. | 609 | * 08-19-04 01.05.01 Original release. |
| 610 | * 08-30-05 01.05.02 Added DeviceInfo bit for SEP. | ||
| 611 | * Added PrimFlags and Primitive field to SAS IO Unit | ||
| 612 | * Control request, and added a new operation code. | ||
| 585 | * -------------------------------------------------------------------------- | 613 | * -------------------------------------------------------------------------- |
| 586 | 614 | ||
| 587 | mpi_type.h | 615 | mpi_type.h |
| @@ -592,24 +620,25 @@ mpi_type.h | |||
| 592 | * 08-08-01 01.02.01 Original release for v1.2 work. | 620 | * 08-08-01 01.02.01 Original release for v1.2 work. |
| 593 | * 05-11-04 01.03.01 Original release for MPI v1.3. | 621 | * 05-11-04 01.03.01 Original release for MPI v1.3. |
| 594 | * 08-19-04 01.05.01 Original release for MPI v1.5. | 622 | * 08-19-04 01.05.01 Original release for MPI v1.5. |
| 623 | * 08-30-05 01.05.02 Added PowerPC option to #ifdef's. | ||
| 595 | * -------------------------------------------------------------------------- | 624 | * -------------------------------------------------------------------------- |
| 596 | 625 | ||
| 597 | mpi_history.txt Parts list history | 626 | mpi_history.txt Parts list history |
| 598 | 627 | ||
| 599 | Filename 01.05.10 01.05.09 | 628 | Filename 01.05.12 01.05.11 01.05.10 01.05.09 |
| 600 | ---------- -------- -------- | 629 | ---------- -------- -------- -------- -------- |
| 601 | mpi.h 01.05.08 01.05.07 | 630 | mpi.h 01.05.10 01.05.09 01.05.08 01.05.07 |
| 602 | mpi_ioc.h 01.05.09 01.05.08 | 631 | mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08 |
| 603 | mpi_cnfg.h 01.05.09 01.05.08 | 632 | mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08 |
| 604 | mpi_init.h 01.05.05 01.05.04 | 633 | mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04 |
| 605 | mpi_targ.h 01.05.05 01.05.04 | 634 | mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04 |
| 606 | mpi_fc.h 01.05.01 01.05.01 | 635 | mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 |
| 607 | mpi_lan.h 01.05.01 01.05.01 | 636 | mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 |
| 608 | mpi_raid.h 01.05.02 01.05.02 | 637 | mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 |
| 609 | mpi_tool.h 01.05.03 01.05.03 | 638 | mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 |
| 610 | mpi_inb.h 01.05.01 01.05.01 | 639 | mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 |
| 611 | mpi_sas.h 01.05.01 01.05.01 | 640 | mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01 |
| 612 | mpi_type.h 01.05.01 01.05.01 | 641 | mpi_type.h 01.05.02 01.05.01 01.05.01 01.05.01 |
| 613 | 642 | ||
| 614 | Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 | 643 | Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 |
| 615 | ---------- -------- -------- -------- -------- -------- -------- | 644 | ---------- -------- -------- -------- -------- -------- -------- |
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h index d5af75afbd94..68941f459ca3 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI initiator mode messages and structures | 6 | * Title: MPI initiator mode messages and structures |
| 7 | * Creation Date: June 8, 2000 | 7 | * Creation Date: June 8, 2000 |
| 8 | * | 8 | * |
| 9 | * mpi_init.h Version: 01.05.05 | 9 | * mpi_init.h Version: 01.05.06 |
| 10 | * | 10 | * |
| 11 | * Version History | 11 | * Version History |
| 12 | * --------------- | 12 | * --------------- |
| @@ -50,6 +50,8 @@ | |||
| 50 | * addressing. | 50 | * addressing. |
| 51 | * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. | 51 | * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. |
| 52 | * Added four new defines for SEP SlotStatus. | 52 | * Added four new defines for SEP SlotStatus. |
| 53 | * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them | ||
| 54 | * unique in the first 32 characters. | ||
| 53 | * -------------------------------------------------------------------------- | 55 | * -------------------------------------------------------------------------- |
| 54 | */ | 56 | */ |
| 55 | 57 | ||
| @@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST | |||
| 290 | 292 | ||
| 291 | /* SCSI IO 32 MsgFlags bits */ | 293 | /* SCSI IO 32 MsgFlags bits */ |
| 292 | #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01) | 294 | #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01) |
| 293 | #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00) | 295 | #define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH (0x00) |
| 294 | #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01) | 296 | #define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01) |
| 295 | 297 | ||
| 296 | #define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02) | 298 | #define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02) |
| 297 | #define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00) | 299 | #define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00) |
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index 93b70e2b4266..2c5f43fa7c73 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages | 6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages |
| 7 | * Creation Date: August 11, 2000 | 7 | * Creation Date: August 11, 2000 |
| 8 | * | 8 | * |
| 9 | * mpi_ioc.h Version: 01.05.09 | 9 | * mpi_ioc.h Version: 01.05.10 |
| 10 | * | 10 | * |
| 11 | * Version History | 11 | * Version History |
| 12 | * --------------- | 12 | * --------------- |
| @@ -83,6 +83,10 @@ | |||
| 83 | * Removed IOCFacts Reply EEDP Capability bit. | 83 | * Removed IOCFacts Reply EEDP Capability bit. |
| 84 | * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. | 84 | * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. |
| 85 | * Added Max SATA Targets to SAS Discovery Error event. | 85 | * Added Max SATA Targets to SAS Discovery Error event. |
| 86 | * 08-30-05 01.05.10 Added 4 new events and their event data structures. | ||
| 87 | * Added new ReasonCode value for SAS Device Status Change | ||
| 88 | * event. | ||
| 89 | * Added new family code for FC949E. | ||
| 86 | * -------------------------------------------------------------------------- | 90 | * -------------------------------------------------------------------------- |
| 87 | */ | 91 | */ |
| 88 | 92 | ||
| @@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY | |||
| 464 | #define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) | 468 | #define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) |
| 465 | #define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012) | 469 | #define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012) |
| 466 | #define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013) | 470 | #define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013) |
| 471 | #define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014) | ||
| 472 | #define MPI_EVENT_IR2 (0x00000015) | ||
| 473 | #define MPI_EVENT_SAS_DISCOVERY (0x00000016) | ||
| 474 | #define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021) | ||
| 467 | 475 | ||
| 468 | /* AckRequired field values */ | 476 | /* AckRequired field values */ |
| 469 | 477 | ||
| @@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE | |||
| 480 | } EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, | 488 | } EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, |
| 481 | EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; | 489 | EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; |
| 482 | 490 | ||
| 491 | /* LogEntryAdded Event data */ | ||
| 492 | |||
| 493 | /* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */ | ||
| 494 | #define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C) | ||
| 495 | typedef struct _EVENT_DATA_LOG_ENTRY | ||
| 496 | { | ||
| 497 | U32 TimeStamp; /* 00h */ | ||
| 498 | U32 Reserved1; /* 04h */ | ||
| 499 | U16 LogSequence; /* 08h */ | ||
| 500 | U16 LogEntryQualifier; /* 0Ah */ | ||
| 501 | U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */ | ||
| 502 | } EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY, | ||
| 503 | MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t; | ||
| 504 | |||
| 505 | typedef struct _EVENT_DATA_LOG_ENTRY_ADDED | ||
| 506 | { | ||
| 507 | U16 LogSequence; /* 00h */ | ||
| 508 | U16 Reserved1; /* 02h */ | ||
| 509 | U32 Reserved2; /* 04h */ | ||
| 510 | EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */ | ||
| 511 | } EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED, | ||
| 512 | MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t; | ||
| 513 | |||
| 483 | /* SCSI Event data for Port, Bus and Device forms */ | 514 | /* SCSI Event data for Port, Bus and Device forms */ |
| 484 | 515 | ||
| 485 | typedef struct _EVENT_DATA_SCSI | 516 | typedef struct _EVENT_DATA_SCSI |
| @@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE | |||
| 538 | #define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) | 569 | #define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) |
| 539 | #define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06) | 570 | #define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06) |
| 540 | #define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) | 571 | #define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) |
| 572 | #define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) | ||
| 541 | 573 | ||
| 542 | 574 | ||
| 543 | /* SCSI Event data for Queue Full event */ | 575 | /* SCSI Event data for Queue Full event */ |
| @@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID | |||
| 579 | #define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) | 611 | #define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) |
| 580 | #define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) | 612 | #define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) |
| 581 | 613 | ||
| 614 | |||
| 615 | /* MPI Integrated RAID Resync Update Event data */ | ||
| 616 | |||
| 617 | typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE | ||
| 618 | { | ||
| 619 | U8 VolumeID; /* 00h */ | ||
| 620 | U8 VolumeBus; /* 01h */ | ||
| 621 | U8 ResyncComplete; /* 02h */ | ||
| 622 | U8 Reserved1; /* 03h */ | ||
| 623 | U32 Reserved2; /* 04h */ | ||
| 624 | } MPI_EVENT_DATA_IR_RESYNC_UPDATE, | ||
| 625 | MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE, | ||
| 626 | MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t; | ||
| 627 | |||
| 628 | /* MPI IR2 Event data */ | ||
| 629 | |||
| 630 | /* MPI_LD_STATE or MPI_PD_STATE */ | ||
| 631 | typedef struct _IR2_STATE_CHANGED | ||
| 632 | { | ||
| 633 | U16 PreviousState; /* 00h */ | ||
| 634 | U16 NewState; /* 02h */ | ||
| 635 | } IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED; | ||
| 636 | |||
| 637 | typedef struct _IR2_PD_INFO | ||
| 638 | { | ||
| 639 | U16 DeviceHandle; /* 00h */ | ||
| 640 | U8 TruncEnclosureHandle; /* 02h */ | ||
| 641 | U8 TruncatedSlot; /* 03h */ | ||
| 642 | } IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO; | ||
| 643 | |||
| 644 | typedef union _MPI_IR2_RC_EVENT_DATA | ||
| 645 | { | ||
| 646 | IR2_STATE_CHANGED StateChanged; | ||
| 647 | U32 Lba; | ||
| 648 | IR2_PD_INFO PdInfo; | ||
| 649 | } MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA; | ||
| 650 | |||
| 651 | typedef struct _MPI_EVENT_DATA_IR2 | ||
| 652 | { | ||
| 653 | U8 TargetID; /* 00h */ | ||
| 654 | U8 Bus; /* 01h */ | ||
| 655 | U8 ReasonCode; /* 02h */ | ||
| 656 | U8 PhysDiskNum; /* 03h */ | ||
| 657 | MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */ | ||
| 658 | } MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2, | ||
| 659 | MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t; | ||
| 660 | |||
| 661 | /* MPI IR2 Event data ReasonCode values */ | ||
| 662 | #define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01) | ||
| 663 | #define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02) | ||
| 664 | #define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03) | ||
| 665 | #define MPI_EVENT_IR2_RC_PD_INSERTED (0x04) | ||
| 666 | #define MPI_EVENT_IR2_RC_PD_REMOVED (0x05) | ||
| 667 | #define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06) | ||
| 668 | #define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07) | ||
| 669 | |||
| 670 | /* defines for logical disk states */ | ||
| 671 | #define MPI_LD_STATE_OPTIMAL (0x00) | ||
| 672 | #define MPI_LD_STATE_DEGRADED (0x01) | ||
| 673 | #define MPI_LD_STATE_FAILED (0x02) | ||
| 674 | #define MPI_LD_STATE_MISSING (0x03) | ||
| 675 | #define MPI_LD_STATE_OFFLINE (0x04) | ||
| 676 | |||
| 677 | /* defines for physical disk states */ | ||
| 678 | #define MPI_PD_STATE_ONLINE (0x00) | ||
| 679 | #define MPI_PD_STATE_MISSING (0x01) | ||
| 680 | #define MPI_PD_STATE_NOT_COMPATIBLE (0x02) | ||
| 681 | #define MPI_PD_STATE_FAILED (0x03) | ||
| 682 | #define MPI_PD_STATE_INITIALIZING (0x04) | ||
| 683 | #define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05) | ||
| 684 | #define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06) | ||
| 685 | #define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF) | ||
| 686 | |||
| 582 | /* MPI Link Status Change Event data */ | 687 | /* MPI Link Status Change Event data */ |
| 583 | 688 | ||
| 584 | typedef struct _EVENT_DATA_LINK_STATUS | 689 | typedef struct _EVENT_DATA_LINK_STATUS |
| @@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS | |||
| 660 | #define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08) | 765 | #define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08) |
| 661 | #define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09) | 766 | #define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09) |
| 662 | 767 | ||
| 768 | /* SAS Discovery Event data */ | ||
| 769 | |||
| 770 | typedef struct _EVENT_DATA_SAS_DISCOVERY | ||
| 771 | { | ||
| 772 | U32 DiscoveryStatus; /* 00h */ | ||
| 773 | U32 Reserved1; /* 04h */ | ||
| 774 | } EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY, | ||
| 775 | EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t; | ||
| 776 | |||
| 777 | #define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000) | ||
| 778 | #define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001) | ||
| 779 | #define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000) | ||
| 780 | #define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16) | ||
| 781 | |||
| 663 | /* SAS Discovery Errror Event data */ | 782 | /* SAS Discovery Errror Event data */ |
| 664 | 783 | ||
| 665 | typedef struct _EVENT_DATA_DISCOVERY_ERROR | 784 | typedef struct _EVENT_DATA_DISCOVERY_ERROR |
| @@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER | |||
| 869 | #define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */ | 988 | #define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */ |
| 870 | #define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */ | 989 | #define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */ |
| 871 | #define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) | 990 | #define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) |
| 991 | #define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006) | ||
| 872 | /* SAS */ | 992 | /* SAS */ |
| 873 | #define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) | 993 | #define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) |
| 874 | #define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002) | 994 | #define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002) |
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h new file mode 100644 index 000000000000..dc98d46f9071 --- /dev/null +++ b/drivers/message/fusion/lsi/mpi_log_fc.h | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * NAME: fc_log.h | ||
| 5 | * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips | ||
| 6 | * DESCRIPTION: Contains the enumerated list of values that may be returned | ||
| 7 | * in the IOCLogInfo field of a MPI Default Reply Message. | ||
| 8 | * | ||
| 9 | * CREATION DATE: 6/02/2000 | ||
| 10 | * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $ | ||
| 11 | */ | ||
| 12 | |||
| 13 | |||
| 14 | /* | ||
| 15 | * MpiIocLogInfo_t enum | ||
| 16 | * | ||
| 17 | * These 32 bit values are used in the IOCLogInfo field of the MPI reply | ||
| 18 | * messages. | ||
| 19 | * The value is 0xabcccccc where | ||
| 20 | * a = The type of log info as per the MPI spec. Since these codes are | ||
| 21 | * all for Fibre Channel this value will always be 2. | ||
| 22 | * b = Specifies a subclass of the firmware where | ||
| 23 | * 0 = FCP Initiator | ||
| 24 | * 1 = FCP Target | ||
| 25 | * 2 = LAN | ||
| 26 | * 3 = MPI Message Layer | ||
| 27 | * 4 = FC Link | ||
| 28 | * 5 = Context Manager | ||
| 29 | * 6 = Invalid Field Offset | ||
| 30 | * 7 = State Change Info | ||
| 31 | * all others are reserved for future use | ||
| 32 | * c = A specific value within the subclass. | ||
| 33 | * | ||
| 34 | * NOTE: Any new values should be added to the end of each subclass so that the | ||
| 35 | * codes remain consistent across firmware releases. | ||
| 36 | */ | ||
| 37 | typedef enum _MpiIocLogInfoFc | ||
| 38 | { | ||
| 39 | MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000, | ||
| 40 | MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */ | ||
| 41 | MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */ | ||
| 42 | MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */ | ||
| 43 | MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */ | ||
| 44 | MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */ | ||
| 45 | MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */ | ||
| 46 | MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */ | ||
| 47 | MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */ | ||
| 48 | MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */ | ||
| 49 | MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */ | ||
| 50 | MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */ | ||
| 51 | |||
| 52 | MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000, | ||
| 53 | MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */ | ||
| 54 | MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */ | ||
| 55 | MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */ | ||
| 56 | MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */ | ||
| 57 | MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */ | ||
| 58 | MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */ | ||
| 59 | MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */ | ||
| 60 | MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */ | ||
| 61 | MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */ | ||
| 62 | MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */ | ||
| 63 | MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */ | ||
| 64 | MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */ | ||
| 65 | MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */ | ||
| 66 | MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */ | ||
| 67 | |||
| 68 | MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000, | ||
| 69 | MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */ | ||
| 70 | MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */ | ||
| 71 | MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */ | ||
| 72 | MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */ | ||
| 73 | |||
| 74 | MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000, | ||
| 75 | |||
| 76 | MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000, | ||
| 77 | MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */ | ||
| 78 | MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */ | ||
| 79 | MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */ | ||
| 80 | MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */ | ||
| 81 | |||
| 82 | MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000, | ||
| 83 | |||
| 84 | MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */ | ||
| 85 | MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff, | ||
| 86 | |||
| 87 | MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */ | ||
| 88 | |||
| 89 | } MpiIocLogInfoFc_t; | ||
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h new file mode 100644 index 000000000000..9259d1ad6e6e --- /dev/null +++ b/drivers/message/fusion/lsi/mpi_log_sas.h | |||
| @@ -0,0 +1,162 @@ | |||
| 1 | |||
| 2 | /*************************************************************************** | ||
| 3 | * * | ||
| 4 | * Copyright 2003 LSI Logic Corporation. All rights reserved. * | ||
| 5 | * * | ||
| 6 | * This file is confidential and a trade secret of LSI Logic. The * | ||
| 7 | * receipt of or possession of this file does not convey any rights to * | ||
| 8 | * reproduce or disclose its contents or to manufacture, use, or sell * | ||
| 9 | * anything it may describe, in whole, or in part, without the specific * | ||
| 10 | * written consent of LSI Logic Corporation. * | ||
| 11 | * * | ||
| 12 | *************************************************************************** | ||
| 13 | * | ||
| 14 | * Name: iopiIocLogInfo.h | ||
| 15 | * Title: SAS Firmware IOP Interface IOC Log Info Definitions | ||
| 16 | * Programmer: Guy Kendall | ||
| 17 | * Creation Date: September 24, 2003 | ||
| 18 | * | ||
| 19 | * Version History | ||
| 20 | * --------------- | ||
| 21 | * | ||
| 22 | * Last Updated | ||
| 23 | * ------------- | ||
| 24 | * Version %version: 22 % | ||
| 25 | * Date Updated %date_modified: % | ||
| 26 | * Programmer %created_by: nperucca % | ||
| 27 | * | ||
| 28 | * Date Who Description | ||
| 29 | * -------- --- ------------------------------------------------------- | ||
| 30 | * 09/24/03 GWK Initial version | ||
| 31 | * | ||
| 32 | * | ||
| 33 | * Description | ||
| 34 | * ------------ | ||
| 35 | * This include file contains SAS firmware interface IOC Log Info codes | ||
| 36 | * | ||
| 37 | *------------------------------------------------------------------------- | ||
| 38 | */ | ||
| 39 | |||
| 40 | #ifndef IOPI_IOCLOGINFO_H_INCLUDED | ||
| 41 | #define IOPI_IOCLOGINFO_H_INCLUDED | ||
| 42 | |||
| 43 | |||
| 44 | /****************************************************************************/ | ||
| 45 | /* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */ | ||
| 46 | /* Format: */ | ||
| 47 | /* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */ | ||
| 48 | /* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */ | ||
| 49 | /* Bits 23-16: LOGINFO_CODE */ | ||
| 50 | /* Bits 15-0: LOGINFO_CODE Specific */ | ||
| 51 | /****************************************************************************/ | ||
| 52 | |||
| 53 | /****************************************************************************/ | ||
| 54 | /* IOC_LOGINFO_ORIGINATOR defines */ | ||
| 55 | /****************************************************************************/ | ||
| 56 | #define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000) | ||
| 57 | #define IOC_LOGINFO_ORIGINATOR_PL (0x01000000) | ||
| 58 | #define IOC_LOGINFO_ORIGINATOR_IR (0x02000000) | ||
| 59 | |||
| 60 | /****************************************************************************/ | ||
| 61 | /* LOGINFO_CODE defines */ | ||
| 62 | /****************************************************************************/ | ||
| 63 | #define IOC_LOGINFO_CODE_MASK (0x00FF0000) | ||
| 64 | #define IOC_LOGINFO_CODE_SHIFT (16) | ||
| 65 | |||
| 66 | /****************************************************************************/ | ||
| 67 | /* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */ | ||
| 68 | /****************************************************************************/ | ||
| 69 | #define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000) | ||
| 70 | #define IOP_LOGINFO_CODE_UNUSED2 (0x00020000) | ||
| 71 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000) | ||
| 72 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */ | ||
| 73 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */ | ||
| 74 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */ | ||
| 75 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */ | ||
| 76 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */ | ||
| 77 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */ | ||
| 78 | #define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ | ||
| 79 | #define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) | ||
| 80 | |||
| 81 | |||
| 82 | /****************************************************************************/ | ||
| 83 | /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ | ||
| 84 | /****************************************************************************/ | ||
| 85 | #define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) | ||
| 86 | #define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) | ||
| 87 | #define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) | ||
| 88 | #define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) | ||
| 89 | #define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000) | ||
| 90 | #define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000) | ||
| 91 | #define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000) | ||
| 92 | #define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000) | ||
| 93 | #define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000) | ||
| 94 | #define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000) | ||
| 95 | #define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000) | ||
| 96 | #define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000) | ||
| 97 | #define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) | ||
| 98 | #define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) | ||
| 99 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) | ||
| 100 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ | ||
| 101 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ | ||
| 102 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ | ||
| 103 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */ | ||
| 104 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */ | ||
| 105 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ | ||
| 106 | #define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ | ||
| 107 | #define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) | ||
| 108 | #define PL_LOGINFO_CODE_RESET (0x00110000) | ||
| 109 | #define PL_LOGINFO_CODE_ABORT (0x00120000) | ||
| 110 | #define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) | ||
| 111 | #define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) | ||
| 112 | #define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) | ||
| 113 | #define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) | ||
| 114 | #define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) | ||
| 115 | #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) | ||
| 116 | #define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500) | ||
| 117 | #define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600) | ||
| 118 | #define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700) | ||
| 119 | #define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800) | ||
| 120 | #define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900) | ||
| 121 | #define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00) | ||
| 122 | #define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00) | ||
| 123 | #define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) | ||
| 124 | #define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) | ||
| 125 | #define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) | ||
| 126 | #define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) | ||
| 127 | |||
| 128 | |||
| 129 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ | ||
| 130 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */ | ||
| 131 | #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */ | ||
| 132 | #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */ | ||
| 133 | #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */ | ||
| 134 | #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */ | ||
| 135 | #define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */ | ||
| 136 | |||
| 137 | #define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ | ||
| 138 | #define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ | ||
| 139 | #define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ | ||
| 140 | #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ | ||
| 141 | #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */ | ||
| 142 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */ | ||
| 143 | #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */ | ||
| 144 | #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */ | ||
| 145 | #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/ | ||
| 146 | |||
| 147 | |||
| 148 | /****************************************************************************/ | ||
| 149 | /* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */ | ||
| 150 | /****************************************************************************/ | ||
| 151 | #define IR_LOGINFO_CODE_UNUSED1 (0x00010000) | ||
| 152 | #define IR_LOGINFO_CODE_UNUSED2 (0x00020000) | ||
| 153 | |||
| 154 | /****************************************************************************/ | ||
| 155 | /* Defines for convienence */ | ||
| 156 | /****************************************************************************/ | ||
| 157 | #define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP) | ||
| 158 | #define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL) | ||
| 159 | #define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR) | ||
| 160 | |||
| 161 | #endif /* end of file */ | ||
| 162 | |||
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h index 230fa69b5353..70514867bddf 100644 --- a/drivers/message/fusion/lsi/mpi_sas.h +++ b/drivers/message/fusion/lsi/mpi_sas.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI Serial Attached SCSI structures and definitions | 6 | * Title: MPI Serial Attached SCSI structures and definitions |
| 7 | * Creation Date: August 19, 2004 | 7 | * Creation Date: August 19, 2004 |
| 8 | * | 8 | * |
| 9 | * mpi_sas.h Version: 01.05.01 | 9 | * mpi_sas.h Version: 01.05.02 |
| 10 | * | 10 | * |
| 11 | * Version History | 11 | * Version History |
| 12 | * --------------- | 12 | * --------------- |
| @@ -14,6 +14,9 @@ | |||
| 14 | * Date Version Description | 14 | * Date Version Description |
| 15 | * -------- -------- ------------------------------------------------------ | 15 | * -------- -------- ------------------------------------------------------ |
| 16 | * 08-19-04 01.05.01 Original release. | 16 | * 08-19-04 01.05.01 Original release. |
| 17 | * 08-30-05 01.05.02 Added DeviceInfo bit for SEP. | ||
| 18 | * Added PrimFlags and Primitive field to SAS IO Unit | ||
| 19 | * Control request, and added a new operation code. | ||
| 17 | * -------------------------------------------------------------------------- | 20 | * -------------------------------------------------------------------------- |
| 18 | */ | 21 | */ |
| 19 | 22 | ||
| @@ -51,6 +54,7 @@ | |||
| 51 | * Values for the SAS DeviceInfo field used in SAS Device Status Change Event | 54 | * Values for the SAS DeviceInfo field used in SAS Device Status Change Event |
| 52 | * data and SAS IO Unit Configuration pages. | 55 | * data and SAS IO Unit Configuration pages. |
| 53 | */ | 56 | */ |
| 57 | #define MPI_SAS_DEVICE_INFO_SEP (0x00004000) | ||
| 54 | #define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) | 58 | #define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) |
| 55 | #define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) | 59 | #define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) |
| 56 | #define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) | 60 | #define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) |
| @@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST | |||
| 212 | U8 TargetID; /* 0Ch */ | 216 | U8 TargetID; /* 0Ch */ |
| 213 | U8 Bus; /* 0Dh */ | 217 | U8 Bus; /* 0Dh */ |
| 214 | U8 PhyNum; /* 0Eh */ | 218 | U8 PhyNum; /* 0Eh */ |
| 215 | U8 Reserved4; /* 0Fh */ | 219 | U8 PrimFlags; /* 0Fh */ |
| 216 | U32 Reserved5; /* 10h */ | 220 | U32 Primitive; /* 10h */ |
| 217 | U64 SASAddress; /* 14h */ | 221 | U64 SASAddress; /* 14h */ |
| 218 | U32 Reserved6; /* 1Ch */ | 222 | U32 Reserved4; /* 1Ch */ |
| 219 | } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, | 223 | } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, |
| 220 | SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; | 224 | SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; |
| 221 | 225 | ||
| 222 | /* values for the Operation field */ | 226 | /* values for the Operation field */ |
| 223 | #define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) | 227 | #define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) |
| 224 | #define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) | 228 | #define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) |
| 225 | #define MPI_SAS_OP_PHY_LINK_RESET (0x06) | 229 | #define MPI_SAS_OP_PHY_LINK_RESET (0x06) |
| 226 | #define MPI_SAS_OP_PHY_HARD_RESET (0x07) | 230 | #define MPI_SAS_OP_PHY_HARD_RESET (0x07) |
| 227 | #define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) | 231 | #define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) |
| 228 | #define MPI_SAS_OP_MAP_CURRENT (0x09) | 232 | #define MPI_SAS_OP_MAP_CURRENT (0x09) |
| 233 | #define MPI_SAS_OP_SEND_PRIMITIVE (0x0A) | ||
| 234 | |||
| 235 | /* values for the PrimFlags field */ | ||
| 236 | #define MPI_SAS_PRIMFLAGS_SINGLE (0x08) | ||
| 237 | #define MPI_SAS_PRIMFLAGS_TRIPLE (0x02) | ||
| 238 | #define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01) | ||
| 229 | 239 | ||
| 230 | 240 | ||
| 231 | /* SAS IO Unit Control Reply */ | 241 | /* SAS IO Unit Control Reply */ |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 537836068c49..d890b2b8a93e 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -148,7 +148,6 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag); | |||
| 148 | static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); | 148 | static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); |
| 149 | static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); | 149 | static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); |
| 150 | static int GetLanConfigPages(MPT_ADAPTER *ioc); | 150 | static int GetLanConfigPages(MPT_ADAPTER *ioc); |
| 151 | static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); | ||
| 152 | static int GetIoUnitPage2(MPT_ADAPTER *ioc); | 151 | static int GetIoUnitPage2(MPT_ADAPTER *ioc); |
| 153 | int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 152 | int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
| 154 | static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); | 153 | static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); |
| @@ -1232,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1232 | dprintk((KERN_INFO MYNAM | 1231 | dprintk((KERN_INFO MYNAM |
| 1233 | ": Not using 64 bit consistent mask\n")); | 1232 | ": Not using 64 bit consistent mask\n")); |
| 1234 | 1233 | ||
| 1235 | ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); | 1234 | ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); |
| 1236 | if (ioc == NULL) { | 1235 | if (ioc == NULL) { |
| 1237 | printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); | 1236 | printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); |
| 1238 | return -ENOMEM; | 1237 | return -ENOMEM; |
| 1239 | } | 1238 | } |
| 1240 | memset(ioc, 0, sizeof(MPT_ADAPTER)); | ||
| 1241 | ioc->alloc_total = sizeof(MPT_ADAPTER); | 1239 | ioc->alloc_total = sizeof(MPT_ADAPTER); |
| 1242 | ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ | 1240 | ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ |
| 1243 | ioc->reply_sz = MPT_REPLY_FRAME_SIZE; | 1241 | ioc->reply_sz = MPT_REPLY_FRAME_SIZE; |
| @@ -1245,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1245 | ioc->pcidev = pdev; | 1243 | ioc->pcidev = pdev; |
| 1246 | ioc->diagPending = 0; | 1244 | ioc->diagPending = 0; |
| 1247 | spin_lock_init(&ioc->diagLock); | 1245 | spin_lock_init(&ioc->diagLock); |
| 1246 | spin_lock_init(&ioc->fc_rescan_work_lock); | ||
| 1247 | spin_lock_init(&ioc->fc_rport_lock); | ||
| 1248 | spin_lock_init(&ioc->initializing_hba_lock); | 1248 | spin_lock_init(&ioc->initializing_hba_lock); |
| 1249 | 1249 | ||
| 1250 | /* Initialize the event logging. | 1250 | /* Initialize the event logging. |
| @@ -1268,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1268 | */ | 1268 | */ |
| 1269 | INIT_LIST_HEAD(&ioc->configQ); | 1269 | INIT_LIST_HEAD(&ioc->configQ); |
| 1270 | 1270 | ||
| 1271 | /* Initialize the fc rport list head. | ||
| 1272 | */ | ||
| 1273 | INIT_LIST_HEAD(&ioc->fc_rports); | ||
| 1274 | |||
| 1271 | /* Find lookup slot. */ | 1275 | /* Find lookup slot. */ |
| 1272 | INIT_LIST_HEAD(&ioc->list); | 1276 | INIT_LIST_HEAD(&ioc->list); |
| 1273 | ioc->id = mpt_ids++; | 1277 | ioc->id = mpt_ids++; |
| @@ -1374,6 +1378,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1374 | ioc->bus_type = FC; | 1378 | ioc->bus_type = FC; |
| 1375 | ioc->errata_flag_1064 = 1; | 1379 | ioc->errata_flag_1064 = 1; |
| 1376 | } | 1380 | } |
| 1381 | else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) { | ||
| 1382 | ioc->prod_name = "LSIFC949E"; | ||
| 1383 | ioc->bus_type = FC; | ||
| 1384 | } | ||
| 1377 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { | 1385 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { |
| 1378 | ioc->prod_name = "LSI53C1030"; | 1386 | ioc->prod_name = "LSI53C1030"; |
| 1379 | ioc->bus_type = SPI; | 1387 | ioc->bus_type = SPI; |
| @@ -1622,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev) | |||
| 1622 | pci_enable_device(pdev); | 1630 | pci_enable_device(pdev); |
| 1623 | 1631 | ||
| 1624 | /* enable interrupts */ | 1632 | /* enable interrupts */ |
| 1625 | CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); | 1633 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); |
| 1626 | ioc->active = 1; | 1634 | ioc->active = 1; |
| 1627 | 1635 | ||
| 1628 | /* F/W not running */ | 1636 | /* F/W not running */ |
| @@ -1715,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 1715 | /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ | 1723 | /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ |
| 1716 | dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", | 1724 | dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", |
| 1717 | ioc->alt_ioc->name)); | 1725 | ioc->alt_ioc->name)); |
| 1718 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); | 1726 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); |
| 1719 | ioc->alt_ioc->active = 1; | 1727 | ioc->alt_ioc->active = 1; |
| 1720 | } | 1728 | } |
| 1721 | 1729 | ||
| @@ -1831,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 1831 | 1839 | ||
| 1832 | if (ret == 0) { | 1840 | if (ret == 0) { |
| 1833 | /* Enable! (reply interrupt) */ | 1841 | /* Enable! (reply interrupt) */ |
| 1834 | CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); | 1842 | CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); |
| 1835 | ioc->active = 1; | 1843 | ioc->active = 1; |
| 1836 | } | 1844 | } |
| 1837 | 1845 | ||
| @@ -1839,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 1839 | /* (re)Enable alt-IOC! (reply interrupt) */ | 1847 | /* (re)Enable alt-IOC! (reply interrupt) */ |
| 1840 | dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", | 1848 | dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", |
| 1841 | ioc->alt_ioc->name)); | 1849 | ioc->alt_ioc->name)); |
| 1842 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); | 1850 | CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); |
| 1843 | ioc->alt_ioc->active = 1; | 1851 | ioc->alt_ioc->active = 1; |
| 1844 | } | 1852 | } |
| 1845 | 1853 | ||
| @@ -1880,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
| 1880 | * (FCPortPage0_t stuff) | 1888 | * (FCPortPage0_t stuff) |
| 1881 | */ | 1889 | */ |
| 1882 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | 1890 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { |
| 1883 | (void) GetFcPortPage0(ioc, ii); | 1891 | (void) mptbase_GetFcPortPage0(ioc, ii); |
| 1884 | } | 1892 | } |
| 1885 | 1893 | ||
| 1886 | if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && | 1894 | if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && |
| @@ -4199,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) | |||
| 4199 | 4207 | ||
| 4200 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 4208 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 4201 | /* | 4209 | /* |
| 4202 | * GetFcPortPage0 - Fetch FCPort config Page0. | 4210 | * mptbase_GetFcPortPage0 - Fetch FCPort config Page0. |
| 4203 | * @ioc: Pointer to MPT_ADAPTER structure | 4211 | * @ioc: Pointer to MPT_ADAPTER structure |
| 4204 | * @portnum: IOC Port number | 4212 | * @portnum: IOC Port number |
| 4205 | * | 4213 | * |
| @@ -4209,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc) | |||
| 4209 | * -EAGAIN if no msg frames currently available | 4217 | * -EAGAIN if no msg frames currently available |
| 4210 | * -EFAULT for non-successful reply or no reply (timeout) | 4218 | * -EFAULT for non-successful reply or no reply (timeout) |
| 4211 | */ | 4219 | */ |
| 4212 | static int | 4220 | int |
| 4213 | GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | 4221 | mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) |
| 4214 | { | 4222 | { |
| 4215 | ConfigPageHeader_t hdr; | 4223 | ConfigPageHeader_t hdr; |
| 4216 | CONFIGPARMS cfg; | 4224 | CONFIGPARMS cfg; |
| @@ -4220,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | |||
| 4220 | int data_sz; | 4228 | int data_sz; |
| 4221 | int copy_sz; | 4229 | int copy_sz; |
| 4222 | int rc; | 4230 | int rc; |
| 4231 | int count = 400; | ||
| 4232 | |||
| 4223 | 4233 | ||
| 4224 | /* Get FCPort Page 0 header */ | 4234 | /* Get FCPort Page 0 header */ |
| 4225 | hdr.PageVersion = 0; | 4235 | hdr.PageVersion = 0; |
| @@ -4243,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | |||
| 4243 | rc = -ENOMEM; | 4253 | rc = -ENOMEM; |
| 4244 | ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); | 4254 | ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); |
| 4245 | if (ppage0_alloc) { | 4255 | if (ppage0_alloc) { |
| 4256 | |||
| 4257 | try_again: | ||
| 4246 | memset((u8 *)ppage0_alloc, 0, data_sz); | 4258 | memset((u8 *)ppage0_alloc, 0, data_sz); |
| 4247 | cfg.physAddr = page0_dma; | 4259 | cfg.physAddr = page0_dma; |
| 4248 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 4260 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; |
| @@ -4274,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | |||
| 4274 | pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); | 4286 | pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); |
| 4275 | pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); | 4287 | pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); |
| 4276 | 4288 | ||
| 4289 | /* | ||
| 4290 | * if still doing discovery, | ||
| 4291 | * hang loose a while until finished | ||
| 4292 | */ | ||
| 4293 | if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { | ||
| 4294 | if (count-- > 0) { | ||
| 4295 | msleep_interruptible(100); | ||
| 4296 | goto try_again; | ||
| 4297 | } | ||
| 4298 | printk(MYIOC_s_INFO_FMT "Firmware discovery not" | ||
| 4299 | " complete.\n", | ||
| 4300 | ioc->name); | ||
| 4301 | } | ||
| 4277 | } | 4302 | } |
| 4278 | 4303 | ||
| 4279 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); | 4304 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); |
| @@ -6358,6 +6383,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory); | |||
| 6358 | EXPORT_SYMBOL(mpt_free_fw_memory); | 6383 | EXPORT_SYMBOL(mpt_free_fw_memory); |
| 6359 | EXPORT_SYMBOL(mptbase_sas_persist_operation); | 6384 | EXPORT_SYMBOL(mptbase_sas_persist_operation); |
| 6360 | EXPORT_SYMBOL(mpt_alt_ioc_wait); | 6385 | EXPORT_SYMBOL(mpt_alt_ioc_wait); |
| 6386 | EXPORT_SYMBOL(mptbase_GetFcPortPage0); | ||
| 6361 | 6387 | ||
| 6362 | 6388 | ||
| 6363 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6389 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 6c48d1f54ac9..47053ac65068 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
| @@ -76,8 +76,8 @@ | |||
| 76 | #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR | 76 | #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| 79 | #define MPT_LINUX_VERSION_COMMON "3.03.05" | 79 | #define MPT_LINUX_VERSION_COMMON "3.03.06" |
| 80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05" | 80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06" |
| 81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" | 81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" |
| 82 | 82 | ||
| 83 | #define show_mptmod_ver(s,ver) \ | 83 | #define show_mptmod_ver(s,ver) \ |
| @@ -413,7 +413,7 @@ typedef struct _MPT_IOCTL { | |||
| 413 | u8 status; /* current command status */ | 413 | u8 status; /* current command status */ |
| 414 | u8 reset; /* 1 if bus reset allowed */ | 414 | u8 reset; /* 1 if bus reset allowed */ |
| 415 | u8 target; /* target for reset */ | 415 | u8 target; /* target for reset */ |
| 416 | struct semaphore sem_ioc; | 416 | struct mutex ioctl_mutex; |
| 417 | } MPT_IOCTL; | 417 | } MPT_IOCTL; |
| 418 | 418 | ||
| 419 | #define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ | 419 | #define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ |
| @@ -421,7 +421,7 @@ typedef struct _MPT_IOCTL { | |||
| 421 | #define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */ | 421 | #define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */ |
| 422 | 422 | ||
| 423 | typedef struct _MPT_SAS_MGMT { | 423 | typedef struct _MPT_SAS_MGMT { |
| 424 | struct semaphore mutex; | 424 | struct mutex mutex; |
| 425 | struct completion done; | 425 | struct completion done; |
| 426 | u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ | 426 | u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ |
| 427 | u8 status; /* current command status */ | 427 | u8 status; /* current command status */ |
| @@ -499,6 +499,22 @@ typedef struct _RaidCfgData { | |||
| 499 | int isRaid; /* bit field, 1 if RAID */ | 499 | int isRaid; /* bit field, 1 if RAID */ |
| 500 | }RaidCfgData; | 500 | }RaidCfgData; |
| 501 | 501 | ||
| 502 | #define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ | ||
| 503 | #define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ | ||
| 504 | #define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */ | ||
| 505 | |||
| 506 | /* | ||
| 507 | * data allocated for each fc rport device | ||
| 508 | */ | ||
| 509 | struct mptfc_rport_info | ||
| 510 | { | ||
| 511 | struct list_head list; | ||
| 512 | struct fc_rport *rport; | ||
| 513 | VirtDevice *vdev; | ||
| 514 | FCDevicePage0_t pg0; | ||
| 515 | u8 flags; | ||
| 516 | }; | ||
| 517 | |||
| 502 | /* | 518 | /* |
| 503 | * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS | 519 | * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS |
| 504 | */ | 520 | */ |
| @@ -612,7 +628,16 @@ typedef struct _MPT_ADAPTER | |||
| 612 | struct list_head list; | 628 | struct list_head list; |
| 613 | struct net_device *netdev; | 629 | struct net_device *netdev; |
| 614 | struct list_head sas_topology; | 630 | struct list_head sas_topology; |
| 631 | struct mutex sas_topology_mutex; | ||
| 615 | MPT_SAS_MGMT sas_mgmt; | 632 | MPT_SAS_MGMT sas_mgmt; |
| 633 | int num_ports; | ||
| 634 | |||
| 635 | struct list_head fc_rports; | ||
| 636 | spinlock_t fc_rport_lock; /* list and ri flags */ | ||
| 637 | spinlock_t fc_rescan_work_lock; | ||
| 638 | int fc_rescan_work_count; | ||
| 639 | struct work_struct fc_rescan_work; | ||
| 640 | |||
| 616 | } MPT_ADAPTER; | 641 | } MPT_ADAPTER; |
| 617 | 642 | ||
| 618 | /* | 643 | /* |
| @@ -999,6 +1024,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | |||
| 999 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 1024 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
| 1000 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | 1025 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); |
| 1001 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 1026 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
| 1027 | extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); | ||
| 1002 | extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); | 1028 | extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); |
| 1003 | 1029 | ||
| 1004 | /* | 1030 | /* |
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 7c340240a50e..bdf709987982 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
| @@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) | |||
| 177 | dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); | 177 | dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); |
| 178 | 178 | ||
| 179 | if (nonblock) { | 179 | if (nonblock) { |
| 180 | if (down_trylock(&ioc->ioctl->sem_ioc)) | 180 | if (!mutex_trylock(&ioc->ioctl->ioctl_mutex)) |
| 181 | rc = -EAGAIN; | 181 | rc = -EAGAIN; |
| 182 | } else { | 182 | } else { |
| 183 | if (down_interruptible(&ioc->ioctl->sem_ioc)) | 183 | if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex)) |
| 184 | rc = -ERESTARTSYS; | 184 | rc = -ERESTARTSYS; |
| 185 | } | 185 | } |
| 186 | dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); | 186 | dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); |
| @@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 557 | else | 557 | else |
| 558 | ret = -EINVAL; | 558 | ret = -EINVAL; |
| 559 | 559 | ||
| 560 | up(&iocp->ioctl->sem_ioc); | 560 | mutex_unlock(&iocp->ioctl->ioctl_mutex); |
| 561 | 561 | ||
| 562 | return ret; | 562 | return ret; |
| 563 | } | 563 | } |
| @@ -2619,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, | |||
| 2619 | 2619 | ||
| 2620 | ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); | 2620 | ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); |
| 2621 | 2621 | ||
| 2622 | up(&iocp->ioctl->sem_ioc); | 2622 | mutex_unlock(&iocp->ioctl->ioctl_mutex); |
| 2623 | 2623 | ||
| 2624 | return ret; | 2624 | return ret; |
| 2625 | } | 2625 | } |
| @@ -2673,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd, | |||
| 2673 | */ | 2673 | */ |
| 2674 | ret = mptctl_do_mpt_command (karg, &uarg->MF); | 2674 | ret = mptctl_do_mpt_command (karg, &uarg->MF); |
| 2675 | 2675 | ||
| 2676 | up(&iocp->ioctl->sem_ioc); | 2676 | mutex_unlock(&iocp->ioctl->ioctl_mutex); |
| 2677 | 2677 | ||
| 2678 | return ret; | 2678 | return ret; |
| 2679 | } | 2679 | } |
| @@ -2743,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2743 | memset(mem, 0, sz); | 2743 | memset(mem, 0, sz); |
| 2744 | ioc->ioctl = (MPT_IOCTL *) mem; | 2744 | ioc->ioctl = (MPT_IOCTL *) mem; |
| 2745 | ioc->ioctl->ioc = ioc; | 2745 | ioc->ioctl->ioc = ioc; |
| 2746 | sema_init(&ioc->ioctl->sem_ioc, 1); | 2746 | mutex_init(&ioc->ioctl->ioctl_mutex); |
| 2747 | return 0; | 2747 | return 0; |
| 2748 | 2748 | ||
| 2749 | out_fail: | 2749 | out_fail: |
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index ba61e1828858..b102c7666d0e 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
| @@ -55,12 +55,14 @@ | |||
| 55 | #include <linux/reboot.h> /* notifier code */ | 55 | #include <linux/reboot.h> /* notifier code */ |
| 56 | #include <linux/sched.h> | 56 | #include <linux/sched.h> |
| 57 | #include <linux/workqueue.h> | 57 | #include <linux/workqueue.h> |
| 58 | #include <linux/sort.h> | ||
| 58 | 59 | ||
| 59 | #include <scsi/scsi.h> | 60 | #include <scsi/scsi.h> |
| 60 | #include <scsi/scsi_cmnd.h> | 61 | #include <scsi/scsi_cmnd.h> |
| 61 | #include <scsi/scsi_device.h> | 62 | #include <scsi/scsi_device.h> |
| 62 | #include <scsi/scsi_host.h> | 63 | #include <scsi/scsi_host.h> |
| 63 | #include <scsi/scsi_tcq.h> | 64 | #include <scsi/scsi_tcq.h> |
| 65 | #include <scsi/scsi_transport_fc.h> | ||
| 64 | 66 | ||
| 65 | #include "mptbase.h" | 67 | #include "mptbase.h" |
| 66 | #include "mptscsih.h" | 68 | #include "mptscsih.h" |
| @@ -79,19 +81,34 @@ static int mpt_pq_filter = 0; | |||
| 79 | module_param(mpt_pq_filter, int, 0); | 81 | module_param(mpt_pq_filter, int, 0); |
| 80 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); | 82 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); |
| 81 | 83 | ||
| 84 | #define MPTFC_DEV_LOSS_TMO (60) | ||
| 85 | static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */ | ||
| 86 | module_param(mptfc_dev_loss_tmo, int, 0); | ||
| 87 | MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the " | ||
| 88 | " transport to wait for an rport to " | ||
| 89 | " return following a device loss event." | ||
| 90 | " Default=60."); | ||
| 91 | |||
| 82 | static int mptfcDoneCtx = -1; | 92 | static int mptfcDoneCtx = -1; |
| 83 | static int mptfcTaskCtx = -1; | 93 | static int mptfcTaskCtx = -1; |
| 84 | static int mptfcInternalCtx = -1; /* Used only for internal commands */ | 94 | static int mptfcInternalCtx = -1; /* Used only for internal commands */ |
| 85 | 95 | ||
| 96 | int mptfc_slave_alloc(struct scsi_device *device); | ||
| 97 | static int mptfc_qcmd(struct scsi_cmnd *SCpnt, | ||
| 98 | void (*done)(struct scsi_cmnd *)); | ||
| 99 | |||
| 100 | static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); | ||
| 101 | static void __devexit mptfc_remove(struct pci_dev *pdev); | ||
| 102 | |||
| 86 | static struct scsi_host_template mptfc_driver_template = { | 103 | static struct scsi_host_template mptfc_driver_template = { |
| 87 | .module = THIS_MODULE, | 104 | .module = THIS_MODULE, |
| 88 | .proc_name = "mptfc", | 105 | .proc_name = "mptfc", |
| 89 | .proc_info = mptscsih_proc_info, | 106 | .proc_info = mptscsih_proc_info, |
| 90 | .name = "MPT FC Host", | 107 | .name = "MPT FC Host", |
| 91 | .info = mptscsih_info, | 108 | .info = mptscsih_info, |
| 92 | .queuecommand = mptscsih_qcmd, | 109 | .queuecommand = mptfc_qcmd, |
| 93 | .target_alloc = mptscsih_target_alloc, | 110 | .target_alloc = mptscsih_target_alloc, |
| 94 | .slave_alloc = mptscsih_slave_alloc, | 111 | .slave_alloc = mptfc_slave_alloc, |
| 95 | .slave_configure = mptscsih_slave_configure, | 112 | .slave_configure = mptscsih_slave_configure, |
| 96 | .target_destroy = mptscsih_target_destroy, | 113 | .target_destroy = mptscsih_target_destroy, |
| 97 | .slave_destroy = mptscsih_slave_destroy, | 114 | .slave_destroy = mptscsih_slave_destroy, |
| @@ -128,19 +145,478 @@ static struct pci_device_id mptfc_pci_table[] = { | |||
| 128 | PCI_ANY_ID, PCI_ANY_ID }, | 145 | PCI_ANY_ID, PCI_ANY_ID }, |
| 129 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X, | 146 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X, |
| 130 | PCI_ANY_ID, PCI_ANY_ID }, | 147 | PCI_ANY_ID, PCI_ANY_ID }, |
| 148 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES, | ||
| 149 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 131 | {0} /* Terminating entry */ | 150 | {0} /* Terminating entry */ |
| 132 | }; | 151 | }; |
| 133 | MODULE_DEVICE_TABLE(pci, mptfc_pci_table); | 152 | MODULE_DEVICE_TABLE(pci, mptfc_pci_table); |
| 134 | 153 | ||
| 135 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 154 | static struct scsi_transport_template *mptfc_transport_template = NULL; |
| 136 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 155 | |
| 156 | struct fc_function_template mptfc_transport_functions = { | ||
| 157 | .dd_fcrport_size = 8, | ||
| 158 | .show_host_node_name = 1, | ||
| 159 | .show_host_port_name = 1, | ||
| 160 | .show_host_supported_classes = 1, | ||
| 161 | .show_host_port_id = 1, | ||
| 162 | .show_rport_supported_classes = 1, | ||
| 163 | .show_starget_node_name = 1, | ||
| 164 | .show_starget_port_name = 1, | ||
| 165 | .show_starget_port_id = 1, | ||
| 166 | .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo, | ||
| 167 | .show_rport_dev_loss_tmo = 1, | ||
| 168 | |||
| 169 | }; | ||
| 170 | |||
| 171 | /* FIXME! values controlling firmware RESCAN event | ||
| 172 | * need to be set low to allow dev_loss_tmo to | ||
| 173 | * work as expected. Currently, firmware doesn't | ||
| 174 | * notify driver of RESCAN event until some number | ||
| 175 | * of seconds elapse. This value can be set via | ||
| 176 | * lsiutil. | ||
| 177 | */ | ||
| 178 | static void | ||
| 179 | mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) | ||
| 180 | { | ||
| 181 | if (timeout > 0) | ||
| 182 | rport->dev_loss_tmo = timeout; | ||
| 183 | else | ||
| 184 | rport->dev_loss_tmo = mptfc_dev_loss_tmo; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int | ||
| 188 | mptfc_FcDevPage0_cmp_func(const void *a, const void *b) | ||
| 189 | { | ||
| 190 | FCDevicePage0_t **aa = (FCDevicePage0_t **)a; | ||
| 191 | FCDevicePage0_t **bb = (FCDevicePage0_t **)b; | ||
| 192 | |||
| 193 | if ((*aa)->CurrentBus == (*bb)->CurrentBus) { | ||
| 194 | if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID) | ||
| 195 | return 0; | ||
| 196 | if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID) | ||
| 197 | return -1; | ||
| 198 | return 1; | ||
| 199 | } | ||
| 200 | if ((*aa)->CurrentBus < (*bb)->CurrentBus) | ||
| 201 | return -1; | ||
| 202 | return 1; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int | ||
| 206 | mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port, | ||
| 207 | void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg)) | ||
| 208 | { | ||
| 209 | ConfigPageHeader_t hdr; | ||
| 210 | CONFIGPARMS cfg; | ||
| 211 | FCDevicePage0_t *ppage0_alloc, *fc; | ||
| 212 | dma_addr_t page0_dma; | ||
| 213 | int data_sz; | ||
| 214 | int ii; | ||
| 215 | |||
| 216 | FCDevicePage0_t *p0_array=NULL, *p_p0; | ||
| 217 | FCDevicePage0_t **pp0_array=NULL, **p_pp0; | ||
| 218 | |||
| 219 | int rc = -ENOMEM; | ||
| 220 | U32 port_id = 0xffffff; | ||
| 221 | int num_targ = 0; | ||
| 222 | int max_bus = ioc->facts.MaxBuses; | ||
| 223 | int max_targ = ioc->facts.MaxDevices; | ||
| 224 | |||
| 225 | if (max_bus == 0 || max_targ == 0) | ||
| 226 | goto out; | ||
| 227 | |||
| 228 | data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ; | ||
| 229 | p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL); | ||
| 230 | if (!p0_array) | ||
| 231 | goto out; | ||
| 232 | |||
| 233 | data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ; | ||
| 234 | p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL); | ||
| 235 | if (!pp0_array) | ||
| 236 | goto out; | ||
| 237 | |||
| 238 | do { | ||
| 239 | /* Get FC Device Page 0 header */ | ||
| 240 | hdr.PageVersion = 0; | ||
| 241 | hdr.PageLength = 0; | ||
| 242 | hdr.PageNumber = 0; | ||
| 243 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE; | ||
| 244 | cfg.cfghdr.hdr = &hdr; | ||
| 245 | cfg.physAddr = -1; | ||
| 246 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 247 | cfg.dir = 0; | ||
| 248 | cfg.pageAddr = port_id; | ||
| 249 | cfg.timeout = 0; | ||
| 250 | |||
| 251 | if ((rc = mpt_config(ioc, &cfg)) != 0) | ||
| 252 | break; | ||
| 253 | |||
| 254 | if (hdr.PageLength <= 0) | ||
| 255 | break; | ||
| 256 | |||
| 257 | data_sz = hdr.PageLength * 4; | ||
| 258 | ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz, | ||
| 259 | &page0_dma); | ||
| 260 | rc = -ENOMEM; | ||
| 261 | if (!ppage0_alloc) | ||
| 262 | break; | ||
| 263 | |||
| 264 | cfg.physAddr = page0_dma; | ||
| 265 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 266 | |||
| 267 | if ((rc = mpt_config(ioc, &cfg)) == 0) { | ||
| 268 | ppage0_alloc->PortIdentifier = | ||
| 269 | le32_to_cpu(ppage0_alloc->PortIdentifier); | ||
| 270 | |||
| 271 | ppage0_alloc->WWNN.Low = | ||
| 272 | le32_to_cpu(ppage0_alloc->WWNN.Low); | ||
| 273 | |||
| 274 | ppage0_alloc->WWNN.High = | ||
| 275 | le32_to_cpu(ppage0_alloc->WWNN.High); | ||
| 276 | |||
| 277 | ppage0_alloc->WWPN.Low = | ||
| 278 | le32_to_cpu(ppage0_alloc->WWPN.Low); | ||
| 279 | |||
| 280 | ppage0_alloc->WWPN.High = | ||
| 281 | le32_to_cpu(ppage0_alloc->WWPN.High); | ||
| 282 | |||
| 283 | ppage0_alloc->BBCredit = | ||
| 284 | le16_to_cpu(ppage0_alloc->BBCredit); | ||
| 285 | |||
| 286 | ppage0_alloc->MaxRxFrameSize = | ||
| 287 | le16_to_cpu(ppage0_alloc->MaxRxFrameSize); | ||
| 288 | |||
| 289 | port_id = ppage0_alloc->PortIdentifier; | ||
| 290 | num_targ++; | ||
| 291 | *p_p0 = *ppage0_alloc; /* save data */ | ||
| 292 | *p_pp0++ = p_p0++; /* save addr */ | ||
| 293 | } | ||
| 294 | pci_free_consistent(ioc->pcidev, data_sz, | ||
| 295 | (u8 *) ppage0_alloc, page0_dma); | ||
| 296 | if (rc != 0) | ||
| 297 | break; | ||
| 298 | |||
| 299 | } while (port_id <= 0xff0000); | ||
| 300 | |||
| 301 | if (num_targ) { | ||
| 302 | /* sort array */ | ||
| 303 | if (num_targ > 1) | ||
| 304 | sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *), | ||
| 305 | mptfc_FcDevPage0_cmp_func, NULL); | ||
| 306 | /* call caller's func for each targ */ | ||
| 307 | for (ii = 0; ii < num_targ; ii++) { | ||
| 308 | fc = *(pp0_array+ii); | ||
| 309 | func(ioc, ioc_port, fc); | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | out: | ||
| 314 | if (pp0_array) | ||
| 315 | kfree(pp0_array); | ||
| 316 | if (p0_array) | ||
| 317 | kfree(p0_array); | ||
| 318 | return rc; | ||
| 319 | } | ||
| 320 | |||
| 321 | static int | ||
| 322 | mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) | ||
| 323 | { | ||
| 324 | /* not currently usable */ | ||
| 325 | if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID | | ||
| 326 | MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID)) | ||
| 327 | return -1; | ||
| 328 | |||
| 329 | if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID)) | ||
| 330 | return -1; | ||
| 331 | |||
| 332 | if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET)) | ||
| 333 | return -1; | ||
| 334 | |||
| 335 | /* | ||
| 336 | * board data structure already normalized to platform endianness | ||
| 337 | * shifted to avoid unaligned access on 64 bit architecture | ||
| 338 | */ | ||
| 339 | rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low; | ||
| 340 | rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low; | ||
| 341 | rid->port_id = pg0->PortIdentifier; | ||
| 342 | rid->roles = FC_RPORT_ROLE_UNKNOWN; | ||
| 343 | rid->roles |= FC_RPORT_ROLE_FCP_TARGET; | ||
| 344 | if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR) | ||
| 345 | rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR; | ||
| 346 | |||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 350 | static void | ||
| 351 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | ||
| 352 | { | ||
| 353 | struct fc_rport_identifiers rport_ids; | ||
| 354 | struct fc_rport *rport; | ||
| 355 | struct mptfc_rport_info *ri; | ||
| 356 | int match = 0; | ||
| 357 | u64 port_name; | ||
| 358 | unsigned long flags; | ||
| 359 | |||
| 360 | if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) | ||
| 361 | return; | ||
| 362 | |||
| 363 | /* scan list looking for a match */ | ||
| 364 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | ||
| 365 | list_for_each_entry(ri, &ioc->fc_rports, list) { | ||
| 366 | port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; | ||
| 367 | if (port_name == rport_ids.port_name) { /* match */ | ||
| 368 | list_move_tail(&ri->list, &ioc->fc_rports); | ||
| 369 | match = 1; | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | if (!match) { /* allocate one */ | ||
| 374 | spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); | ||
| 375 | ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); | ||
| 376 | if (!ri) | ||
| 377 | return; | ||
| 378 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | ||
| 379 | list_add_tail(&ri->list, &ioc->fc_rports); | ||
| 380 | } | ||
| 381 | |||
| 382 | ri->pg0 = *pg0; /* add/update pg0 data */ | ||
| 383 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; | ||
| 384 | |||
| 385 | if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { | ||
| 386 | ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; | ||
| 387 | spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); | ||
| 388 | rport = fc_remote_port_add(ioc->sh,channel, &rport_ids); | ||
| 389 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | ||
| 390 | if (rport) { | ||
| 391 | if (*((struct mptfc_rport_info **)rport->dd_data) != ri) { | ||
| 392 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; | ||
| 393 | ri->vdev = NULL; | ||
| 394 | ri->rport = rport; | ||
| 395 | *((struct mptfc_rport_info **)rport->dd_data) = ri; | ||
| 396 | } | ||
| 397 | rport->dev_loss_tmo = mptfc_dev_loss_tmo; | ||
| 398 | /* | ||
| 399 | * if already mapped, remap here. If not mapped, | ||
| 400 | * slave_alloc will allocate vdev and map | ||
| 401 | */ | ||
| 402 | if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) { | ||
| 403 | ri->vdev->target_id = ri->pg0.CurrentTargetID; | ||
| 404 | ri->vdev->bus_id = ri->pg0.CurrentBus; | ||
| 405 | ri->vdev->vtarget->target_id = ri->vdev->target_id; | ||
| 406 | ri->vdev->vtarget->bus_id = ri->vdev->bus_id; | ||
| 407 | } | ||
| 408 | #ifdef MPT_DEBUG | ||
| 409 | printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " | ||
| 410 | "rport tid %d, tmo %d\n", | ||
| 411 | ioc->sh->host_no, | ||
| 412 | pg0->PortIdentifier, | ||
| 413 | pg0->WWNN, | ||
| 414 | pg0->WWPN, | ||
| 415 | pg0->CurrentTargetID, | ||
| 416 | ri->rport->scsi_target_id, | ||
| 417 | ri->rport->dev_loss_tmo); | ||
| 418 | #endif | ||
| 419 | } else { | ||
| 420 | list_del(&ri->list); | ||
| 421 | kfree(ri); | ||
| 422 | ri = NULL; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); | ||
| 426 | |||
| 427 | } | ||
| 428 | |||
| 137 | /* | 429 | /* |
| 138 | * mptfc_probe - Installs scsi devices per bus. | 430 | * OS entry point to allow host driver to alloc memory |
| 139 | * @pdev: Pointer to pci_dev structure | 431 | * for each scsi device. Called once per device the bus scan. |
| 140 | * | 432 | * Return non-zero if allocation fails. |
| 141 | * Returns 0 for success, non-zero for failure. | 433 | * Init memory once per LUN. |
| 142 | * | ||
| 143 | */ | 434 | */ |
| 435 | int | ||
| 436 | mptfc_slave_alloc(struct scsi_device *sdev) | ||
| 437 | { | ||
| 438 | MPT_SCSI_HOST *hd; | ||
| 439 | VirtTarget *vtarget; | ||
| 440 | VirtDevice *vdev; | ||
| 441 | struct scsi_target *starget; | ||
| 442 | struct fc_rport *rport; | ||
| 443 | struct mptfc_rport_info *ri; | ||
| 444 | unsigned long flags; | ||
| 445 | |||
| 446 | |||
| 447 | rport = starget_to_rport(scsi_target(sdev)); | ||
| 448 | |||
| 449 | if (!rport || fc_remote_port_chkready(rport)) | ||
| 450 | return -ENXIO; | ||
| 451 | |||
| 452 | hd = (MPT_SCSI_HOST *)sdev->host->hostdata; | ||
| 453 | |||
| 454 | vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); | ||
| 455 | if (!vdev) { | ||
| 456 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | ||
| 457 | hd->ioc->name, sizeof(VirtDevice)); | ||
| 458 | return -ENOMEM; | ||
| 459 | } | ||
| 460 | memset(vdev, 0, sizeof(VirtDevice)); | ||
| 461 | |||
| 462 | spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags); | ||
| 463 | |||
| 464 | if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) { | ||
| 465 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); | ||
| 466 | kfree(vdev); | ||
| 467 | return -ENODEV; | ||
| 468 | } | ||
| 469 | |||
| 470 | sdev->hostdata = vdev; | ||
| 471 | starget = scsi_target(sdev); | ||
| 472 | vtarget = starget->hostdata; | ||
| 473 | if (vtarget->num_luns == 0) { | ||
| 474 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES | | ||
| 475 | MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
| 476 | hd->Targets[sdev->id] = vtarget; | ||
| 477 | } | ||
| 478 | |||
| 479 | vtarget->target_id = vdev->target_id; | ||
| 480 | vtarget->bus_id = vdev->bus_id; | ||
| 481 | |||
| 482 | vdev->vtarget = vtarget; | ||
| 483 | vdev->ioc_id = hd->ioc->id; | ||
| 484 | vdev->lun = sdev->lun; | ||
| 485 | vdev->target_id = ri->pg0.CurrentTargetID; | ||
| 486 | vdev->bus_id = ri->pg0.CurrentBus; | ||
| 487 | |||
| 488 | ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; | ||
| 489 | ri->vdev = vdev; | ||
| 490 | |||
| 491 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); | ||
| 492 | |||
| 493 | vtarget->num_luns++; | ||
| 494 | |||
| 495 | #ifdef MPT_DEBUG | ||
| 496 | printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " | ||
| 497 | "CurrentTargetID %d, %x %llx %llx\n", | ||
| 498 | sdev->host->host_no, | ||
| 499 | vtarget->num_luns, | ||
| 500 | sdev->id, ri->pg0.CurrentTargetID, | ||
| 501 | ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN); | ||
| 502 | #endif | ||
| 503 | |||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | |||
| 507 | static int | ||
| 508 | mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | ||
| 509 | { | ||
| 510 | struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); | ||
| 511 | int err; | ||
| 512 | |||
| 513 | err = fc_remote_port_chkready(rport); | ||
| 514 | if (unlikely(err)) { | ||
| 515 | SCpnt->result = err; | ||
| 516 | done(SCpnt); | ||
| 517 | return 0; | ||
| 518 | } | ||
| 519 | return mptscsih_qcmd(SCpnt,done); | ||
| 520 | } | ||
| 521 | |||
| 522 | static void | ||
| 523 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) | ||
| 524 | { | ||
| 525 | unsigned class = 0, cos = 0; | ||
| 526 | |||
| 527 | /* don't know what to do as only one scsi (fc) host was allocated */ | ||
| 528 | if (portnum != 0) | ||
| 529 | return; | ||
| 530 | |||
| 531 | class = ioc->fc_port_page0[portnum].SupportedServiceClass; | ||
| 532 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1) | ||
| 533 | cos |= FC_COS_CLASS1; | ||
| 534 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2) | ||
| 535 | cos |= FC_COS_CLASS2; | ||
| 536 | if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3) | ||
| 537 | cos |= FC_COS_CLASS3; | ||
| 538 | |||
| 539 | fc_host_node_name(ioc->sh) = | ||
| 540 | (u64)ioc->fc_port_page0[portnum].WWNN.High << 32 | ||
| 541 | | (u64)ioc->fc_port_page0[portnum].WWNN.Low; | ||
| 542 | |||
| 543 | fc_host_port_name(ioc->sh) = | ||
| 544 | (u64)ioc->fc_port_page0[portnum].WWPN.High << 32 | ||
| 545 | | (u64)ioc->fc_port_page0[portnum].WWPN.Low; | ||
| 546 | |||
| 547 | fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier; | ||
| 548 | |||
| 549 | fc_host_supported_classes(ioc->sh) = cos; | ||
| 550 | |||
| 551 | fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN; | ||
| 552 | } | ||
| 553 | |||
| 554 | static void | ||
| 555 | mptfc_rescan_devices(void *arg) | ||
| 556 | { | ||
| 557 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; | ||
| 558 | int ii; | ||
| 559 | int work_to_do; | ||
| 560 | unsigned long flags; | ||
| 561 | struct mptfc_rport_info *ri; | ||
| 562 | |||
| 563 | do { | ||
| 564 | /* start by tagging all ports as missing */ | ||
| 565 | spin_lock_irqsave(&ioc->fc_rport_lock,flags); | ||
| 566 | list_for_each_entry(ri, &ioc->fc_rports, list) { | ||
| 567 | if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { | ||
| 568 | ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING; | ||
| 569 | } | ||
| 570 | } | ||
| 571 | spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); | ||
| 572 | |||
| 573 | /* | ||
| 574 | * now rescan devices known to adapter, | ||
| 575 | * will reregister existing rports | ||
| 576 | */ | ||
| 577 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | ||
| 578 | (void) mptbase_GetFcPortPage0(ioc, ii); | ||
| 579 | mptfc_init_host_attr(ioc,ii); /* refresh */ | ||
| 580 | mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); | ||
| 581 | } | ||
| 582 | |||
| 583 | /* delete devices still missing */ | ||
| 584 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | ||
| 585 | list_for_each_entry(ri, &ioc->fc_rports, list) { | ||
| 586 | /* if newly missing, delete it */ | ||
| 587 | if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED | | ||
| 588 | MPT_RPORT_INFO_FLAGS_MISSING)) | ||
| 589 | == (MPT_RPORT_INFO_FLAGS_REGISTERED | | ||
| 590 | MPT_RPORT_INFO_FLAGS_MISSING)) { | ||
| 591 | |||
| 592 | ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| | ||
| 593 | MPT_RPORT_INFO_FLAGS_MISSING); | ||
| 594 | fc_remote_port_delete(ri->rport); | ||
| 595 | /* | ||
| 596 | * remote port not really deleted 'cause | ||
| 597 | * binding is by WWPN and driver only | ||
| 598 | * registers FCP_TARGETs | ||
| 599 | */ | ||
| 600 | #ifdef MPT_DEBUG | ||
| 601 | printk ("mptfc_rescan.%d: %llx deleted\n", | ||
| 602 | ioc->sh->host_no, ri->pg0.WWPN); | ||
| 603 | #endif | ||
| 604 | } | ||
| 605 | } | ||
| 606 | spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); | ||
| 607 | |||
| 608 | /* | ||
| 609 | * allow multiple passes as target state | ||
| 610 | * might have changed during scan | ||
| 611 | */ | ||
| 612 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | ||
| 613 | if (ioc->fc_rescan_work_count > 2) /* only need one more */ | ||
| 614 | ioc->fc_rescan_work_count = 2; | ||
| 615 | work_to_do = --ioc->fc_rescan_work_count; | ||
| 616 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | ||
| 617 | } while (work_to_do); | ||
| 618 | } | ||
| 619 | |||
| 144 | static int | 620 | static int |
| 145 | mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 621 | mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 146 | { | 622 | { |
| @@ -148,17 +624,16 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 148 | MPT_SCSI_HOST *hd; | 624 | MPT_SCSI_HOST *hd; |
| 149 | MPT_ADAPTER *ioc; | 625 | MPT_ADAPTER *ioc; |
| 150 | unsigned long flags; | 626 | unsigned long flags; |
| 151 | int sz, ii; | 627 | int ii; |
| 152 | int numSGE = 0; | 628 | int numSGE = 0; |
| 153 | int scale; | 629 | int scale; |
| 154 | int ioc_cap; | 630 | int ioc_cap; |
| 155 | u8 *mem; | ||
| 156 | int error=0; | 631 | int error=0; |
| 157 | int r; | 632 | int r; |
| 158 | 633 | ||
| 159 | if ((r = mpt_attach(pdev,id)) != 0) | 634 | if ((r = mpt_attach(pdev,id)) != 0) |
| 160 | return r; | 635 | return r; |
| 161 | 636 | ||
| 162 | ioc = pci_get_drvdata(pdev); | 637 | ioc = pci_get_drvdata(pdev); |
| 163 | ioc->DoneCtx = mptfcDoneCtx; | 638 | ioc->DoneCtx = mptfcDoneCtx; |
| 164 | ioc->TaskCtx = mptfcTaskCtx; | 639 | ioc->TaskCtx = mptfcTaskCtx; |
| @@ -194,7 +669,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 194 | printk(MYIOC_s_WARN_FMT | 669 | printk(MYIOC_s_WARN_FMT |
| 195 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", | 670 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", |
| 196 | ioc->name, ioc); | 671 | ioc->name, ioc); |
| 197 | return 0; | 672 | return -ENODEV; |
| 198 | } | 673 | } |
| 199 | 674 | ||
| 200 | sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); | 675 | sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); |
| @@ -207,6 +682,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 207 | goto out_mptfc_probe; | 682 | goto out_mptfc_probe; |
| 208 | } | 683 | } |
| 209 | 684 | ||
| 685 | INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); | ||
| 686 | |||
| 210 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 687 | spin_lock_irqsave(&ioc->FreeQlock, flags); |
| 211 | 688 | ||
| 212 | /* Attach the SCSI Host to the IOC structure | 689 | /* Attach the SCSI Host to the IOC structure |
| @@ -268,36 +745,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 268 | /* SCSI needs scsi_cmnd lookup table! | 745 | /* SCSI needs scsi_cmnd lookup table! |
| 269 | * (with size equal to req_depth*PtrSz!) | 746 | * (with size equal to req_depth*PtrSz!) |
| 270 | */ | 747 | */ |
| 271 | sz = ioc->req_depth * sizeof(void *); | 748 | hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); |
| 272 | mem = kmalloc(sz, GFP_ATOMIC); | 749 | if (!hd->ScsiLookup) { |
| 273 | if (mem == NULL) { | ||
| 274 | error = -ENOMEM; | 750 | error = -ENOMEM; |
| 275 | goto out_mptfc_probe; | 751 | goto out_mptfc_probe; |
| 276 | } | 752 | } |
| 277 | 753 | ||
| 278 | memset(mem, 0, sz); | 754 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", |
| 279 | hd->ScsiLookup = (struct scsi_cmnd **) mem; | 755 | ioc->name, hd->ScsiLookup)); |
| 280 | |||
| 281 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", | ||
| 282 | ioc->name, hd->ScsiLookup, sz)); | ||
| 283 | 756 | ||
| 284 | /* Allocate memory for the device structures. | 757 | /* Allocate memory for the device structures. |
| 285 | * A non-Null pointer at an offset | 758 | * A non-Null pointer at an offset |
| 286 | * indicates a device exists. | 759 | * indicates a device exists. |
| 287 | * max_id = 1 + maximum id (hosts.h) | 760 | * max_id = 1 + maximum id (hosts.h) |
| 288 | */ | 761 | */ |
| 289 | sz = sh->max_id * sizeof(void *); | 762 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); |
| 290 | mem = kmalloc(sz, GFP_ATOMIC); | 763 | if (!hd->Targets) { |
| 291 | if (mem == NULL) { | ||
| 292 | error = -ENOMEM; | 764 | error = -ENOMEM; |
| 293 | goto out_mptfc_probe; | 765 | goto out_mptfc_probe; |
| 294 | } | 766 | } |
| 295 | 767 | ||
| 296 | memset(mem, 0, sz); | 768 | dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); |
| 297 | hd->Targets = (VirtTarget **) mem; | ||
| 298 | |||
| 299 | dprintk((KERN_INFO | ||
| 300 | " vdev @ %p, sz=%d\n", hd->Targets, sz)); | ||
| 301 | 769 | ||
| 302 | /* Clear the TM flags | 770 | /* Clear the TM flags |
| 303 | */ | 771 | */ |
| @@ -332,6 +800,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 332 | hd->scandv_wait_done = 0; | 800 | hd->scandv_wait_done = 0; |
| 333 | hd->last_queue_full = 0; | 801 | hd->last_queue_full = 0; |
| 334 | 802 | ||
| 803 | sh->transportt = mptfc_transport_template; | ||
| 335 | error = scsi_add_host (sh, &ioc->pcidev->dev); | 804 | error = scsi_add_host (sh, &ioc->pcidev->dev); |
| 336 | if(error) { | 805 | if(error) { |
| 337 | dprintk((KERN_ERR MYNAM | 806 | dprintk((KERN_ERR MYNAM |
| @@ -339,7 +808,11 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 339 | goto out_mptfc_probe; | 808 | goto out_mptfc_probe; |
| 340 | } | 809 | } |
| 341 | 810 | ||
| 342 | scsi_scan_host(sh); | 811 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { |
| 812 | mptfc_init_host_attr(ioc,ii); | ||
| 813 | mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); | ||
| 814 | } | ||
| 815 | |||
| 343 | return 0; | 816 | return 0; |
| 344 | 817 | ||
| 345 | out_mptfc_probe: | 818 | out_mptfc_probe: |
| @@ -352,7 +825,7 @@ static struct pci_driver mptfc_driver = { | |||
| 352 | .name = "mptfc", | 825 | .name = "mptfc", |
| 353 | .id_table = mptfc_pci_table, | 826 | .id_table = mptfc_pci_table, |
| 354 | .probe = mptfc_probe, | 827 | .probe = mptfc_probe, |
| 355 | .remove = __devexit_p(mptscsih_remove), | 828 | .remove = __devexit_p(mptfc_remove), |
| 356 | .shutdown = mptscsih_shutdown, | 829 | .shutdown = mptscsih_shutdown, |
| 357 | #ifdef CONFIG_PM | 830 | #ifdef CONFIG_PM |
| 358 | .suspend = mptscsih_suspend, | 831 | .suspend = mptscsih_suspend, |
| @@ -370,9 +843,20 @@ static struct pci_driver mptfc_driver = { | |||
| 370 | static int __init | 843 | static int __init |
| 371 | mptfc_init(void) | 844 | mptfc_init(void) |
| 372 | { | 845 | { |
| 846 | int error; | ||
| 373 | 847 | ||
| 374 | show_mptmod_ver(my_NAME, my_VERSION); | 848 | show_mptmod_ver(my_NAME, my_VERSION); |
| 375 | 849 | ||
| 850 | /* sanity check module parameter */ | ||
| 851 | if (mptfc_dev_loss_tmo == 0) | ||
| 852 | mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; | ||
| 853 | |||
| 854 | mptfc_transport_template = | ||
| 855 | fc_attach_transport(&mptfc_transport_functions); | ||
| 856 | |||
| 857 | if (!mptfc_transport_template) | ||
| 858 | return -ENODEV; | ||
| 859 | |||
| 376 | mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); | 860 | mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); |
| 377 | mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); | 861 | mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); |
| 378 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); | 862 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); |
| @@ -387,7 +871,33 @@ mptfc_init(void) | |||
| 387 | ": Registered for IOC reset notifications\n")); | 871 | ": Registered for IOC reset notifications\n")); |
| 388 | } | 872 | } |
| 389 | 873 | ||
| 390 | return pci_register_driver(&mptfc_driver); | 874 | error = pci_register_driver(&mptfc_driver); |
| 875 | if (error) { | ||
| 876 | fc_release_transport(mptfc_transport_template); | ||
| 877 | } | ||
| 878 | |||
| 879 | return error; | ||
| 880 | } | ||
| 881 | |||
| 882 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 883 | /** | ||
| 884 | * mptfc_remove - Removed fc infrastructure for devices | ||
| 885 | * @pdev: Pointer to pci_dev structure | ||
| 886 | * | ||
| 887 | */ | ||
| 888 | static void __devexit mptfc_remove(struct pci_dev *pdev) | ||
| 889 | { | ||
| 890 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | ||
| 891 | struct mptfc_rport_info *p, *n; | ||
| 892 | |||
| 893 | fc_remove_host(ioc->sh); | ||
| 894 | |||
| 895 | list_for_each_entry_safe(p, n, &ioc->fc_rports, list) { | ||
| 896 | list_del(&p->list); | ||
| 897 | kfree(p); | ||
| 898 | } | ||
| 899 | |||
| 900 | mptscsih_remove(pdev); | ||
| 391 | } | 901 | } |
| 392 | 902 | ||
| 393 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 903 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| @@ -400,7 +910,8 @@ static void __exit | |||
| 400 | mptfc_exit(void) | 910 | mptfc_exit(void) |
| 401 | { | 911 | { |
| 402 | pci_unregister_driver(&mptfc_driver); | 912 | pci_unregister_driver(&mptfc_driver); |
| 403 | 913 | fc_release_transport(mptfc_transport_template); | |
| 914 | |||
| 404 | mpt_reset_deregister(mptfcDoneCtx); | 915 | mpt_reset_deregister(mptfcDoneCtx); |
| 405 | dprintk((KERN_INFO MYNAM | 916 | dprintk((KERN_INFO MYNAM |
| 406 | ": Deregistered for IOC reset notifications\n")); | 917 | ": Deregistered for IOC reset notifications\n")); |
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 014085d8ec85..73f59528212a 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c | |||
| @@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev) | |||
| 411 | goto out; | 411 | goto out; |
| 412 | priv->mpt_txfidx_tail = -1; | 412 | priv->mpt_txfidx_tail = -1; |
| 413 | 413 | ||
| 414 | priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl), | 414 | priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl), |
| 415 | GFP_KERNEL); | 415 | GFP_KERNEL); |
| 416 | if (priv->SendCtl == NULL) | 416 | if (priv->SendCtl == NULL) |
| 417 | goto out_mpt_txfidx; | 417 | goto out_mpt_txfidx; |
| 418 | for (i = 0; i < priv->tx_max_out; i++) { | 418 | for (i = 0; i < priv->tx_max_out; i++) |
| 419 | memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl)); | ||
| 420 | priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i; | 419 | priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i; |
| 421 | } | ||
| 422 | 420 | ||
| 423 | dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); | 421 | dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); |
| 424 | 422 | ||
| @@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev) | |||
| 428 | goto out_SendCtl; | 426 | goto out_SendCtl; |
| 429 | priv->mpt_rxfidx_tail = -1; | 427 | priv->mpt_rxfidx_tail = -1; |
| 430 | 428 | ||
| 431 | priv->RcvCtl = kmalloc(priv->max_buckets_out * | 429 | priv->RcvCtl = kcalloc(priv->max_buckets_out, |
| 432 | sizeof(struct BufferControl), | 430 | sizeof(struct BufferControl), |
| 433 | GFP_KERNEL); | 431 | GFP_KERNEL); |
| 434 | if (priv->RcvCtl == NULL) | 432 | if (priv->RcvCtl == NULL) |
| 435 | goto out_mpt_rxfidx; | 433 | goto out_mpt_rxfidx; |
| 436 | for (i = 0; i < priv->max_buckets_out; i++) { | 434 | for (i = 0; i < priv->max_buckets_out; i++) |
| 437 | memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl)); | ||
| 438 | priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; | 435 | priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; |
| 439 | } | ||
| 440 | 436 | ||
| 441 | /**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - ")); | 437 | /**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - ")); |
| 442 | /**/ for (i = 0; i < priv->tx_max_out; i++) | 438 | /**/ for (i = 0; i < priv->tx_max_out; i++) |
| @@ -848,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) | |||
| 848 | } | 844 | } |
| 849 | 845 | ||
| 850 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 846 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 851 | static inline void | 847 | static void |
| 852 | mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) | 848 | mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) |
| 853 | /* | 849 | /* |
| 854 | * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue | 850 | * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue |
| @@ -870,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) | |||
| 870 | } | 866 | } |
| 871 | 867 | ||
| 872 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 868 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 873 | static inline int | 869 | static int |
| 874 | mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) | 870 | mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) |
| 875 | { | 871 | { |
| 876 | struct mpt_lan_priv *priv = dev->priv; | 872 | struct mpt_lan_priv *priv = dev->priv; |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 17e9757e728b..5a06d8d8694e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * Copyright (c) 1999-2005 LSI Logic Corporation | 6 | * Copyright (c) 1999-2005 LSI Logic Corporation |
| 7 | * (mailto:mpt_linux_developer@lsil.com) | 7 | * (mailto:mpt_linux_developer@lsil.com) |
| 8 | * Copyright (c) 2005 Dell | 8 | * Copyright (c) 2005-2006 Dell |
| 9 | */ | 9 | */ |
| 10 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 10 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 11 | /* | 11 | /* |
| @@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */ | |||
| 86 | static int mptsasMgmtCtx = -1; | 86 | static int mptsasMgmtCtx = -1; |
| 87 | 87 | ||
| 88 | 88 | ||
| 89 | enum mptsas_hotplug_action { | ||
| 90 | MPTSAS_ADD_DEVICE, | ||
| 91 | MPTSAS_DEL_DEVICE, | ||
| 92 | }; | ||
| 93 | |||
| 94 | struct mptsas_hotplug_event { | ||
| 95 | struct work_struct work; | ||
| 96 | MPT_ADAPTER *ioc; | ||
| 97 | enum mptsas_hotplug_action event_type; | ||
| 98 | u64 sas_address; | ||
| 99 | u32 channel; | ||
| 100 | u32 id; | ||
| 101 | u32 device_info; | ||
| 102 | u16 handle; | ||
| 103 | u16 parent_handle; | ||
| 104 | u8 phy_id; | ||
| 105 | }; | ||
| 106 | |||
| 89 | /* | 107 | /* |
| 90 | * SAS topology structures | 108 | * SAS topology structures |
| 91 | * | 109 | * |
| @@ -99,8 +117,8 @@ struct mptsas_devinfo { | |||
| 99 | u8 phy_id; /* phy number of parent device */ | 117 | u8 phy_id; /* phy number of parent device */ |
| 100 | u8 port_id; /* sas physical port this device | 118 | u8 port_id; /* sas physical port this device |
| 101 | is assoc'd with */ | 119 | is assoc'd with */ |
| 102 | u8 target; /* logical target id of this device */ | 120 | u8 id; /* logical target id of this device */ |
| 103 | u8 bus; /* logical bus number of this device */ | 121 | u8 channel; /* logical bus number of this device */ |
| 104 | u64 sas_address; /* WWN of this device, | 122 | u64 sas_address; /* WWN of this device, |
| 105 | SATA is assigned by HBA,expander */ | 123 | SATA is assigned by HBA,expander */ |
| 106 | u32 device_info; /* bitfield detailed info about this device */ | 124 | u32 device_info; /* bitfield detailed info about this device */ |
| @@ -114,6 +132,7 @@ struct mptsas_phyinfo { | |||
| 114 | u8 programmed_link_rate; /* programmed max/min phy link rate */ | 132 | u8 programmed_link_rate; /* programmed max/min phy link rate */ |
| 115 | struct mptsas_devinfo identify; /* point to phy device info */ | 133 | struct mptsas_devinfo identify; /* point to phy device info */ |
| 116 | struct mptsas_devinfo attached; /* point to attached device info */ | 134 | struct mptsas_devinfo attached; /* point to attached device info */ |
| 135 | struct sas_phy *phy; | ||
| 117 | struct sas_rphy *rphy; | 136 | struct sas_rphy *rphy; |
| 118 | }; | 137 | }; |
| 119 | 138 | ||
| @@ -239,13 +258,12 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
| 239 | struct scsi_target *starget; | 258 | struct scsi_target *starget; |
| 240 | int i; | 259 | int i; |
| 241 | 260 | ||
| 242 | vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); | 261 | vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); |
| 243 | if (!vdev) { | 262 | if (!vdev) { |
| 244 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | 263 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", |
| 245 | hd->ioc->name, sizeof(VirtDevice)); | 264 | hd->ioc->name, sizeof(VirtDevice)); |
| 246 | return -ENOMEM; | 265 | return -ENOMEM; |
| 247 | } | 266 | } |
| 248 | memset(vdev, 0, sizeof(VirtDevice)); | ||
| 249 | vdev->ioc_id = hd->ioc->id; | 267 | vdev->ioc_id = hd->ioc->id; |
| 250 | sdev->hostdata = vdev; | 268 | sdev->hostdata = vdev; |
| 251 | starget = scsi_target(sdev); | 269 | starget = scsi_target(sdev); |
| @@ -256,19 +274,32 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
| 256 | hd->Targets[sdev->id] = vtarget; | 274 | hd->Targets[sdev->id] = vtarget; |
| 257 | } | 275 | } |
| 258 | 276 | ||
| 277 | /* | ||
| 278 | RAID volumes placed beyond the last expected port. | ||
| 279 | */ | ||
| 280 | if (sdev->channel == hd->ioc->num_ports) { | ||
| 281 | vdev->target_id = sdev->id; | ||
| 282 | vdev->bus_id = 0; | ||
| 283 | vdev->lun = 0; | ||
| 284 | goto out; | ||
| 285 | } | ||
| 286 | |||
| 259 | rphy = dev_to_rphy(sdev->sdev_target->dev.parent); | 287 | rphy = dev_to_rphy(sdev->sdev_target->dev.parent); |
| 288 | mutex_lock(&hd->ioc->sas_topology_mutex); | ||
| 260 | list_for_each_entry(p, &hd->ioc->sas_topology, list) { | 289 | list_for_each_entry(p, &hd->ioc->sas_topology, list) { |
| 261 | for (i = 0; i < p->num_phys; i++) { | 290 | for (i = 0; i < p->num_phys; i++) { |
| 262 | if (p->phy_info[i].attached.sas_address == | 291 | if (p->phy_info[i].attached.sas_address == |
| 263 | rphy->identify.sas_address) { | 292 | rphy->identify.sas_address) { |
| 264 | vdev->target_id = | 293 | vdev->target_id = |
| 265 | p->phy_info[i].attached.target; | 294 | p->phy_info[i].attached.id; |
| 266 | vdev->bus_id = p->phy_info[i].attached.bus; | 295 | vdev->bus_id = p->phy_info[i].attached.channel; |
| 267 | vdev->lun = sdev->lun; | 296 | vdev->lun = sdev->lun; |
| 297 | mutex_unlock(&hd->ioc->sas_topology_mutex); | ||
| 268 | goto out; | 298 | goto out; |
| 269 | } | 299 | } |
| 270 | } | 300 | } |
| 271 | } | 301 | } |
| 302 | mutex_unlock(&hd->ioc->sas_topology_mutex); | ||
| 272 | 303 | ||
| 273 | printk("No matching SAS device found!!\n"); | 304 | printk("No matching SAS device found!!\n"); |
| 274 | kfree(vdev); | 305 | kfree(vdev); |
| @@ -282,6 +313,42 @@ mptsas_slave_alloc(struct scsi_device *sdev) | |||
| 282 | return 0; | 313 | return 0; |
| 283 | } | 314 | } |
| 284 | 315 | ||
| 316 | static void | ||
| 317 | mptsas_slave_destroy(struct scsi_device *sdev) | ||
| 318 | { | ||
| 319 | struct Scsi_Host *host = sdev->host; | ||
| 320 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
| 321 | struct sas_rphy *rphy; | ||
| 322 | struct mptsas_portinfo *p; | ||
| 323 | int i; | ||
| 324 | |||
| 325 | /* | ||
| 326 | * Handle hotplug removal case. | ||
| 327 | * We need to clear out attached data structure. | ||
| 328 | */ | ||
| 329 | rphy = dev_to_rphy(sdev->sdev_target->dev.parent); | ||
| 330 | |||
| 331 | mutex_lock(&hd->ioc->sas_topology_mutex); | ||
| 332 | list_for_each_entry(p, &hd->ioc->sas_topology, list) { | ||
| 333 | for (i = 0; i < p->num_phys; i++) { | ||
| 334 | if (p->phy_info[i].attached.sas_address == | ||
| 335 | rphy->identify.sas_address) { | ||
| 336 | memset(&p->phy_info[i].attached, 0, | ||
| 337 | sizeof(struct mptsas_devinfo)); | ||
| 338 | p->phy_info[i].rphy = NULL; | ||
| 339 | goto out; | ||
| 340 | } | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | out: | ||
| 345 | mutex_unlock(&hd->ioc->sas_topology_mutex); | ||
| 346 | /* | ||
| 347 | * TODO: Issue target reset to flush firmware outstanding commands. | ||
| 348 | */ | ||
| 349 | mptscsih_slave_destroy(sdev); | ||
| 350 | } | ||
| 351 | |||
| 285 | static struct scsi_host_template mptsas_driver_template = { | 352 | static struct scsi_host_template mptsas_driver_template = { |
| 286 | .module = THIS_MODULE, | 353 | .module = THIS_MODULE, |
| 287 | .proc_name = "mptsas", | 354 | .proc_name = "mptsas", |
| @@ -293,7 +360,7 @@ static struct scsi_host_template mptsas_driver_template = { | |||
| 293 | .slave_alloc = mptsas_slave_alloc, | 360 | .slave_alloc = mptsas_slave_alloc, |
| 294 | .slave_configure = mptscsih_slave_configure, | 361 | .slave_configure = mptscsih_slave_configure, |
| 295 | .target_destroy = mptscsih_target_destroy, | 362 | .target_destroy = mptscsih_target_destroy, |
| 296 | .slave_destroy = mptscsih_slave_destroy, | 363 | .slave_destroy = mptsas_slave_destroy, |
| 297 | .change_queue_depth = mptscsih_change_queue_depth, | 364 | .change_queue_depth = mptscsih_change_queue_depth, |
| 298 | .eh_abort_handler = mptscsih_abort, | 365 | .eh_abort_handler = mptscsih_abort, |
| 299 | .eh_device_reset_handler = mptscsih_dev_reset, | 366 | .eh_device_reset_handler = mptscsih_dev_reset, |
| @@ -399,7 +466,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | |||
| 399 | if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP) | 466 | if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP) |
| 400 | return -ENXIO; | 467 | return -ENXIO; |
| 401 | 468 | ||
| 402 | if (down_interruptible(&ioc->sas_mgmt.mutex)) | 469 | if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex)) |
| 403 | goto out; | 470 | goto out; |
| 404 | 471 | ||
| 405 | mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc); | 472 | mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc); |
| @@ -450,7 +517,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) | |||
| 450 | error = 0; | 517 | error = 0; |
| 451 | 518 | ||
| 452 | out_unlock: | 519 | out_unlock: |
| 453 | up(&ioc->sas_mgmt.mutex); | 520 | mutex_unlock(&ioc->sas_mgmt.mutex); |
| 454 | out: | 521 | out: |
| 455 | return error; | 522 | return error; |
| 456 | } | 523 | } |
| @@ -649,8 +716,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | |||
| 649 | device_info->handle = le16_to_cpu(buffer->DevHandle); | 716 | device_info->handle = le16_to_cpu(buffer->DevHandle); |
| 650 | device_info->phy_id = buffer->PhyNum; | 717 | device_info->phy_id = buffer->PhyNum; |
| 651 | device_info->port_id = buffer->PhysicalPort; | 718 | device_info->port_id = buffer->PhysicalPort; |
| 652 | device_info->target = buffer->TargetID; | 719 | device_info->id = buffer->TargetID; |
| 653 | device_info->bus = buffer->Bus; | 720 | device_info->channel = buffer->Bus; |
| 654 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | 721 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); |
| 655 | device_info->sas_address = le64_to_cpu(sas_address); | 722 | device_info->sas_address = le64_to_cpu(sas_address); |
| 656 | device_info->device_info = | 723 | device_info->device_info = |
| @@ -858,36 +925,36 @@ mptsas_parse_device_info(struct sas_identify *identify, | |||
| 858 | static int mptsas_probe_one_phy(struct device *dev, | 925 | static int mptsas_probe_one_phy(struct device *dev, |
| 859 | struct mptsas_phyinfo *phy_info, int index, int local) | 926 | struct mptsas_phyinfo *phy_info, int index, int local) |
| 860 | { | 927 | { |
| 861 | struct sas_phy *port; | 928 | struct sas_phy *phy; |
| 862 | int error; | 929 | int error; |
| 863 | 930 | ||
| 864 | port = sas_phy_alloc(dev, index); | 931 | phy = sas_phy_alloc(dev, index); |
| 865 | if (!port) | 932 | if (!phy) |
| 866 | return -ENOMEM; | 933 | return -ENOMEM; |
| 867 | 934 | ||
| 868 | port->port_identifier = phy_info->port_id; | 935 | phy->port_identifier = phy_info->port_id; |
| 869 | mptsas_parse_device_info(&port->identify, &phy_info->identify); | 936 | mptsas_parse_device_info(&phy->identify, &phy_info->identify); |
| 870 | 937 | ||
| 871 | /* | 938 | /* |
| 872 | * Set Negotiated link rate. | 939 | * Set Negotiated link rate. |
| 873 | */ | 940 | */ |
| 874 | switch (phy_info->negotiated_link_rate) { | 941 | switch (phy_info->negotiated_link_rate) { |
| 875 | case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: | 942 | case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: |
| 876 | port->negotiated_linkrate = SAS_PHY_DISABLED; | 943 | phy->negotiated_linkrate = SAS_PHY_DISABLED; |
| 877 | break; | 944 | break; |
| 878 | case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: | 945 | case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: |
| 879 | port->negotiated_linkrate = SAS_LINK_RATE_FAILED; | 946 | phy->negotiated_linkrate = SAS_LINK_RATE_FAILED; |
| 880 | break; | 947 | break; |
| 881 | case MPI_SAS_IOUNIT0_RATE_1_5: | 948 | case MPI_SAS_IOUNIT0_RATE_1_5: |
| 882 | port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; | 949 | phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; |
| 883 | break; | 950 | break; |
| 884 | case MPI_SAS_IOUNIT0_RATE_3_0: | 951 | case MPI_SAS_IOUNIT0_RATE_3_0: |
| 885 | port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; | 952 | phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; |
| 886 | break; | 953 | break; |
| 887 | case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: | 954 | case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: |
| 888 | case MPI_SAS_IOUNIT0_RATE_UNKNOWN: | 955 | case MPI_SAS_IOUNIT0_RATE_UNKNOWN: |
| 889 | default: | 956 | default: |
| 890 | port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; | 957 | phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; |
| 891 | break; | 958 | break; |
| 892 | } | 959 | } |
| 893 | 960 | ||
| @@ -896,10 +963,10 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 896 | */ | 963 | */ |
| 897 | switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { | 964 | switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { |
| 898 | case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: | 965 | case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: |
| 899 | port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; | 966 | phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; |
| 900 | break; | 967 | break; |
| 901 | case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: | 968 | case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: |
| 902 | port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; | 969 | phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; |
| 903 | break; | 970 | break; |
| 904 | default: | 971 | default: |
| 905 | break; | 972 | break; |
| @@ -911,10 +978,10 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 911 | switch (phy_info->programmed_link_rate & | 978 | switch (phy_info->programmed_link_rate & |
| 912 | MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { | 979 | MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { |
| 913 | case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: | 980 | case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: |
| 914 | port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; | 981 | phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; |
| 915 | break; | 982 | break; |
| 916 | case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: | 983 | case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: |
| 917 | port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; | 984 | phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; |
| 918 | break; | 985 | break; |
| 919 | default: | 986 | default: |
| 920 | break; | 987 | break; |
| @@ -925,10 +992,10 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 925 | */ | 992 | */ |
| 926 | switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { | 993 | switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { |
| 927 | case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: | 994 | case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: |
| 928 | port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; | 995 | phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; |
| 929 | break; | 996 | break; |
| 930 | case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: | 997 | case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: |
| 931 | port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; | 998 | phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; |
| 932 | break; | 999 | break; |
| 933 | default: | 1000 | default: |
| 934 | break; | 1001 | break; |
| @@ -940,28 +1007,29 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 940 | switch (phy_info->programmed_link_rate & | 1007 | switch (phy_info->programmed_link_rate & |
| 941 | MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { | 1008 | MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { |
| 942 | case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: | 1009 | case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: |
| 943 | port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; | 1010 | phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; |
| 944 | break; | 1011 | break; |
| 945 | case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: | 1012 | case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: |
| 946 | port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; | 1013 | phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; |
| 947 | break; | 1014 | break; |
| 948 | default: | 1015 | default: |
| 949 | break; | 1016 | break; |
| 950 | } | 1017 | } |
| 951 | 1018 | ||
| 952 | if (local) | 1019 | if (local) |
| 953 | port->local_attached = 1; | 1020 | phy->local_attached = 1; |
| 954 | 1021 | ||
| 955 | error = sas_phy_add(port); | 1022 | error = sas_phy_add(phy); |
| 956 | if (error) { | 1023 | if (error) { |
| 957 | sas_phy_free(port); | 1024 | sas_phy_free(phy); |
| 958 | return error; | 1025 | return error; |
| 959 | } | 1026 | } |
| 1027 | phy_info->phy = phy; | ||
| 960 | 1028 | ||
| 961 | if (phy_info->attached.handle) { | 1029 | if (phy_info->attached.handle) { |
| 962 | struct sas_rphy *rphy; | 1030 | struct sas_rphy *rphy; |
| 963 | 1031 | ||
| 964 | rphy = sas_rphy_alloc(port); | 1032 | rphy = sas_rphy_alloc(phy); |
| 965 | if (!rphy) | 1033 | if (!rphy) |
| 966 | return 0; /* non-fatal: an rphy can be added later */ | 1034 | return 0; /* non-fatal: an rphy can be added later */ |
| 967 | 1035 | ||
| @@ -985,16 +1053,19 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) | |||
| 985 | u32 handle = 0xFFFF; | 1053 | u32 handle = 0xFFFF; |
| 986 | int error = -ENOMEM, i; | 1054 | int error = -ENOMEM, i; |
| 987 | 1055 | ||
| 988 | port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); | 1056 | port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); |
| 989 | if (!port_info) | 1057 | if (!port_info) |
| 990 | goto out; | 1058 | goto out; |
| 991 | memset(port_info, 0, sizeof(*port_info)); | ||
| 992 | 1059 | ||
| 993 | error = mptsas_sas_io_unit_pg0(ioc, port_info); | 1060 | error = mptsas_sas_io_unit_pg0(ioc, port_info); |
| 994 | if (error) | 1061 | if (error) |
| 995 | goto out_free_port_info; | 1062 | goto out_free_port_info; |
| 996 | 1063 | ||
| 1064 | ioc->num_ports = port_info->num_phys; | ||
| 1065 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 997 | list_add_tail(&port_info->list, &ioc->sas_topology); | 1066 | list_add_tail(&port_info->list, &ioc->sas_topology); |
| 1067 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1068 | |||
| 998 | for (i = 0; i < port_info->num_phys; i++) { | 1069 | for (i = 0; i < port_info->num_phys; i++) { |
| 999 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], | 1070 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], |
| 1000 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << | 1071 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << |
| @@ -1034,10 +1105,9 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | |||
| 1034 | struct mptsas_portinfo *port_info, *p; | 1105 | struct mptsas_portinfo *port_info, *p; |
| 1035 | int error = -ENOMEM, i, j; | 1106 | int error = -ENOMEM, i, j; |
| 1036 | 1107 | ||
| 1037 | port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); | 1108 | port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); |
| 1038 | if (!port_info) | 1109 | if (!port_info) |
| 1039 | goto out; | 1110 | goto out; |
| 1040 | memset(port_info, 0, sizeof(*port_info)); | ||
| 1041 | 1111 | ||
| 1042 | error = mptsas_sas_expander_pg0(ioc, port_info, | 1112 | error = mptsas_sas_expander_pg0(ioc, port_info, |
| 1043 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | 1113 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << |
| @@ -1047,7 +1117,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | |||
| 1047 | 1117 | ||
| 1048 | *handle = port_info->handle; | 1118 | *handle = port_info->handle; |
| 1049 | 1119 | ||
| 1120 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 1050 | list_add_tail(&port_info->list, &ioc->sas_topology); | 1121 | list_add_tail(&port_info->list, &ioc->sas_topology); |
| 1122 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1123 | |||
| 1051 | for (i = 0; i < port_info->num_phys; i++) { | 1124 | for (i = 0; i < port_info->num_phys; i++) { |
| 1052 | struct device *parent; | 1125 | struct device *parent; |
| 1053 | 1126 | ||
| @@ -1079,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | |||
| 1079 | * HBA phys. | 1152 | * HBA phys. |
| 1080 | */ | 1153 | */ |
| 1081 | parent = &ioc->sh->shost_gendev; | 1154 | parent = &ioc->sh->shost_gendev; |
| 1155 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 1082 | list_for_each_entry(p, &ioc->sas_topology, list) { | 1156 | list_for_each_entry(p, &ioc->sas_topology, list) { |
| 1083 | for (j = 0; j < p->num_phys; j++) { | 1157 | for (j = 0; j < p->num_phys; j++) { |
| 1084 | if (port_info->phy_info[i].identify.handle == | 1158 | if (port_info->phy_info[i].identify.handle == |
| @@ -1086,6 +1160,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | |||
| 1086 | parent = &p->phy_info[j].rphy->dev; | 1160 | parent = &p->phy_info[j].rphy->dev; |
| 1087 | } | 1161 | } |
| 1088 | } | 1162 | } |
| 1163 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1089 | 1164 | ||
| 1090 | mptsas_probe_one_phy(parent, &port_info->phy_info[i], | 1165 | mptsas_probe_one_phy(parent, &port_info->phy_info[i], |
| 1091 | *index, 0); | 1166 | *index, 0); |
| @@ -1111,6 +1186,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | |||
| 1111 | ; | 1186 | ; |
| 1112 | } | 1187 | } |
| 1113 | 1188 | ||
| 1189 | static struct mptsas_phyinfo * | ||
| 1190 | mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) | ||
| 1191 | { | ||
| 1192 | struct mptsas_portinfo *port_info; | ||
| 1193 | struct mptsas_devinfo device_info; | ||
| 1194 | struct mptsas_phyinfo *phy_info = NULL; | ||
| 1195 | int i, error; | ||
| 1196 | |||
| 1197 | /* | ||
| 1198 | * Retrieve the parent sas_address | ||
| 1199 | */ | ||
| 1200 | error = mptsas_sas_device_pg0(ioc, &device_info, | ||
| 1201 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | ||
| 1202 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
| 1203 | parent_handle); | ||
| 1204 | if (error) { | ||
| 1205 | printk("mptsas: failed to retrieve device page\n"); | ||
| 1206 | return NULL; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | /* | ||
| 1210 | * The phy_info structures are never deallocated during lifetime of | ||
| 1211 | * a host, so the code below is safe without additional refcounting. | ||
| 1212 | */ | ||
| 1213 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 1214 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||
| 1215 | for (i = 0; i < port_info->num_phys; i++) { | ||
| 1216 | if (port_info->phy_info[i].identify.sas_address == | ||
| 1217 | device_info.sas_address && | ||
| 1218 | port_info->phy_info[i].phy_id == phy_id) { | ||
| 1219 | phy_info = &port_info->phy_info[i]; | ||
| 1220 | break; | ||
| 1221 | } | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1225 | |||
| 1226 | return phy_info; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | static struct mptsas_phyinfo * | ||
| 1230 | mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) | ||
| 1231 | { | ||
| 1232 | struct mptsas_portinfo *port_info; | ||
| 1233 | struct mptsas_phyinfo *phy_info = NULL; | ||
| 1234 | int i; | ||
| 1235 | |||
| 1236 | /* | ||
| 1237 | * The phy_info structures are never deallocated during lifetime of | ||
| 1238 | * a host, so the code below is safe without additional refcounting. | ||
| 1239 | */ | ||
| 1240 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 1241 | list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||
| 1242 | for (i = 0; i < port_info->num_phys; i++) { | ||
| 1243 | if (port_info->phy_info[i].attached.handle == handle) { | ||
| 1244 | phy_info = &port_info->phy_info[i]; | ||
| 1245 | break; | ||
| 1246 | } | ||
| 1247 | } | ||
| 1248 | } | ||
| 1249 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1250 | |||
| 1251 | return phy_info; | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | static void | ||
| 1255 | mptsas_hotplug_work(void *arg) | ||
| 1256 | { | ||
| 1257 | struct mptsas_hotplug_event *ev = arg; | ||
| 1258 | MPT_ADAPTER *ioc = ev->ioc; | ||
| 1259 | struct mptsas_phyinfo *phy_info; | ||
| 1260 | struct sas_rphy *rphy; | ||
| 1261 | char *ds = NULL; | ||
| 1262 | |||
| 1263 | if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 1264 | ds = "ssp"; | ||
| 1265 | if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
| 1266 | ds = "stp"; | ||
| 1267 | if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 1268 | ds = "sata"; | ||
| 1269 | |||
| 1270 | switch (ev->event_type) { | ||
| 1271 | case MPTSAS_DEL_DEVICE: | ||
| 1272 | printk(MYIOC_s_INFO_FMT | ||
| 1273 | "removing %s device, channel %d, id %d, phy %d\n", | ||
| 1274 | ioc->name, ds, ev->channel, ev->id, ev->phy_id); | ||
| 1275 | |||
| 1276 | phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle); | ||
| 1277 | if (!phy_info) { | ||
| 1278 | printk("mptsas: remove event for non-existant PHY.\n"); | ||
| 1279 | break; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | if (phy_info->rphy) { | ||
| 1283 | sas_rphy_delete(phy_info->rphy); | ||
| 1284 | phy_info->rphy = NULL; | ||
| 1285 | } | ||
| 1286 | break; | ||
| 1287 | case MPTSAS_ADD_DEVICE: | ||
| 1288 | printk(MYIOC_s_INFO_FMT | ||
| 1289 | "attaching %s device, channel %d, id %d, phy %d\n", | ||
| 1290 | ioc->name, ds, ev->channel, ev->id, ev->phy_id); | ||
| 1291 | |||
| 1292 | phy_info = mptsas_find_phyinfo_by_parent(ioc, | ||
| 1293 | ev->parent_handle, ev->phy_id); | ||
| 1294 | if (!phy_info) { | ||
| 1295 | printk("mptsas: add event for non-existant PHY.\n"); | ||
| 1296 | break; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | if (phy_info->rphy) { | ||
| 1300 | printk("mptsas: trying to add existing device.\n"); | ||
| 1301 | break; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | /* fill attached info */ | ||
| 1305 | phy_info->attached.handle = ev->handle; | ||
| 1306 | phy_info->attached.phy_id = ev->phy_id; | ||
| 1307 | phy_info->attached.port_id = phy_info->identify.port_id; | ||
| 1308 | phy_info->attached.id = ev->id; | ||
| 1309 | phy_info->attached.channel = ev->channel; | ||
| 1310 | phy_info->attached.sas_address = ev->sas_address; | ||
| 1311 | phy_info->attached.device_info = ev->device_info; | ||
| 1312 | |||
| 1313 | rphy = sas_rphy_alloc(phy_info->phy); | ||
| 1314 | if (!rphy) | ||
| 1315 | break; /* non-fatal: an rphy can be added later */ | ||
| 1316 | |||
| 1317 | mptsas_parse_device_info(&rphy->identify, &phy_info->attached); | ||
| 1318 | if (sas_rphy_add(rphy)) { | ||
| 1319 | sas_rphy_free(rphy); | ||
| 1320 | break; | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | phy_info->rphy = rphy; | ||
| 1324 | break; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | kfree(ev); | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | static void | ||
| 1331 | mptscsih_send_sas_event(MPT_ADAPTER *ioc, | ||
| 1332 | EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) | ||
| 1333 | { | ||
| 1334 | struct mptsas_hotplug_event *ev; | ||
| 1335 | u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo); | ||
| 1336 | __le64 sas_address; | ||
| 1337 | |||
| 1338 | if ((device_info & | ||
| 1339 | (MPI_SAS_DEVICE_INFO_SSP_TARGET | | ||
| 1340 | MPI_SAS_DEVICE_INFO_STP_TARGET | | ||
| 1341 | MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) | ||
| 1342 | return; | ||
| 1343 | |||
| 1344 | if ((sas_event_data->ReasonCode & | ||
| 1345 | (MPI_EVENT_SAS_DEV_STAT_RC_ADDED | | ||
| 1346 | MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0) | ||
| 1347 | return; | ||
| 1348 | |||
| 1349 | ev = kmalloc(sizeof(*ev), GFP_ATOMIC); | ||
| 1350 | if (!ev) { | ||
| 1351 | printk(KERN_WARNING "mptsas: lost hotplug event\n"); | ||
| 1352 | return; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | |||
| 1356 | INIT_WORK(&ev->work, mptsas_hotplug_work, ev); | ||
| 1357 | ev->ioc = ioc; | ||
| 1358 | ev->handle = le16_to_cpu(sas_event_data->DevHandle); | ||
| 1359 | ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); | ||
| 1360 | ev->channel = sas_event_data->Bus; | ||
| 1361 | ev->id = sas_event_data->TargetID; | ||
| 1362 | ev->phy_id = sas_event_data->PhyNum; | ||
| 1363 | memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64)); | ||
| 1364 | ev->sas_address = le64_to_cpu(sas_address); | ||
| 1365 | ev->device_info = device_info; | ||
| 1366 | |||
| 1367 | if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED) | ||
| 1368 | ev->event_type = MPTSAS_ADD_DEVICE; | ||
| 1369 | else | ||
| 1370 | ev->event_type = MPTSAS_DEL_DEVICE; | ||
| 1371 | |||
| 1372 | schedule_work(&ev->work); | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | static int | ||
| 1376 | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | ||
| 1377 | { | ||
| 1378 | u8 event = le32_to_cpu(reply->Event) & 0xFF; | ||
| 1379 | |||
| 1380 | if (!ioc->sh) | ||
| 1381 | return 1; | ||
| 1382 | |||
| 1383 | switch (event) { | ||
| 1384 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: | ||
| 1385 | mptscsih_send_sas_event(ioc, | ||
| 1386 | (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); | ||
| 1387 | return 1; /* currently means nothing really */ | ||
| 1388 | |||
| 1389 | default: | ||
| 1390 | return mptscsih_event_process(ioc, reply); | ||
| 1391 | } | ||
| 1392 | } | ||
| 1393 | |||
| 1114 | static int | 1394 | static int |
| 1115 | mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 1395 | mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 1116 | { | 1396 | { |
| @@ -1118,11 +1398,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1118 | MPT_SCSI_HOST *hd; | 1398 | MPT_SCSI_HOST *hd; |
| 1119 | MPT_ADAPTER *ioc; | 1399 | MPT_ADAPTER *ioc; |
| 1120 | unsigned long flags; | 1400 | unsigned long flags; |
| 1121 | int sz, ii; | 1401 | int ii; |
| 1122 | int numSGE = 0; | 1402 | int numSGE = 0; |
| 1123 | int scale; | 1403 | int scale; |
| 1124 | int ioc_cap; | 1404 | int ioc_cap; |
| 1125 | u8 *mem; | ||
| 1126 | int error=0; | 1405 | int error=0; |
| 1127 | int r; | 1406 | int r; |
| 1128 | 1407 | ||
| @@ -1203,7 +1482,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1203 | sh->unique_id = ioc->id; | 1482 | sh->unique_id = ioc->id; |
| 1204 | 1483 | ||
| 1205 | INIT_LIST_HEAD(&ioc->sas_topology); | 1484 | INIT_LIST_HEAD(&ioc->sas_topology); |
| 1206 | init_MUTEX(&ioc->sas_mgmt.mutex); | 1485 | mutex_init(&ioc->sas_topology_mutex); |
| 1486 | |||
| 1487 | mutex_init(&ioc->sas_mgmt.mutex); | ||
| 1207 | init_completion(&ioc->sas_mgmt.done); | 1488 | init_completion(&ioc->sas_mgmt.done); |
| 1208 | 1489 | ||
| 1209 | /* Verify that we won't exceed the maximum | 1490 | /* Verify that we won't exceed the maximum |
| @@ -1244,36 +1525,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1244 | /* SCSI needs scsi_cmnd lookup table! | 1525 | /* SCSI needs scsi_cmnd lookup table! |
| 1245 | * (with size equal to req_depth*PtrSz!) | 1526 | * (with size equal to req_depth*PtrSz!) |
| 1246 | */ | 1527 | */ |
| 1247 | sz = ioc->req_depth * sizeof(void *); | 1528 | hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); |
| 1248 | mem = kmalloc(sz, GFP_ATOMIC); | 1529 | if (!hd->ScsiLookup) { |
| 1249 | if (mem == NULL) { | ||
| 1250 | error = -ENOMEM; | 1530 | error = -ENOMEM; |
| 1251 | goto out_mptsas_probe; | 1531 | goto out_mptsas_probe; |
| 1252 | } | 1532 | } |
| 1253 | 1533 | ||
| 1254 | memset(mem, 0, sz); | 1534 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", |
| 1255 | hd->ScsiLookup = (struct scsi_cmnd **) mem; | 1535 | ioc->name, hd->ScsiLookup)); |
| 1256 | |||
| 1257 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", | ||
| 1258 | ioc->name, hd->ScsiLookup, sz)); | ||
| 1259 | 1536 | ||
| 1260 | /* Allocate memory for the device structures. | 1537 | /* Allocate memory for the device structures. |
| 1261 | * A non-Null pointer at an offset | 1538 | * A non-Null pointer at an offset |
| 1262 | * indicates a device exists. | 1539 | * indicates a device exists. |
| 1263 | * max_id = 1 + maximum id (hosts.h) | 1540 | * max_id = 1 + maximum id (hosts.h) |
| 1264 | */ | 1541 | */ |
| 1265 | sz = sh->max_id * sizeof(void *); | 1542 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); |
| 1266 | mem = kmalloc(sz, GFP_ATOMIC); | 1543 | if (!hd->Targets) { |
| 1267 | if (mem == NULL) { | ||
| 1268 | error = -ENOMEM; | 1544 | error = -ENOMEM; |
| 1269 | goto out_mptsas_probe; | 1545 | goto out_mptsas_probe; |
| 1270 | } | 1546 | } |
| 1271 | 1547 | ||
| 1272 | memset(mem, 0, sz); | 1548 | dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets)); |
| 1273 | hd->Targets = (VirtTarget **) mem; | ||
| 1274 | |||
| 1275 | dprintk((KERN_INFO | ||
| 1276 | " vtarget @ %p, sz=%d\n", hd->Targets, sz)); | ||
| 1277 | 1549 | ||
| 1278 | /* Clear the TM flags | 1550 | /* Clear the TM flags |
| 1279 | */ | 1551 | */ |
| @@ -1324,6 +1596,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1324 | 1596 | ||
| 1325 | mptsas_scan_sas_topology(ioc); | 1597 | mptsas_scan_sas_topology(ioc); |
| 1326 | 1598 | ||
| 1599 | /* | ||
| 1600 | Reporting RAID volumes. | ||
| 1601 | */ | ||
| 1602 | if (!ioc->raid_data.pIocPg2) | ||
| 1603 | return 0; | ||
| 1604 | if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||
| 1605 | return 0; | ||
| 1606 | for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) { | ||
| 1607 | scsi_add_device(sh, | ||
| 1608 | ioc->num_ports, | ||
| 1609 | ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, | ||
| 1610 | 0); | ||
| 1611 | } | ||
| 1612 | |||
| 1327 | return 0; | 1613 | return 0; |
| 1328 | 1614 | ||
| 1329 | out_mptsas_probe: | 1615 | out_mptsas_probe: |
| @@ -1339,10 +1625,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) | |||
| 1339 | 1625 | ||
| 1340 | sas_remove_host(ioc->sh); | 1626 | sas_remove_host(ioc->sh); |
| 1341 | 1627 | ||
| 1628 | mutex_lock(&ioc->sas_topology_mutex); | ||
| 1342 | list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { | 1629 | list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { |
| 1343 | list_del(&p->list); | 1630 | list_del(&p->list); |
| 1344 | kfree(p); | 1631 | kfree(p); |
| 1345 | } | 1632 | } |
| 1633 | mutex_unlock(&ioc->sas_topology_mutex); | ||
| 1346 | 1634 | ||
| 1347 | mptscsih_remove(pdev); | 1635 | mptscsih_remove(pdev); |
| 1348 | } | 1636 | } |
| @@ -1393,7 +1681,7 @@ mptsas_init(void) | |||
| 1393 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); | 1681 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); |
| 1394 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); | 1682 | mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); |
| 1395 | 1683 | ||
| 1396 | if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { | 1684 | if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { |
| 1397 | devtprintk((KERN_INFO MYNAM | 1685 | devtprintk((KERN_INFO MYNAM |
| 1398 | ": Registered for IOC event notifications\n")); | 1686 | ": Registered for IOC event notifications\n")); |
| 1399 | } | 1687 | } |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 93a16fa3c4ba..cdac5578fdf2 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
| @@ -893,6 +893,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) | |||
| 893 | * when a lun is disable by mid-layer. | 893 | * when a lun is disable by mid-layer. |
| 894 | * Do NOT access the referenced scsi_cmnd structure or | 894 | * Do NOT access the referenced scsi_cmnd structure or |
| 895 | * members. Will cause either a paging or NULL ptr error. | 895 | * members. Will cause either a paging or NULL ptr error. |
| 896 | * (BUT, BUT, BUT, the code does reference it! - mdr) | ||
| 896 | * @hd: Pointer to a SCSI HOST structure | 897 | * @hd: Pointer to a SCSI HOST structure |
| 897 | * @vdevice: per device private data | 898 | * @vdevice: per device private data |
| 898 | * | 899 | * |
| @@ -2162,10 +2163,9 @@ mptscsih_target_alloc(struct scsi_target *starget) | |||
| 2162 | { | 2163 | { |
| 2163 | VirtTarget *vtarget; | 2164 | VirtTarget *vtarget; |
| 2164 | 2165 | ||
| 2165 | vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL); | 2166 | vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); |
| 2166 | if (!vtarget) | 2167 | if (!vtarget) |
| 2167 | return -ENOMEM; | 2168 | return -ENOMEM; |
| 2168 | memset(vtarget, 0, sizeof(VirtTarget)); | ||
| 2169 | starget->hostdata = vtarget; | 2169 | starget->hostdata = vtarget; |
| 2170 | return 0; | 2170 | return 0; |
| 2171 | } | 2171 | } |
| @@ -2185,14 +2185,13 @@ mptscsih_slave_alloc(struct scsi_device *sdev) | |||
| 2185 | VirtDevice *vdev; | 2185 | VirtDevice *vdev; |
| 2186 | struct scsi_target *starget; | 2186 | struct scsi_target *starget; |
| 2187 | 2187 | ||
| 2188 | vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); | 2188 | vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); |
| 2189 | if (!vdev) { | 2189 | if (!vdev) { |
| 2190 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | 2190 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", |
| 2191 | hd->ioc->name, sizeof(VirtDevice)); | 2191 | hd->ioc->name, sizeof(VirtDevice)); |
| 2192 | return -ENOMEM; | 2192 | return -ENOMEM; |
| 2193 | } | 2193 | } |
| 2194 | 2194 | ||
| 2195 | memset(vdev, 0, sizeof(VirtDevice)); | ||
| 2196 | vdev->ioc_id = hd->ioc->id; | 2195 | vdev->ioc_id = hd->ioc->id; |
| 2197 | vdev->target_id = sdev->id; | 2196 | vdev->target_id = sdev->id; |
| 2198 | vdev->bus_id = sdev->channel; | 2197 | vdev->bus_id = sdev->channel; |
| @@ -2559,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
| 2559 | hd->cmdPtr = NULL; | 2558 | hd->cmdPtr = NULL; |
| 2560 | } | 2559 | } |
| 2561 | 2560 | ||
| 2562 | /* 7. Set flag to force DV and re-read IOC Page 3 | 2561 | /* 7. SPI: Set flag to force DV and re-read IOC Page 3 |
| 2563 | */ | 2562 | */ |
| 2564 | if (ioc->bus_type == SPI) { | 2563 | if (ioc->bus_type == SPI) { |
| 2565 | ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | 2564 | ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; |
| 2566 | ddvtprintk(("Set reload IOC Pg3 Flag\n")); | 2565 | ddvtprintk(("Set reload IOC Pg3 Flag\n")); |
| 2567 | } | 2566 | } |
| 2568 | 2567 | ||
| 2568 | /* 7. FC: Rescan for blocked rports which might have returned. | ||
| 2569 | */ | ||
| 2570 | else if (ioc->bus_type == FC) { | ||
| 2571 | int work_count; | ||
| 2572 | unsigned long flags; | ||
| 2573 | |||
| 2574 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | ||
| 2575 | work_count = ++ioc->fc_rescan_work_count; | ||
| 2576 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | ||
| 2577 | if (work_count == 1) | ||
| 2578 | schedule_work(&ioc->fc_rescan_work); | ||
| 2579 | } | ||
| 2569 | dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); | 2580 | dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); |
| 2570 | 2581 | ||
| 2571 | } | 2582 | } |
| @@ -2589,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2589 | { | 2600 | { |
| 2590 | MPT_SCSI_HOST *hd; | 2601 | MPT_SCSI_HOST *hd; |
| 2591 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | 2602 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; |
| 2603 | int work_count; | ||
| 2604 | unsigned long flags; | ||
| 2592 | 2605 | ||
| 2593 | devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2606 | devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", |
| 2594 | ioc->name, event)); | 2607 | ioc->name, event)); |
| @@ -2610,11 +2623,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
| 2610 | /* FIXME! */ | 2623 | /* FIXME! */ |
| 2611 | break; | 2624 | break; |
| 2612 | 2625 | ||
| 2626 | case MPI_EVENT_RESCAN: /* 06 */ | ||
| 2627 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | ||
| 2628 | work_count = ++ioc->fc_rescan_work_count; | ||
| 2629 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | ||
| 2630 | if (work_count == 1) | ||
| 2631 | schedule_work(&ioc->fc_rescan_work); | ||
| 2632 | break; | ||
| 2633 | |||
| 2613 | /* | 2634 | /* |
| 2614 | * CHECKME! Don't think we need to do | 2635 | * CHECKME! Don't think we need to do |
| 2615 | * anything for these, but... | 2636 | * anything for these, but... |
| 2616 | */ | 2637 | */ |
| 2617 | case MPI_EVENT_RESCAN: /* 06 */ | ||
| 2618 | case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ | 2638 | case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ |
| 2619 | case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ | 2639 | case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ |
| 2620 | /* | 2640 | /* |
| @@ -3954,8 +3974,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
| 3954 | 3974 | ||
| 3955 | /* Search IOC page 3 to determine if this is hidden physical disk | 3975 | /* Search IOC page 3 to determine if this is hidden physical disk |
| 3956 | */ | 3976 | */ |
| 3957 | /* Search IOC page 3 to determine if this is hidden physical disk | ||
| 3958 | */ | ||
| 3959 | static int | 3977 | static int |
| 3960 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | 3978 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) |
| 3961 | { | 3979 | { |
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index ce332a6085e5..7dce29277cb7 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
| @@ -158,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 158 | MPT_SCSI_HOST *hd; | 158 | MPT_SCSI_HOST *hd; |
| 159 | MPT_ADAPTER *ioc; | 159 | MPT_ADAPTER *ioc; |
| 160 | unsigned long flags; | 160 | unsigned long flags; |
| 161 | int sz, ii; | 161 | int ii; |
| 162 | int numSGE = 0; | 162 | int numSGE = 0; |
| 163 | int scale; | 163 | int scale; |
| 164 | int ioc_cap; | 164 | int ioc_cap; |
| 165 | u8 *mem; | ||
| 166 | int error=0; | 165 | int error=0; |
| 167 | int r; | 166 | int r; |
| 168 | 167 | ||
| @@ -288,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 288 | /* SCSI needs scsi_cmnd lookup table! | 287 | /* SCSI needs scsi_cmnd lookup table! |
| 289 | * (with size equal to req_depth*PtrSz!) | 288 | * (with size equal to req_depth*PtrSz!) |
| 290 | */ | 289 | */ |
| 291 | sz = ioc->req_depth * sizeof(void *); | 290 | hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); |
| 292 | mem = kmalloc(sz, GFP_ATOMIC); | 291 | if (!hd->ScsiLookup) { |
| 293 | if (mem == NULL) { | ||
| 294 | error = -ENOMEM; | 292 | error = -ENOMEM; |
| 295 | goto out_mptspi_probe; | 293 | goto out_mptspi_probe; |
| 296 | } | 294 | } |
| 297 | 295 | ||
| 298 | memset(mem, 0, sz); | 296 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", |
| 299 | hd->ScsiLookup = (struct scsi_cmnd **) mem; | 297 | ioc->name, hd->ScsiLookup)); |
| 300 | |||
| 301 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", | ||
| 302 | ioc->name, hd->ScsiLookup, sz)); | ||
| 303 | 298 | ||
| 304 | /* Allocate memory for the device structures. | 299 | /* Allocate memory for the device structures. |
| 305 | * A non-Null pointer at an offset | 300 | * A non-Null pointer at an offset |
| 306 | * indicates a device exists. | 301 | * indicates a device exists. |
| 307 | * max_id = 1 + maximum id (hosts.h) | 302 | * max_id = 1 + maximum id (hosts.h) |
| 308 | */ | 303 | */ |
| 309 | sz = sh->max_id * sizeof(void *); | 304 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); |
| 310 | mem = kmalloc(sz, GFP_ATOMIC); | 305 | if (!hd->Targets) { |
| 311 | if (mem == NULL) { | ||
| 312 | error = -ENOMEM; | 306 | error = -ENOMEM; |
| 313 | goto out_mptspi_probe; | 307 | goto out_mptspi_probe; |
| 314 | } | 308 | } |
| 315 | 309 | ||
| 316 | memset(mem, 0, sz); | 310 | dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); |
| 317 | hd->Targets = (VirtTarget **) mem; | ||
| 318 | |||
| 319 | dprintk((KERN_INFO | ||
| 320 | " vdev @ %p, sz=%d\n", hd->Targets, sz)); | ||
| 321 | 311 | ||
| 322 | /* Clear the TM flags | 312 | /* Clear the TM flags |
| 323 | */ | 313 | */ |
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index c5b656cdea7c..d698d7709c31 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
| @@ -88,11 +88,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
| 88 | struct device *dev = &pdev->dev; | 88 | struct device *dev = &pdev->dev; |
| 89 | int i; | 89 | int i; |
| 90 | 90 | ||
| 91 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
| 92 | printk(KERN_ERR "%s: device already claimed\n", c->name); | ||
| 93 | return -ENODEV; | ||
| 94 | } | ||
| 95 | |||
| 96 | for (i = 0; i < 6; i++) { | 91 | for (i = 0; i < 6; i++) { |
| 97 | /* Skip I/O spaces */ | 92 | /* Skip I/O spaces */ |
| 98 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { | 93 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { |
| @@ -319,6 +314,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
| 319 | return rc; | 314 | return rc; |
| 320 | } | 315 | } |
| 321 | 316 | ||
| 317 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
| 318 | printk(KERN_ERR "i2o: device already claimed\n"); | ||
| 319 | return -ENODEV; | ||
| 320 | } | ||
| 321 | |||
| 322 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 322 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
| 323 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", | 323 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", |
| 324 | pci_name(pdev)); | 324 | pci_name(pdev)); |
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 55ba23075c90..75f401d52fda 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c | |||
| @@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device *dev) | |||
| 77 | static struct bus_type mcp_bus_type = { | 77 | static struct bus_type mcp_bus_type = { |
| 78 | .name = "mcp", | 78 | .name = "mcp", |
| 79 | .match = mcp_bus_match, | 79 | .match = mcp_bus_match, |
| 80 | .probe = mcp_bus_probe, | ||
| 81 | .remove = mcp_bus_remove, | ||
| 80 | .suspend = mcp_bus_suspend, | 82 | .suspend = mcp_bus_suspend, |
| 81 | .resume = mcp_bus_resume, | 83 | .resume = mcp_bus_resume, |
| 82 | }; | 84 | }; |
| @@ -227,8 +229,6 @@ EXPORT_SYMBOL(mcp_host_unregister); | |||
| 227 | int mcp_driver_register(struct mcp_driver *mcpdrv) | 229 | int mcp_driver_register(struct mcp_driver *mcpdrv) |
| 228 | { | 230 | { |
| 229 | mcpdrv->drv.bus = &mcp_bus_type; | 231 | mcpdrv->drv.bus = &mcp_bus_type; |
| 230 | mcpdrv->drv.probe = mcp_bus_probe; | ||
| 231 | mcpdrv->drv.remove = mcp_bus_remove; | ||
| 232 | return driver_register(&mcpdrv->drv); | 232 | return driver_register(&mcpdrv->drv); |
| 233 | } | 233 | } |
| 234 | EXPORT_SYMBOL(mcp_driver_register); | 234 | EXPORT_SYMBOL(mcp_driver_register); |
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index ec701667abfc..a2a35fd946ee 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c | |||
| @@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device *dev) | |||
| 136 | return ret; | 136 | return ret; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | static struct bus_type mmc_bus_type = { | 139 | static int mmc_bus_probe(struct device *dev) |
| 140 | .name = "mmc", | ||
| 141 | .dev_attrs = mmc_dev_attrs, | ||
| 142 | .match = mmc_bus_match, | ||
| 143 | .uevent = mmc_bus_uevent, | ||
| 144 | .suspend = mmc_bus_suspend, | ||
| 145 | .resume = mmc_bus_resume, | ||
| 146 | }; | ||
| 147 | |||
| 148 | |||
| 149 | static int mmc_drv_probe(struct device *dev) | ||
| 150 | { | 140 | { |
| 151 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 141 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 152 | struct mmc_card *card = dev_to_mmc_card(dev); | 142 | struct mmc_card *card = dev_to_mmc_card(dev); |
| @@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device *dev) | |||
| 154 | return drv->probe(card); | 144 | return drv->probe(card); |
| 155 | } | 145 | } |
| 156 | 146 | ||
| 157 | static int mmc_drv_remove(struct device *dev) | 147 | static int mmc_bus_remove(struct device *dev) |
| 158 | { | 148 | { |
| 159 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 149 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 160 | struct mmc_card *card = dev_to_mmc_card(dev); | 150 | struct mmc_card *card = dev_to_mmc_card(dev); |
| @@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device *dev) | |||
| 164 | return 0; | 154 | return 0; |
| 165 | } | 155 | } |
| 166 | 156 | ||
| 157 | static struct bus_type mmc_bus_type = { | ||
| 158 | .name = "mmc", | ||
| 159 | .dev_attrs = mmc_dev_attrs, | ||
| 160 | .match = mmc_bus_match, | ||
| 161 | .uevent = mmc_bus_uevent, | ||
| 162 | .probe = mmc_bus_probe, | ||
| 163 | .remove = mmc_bus_remove, | ||
| 164 | .suspend = mmc_bus_suspend, | ||
| 165 | .resume = mmc_bus_resume, | ||
| 166 | }; | ||
| 167 | 167 | ||
| 168 | /** | 168 | /** |
| 169 | * mmc_register_driver - register a media driver | 169 | * mmc_register_driver - register a media driver |
| @@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device *dev) | |||
| 172 | int mmc_register_driver(struct mmc_driver *drv) | 172 | int mmc_register_driver(struct mmc_driver *drv) |
| 173 | { | 173 | { |
| 174 | drv->drv.bus = &mmc_bus_type; | 174 | drv->drv.bus = &mmc_bus_type; |
| 175 | drv->drv.probe = mmc_drv_probe; | ||
| 176 | drv->drv.remove = mmc_drv_remove; | ||
| 177 | return driver_register(&drv->drv); | 175 | return driver_register(&drv->drv); |
| 178 | } | 176 | } |
| 179 | 177 | ||
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 9a2aa4033c6a..5038e90ceb12 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
| @@ -47,6 +47,22 @@ config MTD_MS02NV | |||
| 47 | accelerator. Say Y here if you have a DECstation 5000/2x0 or a | 47 | accelerator. Say Y here if you have a DECstation 5000/2x0 or a |
| 48 | DECsystem 5900 equipped with such a module. | 48 | DECsystem 5900 equipped with such a module. |
| 49 | 49 | ||
| 50 | config MTD_DATAFLASH | ||
| 51 | tristate "Support for AT45xxx DataFlash" | ||
| 52 | depends on MTD && SPI_MASTER && EXPERIMENTAL | ||
| 53 | help | ||
| 54 | This enables access to AT45xxx DataFlash chips, using SPI. | ||
| 55 | Sometimes DataFlash chips are packaged inside MMC-format | ||
| 56 | cards; at this writing, the MMC stack won't handle those. | ||
| 57 | |||
| 58 | config MTD_M25P80 | ||
| 59 | tristate "Support for M25 SPI Flash" | ||
| 60 | depends on MTD && SPI_MASTER && EXPERIMENTAL | ||
| 61 | help | ||
| 62 | This enables access to ST M25P80 and similar SPI flash chips, | ||
| 63 | used for program and data storage. Set up your spi devices | ||
| 64 | with the right board-specific platform data. | ||
| 65 | |||
| 50 | config MTD_SLRAM | 66 | config MTD_SLRAM |
| 51 | tristate "Uncached system RAM" | 67 | tristate "Uncached system RAM" |
| 52 | depends on MTD | 68 | depends on MTD |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e38db348057d..7c5ed2178380 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
| @@ -23,3 +23,5 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o | |||
| 23 | obj-$(CONFIG_MTD_LART) += lart.o | 23 | obj-$(CONFIG_MTD_LART) += lart.o |
| 24 | obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o | 24 | obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o |
| 25 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o | 25 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o |
| 26 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o | ||
| 27 | obj-$(CONFIG_MTD_M25P80) += m25p80.o | ||
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index be5e88b3888d..e4345cf744a2 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
| @@ -138,7 +138,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc) | |||
| 138 | bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is | 138 | bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is |
| 139 | required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ | 139 | required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ |
| 140 | 140 | ||
| 141 | static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, | 141 | static int DoC_Command(struct DiskOnChip *doc, unsigned char command, |
| 142 | unsigned char xtraflags) | 142 | unsigned char xtraflags) |
| 143 | { | 143 | { |
| 144 | void __iomem *docptr = doc->virtadr; | 144 | void __iomem *docptr = doc->virtadr; |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index fcb28a6fd89f..681a9c73a2a3 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
| @@ -103,7 +103,7 @@ static inline int DoC_WaitReady(void __iomem * docptr) | |||
| 103 | with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is | 103 | with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is |
| 104 | required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ | 104 | required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ |
| 105 | 105 | ||
| 106 | static inline void DoC_Command(void __iomem * docptr, unsigned char command, | 106 | static void DoC_Command(void __iomem * docptr, unsigned char command, |
| 107 | unsigned char xtraflags) | 107 | unsigned char xtraflags) |
| 108 | { | 108 | { |
| 109 | /* Assert the CLE (Command Latch Enable) line to the flash chip */ | 109 | /* Assert the CLE (Command Latch Enable) line to the flash chip */ |
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 0595cc7324b2..5f57f29efee4 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c | |||
| @@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(void __iomem * docptr) | |||
| 118 | /* DoC_Command: Send a flash command to the flash chip through the Flash | 118 | /* DoC_Command: Send a flash command to the flash chip through the Flash |
| 119 | * command register. Need 2 Write Pipeline Terminates to complete send. | 119 | * command register. Need 2 Write Pipeline Terminates to complete send. |
| 120 | */ | 120 | */ |
| 121 | static inline void DoC_Command(void __iomem * docptr, unsigned char command, | 121 | static void DoC_Command(void __iomem * docptr, unsigned char command, |
| 122 | unsigned char xtraflags) | 122 | unsigned char xtraflags) |
| 123 | { | 123 | { |
| 124 | WriteDOC(command, docptr, Mplus_FlashCmd); | 124 | WriteDOC(command, docptr, Mplus_FlashCmd); |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c new file mode 100644 index 000000000000..d5f24089be71 --- /dev/null +++ b/drivers/mtd/devices/m25p80.c | |||
| @@ -0,0 +1,582 @@ | |||
| 1 | /* | ||
| 2 | * MTD SPI driver for ST M25Pxx flash chips | ||
| 3 | * | ||
| 4 | * Author: Mike Lavender, mike@steroidmicros.com | ||
| 5 | * | ||
| 6 | * Copyright (c) 2005, Intec Automation Inc. | ||
| 7 | * | ||
| 8 | * Some parts are based on lart.c by Abraham Van Der Merwe | ||
| 9 | * | ||
| 10 | * Cleaned up and generalized based on mtd_dataflash.c | ||
| 11 | * | ||
| 12 | * This code is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License version 2 as | ||
| 14 | * published by the Free Software Foundation. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/device.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/mtd/mtd.h> | ||
| 24 | #include <linux/mtd/partitions.h> | ||
| 25 | #include <linux/spi/spi.h> | ||
| 26 | #include <linux/spi/flash.h> | ||
| 27 | |||
| 28 | #include <asm/semaphore.h> | ||
| 29 | |||
| 30 | |||
| 31 | /* NOTE: AT 25F and SST 25LF series are very similar, | ||
| 32 | * but commands for sector erase and chip id differ... | ||
| 33 | */ | ||
| 34 | |||
| 35 | #define FLASH_PAGESIZE 256 | ||
| 36 | |||
| 37 | /* Flash opcodes. */ | ||
| 38 | #define OPCODE_WREN 6 /* Write enable */ | ||
| 39 | #define OPCODE_RDSR 5 /* Read status register */ | ||
| 40 | #define OPCODE_READ 3 /* Read data bytes */ | ||
| 41 | #define OPCODE_PP 2 /* Page program */ | ||
| 42 | #define OPCODE_SE 0xd8 /* Sector erase */ | ||
| 43 | #define OPCODE_RES 0xab /* Read Electronic Signature */ | ||
| 44 | #define OPCODE_RDID 0x9f /* Read JEDEC ID */ | ||
| 45 | |||
| 46 | /* Status Register bits. */ | ||
| 47 | #define SR_WIP 1 /* Write in progress */ | ||
| 48 | #define SR_WEL 2 /* Write enable latch */ | ||
| 49 | #define SR_BP0 4 /* Block protect 0 */ | ||
| 50 | #define SR_BP1 8 /* Block protect 1 */ | ||
| 51 | #define SR_BP2 0x10 /* Block protect 2 */ | ||
| 52 | #define SR_SRWD 0x80 /* SR write protect */ | ||
| 53 | |||
| 54 | /* Define max times to check status register before we give up. */ | ||
| 55 | #define MAX_READY_WAIT_COUNT 100000 | ||
| 56 | |||
| 57 | |||
| 58 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 59 | #define mtd_has_partitions() (1) | ||
| 60 | #else | ||
| 61 | #define mtd_has_partitions() (0) | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /****************************************************************************/ | ||
| 65 | |||
| 66 | struct m25p { | ||
| 67 | struct spi_device *spi; | ||
| 68 | struct semaphore lock; | ||
| 69 | struct mtd_info mtd; | ||
| 70 | unsigned partitioned; | ||
| 71 | u8 command[4]; | ||
| 72 | }; | ||
| 73 | |||
| 74 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) | ||
| 75 | { | ||
| 76 | return container_of(mtd, struct m25p, mtd); | ||
| 77 | } | ||
| 78 | |||
| 79 | /****************************************************************************/ | ||
| 80 | |||
| 81 | /* | ||
| 82 | * Internal helper functions | ||
| 83 | */ | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Read the status register, returning its value in the location | ||
| 87 | * Return the status register value. | ||
| 88 | * Returns negative if error occurred. | ||
| 89 | */ | ||
| 90 | static int read_sr(struct m25p *flash) | ||
| 91 | { | ||
| 92 | ssize_t retval; | ||
| 93 | u8 code = OPCODE_RDSR; | ||
| 94 | u8 val; | ||
| 95 | |||
| 96 | retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); | ||
| 97 | |||
| 98 | if (retval < 0) { | ||
| 99 | dev_err(&flash->spi->dev, "error %d reading SR\n", | ||
| 100 | (int) retval); | ||
| 101 | return retval; | ||
| 102 | } | ||
| 103 | |||
| 104 | return val; | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | /* | ||
| 109 | * Set write enable latch with Write Enable command. | ||
| 110 | * Returns negative if error occurred. | ||
| 111 | */ | ||
| 112 | static inline int write_enable(struct m25p *flash) | ||
| 113 | { | ||
| 114 | u8 code = OPCODE_WREN; | ||
| 115 | |||
| 116 | return spi_write_then_read(flash->spi, &code, 1, NULL, 0); | ||
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | /* | ||
| 121 | * Service routine to read status register until ready, or timeout occurs. | ||
| 122 | * Returns non-zero if error. | ||
| 123 | */ | ||
| 124 | static int wait_till_ready(struct m25p *flash) | ||
| 125 | { | ||
| 126 | int count; | ||
| 127 | int sr; | ||
| 128 | |||
| 129 | /* one chip guarantees max 5 msec wait here after page writes, | ||
| 130 | * but potentially three seconds (!) after page erase. | ||
| 131 | */ | ||
| 132 | for (count = 0; count < MAX_READY_WAIT_COUNT; count++) { | ||
| 133 | if ((sr = read_sr(flash)) < 0) | ||
| 134 | break; | ||
| 135 | else if (!(sr & SR_WIP)) | ||
| 136 | return 0; | ||
| 137 | |||
| 138 | /* REVISIT sometimes sleeping would be best */ | ||
| 139 | } | ||
| 140 | |||
| 141 | return 1; | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | /* | ||
| 146 | * Erase one sector of flash memory at offset ``offset'' which is any | ||
| 147 | * address within the sector which should be erased. | ||
| 148 | * | ||
| 149 | * Returns 0 if successful, non-zero otherwise. | ||
| 150 | */ | ||
| 151 | static int erase_sector(struct m25p *flash, u32 offset) | ||
| 152 | { | ||
| 153 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id, | ||
| 154 | __FUNCTION__, offset); | ||
| 155 | |||
| 156 | /* Wait until finished previous write command. */ | ||
| 157 | if (wait_till_ready(flash)) | ||
| 158 | return 1; | ||
| 159 | |||
| 160 | /* Send write enable, then erase commands. */ | ||
| 161 | write_enable(flash); | ||
| 162 | |||
| 163 | /* Set up command buffer. */ | ||
| 164 | flash->command[0] = OPCODE_SE; | ||
| 165 | flash->command[1] = offset >> 16; | ||
| 166 | flash->command[2] = offset >> 8; | ||
| 167 | flash->command[3] = offset; | ||
| 168 | |||
| 169 | spi_write(flash->spi, flash->command, sizeof(flash->command)); | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | /****************************************************************************/ | ||
| 175 | |||
| 176 | /* | ||
| 177 | * MTD implementation | ||
| 178 | */ | ||
| 179 | |||
| 180 | /* | ||
| 181 | * Erase an address range on the flash chip. The address range may extend | ||
| 182 | * one or more erase sectors. Return an error is there is a problem erasing. | ||
| 183 | */ | ||
| 184 | static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
| 185 | { | ||
| 186 | struct m25p *flash = mtd_to_m25p(mtd); | ||
| 187 | u32 addr,len; | ||
| 188 | |||
| 189 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | ||
| 190 | flash->spi->dev.bus_id, __FUNCTION__, "at", | ||
| 191 | (u32)instr->addr, instr->len); | ||
| 192 | |||
| 193 | /* sanity checks */ | ||
| 194 | if (instr->addr + instr->len > flash->mtd.size) | ||
| 195 | return -EINVAL; | ||
| 196 | if ((instr->addr % mtd->erasesize) != 0 | ||
| 197 | || (instr->len % mtd->erasesize) != 0) { | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | |||
| 201 | addr = instr->addr; | ||
| 202 | len = instr->len; | ||
| 203 | |||
| 204 | down(&flash->lock); | ||
| 205 | |||
| 206 | /* now erase those sectors */ | ||
| 207 | while (len) { | ||
| 208 | if (erase_sector(flash, addr)) { | ||
| 209 | instr->state = MTD_ERASE_FAILED; | ||
| 210 | up(&flash->lock); | ||
| 211 | return -EIO; | ||
| 212 | } | ||
| 213 | |||
| 214 | addr += mtd->erasesize; | ||
| 215 | len -= mtd->erasesize; | ||
| 216 | } | ||
| 217 | |||
| 218 | up(&flash->lock); | ||
| 219 | |||
| 220 | instr->state = MTD_ERASE_DONE; | ||
| 221 | mtd_erase_callback(instr); | ||
| 222 | |||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | /* | ||
| 227 | * Read an address range from the flash chip. The address range | ||
| 228 | * may be any size provided it is within the physical boundaries. | ||
| 229 | */ | ||
| 230 | static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
| 231 | size_t *retlen, u_char *buf) | ||
| 232 | { | ||
| 233 | struct m25p *flash = mtd_to_m25p(mtd); | ||
| 234 | struct spi_transfer t[2]; | ||
| 235 | struct spi_message m; | ||
| 236 | |||
| 237 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | ||
| 238 | flash->spi->dev.bus_id, __FUNCTION__, "from", | ||
| 239 | (u32)from, len); | ||
| 240 | |||
| 241 | /* sanity checks */ | ||
| 242 | if (!len) | ||
| 243 | return 0; | ||
| 244 | |||
| 245 | if (from + len > flash->mtd.size) | ||
| 246 | return -EINVAL; | ||
| 247 | |||
| 248 | spi_message_init(&m); | ||
| 249 | memset(t, 0, (sizeof t)); | ||
| 250 | |||
| 251 | t[0].tx_buf = flash->command; | ||
| 252 | t[0].len = sizeof(flash->command); | ||
| 253 | spi_message_add_tail(&t[0], &m); | ||
| 254 | |||
| 255 | t[1].rx_buf = buf; | ||
| 256 | t[1].len = len; | ||
| 257 | spi_message_add_tail(&t[1], &m); | ||
| 258 | |||
| 259 | /* Byte count starts at zero. */ | ||
| 260 | if (retlen) | ||
| 261 | *retlen = 0; | ||
| 262 | |||
| 263 | down(&flash->lock); | ||
| 264 | |||
| 265 | /* Wait till previous write/erase is done. */ | ||
| 266 | if (wait_till_ready(flash)) { | ||
| 267 | /* REVISIT status return?? */ | ||
| 268 | up(&flash->lock); | ||
| 269 | return 1; | ||
| 270 | } | ||
| 271 | |||
| 272 | /* NOTE: OPCODE_FAST_READ (if available) is faster... */ | ||
| 273 | |||
| 274 | /* Set up the write data buffer. */ | ||
| 275 | flash->command[0] = OPCODE_READ; | ||
| 276 | flash->command[1] = from >> 16; | ||
| 277 | flash->command[2] = from >> 8; | ||
| 278 | flash->command[3] = from; | ||
| 279 | |||
| 280 | spi_sync(flash->spi, &m); | ||
| 281 | |||
| 282 | *retlen = m.actual_length - sizeof(flash->command); | ||
| 283 | |||
| 284 | up(&flash->lock); | ||
| 285 | |||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Write an address range to the flash chip. Data must be written in | ||
| 291 | * FLASH_PAGESIZE chunks. The address range may be any size provided | ||
| 292 | * it is within the physical boundaries. | ||
| 293 | */ | ||
| 294 | static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
| 295 | size_t *retlen, const u_char *buf) | ||
| 296 | { | ||
| 297 | struct m25p *flash = mtd_to_m25p(mtd); | ||
| 298 | u32 page_offset, page_size; | ||
| 299 | struct spi_transfer t[2]; | ||
| 300 | struct spi_message m; | ||
| 301 | |||
| 302 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | ||
| 303 | flash->spi->dev.bus_id, __FUNCTION__, "to", | ||
| 304 | (u32)to, len); | ||
| 305 | |||
| 306 | if (retlen) | ||
| 307 | *retlen = 0; | ||
| 308 | |||
| 309 | /* sanity checks */ | ||
| 310 | if (!len) | ||
| 311 | return(0); | ||
| 312 | |||
| 313 | if (to + len > flash->mtd.size) | ||
| 314 | return -EINVAL; | ||
| 315 | |||
| 316 | spi_message_init(&m); | ||
| 317 | memset(t, 0, (sizeof t)); | ||
| 318 | |||
| 319 | t[0].tx_buf = flash->command; | ||
| 320 | t[0].len = sizeof(flash->command); | ||
| 321 | spi_message_add_tail(&t[0], &m); | ||
| 322 | |||
| 323 | t[1].tx_buf = buf; | ||
| 324 | spi_message_add_tail(&t[1], &m); | ||
| 325 | |||
| 326 | down(&flash->lock); | ||
| 327 | |||
| 328 | /* Wait until finished previous write command. */ | ||
| 329 | if (wait_till_ready(flash)) | ||
| 330 | return 1; | ||
| 331 | |||
| 332 | write_enable(flash); | ||
| 333 | |||
| 334 | /* Set up the opcode in the write buffer. */ | ||
| 335 | flash->command[0] = OPCODE_PP; | ||
| 336 | flash->command[1] = to >> 16; | ||
| 337 | flash->command[2] = to >> 8; | ||
| 338 | flash->command[3] = to; | ||
| 339 | |||
| 340 | /* what page do we start with? */ | ||
| 341 | page_offset = to % FLASH_PAGESIZE; | ||
| 342 | |||
| 343 | /* do all the bytes fit onto one page? */ | ||
| 344 | if (page_offset + len <= FLASH_PAGESIZE) { | ||
| 345 | t[1].len = len; | ||
| 346 | |||
| 347 | spi_sync(flash->spi, &m); | ||
| 348 | |||
| 349 | *retlen = m.actual_length - sizeof(flash->command); | ||
| 350 | } else { | ||
| 351 | u32 i; | ||
| 352 | |||
| 353 | /* the size of data remaining on the first page */ | ||
| 354 | page_size = FLASH_PAGESIZE - page_offset; | ||
| 355 | |||
| 356 | t[1].len = page_size; | ||
| 357 | spi_sync(flash->spi, &m); | ||
| 358 | |||
| 359 | *retlen = m.actual_length - sizeof(flash->command); | ||
| 360 | |||
| 361 | /* write everything in PAGESIZE chunks */ | ||
| 362 | for (i = page_size; i < len; i += page_size) { | ||
| 363 | page_size = len - i; | ||
| 364 | if (page_size > FLASH_PAGESIZE) | ||
| 365 | page_size = FLASH_PAGESIZE; | ||
| 366 | |||
| 367 | /* write the next page to flash */ | ||
| 368 | flash->command[1] = (to + i) >> 16; | ||
| 369 | flash->command[2] = (to + i) >> 8; | ||
| 370 | flash->command[3] = (to + i); | ||
| 371 | |||
| 372 | t[1].tx_buf = buf + i; | ||
| 373 | t[1].len = page_size; | ||
| 374 | |||
| 375 | wait_till_ready(flash); | ||
| 376 | |||
| 377 | write_enable(flash); | ||
| 378 | |||
| 379 | spi_sync(flash->spi, &m); | ||
| 380 | |||
| 381 | if (retlen) | ||
| 382 | *retlen += m.actual_length | ||
| 383 | - sizeof(flash->command); | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | up(&flash->lock); | ||
| 388 | |||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | |||
| 393 | /****************************************************************************/ | ||
| 394 | |||
| 395 | /* | ||
| 396 | * SPI device driver setup and teardown | ||
| 397 | */ | ||
| 398 | |||
| 399 | struct flash_info { | ||
| 400 | char *name; | ||
| 401 | u8 id; | ||
| 402 | u16 jedec_id; | ||
| 403 | unsigned sector_size; | ||
| 404 | unsigned n_sectors; | ||
| 405 | }; | ||
| 406 | |||
| 407 | static struct flash_info __devinitdata m25p_data [] = { | ||
| 408 | /* REVISIT: fill in JEDEC ids, for parts that have them */ | ||
| 409 | { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, | ||
| 410 | { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, | ||
| 411 | { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, | ||
| 412 | { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, | ||
| 413 | { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, | ||
| 414 | { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, | ||
| 415 | { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, | ||
| 416 | { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, | ||
| 417 | }; | ||
| 418 | |||
| 419 | /* | ||
| 420 | * board specific setup should have ensured the SPI clock used here | ||
| 421 | * matches what the READ command supports, at least until this driver | ||
| 422 | * understands FAST_READ (for clocks over 25 MHz). | ||
| 423 | */ | ||
| 424 | static int __devinit m25p_probe(struct spi_device *spi) | ||
| 425 | { | ||
| 426 | struct flash_platform_data *data; | ||
| 427 | struct m25p *flash; | ||
| 428 | struct flash_info *info; | ||
| 429 | unsigned i; | ||
| 430 | |||
| 431 | /* Platform data helps sort out which chip type we have, as | ||
| 432 | * well as how this board partitions it. | ||
| 433 | */ | ||
| 434 | data = spi->dev.platform_data; | ||
| 435 | if (!data || !data->type) { | ||
| 436 | /* FIXME some chips can identify themselves with RES | ||
| 437 | * or JEDEC get-id commands. Try them ... | ||
| 438 | */ | ||
| 439 | DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n", | ||
| 440 | flash->spi->dev.bus_id); | ||
| 441 | return -ENODEV; | ||
| 442 | } | ||
| 443 | |||
| 444 | for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) { | ||
| 445 | if (strcmp(data->type, info->name) == 0) | ||
| 446 | break; | ||
| 447 | } | ||
| 448 | if (i == ARRAY_SIZE(m25p_data)) { | ||
| 449 | DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n", | ||
| 450 | flash->spi->dev.bus_id, data->type); | ||
| 451 | return -ENODEV; | ||
| 452 | } | ||
| 453 | |||
| 454 | flash = kzalloc(sizeof *flash, SLAB_KERNEL); | ||
| 455 | if (!flash) | ||
| 456 | return -ENOMEM; | ||
| 457 | |||
| 458 | flash->spi = spi; | ||
| 459 | init_MUTEX(&flash->lock); | ||
| 460 | dev_set_drvdata(&spi->dev, flash); | ||
| 461 | |||
| 462 | if (data->name) | ||
| 463 | flash->mtd.name = data->name; | ||
| 464 | else | ||
| 465 | flash->mtd.name = spi->dev.bus_id; | ||
| 466 | |||
| 467 | flash->mtd.type = MTD_NORFLASH; | ||
| 468 | flash->mtd.flags = MTD_CAP_NORFLASH; | ||
| 469 | flash->mtd.size = info->sector_size * info->n_sectors; | ||
| 470 | flash->mtd.erasesize = info->sector_size; | ||
| 471 | flash->mtd.erase = m25p80_erase; | ||
| 472 | flash->mtd.read = m25p80_read; | ||
| 473 | flash->mtd.write = m25p80_write; | ||
| 474 | |||
| 475 | dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name, | ||
| 476 | flash->mtd.size / 1024); | ||
| 477 | |||
| 478 | DEBUG(MTD_DEBUG_LEVEL2, | ||
| 479 | "mtd .name = %s, .size = 0x%.8x (%uM) " | ||
| 480 | ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n", | ||
| 481 | flash->mtd.name, | ||
| 482 | flash->mtd.size, flash->mtd.size / (1024*1024), | ||
| 483 | flash->mtd.erasesize, flash->mtd.erasesize / 1024, | ||
| 484 | flash->mtd.numeraseregions); | ||
| 485 | |||
| 486 | if (flash->mtd.numeraseregions) | ||
| 487 | for (i = 0; i < flash->mtd.numeraseregions; i++) | ||
| 488 | DEBUG(MTD_DEBUG_LEVEL2, | ||
| 489 | "mtd.eraseregions[%d] = { .offset = 0x%.8x, " | ||
| 490 | ".erasesize = 0x%.8x (%uK), " | ||
| 491 | ".numblocks = %d }\n", | ||
| 492 | i, flash->mtd.eraseregions[i].offset, | ||
| 493 | flash->mtd.eraseregions[i].erasesize, | ||
| 494 | flash->mtd.eraseregions[i].erasesize / 1024, | ||
| 495 | flash->mtd.eraseregions[i].numblocks); | ||
| 496 | |||
| 497 | |||
| 498 | /* partitions should match sector boundaries; and it may be good to | ||
| 499 | * use readonly partitions for writeprotected sectors (BP2..BP0). | ||
| 500 | */ | ||
| 501 | if (mtd_has_partitions()) { | ||
| 502 | struct mtd_partition *parts = NULL; | ||
| 503 | int nr_parts = 0; | ||
| 504 | |||
| 505 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
| 506 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
| 507 | |||
| 508 | nr_parts = parse_mtd_partitions(&flash->mtd, | ||
| 509 | part_probes, &parts, 0); | ||
| 510 | #endif | ||
| 511 | |||
| 512 | if (nr_parts <= 0 && data && data->parts) { | ||
| 513 | parts = data->parts; | ||
| 514 | nr_parts = data->nr_parts; | ||
| 515 | } | ||
| 516 | |||
| 517 | if (nr_parts > 0) { | ||
| 518 | for (i = 0; i < data->nr_parts; i++) { | ||
| 519 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | ||
| 520 | "{.name = %s, .offset = 0x%.8x, " | ||
| 521 | ".size = 0x%.8x (%uK) }\n", | ||
| 522 | i, data->parts[i].name, | ||
| 523 | data->parts[i].offset, | ||
| 524 | data->parts[i].size, | ||
| 525 | data->parts[i].size / 1024); | ||
| 526 | } | ||
| 527 | flash->partitioned = 1; | ||
| 528 | return add_mtd_partitions(&flash->mtd, parts, nr_parts); | ||
| 529 | } | ||
| 530 | } else if (data->nr_parts) | ||
| 531 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | ||
| 532 | data->nr_parts, data->name); | ||
| 533 | |||
| 534 | return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0; | ||
| 535 | } | ||
| 536 | |||
| 537 | |||
| 538 | static int __devexit m25p_remove(struct spi_device *spi) | ||
| 539 | { | ||
| 540 | struct m25p *flash = dev_get_drvdata(&spi->dev); | ||
| 541 | int status; | ||
| 542 | |||
| 543 | /* Clean up MTD stuff. */ | ||
| 544 | if (mtd_has_partitions() && flash->partitioned) | ||
| 545 | status = del_mtd_partitions(&flash->mtd); | ||
| 546 | else | ||
| 547 | status = del_mtd_device(&flash->mtd); | ||
| 548 | if (status == 0) | ||
| 549 | kfree(flash); | ||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | |||
| 554 | static struct spi_driver m25p80_driver = { | ||
| 555 | .driver = { | ||
| 556 | .name = "m25p80", | ||
| 557 | .bus = &spi_bus_type, | ||
| 558 | .owner = THIS_MODULE, | ||
| 559 | }, | ||
| 560 | .probe = m25p_probe, | ||
| 561 | .remove = __devexit_p(m25p_remove), | ||
| 562 | }; | ||
| 563 | |||
| 564 | |||
| 565 | static int m25p80_init(void) | ||
| 566 | { | ||
| 567 | return spi_register_driver(&m25p80_driver); | ||
| 568 | } | ||
| 569 | |||
| 570 | |||
| 571 | static void m25p80_exit(void) | ||
| 572 | { | ||
| 573 | spi_unregister_driver(&m25p80_driver); | ||
| 574 | } | ||
| 575 | |||
| 576 | |||
| 577 | module_init(m25p80_init); | ||
| 578 | module_exit(m25p80_exit); | ||
| 579 | |||
| 580 | MODULE_LICENSE("GPL"); | ||
| 581 | MODULE_AUTHOR("Mike Lavender"); | ||
| 582 | MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips"); | ||
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c new file mode 100644 index 000000000000..155737e7483f --- /dev/null +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
| @@ -0,0 +1,629 @@ | |||
| 1 | /* | ||
| 2 | * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework | ||
| 3 | * | ||
| 4 | * Largely derived from at91_dataflash.c: | ||
| 5 | * Copyright (C) 2003-2005 SAN People (Pty) Ltd | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version | ||
| 10 | * 2 of the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | #include <linux/config.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/spi/spi.h> | ||
| 19 | #include <linux/spi/flash.h> | ||
| 20 | |||
| 21 | #include <linux/mtd/mtd.h> | ||
| 22 | #include <linux/mtd/partitions.h> | ||
| 23 | |||
| 24 | |||
| 25 | /* | ||
| 26 | * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in | ||
| 27 | * each chip, which may be used for double buffered I/O; but this driver | ||
| 28 | * doesn't (yet) use these for any kind of i/o overlap or prefetching. | ||
| 29 | * | ||
| 30 | * Sometimes DataFlash is packaged in MMC-format cards, although the | ||
| 31 | * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash | ||
| 32 | * protocols during enumeration. | ||
| 33 | */ | ||
| 34 | |||
| 35 | #define CONFIG_DATAFLASH_WRITE_VERIFY | ||
| 36 | |||
| 37 | /* reads can bypass the buffers */ | ||
| 38 | #define OP_READ_CONTINUOUS 0xE8 | ||
| 39 | #define OP_READ_PAGE 0xD2 | ||
| 40 | |||
| 41 | /* group B requests can run even while status reports "busy" */ | ||
| 42 | #define OP_READ_STATUS 0xD7 /* group B */ | ||
| 43 | |||
| 44 | /* move data between host and buffer */ | ||
| 45 | #define OP_READ_BUFFER1 0xD4 /* group B */ | ||
| 46 | #define OP_READ_BUFFER2 0xD6 /* group B */ | ||
| 47 | #define OP_WRITE_BUFFER1 0x84 /* group B */ | ||
| 48 | #define OP_WRITE_BUFFER2 0x87 /* group B */ | ||
| 49 | |||
| 50 | /* erasing flash */ | ||
| 51 | #define OP_ERASE_PAGE 0x81 | ||
| 52 | #define OP_ERASE_BLOCK 0x50 | ||
| 53 | |||
| 54 | /* move data between buffer and flash */ | ||
| 55 | #define OP_TRANSFER_BUF1 0x53 | ||
| 56 | #define OP_TRANSFER_BUF2 0x55 | ||
| 57 | #define OP_MREAD_BUFFER1 0xD4 | ||
| 58 | #define OP_MREAD_BUFFER2 0xD6 | ||
| 59 | #define OP_MWERASE_BUFFER1 0x83 | ||
| 60 | #define OP_MWERASE_BUFFER2 0x86 | ||
| 61 | #define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ | ||
| 62 | #define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ | ||
| 63 | |||
| 64 | /* write to buffer, then write-erase to flash */ | ||
| 65 | #define OP_PROGRAM_VIA_BUF1 0x82 | ||
| 66 | #define OP_PROGRAM_VIA_BUF2 0x85 | ||
| 67 | |||
| 68 | /* compare buffer to flash */ | ||
| 69 | #define OP_COMPARE_BUF1 0x60 | ||
| 70 | #define OP_COMPARE_BUF2 0x61 | ||
| 71 | |||
| 72 | /* read flash to buffer, then write-erase to flash */ | ||
| 73 | #define OP_REWRITE_VIA_BUF1 0x58 | ||
| 74 | #define OP_REWRITE_VIA_BUF2 0x59 | ||
| 75 | |||
| 76 | /* newer chips report JEDEC manufacturer and device IDs; chip | ||
| 77 | * serial number and OTP bits; and per-sector writeprotect. | ||
| 78 | */ | ||
| 79 | #define OP_READ_ID 0x9F | ||
| 80 | #define OP_READ_SECURITY 0x77 | ||
| 81 | #define OP_WRITE_SECURITY 0x9A /* OTP bits */ | ||
| 82 | |||
| 83 | |||
| 84 | struct dataflash { | ||
| 85 | u8 command[4]; | ||
| 86 | char name[24]; | ||
| 87 | |||
| 88 | unsigned partitioned:1; | ||
| 89 | |||
| 90 | unsigned short page_offset; /* offset in flash address */ | ||
| 91 | unsigned int page_size; /* of bytes per page */ | ||
| 92 | |||
| 93 | struct semaphore lock; | ||
| 94 | struct spi_device *spi; | ||
| 95 | |||
| 96 | struct mtd_info mtd; | ||
| 97 | }; | ||
| 98 | |||
| 99 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 100 | #define mtd_has_partitions() (1) | ||
| 101 | #else | ||
| 102 | #define mtd_has_partitions() (0) | ||
| 103 | #endif | ||
| 104 | |||
| 105 | /* ......................................................................... */ | ||
| 106 | |||
| 107 | /* | ||
| 108 | * Return the status of the DataFlash device. | ||
| 109 | */ | ||
| 110 | static inline int dataflash_status(struct spi_device *spi) | ||
| 111 | { | ||
| 112 | /* NOTE: at45db321c over 25 MHz wants to write | ||
| 113 | * a dummy byte after the opcode... | ||
| 114 | */ | ||
| 115 | return spi_w8r8(spi, OP_READ_STATUS); | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Poll the DataFlash device until it is READY. | ||
| 120 | * This usually takes 5-20 msec or so; more for sector erase. | ||
| 121 | */ | ||
| 122 | static int dataflash_waitready(struct spi_device *spi) | ||
| 123 | { | ||
| 124 | int status; | ||
| 125 | |||
| 126 | for (;;) { | ||
| 127 | status = dataflash_status(spi); | ||
| 128 | if (status < 0) { | ||
| 129 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", | ||
| 130 | spi->dev.bus_id, status); | ||
| 131 | status = 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (status & (1 << 7)) /* RDY/nBSY */ | ||
| 135 | return status; | ||
| 136 | |||
| 137 | msleep(3); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | /* ......................................................................... */ | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Erase pages of flash. | ||
| 145 | */ | ||
| 146 | static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
| 147 | { | ||
| 148 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
| 149 | struct spi_device *spi = priv->spi; | ||
| 150 | struct spi_transfer x = { .tx_dma = 0, }; | ||
| 151 | struct spi_message msg; | ||
| 152 | unsigned blocksize = priv->page_size << 3; | ||
| 153 | u8 *command; | ||
| 154 | |||
| 155 | DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n", | ||
| 156 | spi->dev.bus_id, | ||
| 157 | instr->addr, instr->len); | ||
| 158 | |||
| 159 | /* Sanity checks */ | ||
| 160 | if ((instr->addr + instr->len) > mtd->size | ||
| 161 | || (instr->len % priv->page_size) != 0 | ||
| 162 | || (instr->addr % priv->page_size) != 0) | ||
| 163 | return -EINVAL; | ||
| 164 | |||
| 165 | spi_message_init(&msg); | ||
| 166 | |||
| 167 | x.tx_buf = command = priv->command; | ||
| 168 | x.len = 4; | ||
| 169 | spi_message_add_tail(&x, &msg); | ||
| 170 | |||
| 171 | down(&priv->lock); | ||
| 172 | while (instr->len > 0) { | ||
| 173 | unsigned int pageaddr; | ||
| 174 | int status; | ||
| 175 | int do_block; | ||
| 176 | |||
| 177 | /* Calculate flash page address; use block erase (for speed) if | ||
| 178 | * we're at a block boundary and need to erase the whole block. | ||
| 179 | */ | ||
| 180 | pageaddr = instr->addr / priv->page_size; | ||
| 181 | do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize; | ||
| 182 | pageaddr = pageaddr << priv->page_offset; | ||
| 183 | |||
| 184 | command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; | ||
| 185 | command[1] = (u8)(pageaddr >> 16); | ||
| 186 | command[2] = (u8)(pageaddr >> 8); | ||
| 187 | command[3] = 0; | ||
| 188 | |||
| 189 | DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", | ||
| 190 | do_block ? "block" : "page", | ||
| 191 | command[0], command[1], command[2], command[3], | ||
| 192 | pageaddr); | ||
| 193 | |||
| 194 | status = spi_sync(spi, &msg); | ||
| 195 | (void) dataflash_waitready(spi); | ||
| 196 | |||
| 197 | if (status < 0) { | ||
| 198 | printk(KERN_ERR "%s: erase %x, err %d\n", | ||
| 199 | spi->dev.bus_id, pageaddr, status); | ||
| 200 | /* REVISIT: can retry instr->retries times; or | ||
| 201 | * giveup and instr->fail_addr = instr->addr; | ||
| 202 | */ | ||
| 203 | continue; | ||
| 204 | } | ||
| 205 | |||
| 206 | if (do_block) { | ||
| 207 | instr->addr += blocksize; | ||
| 208 | instr->len -= blocksize; | ||
| 209 | } else { | ||
| 210 | instr->addr += priv->page_size; | ||
| 211 | instr->len -= priv->page_size; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | up(&priv->lock); | ||
| 215 | |||
| 216 | /* Inform MTD subsystem that erase is complete */ | ||
| 217 | instr->state = MTD_ERASE_DONE; | ||
| 218 | mtd_erase_callback(instr); | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Read from the DataFlash device. | ||
| 225 | * from : Start offset in flash device | ||
| 226 | * len : Amount to read | ||
| 227 | * retlen : About of data actually read | ||
| 228 | * buf : Buffer containing the data | ||
| 229 | */ | ||
| 230 | static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
| 231 | size_t *retlen, u_char *buf) | ||
| 232 | { | ||
| 233 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
| 234 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | ||
| 235 | struct spi_message msg; | ||
| 236 | unsigned int addr; | ||
| 237 | u8 *command; | ||
| 238 | int status; | ||
| 239 | |||
| 240 | DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", | ||
| 241 | priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len)); | ||
| 242 | |||
| 243 | *retlen = 0; | ||
| 244 | |||
| 245 | /* Sanity checks */ | ||
| 246 | if (!len) | ||
| 247 | return 0; | ||
| 248 | if (from + len > mtd->size) | ||
| 249 | return -EINVAL; | ||
| 250 | |||
| 251 | /* Calculate flash page/byte address */ | ||
| 252 | addr = (((unsigned)from / priv->page_size) << priv->page_offset) | ||
| 253 | + ((unsigned)from % priv->page_size); | ||
| 254 | |||
| 255 | command = priv->command; | ||
| 256 | |||
| 257 | DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", | ||
| 258 | command[0], command[1], command[2], command[3]); | ||
| 259 | |||
| 260 | spi_message_init(&msg); | ||
| 261 | |||
| 262 | x[0].tx_buf = command; | ||
| 263 | x[0].len = 8; | ||
| 264 | spi_message_add_tail(&x[0], &msg); | ||
| 265 | |||
| 266 | x[1].rx_buf = buf; | ||
| 267 | x[1].len = len; | ||
| 268 | spi_message_add_tail(&x[1], &msg); | ||
| 269 | |||
| 270 | down(&priv->lock); | ||
| 271 | |||
| 272 | /* Continuous read, max clock = f(car) which may be less than | ||
| 273 | * the peak rate available. Some chips support commands with | ||
| 274 | * fewer "don't care" bytes. Both buffers stay unchanged. | ||
| 275 | */ | ||
| 276 | command[0] = OP_READ_CONTINUOUS; | ||
| 277 | command[1] = (u8)(addr >> 16); | ||
| 278 | command[2] = (u8)(addr >> 8); | ||
| 279 | command[3] = (u8)(addr >> 0); | ||
| 280 | /* plus 4 "don't care" bytes */ | ||
| 281 | |||
| 282 | status = spi_sync(priv->spi, &msg); | ||
| 283 | up(&priv->lock); | ||
| 284 | |||
| 285 | if (status >= 0) { | ||
| 286 | *retlen = msg.actual_length - 8; | ||
| 287 | status = 0; | ||
| 288 | } else | ||
| 289 | DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", | ||
| 290 | priv->spi->dev.bus_id, | ||
| 291 | (unsigned)from, (unsigned)(from + len), | ||
| 292 | status); | ||
| 293 | return status; | ||
| 294 | } | ||
| 295 | |||
| 296 | /* | ||
| 297 | * Write to the DataFlash device. | ||
| 298 | * to : Start offset in flash device | ||
| 299 | * len : Amount to write | ||
| 300 | * retlen : Amount of data actually written | ||
| 301 | * buf : Buffer containing the data | ||
| 302 | */ | ||
| 303 | static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
| 304 | size_t * retlen, const u_char * buf) | ||
| 305 | { | ||
| 306 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
| 307 | struct spi_device *spi = priv->spi; | ||
| 308 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | ||
| 309 | struct spi_message msg; | ||
| 310 | unsigned int pageaddr, addr, offset, writelen; | ||
| 311 | size_t remaining = len; | ||
| 312 | u_char *writebuf = (u_char *) buf; | ||
| 313 | int status = -EINVAL; | ||
| 314 | u8 *command; | ||
| 315 | |||
| 316 | DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", | ||
| 317 | spi->dev.bus_id, (unsigned)to, (unsigned)(to + len)); | ||
| 318 | |||
| 319 | *retlen = 0; | ||
| 320 | |||
| 321 | /* Sanity checks */ | ||
| 322 | if (!len) | ||
| 323 | return 0; | ||
| 324 | if ((to + len) > mtd->size) | ||
| 325 | return -EINVAL; | ||
| 326 | |||
| 327 | spi_message_init(&msg); | ||
| 328 | |||
| 329 | x[0].tx_buf = command = priv->command; | ||
| 330 | x[0].len = 4; | ||
| 331 | spi_message_add_tail(&x[0], &msg); | ||
| 332 | |||
| 333 | pageaddr = ((unsigned)to / priv->page_size); | ||
| 334 | offset = ((unsigned)to % priv->page_size); | ||
| 335 | if (offset + len > priv->page_size) | ||
| 336 | writelen = priv->page_size - offset; | ||
| 337 | else | ||
| 338 | writelen = len; | ||
| 339 | |||
| 340 | down(&priv->lock); | ||
| 341 | while (remaining > 0) { | ||
| 342 | DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", | ||
| 343 | pageaddr, offset, writelen); | ||
| 344 | |||
| 345 | /* REVISIT: | ||
| 346 | * (a) each page in a sector must be rewritten at least | ||
| 347 | * once every 10K sibling erase/program operations. | ||
| 348 | * (b) for pages that are already erased, we could | ||
| 349 | * use WRITE+MWRITE not PROGRAM for ~30% speedup. | ||
| 350 | * (c) WRITE to buffer could be done while waiting for | ||
| 351 | * a previous MWRITE/MWERASE to complete ... | ||
| 352 | * (d) error handling here seems to be mostly missing. | ||
| 353 | * | ||
| 354 | * Two persistent bits per page, plus a per-sector counter, | ||
| 355 | * could support (a) and (b) ... we might consider using | ||
| 356 | * the second half of sector zero, which is just one block, | ||
| 357 | * to track that state. (On AT91, that sector should also | ||
| 358 | * support boot-from-DataFlash.) | ||
| 359 | */ | ||
| 360 | |||
| 361 | addr = pageaddr << priv->page_offset; | ||
| 362 | |||
| 363 | /* (1) Maybe transfer partial page to Buffer1 */ | ||
| 364 | if (writelen != priv->page_size) { | ||
| 365 | command[0] = OP_TRANSFER_BUF1; | ||
| 366 | command[1] = (addr & 0x00FF0000) >> 16; | ||
| 367 | command[2] = (addr & 0x0000FF00) >> 8; | ||
| 368 | command[3] = 0; | ||
| 369 | |||
| 370 | DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", | ||
| 371 | command[0], command[1], command[2], command[3]); | ||
| 372 | |||
| 373 | status = spi_sync(spi, &msg); | ||
| 374 | if (status < 0) | ||
| 375 | DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", | ||
| 376 | spi->dev.bus_id, addr, status); | ||
| 377 | |||
| 378 | (void) dataflash_waitready(priv->spi); | ||
| 379 | } | ||
| 380 | |||
| 381 | /* (2) Program full page via Buffer1 */ | ||
| 382 | addr += offset; | ||
| 383 | command[0] = OP_PROGRAM_VIA_BUF1; | ||
| 384 | command[1] = (addr & 0x00FF0000) >> 16; | ||
| 385 | command[2] = (addr & 0x0000FF00) >> 8; | ||
| 386 | command[3] = (addr & 0x000000FF); | ||
| 387 | |||
| 388 | DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", | ||
| 389 | command[0], command[1], command[2], command[3]); | ||
| 390 | |||
| 391 | x[1].tx_buf = writebuf; | ||
| 392 | x[1].len = writelen; | ||
| 393 | spi_message_add_tail(x + 1, &msg); | ||
| 394 | status = spi_sync(spi, &msg); | ||
| 395 | spi_transfer_del(x + 1); | ||
| 396 | if (status < 0) | ||
| 397 | DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", | ||
| 398 | spi->dev.bus_id, addr, writelen, status); | ||
| 399 | |||
| 400 | (void) dataflash_waitready(priv->spi); | ||
| 401 | |||
| 402 | |||
| 403 | #ifdef CONFIG_DATAFLASH_WRITE_VERIFY | ||
| 404 | |||
| 405 | /* (3) Compare to Buffer1 */ | ||
| 406 | addr = pageaddr << priv->page_offset; | ||
| 407 | command[0] = OP_COMPARE_BUF1; | ||
| 408 | command[1] = (addr & 0x00FF0000) >> 16; | ||
| 409 | command[2] = (addr & 0x0000FF00) >> 8; | ||
| 410 | command[3] = 0; | ||
| 411 | |||
| 412 | DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", | ||
| 413 | command[0], command[1], command[2], command[3]); | ||
| 414 | |||
| 415 | status = spi_sync(spi, &msg); | ||
| 416 | if (status < 0) | ||
| 417 | DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", | ||
| 418 | spi->dev.bus_id, addr, status); | ||
| 419 | |||
| 420 | status = dataflash_waitready(priv->spi); | ||
| 421 | |||
| 422 | /* Check result of the compare operation */ | ||
| 423 | if ((status & (1 << 6)) == 1) { | ||
| 424 | printk(KERN_ERR "%s: compare page %u, err %d\n", | ||
| 425 | spi->dev.bus_id, pageaddr, status); | ||
| 426 | remaining = 0; | ||
| 427 | status = -EIO; | ||
| 428 | break; | ||
| 429 | } else | ||
| 430 | status = 0; | ||
| 431 | |||
| 432 | #endif /* CONFIG_DATAFLASH_WRITE_VERIFY */ | ||
| 433 | |||
| 434 | remaining = remaining - writelen; | ||
| 435 | pageaddr++; | ||
| 436 | offset = 0; | ||
| 437 | writebuf += writelen; | ||
| 438 | *retlen += writelen; | ||
| 439 | |||
| 440 | if (remaining > priv->page_size) | ||
| 441 | writelen = priv->page_size; | ||
| 442 | else | ||
| 443 | writelen = remaining; | ||
| 444 | } | ||
| 445 | up(&priv->lock); | ||
| 446 | |||
| 447 | return status; | ||
| 448 | } | ||
| 449 | |||
| 450 | /* ......................................................................... */ | ||
| 451 | |||
| 452 | /* | ||
| 453 | * Register DataFlash device with MTD subsystem. | ||
| 454 | */ | ||
| 455 | static int __devinit | ||
| 456 | add_dataflash(struct spi_device *spi, char *name, | ||
| 457 | int nr_pages, int pagesize, int pageoffset) | ||
| 458 | { | ||
| 459 | struct dataflash *priv; | ||
| 460 | struct mtd_info *device; | ||
| 461 | struct flash_platform_data *pdata = spi->dev.platform_data; | ||
| 462 | |||
| 463 | priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL); | ||
| 464 | if (!priv) | ||
| 465 | return -ENOMEM; | ||
| 466 | |||
| 467 | init_MUTEX(&priv->lock); | ||
| 468 | priv->spi = spi; | ||
| 469 | priv->page_size = pagesize; | ||
| 470 | priv->page_offset = pageoffset; | ||
| 471 | |||
| 472 | /* name must be usable with cmdlinepart */ | ||
| 473 | sprintf(priv->name, "spi%d.%d-%s", | ||
| 474 | spi->master->bus_num, spi->chip_select, | ||
| 475 | name); | ||
| 476 | |||
| 477 | device = &priv->mtd; | ||
| 478 | device->name = (pdata && pdata->name) ? pdata->name : priv->name; | ||
| 479 | device->size = nr_pages * pagesize; | ||
| 480 | device->erasesize = pagesize; | ||
| 481 | device->owner = THIS_MODULE; | ||
| 482 | device->type = MTD_DATAFLASH; | ||
| 483 | device->flags = MTD_CAP_NORFLASH; | ||
| 484 | device->erase = dataflash_erase; | ||
| 485 | device->read = dataflash_read; | ||
| 486 | device->write = dataflash_write; | ||
| 487 | device->priv = priv; | ||
| 488 | |||
| 489 | dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024); | ||
| 490 | dev_set_drvdata(&spi->dev, priv); | ||
| 491 | |||
| 492 | if (mtd_has_partitions()) { | ||
| 493 | struct mtd_partition *parts; | ||
| 494 | int nr_parts = 0; | ||
| 495 | |||
| 496 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
| 497 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
| 498 | |||
| 499 | nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0); | ||
| 500 | #endif | ||
| 501 | |||
| 502 | if (nr_parts <= 0 && pdata && pdata->parts) { | ||
| 503 | parts = pdata->parts; | ||
| 504 | nr_parts = pdata->nr_parts; | ||
| 505 | } | ||
| 506 | |||
| 507 | if (nr_parts > 0) { | ||
| 508 | priv->partitioned = 1; | ||
| 509 | return add_mtd_partitions(device, parts, nr_parts); | ||
| 510 | } | ||
| 511 | } else if (pdata && pdata->nr_parts) | ||
| 512 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | ||
| 513 | pdata->nr_parts, device->name); | ||
| 514 | |||
| 515 | return add_mtd_device(device) == 1 ? -ENODEV : 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | /* | ||
| 519 | * Detect and initialize DataFlash device: | ||
| 520 | * | ||
| 521 | * Device Density ID code #Pages PageSize Offset | ||
| 522 | * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 | ||
| 523 | * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9 | ||
| 524 | * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 | ||
| 525 | * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 | ||
| 526 | * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 | ||
| 527 | * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 | ||
| 528 | * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 | ||
| 529 | * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 | ||
| 530 | */ | ||
| 531 | static int __devinit dataflash_probe(struct spi_device *spi) | ||
| 532 | { | ||
| 533 | int status; | ||
| 534 | |||
| 535 | status = dataflash_status(spi); | ||
| 536 | if (status <= 0 || status == 0xff) { | ||
| 537 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", | ||
| 538 | spi->dev.bus_id, status); | ||
| 539 | if (status == 0xff) | ||
| 540 | status = -ENODEV; | ||
| 541 | return status; | ||
| 542 | } | ||
| 543 | |||
| 544 | /* if there's a device there, assume it's dataflash. | ||
| 545 | * board setup should have set spi->max_speed_max to | ||
| 546 | * match f(car) for continuous reads, mode 0 or 3. | ||
| 547 | */ | ||
| 548 | switch (status & 0x3c) { | ||
| 549 | case 0x0c: /* 0 0 1 1 x x */ | ||
| 550 | status = add_dataflash(spi, "AT45DB011B", 512, 264, 9); | ||
| 551 | break; | ||
| 552 | case 0x14: /* 0 1 0 1 x x */ | ||
| 553 | status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9); | ||
| 554 | break; | ||
| 555 | case 0x1c: /* 0 1 1 1 x x */ | ||
| 556 | status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9); | ||
| 557 | break; | ||
| 558 | case 0x24: /* 1 0 0 1 x x */ | ||
| 559 | status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9); | ||
| 560 | break; | ||
| 561 | case 0x2c: /* 1 0 1 1 x x */ | ||
| 562 | status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10); | ||
| 563 | break; | ||
| 564 | case 0x34: /* 1 1 0 1 x x */ | ||
| 565 | status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10); | ||
| 566 | break; | ||
| 567 | case 0x38: /* 1 1 1 x x x */ | ||
| 568 | case 0x3c: | ||
| 569 | status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11); | ||
| 570 | break; | ||
| 571 | /* obsolete AT45DB1282 not (yet?) supported */ | ||
| 572 | default: | ||
| 573 | DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", | ||
| 574 | spi->dev.bus_id, status & 0x3c); | ||
| 575 | status = -ENODEV; | ||
| 576 | } | ||
| 577 | |||
| 578 | if (status < 0) | ||
| 579 | DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", | ||
| 580 | spi->dev.bus_id, status); | ||
| 581 | |||
| 582 | return status; | ||
| 583 | } | ||
| 584 | |||
| 585 | static int __devexit dataflash_remove(struct spi_device *spi) | ||
| 586 | { | ||
| 587 | struct dataflash *flash = dev_get_drvdata(&spi->dev); | ||
| 588 | int status; | ||
| 589 | |||
| 590 | DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id); | ||
| 591 | |||
| 592 | if (mtd_has_partitions() && flash->partitioned) | ||
| 593 | status = del_mtd_partitions(&flash->mtd); | ||
| 594 | else | ||
| 595 | status = del_mtd_device(&flash->mtd); | ||
| 596 | if (status == 0) | ||
| 597 | kfree(flash); | ||
| 598 | return status; | ||
| 599 | } | ||
| 600 | |||
| 601 | static struct spi_driver dataflash_driver = { | ||
| 602 | .driver = { | ||
| 603 | .name = "mtd_dataflash", | ||
| 604 | .bus = &spi_bus_type, | ||
| 605 | .owner = THIS_MODULE, | ||
| 606 | }, | ||
| 607 | |||
| 608 | .probe = dataflash_probe, | ||
| 609 | .remove = __devexit_p(dataflash_remove), | ||
| 610 | |||
| 611 | /* FIXME: investigate suspend and resume... */ | ||
| 612 | }; | ||
| 613 | |||
| 614 | static int __init dataflash_init(void) | ||
| 615 | { | ||
| 616 | return spi_register_driver(&dataflash_driver); | ||
| 617 | } | ||
| 618 | module_init(dataflash_init); | ||
| 619 | |||
| 620 | static void __exit dataflash_exit(void) | ||
| 621 | { | ||
| 622 | spi_unregister_driver(&dataflash_driver); | ||
| 623 | } | ||
| 624 | module_exit(dataflash_exit); | ||
| 625 | |||
| 626 | |||
| 627 | MODULE_LICENSE("GPL"); | ||
| 628 | MODULE_AUTHOR("Andrew Victor, David Brownell"); | ||
| 629 | MODULE_DESCRIPTION("MTD DataFlash driver"); | ||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 21d4e8f4b7af..ec5e45e4e4ef 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
| @@ -1506,7 +1506,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) | |||
| 1506 | return 1; | 1506 | return 1; |
| 1507 | } | 1507 | } |
| 1508 | 1508 | ||
| 1509 | static inline int __init doc_probe(unsigned long physadr) | 1509 | static int __init doc_probe(unsigned long physadr) |
| 1510 | { | 1510 | { |
| 1511 | unsigned char ChipID; | 1511 | unsigned char ChipID; |
| 1512 | struct mtd_info *mtd; | 1512 | struct mtd_info *mtd; |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c15f3e9ea07..171999e67eec 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -1387,7 +1387,7 @@ config FORCEDETH | |||
| 1387 | 1387 | ||
| 1388 | config CS89x0 | 1388 | config CS89x0 |
| 1389 | tristate "CS89x0 support" | 1389 | tristate "CS89x0 support" |
| 1390 | depends on NET_PCI && (ISA || ARCH_IXDP2X01 || ARCH_PNX010X) | 1390 | depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X) |
| 1391 | ---help--- | 1391 | ---help--- |
| 1392 | Support for CS89x0 chipset based Ethernet cards. If you have a | 1392 | Support for CS89x0 chipset based Ethernet cards. If you have a |
| 1393 | network (Ethernet) card of this type, say Y and read the | 1393 | network (Ethernet) card of this type, say Y and read the |
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index e2cfde7e31ec..fab6586d87e9 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c | |||
| @@ -87,6 +87,12 @@ | |||
| 87 | Deepak Saxena : dsaxena@plexity.net | 87 | Deepak Saxena : dsaxena@plexity.net |
| 88 | : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support | 88 | : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support |
| 89 | 89 | ||
| 90 | Dmitry Pervushin : dpervushin@ru.mvista.com | ||
| 91 | : PNX010X platform support | ||
| 92 | |||
| 93 | Deepak Saxena : dsaxena@plexity.net | ||
| 94 | : Intel IXDP2351 platform support | ||
| 95 | |||
| 90 | */ | 96 | */ |
| 91 | 97 | ||
| 92 | /* Always include 'config.h' first in case the user wants to turn on | 98 | /* Always include 'config.h' first in case the user wants to turn on |
| @@ -171,6 +177,10 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0}; | |||
| 171 | static unsigned int netcard_portlist[] __initdata = | 177 | static unsigned int netcard_portlist[] __initdata = |
| 172 | { 0x0300, 0}; | 178 | { 0x0300, 0}; |
| 173 | static unsigned int cs8900_irq_map[] = {1,0,0,0}; | 179 | static unsigned int cs8900_irq_map[] = {1,0,0,0}; |
| 180 | #elif defined(CONFIG_MACH_IXDP2351) | ||
| 181 | static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; | ||
| 182 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; | ||
| 183 | #include <asm/irq.h> | ||
| 174 | #elif defined(CONFIG_ARCH_IXDP2X01) | 184 | #elif defined(CONFIG_ARCH_IXDP2X01) |
| 175 | #include <asm/irq.h> | 185 | #include <asm/irq.h> |
| 176 | static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; | 186 | static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; |
| @@ -338,45 +348,55 @@ out: | |||
| 338 | } | 348 | } |
| 339 | #endif | 349 | #endif |
| 340 | 350 | ||
| 341 | #if defined(CONFIG_ARCH_IXDP2X01) | 351 | #if defined(CONFIG_MACH_IXDP2351) |
| 342 | static int | 352 | static u16 |
| 343 | readword(unsigned long base_addr, int portno) | 353 | readword(unsigned long base_addr, int portno) |
| 344 | { | 354 | { |
| 345 | return (u16)__raw_readl(base_addr + (portno << 1)); | 355 | return __raw_readw(base_addr + (portno << 1)); |
| 346 | } | 356 | } |
| 347 | 357 | ||
| 348 | static void | 358 | static void |
| 349 | writeword(unsigned long base_addr, int portno, int value) | 359 | writeword(unsigned long base_addr, int portno, u16 value) |
| 350 | { | 360 | { |
| 351 | __raw_writel((u16)value, base_addr + (portno << 1)); | 361 | __raw_writew(value, base_addr + (portno << 1)); |
| 352 | } | 362 | } |
| 353 | #else | 363 | #elif defined(CONFIG_ARCH_IXDP2X01) |
| 354 | #if defined(CONFIG_ARCH_PNX010X) | 364 | static u16 |
| 355 | static int | 365 | readword(unsigned long base_addr, int portno) |
| 366 | { | ||
| 367 | return __raw_readl(base_addr + (portno << 1)); | ||
| 368 | } | ||
| 369 | |||
| 370 | static void | ||
| 371 | writeword(unsigned long base_addr, int portno, u16 value) | ||
| 372 | { | ||
| 373 | __raw_writel(value, base_addr + (portno << 1)); | ||
| 374 | } | ||
| 375 | #elif defined(CONFIG_ARCH_PNX010X) | ||
| 376 | static u16 | ||
| 356 | readword(unsigned long base_addr, int portno) | 377 | readword(unsigned long base_addr, int portno) |
| 357 | { | 378 | { |
| 358 | return inw(base_addr + (portno << 1)); | 379 | return inw(base_addr + (portno << 1)); |
| 359 | } | 380 | } |
| 360 | 381 | ||
| 361 | static void | 382 | static void |
| 362 | writeword(unsigned long base_addr, int portno, int value) | 383 | writeword(unsigned long base_addr, int portno, u16 value) |
| 363 | { | 384 | { |
| 364 | outw(value, base_addr + (portno << 1)); | 385 | outw(value, base_addr + (portno << 1)); |
| 365 | } | 386 | } |
| 366 | #else | 387 | #else |
| 367 | static int | 388 | static u16 |
| 368 | readword(unsigned long base_addr, int portno) | 389 | readword(unsigned long base_addr, int portno) |
| 369 | { | 390 | { |
| 370 | return inw(base_addr + portno); | 391 | return inw(base_addr + portno); |
| 371 | } | 392 | } |
| 372 | 393 | ||
| 373 | static void | 394 | static void |
| 374 | writeword(unsigned long base_addr, int portno, int value) | 395 | writeword(unsigned long base_addr, int portno, u16 value) |
| 375 | { | 396 | { |
| 376 | outw(value, base_addr + portno); | 397 | outw(value, base_addr + portno); |
| 377 | } | 398 | } |
| 378 | #endif | 399 | #endif |
| 379 | #endif | ||
| 380 | 400 | ||
| 381 | static void | 401 | static void |
| 382 | readwords(unsigned long base_addr, int portno, void *buf, int length) | 402 | readwords(unsigned long base_addr, int portno, void *buf, int length) |
| @@ -384,11 +404,11 @@ readwords(unsigned long base_addr, int portno, void *buf, int length) | |||
| 384 | u8 *buf8 = (u8 *)buf; | 404 | u8 *buf8 = (u8 *)buf; |
| 385 | 405 | ||
| 386 | do { | 406 | do { |
| 387 | u32 tmp32; | 407 | u16 tmp16; |
| 388 | 408 | ||
| 389 | tmp32 = readword(base_addr, portno); | 409 | tmp16 = readword(base_addr, portno); |
| 390 | *buf8++ = (u8)tmp32; | 410 | *buf8++ = (u8)tmp16; |
| 391 | *buf8++ = (u8)(tmp32 >> 8); | 411 | *buf8++ = (u8)(tmp16 >> 8); |
| 392 | } while (--length); | 412 | } while (--length); |
| 393 | } | 413 | } |
| 394 | 414 | ||
| @@ -398,23 +418,23 @@ writewords(unsigned long base_addr, int portno, void *buf, int length) | |||
| 398 | u8 *buf8 = (u8 *)buf; | 418 | u8 *buf8 = (u8 *)buf; |
| 399 | 419 | ||
| 400 | do { | 420 | do { |
| 401 | u32 tmp32; | 421 | u16 tmp16; |
| 402 | 422 | ||
| 403 | tmp32 = *buf8++; | 423 | tmp16 = *buf8++; |
| 404 | tmp32 |= (*buf8++) << 8; | 424 | tmp16 |= (*buf8++) << 8; |
| 405 | writeword(base_addr, portno, tmp32); | 425 | writeword(base_addr, portno, tmp16); |
| 406 | } while (--length); | 426 | } while (--length); |
| 407 | } | 427 | } |
| 408 | 428 | ||
| 409 | static int | 429 | static u16 |
| 410 | readreg(struct net_device *dev, int regno) | 430 | readreg(struct net_device *dev, u16 regno) |
| 411 | { | 431 | { |
| 412 | writeword(dev->base_addr, ADD_PORT, regno); | 432 | writeword(dev->base_addr, ADD_PORT, regno); |
| 413 | return readword(dev->base_addr, DATA_PORT); | 433 | return readword(dev->base_addr, DATA_PORT); |
| 414 | } | 434 | } |
| 415 | 435 | ||
| 416 | static void | 436 | static void |
| 417 | writereg(struct net_device *dev, int regno, int value) | 437 | writereg(struct net_device *dev, u16 regno, u16 value) |
| 418 | { | 438 | { |
| 419 | writeword(dev->base_addr, ADD_PORT, regno); | 439 | writeword(dev->base_addr, ADD_PORT, regno); |
| 420 | writeword(dev->base_addr, DATA_PORT, value); | 440 | writeword(dev->base_addr, DATA_PORT, value); |
| @@ -780,7 +800,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 780 | } else { | 800 | } else { |
| 781 | i = lp->isa_config & INT_NO_MASK; | 801 | i = lp->isa_config & INT_NO_MASK; |
| 782 | if (lp->chip_type == CS8900) { | 802 | if (lp->chip_type == CS8900) { |
| 783 | #if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) | 803 | #if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) |
| 784 | i = cs8900_irq_map[0]; | 804 | i = cs8900_irq_map[0]; |
| 785 | #else | 805 | #else |
| 786 | /* Translate the IRQ using the IRQ mapping table. */ | 806 | /* Translate the IRQ using the IRQ mapping table. */ |
| @@ -1012,7 +1032,7 @@ skip_this_frame: | |||
| 1012 | 1032 | ||
| 1013 | void __init reset_chip(struct net_device *dev) | 1033 | void __init reset_chip(struct net_device *dev) |
| 1014 | { | 1034 | { |
| 1015 | #ifndef CONFIG_ARCH_IXDP2X01 | 1035 | #if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) |
| 1016 | struct net_local *lp = netdev_priv(dev); | 1036 | struct net_local *lp = netdev_priv(dev); |
| 1017 | int ioaddr = dev->base_addr; | 1037 | int ioaddr = dev->base_addr; |
| 1018 | #endif | 1038 | #endif |
| @@ -1023,7 +1043,7 @@ void __init reset_chip(struct net_device *dev) | |||
| 1023 | /* wait 30 ms */ | 1043 | /* wait 30 ms */ |
| 1024 | msleep(30); | 1044 | msleep(30); |
| 1025 | 1045 | ||
| 1026 | #ifndef CONFIG_ARCH_IXDP2X01 | 1046 | #if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) |
| 1027 | if (lp->chip_type != CS8900) { | 1047 | if (lp->chip_type != CS8900) { |
| 1028 | /* Hardware problem requires PNP registers to be reconfigured after a reset */ | 1048 | /* Hardware problem requires PNP registers to be reconfigured after a reset */ |
| 1029 | writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); | 1049 | writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); |
| @@ -1287,7 +1307,7 @@ net_open(struct net_device *dev) | |||
| 1287 | else | 1307 | else |
| 1288 | #endif | 1308 | #endif |
| 1289 | { | 1309 | { |
| 1290 | #if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) | 1310 | #if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) |
| 1291 | if (((1 << dev->irq) & lp->irq_map) == 0) { | 1311 | if (((1 << dev->irq) & lp->irq_map) == 0) { |
| 1292 | printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", | 1312 | printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", |
| 1293 | dev->name, dev->irq, lp->irq_map); | 1313 | dev->name, dev->irq, lp->irq_map); |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 23de22631c64..4726722a0635 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
| @@ -592,7 +592,7 @@ static inline void e100_write_flush(struct nic *nic) | |||
| 592 | (void)readb(&nic->csr->scb.status); | 592 | (void)readb(&nic->csr->scb.status); |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | static inline void e100_enable_irq(struct nic *nic) | 595 | static void e100_enable_irq(struct nic *nic) |
| 596 | { | 596 | { |
| 597 | unsigned long flags; | 597 | unsigned long flags; |
| 598 | 598 | ||
| @@ -602,7 +602,7 @@ static inline void e100_enable_irq(struct nic *nic) | |||
| 602 | e100_write_flush(nic); | 602 | e100_write_flush(nic); |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | static inline void e100_disable_irq(struct nic *nic) | 605 | static void e100_disable_irq(struct nic *nic) |
| 606 | { | 606 | { |
| 607 | unsigned long flags; | 607 | unsigned long flags; |
| 608 | 608 | ||
| @@ -791,7 +791,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) | |||
| 791 | 791 | ||
| 792 | #define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ | 792 | #define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ |
| 793 | #define E100_WAIT_SCB_FAST 20 /* delay like the old code */ | 793 | #define E100_WAIT_SCB_FAST 20 /* delay like the old code */ |
| 794 | static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) | 794 | static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) |
| 795 | { | 795 | { |
| 796 | unsigned long flags; | 796 | unsigned long flags; |
| 797 | unsigned int i; | 797 | unsigned int i; |
| @@ -822,7 +822,7 @@ err_unlock: | |||
| 822 | return err; | 822 | return err; |
| 823 | } | 823 | } |
| 824 | 824 | ||
| 825 | static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb, | 825 | static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, |
| 826 | void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) | 826 | void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) |
| 827 | { | 827 | { |
| 828 | struct cb *cb; | 828 | struct cb *cb; |
| @@ -1567,7 +1567,7 @@ static void e100_watchdog(unsigned long data) | |||
| 1567 | mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); | 1567 | mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); |
| 1568 | } | 1568 | } |
| 1569 | 1569 | ||
| 1570 | static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, | 1570 | static void e100_xmit_prepare(struct nic *nic, struct cb *cb, |
| 1571 | struct sk_buff *skb) | 1571 | struct sk_buff *skb) |
| 1572 | { | 1572 | { |
| 1573 | cb->command = nic->tx_command; | 1573 | cb->command = nic->tx_command; |
| @@ -1617,7 +1617,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
| 1617 | return 0; | 1617 | return 0; |
| 1618 | } | 1618 | } |
| 1619 | 1619 | ||
| 1620 | static inline int e100_tx_clean(struct nic *nic) | 1620 | static int e100_tx_clean(struct nic *nic) |
| 1621 | { | 1621 | { |
| 1622 | struct cb *cb; | 1622 | struct cb *cb; |
| 1623 | int tx_cleaned = 0; | 1623 | int tx_cleaned = 0; |
| @@ -1728,7 +1728,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx) | |||
| 1728 | } | 1728 | } |
| 1729 | 1729 | ||
| 1730 | #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) | 1730 | #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) |
| 1731 | static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) | 1731 | static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) |
| 1732 | { | 1732 | { |
| 1733 | if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN))) | 1733 | if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN))) |
| 1734 | return -ENOMEM; | 1734 | return -ENOMEM; |
| @@ -1762,7 +1762,7 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) | |||
| 1762 | return 0; | 1762 | return 0; |
| 1763 | } | 1763 | } |
| 1764 | 1764 | ||
| 1765 | static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, | 1765 | static int e100_rx_indicate(struct nic *nic, struct rx *rx, |
| 1766 | unsigned int *work_done, unsigned int work_to_do) | 1766 | unsigned int *work_done, unsigned int work_to_do) |
| 1767 | { | 1767 | { |
| 1768 | struct sk_buff *skb = rx->skb; | 1768 | struct sk_buff *skb = rx->skb; |
| @@ -1822,7 +1822,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
| 1822 | return 0; | 1822 | return 0; |
| 1823 | } | 1823 | } |
| 1824 | 1824 | ||
| 1825 | static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done, | 1825 | static void e100_rx_clean(struct nic *nic, unsigned int *work_done, |
| 1826 | unsigned int work_to_do) | 1826 | unsigned int work_to_do) |
| 1827 | { | 1827 | { |
| 1828 | struct rx *rx; | 1828 | struct rx *rx; |
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index d6388e1533f0..76139478c3df 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c | |||
| @@ -94,7 +94,7 @@ static inline int card_wait_for_busy_clear(const int ioaddr[], | |||
| 94 | const char* name); | 94 | const char* name); |
| 95 | static inline int card_wait_for_ready(const int ioaddr[], const char* name, | 95 | static inline int card_wait_for_ready(const int ioaddr[], const char* name, |
| 96 | unsigned char in[]); | 96 | unsigned char in[]); |
| 97 | static inline int card_send_command(const int ioaddr[], const char* name, | 97 | static int card_send_command(const int ioaddr[], const char* name, |
| 98 | const unsigned char out[], unsigned char in[]); | 98 | const unsigned char out[], unsigned char in[]); |
| 99 | 99 | ||
| 100 | /* SB1000 hardware routines to be used during frame rx interrupt */ | 100 | /* SB1000 hardware routines to be used during frame rx interrupt */ |
| @@ -309,7 +309,7 @@ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[]) | |||
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | /* Card Send Command (cannot be used during an interrupt) */ | 311 | /* Card Send Command (cannot be used during an interrupt) */ |
| 312 | static inline int | 312 | static int |
| 313 | card_send_command(const int ioaddr[], const char* name, | 313 | card_send_command(const int ioaddr[], const char* name, |
| 314 | const unsigned char out[], unsigned char in[]) | 314 | const unsigned char out[], unsigned char in[]) |
| 315 | { | 315 | { |
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index ffac50899454..4b13b76425c1 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c | |||
| @@ -435,7 +435,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb, | |||
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | 437 | ||
| 438 | static inline int | 438 | static int |
| 439 | hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, | 439 | hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, |
| 440 | struct hostap_80211_rx_status *rx_stats, u16 type, | 440 | struct hostap_80211_rx_status *rx_stats, u16 type, |
| 441 | u16 stype) | 441 | u16 stype) |
| @@ -499,7 +499,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, | |||
| 499 | 499 | ||
| 500 | 500 | ||
| 501 | /* Called only as a tasklet (software IRQ) */ | 501 | /* Called only as a tasklet (software IRQ) */ |
| 502 | static inline struct net_device *prism2_rx_get_wds(local_info_t *local, | 502 | static struct net_device *prism2_rx_get_wds(local_info_t *local, |
| 503 | u8 *addr) | 503 | u8 *addr) |
| 504 | { | 504 | { |
| 505 | struct hostap_interface *iface = NULL; | 505 | struct hostap_interface *iface = NULL; |
| @@ -519,7 +519,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local, | |||
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | 521 | ||
| 522 | static inline int | 522 | static int |
| 523 | hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr, | 523 | hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr, |
| 524 | u16 fc, struct net_device **wds) | 524 | u16 fc, struct net_device **wds) |
| 525 | { | 525 | { |
| @@ -615,7 +615,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb) | |||
| 615 | 615 | ||
| 616 | 616 | ||
| 617 | /* Called only as a tasklet (software IRQ) */ | 617 | /* Called only as a tasklet (software IRQ) */ |
| 618 | static inline int | 618 | static int |
| 619 | hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, | 619 | hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, |
| 620 | struct ieee80211_crypt_data *crypt) | 620 | struct ieee80211_crypt_data *crypt) |
| 621 | { | 621 | { |
| @@ -654,7 +654,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, | |||
| 654 | 654 | ||
| 655 | 655 | ||
| 656 | /* Called only as a tasklet (software IRQ) */ | 656 | /* Called only as a tasklet (software IRQ) */ |
| 657 | static inline int | 657 | static int |
| 658 | hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, | 658 | hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, |
| 659 | int keyidx, struct ieee80211_crypt_data *crypt) | 659 | int keyidx, struct ieee80211_crypt_data *crypt) |
| 660 | { | 660 | { |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index abfae7fedebc..b1f142d9e232 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
| @@ -253,7 +253,7 @@ static void prism2_clear_cmd_queue(local_info_t *local) | |||
| 253 | * @dev: pointer to net_device | 253 | * @dev: pointer to net_device |
| 254 | * @entry: Prism2 command queue entry to be issued | 254 | * @entry: Prism2 command queue entry to be issued |
| 255 | */ | 255 | */ |
| 256 | static inline int hfa384x_cmd_issue(struct net_device *dev, | 256 | static int hfa384x_cmd_issue(struct net_device *dev, |
| 257 | struct hostap_cmd_queue *entry) | 257 | struct hostap_cmd_queue *entry) |
| 258 | { | 258 | { |
| 259 | struct hostap_interface *iface; | 259 | struct hostap_interface *iface; |
| @@ -743,7 +743,7 @@ static void prism2_cmd_ev(struct net_device *dev) | |||
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | 745 | ||
| 746 | static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off) | 746 | static int hfa384x_wait_offset(struct net_device *dev, u16 o_off) |
| 747 | { | 747 | { |
| 748 | int tries = HFA384X_BAP_BUSY_TIMEOUT; | 748 | int tries = HFA384X_BAP_BUSY_TIMEOUT; |
| 749 | int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; | 749 | int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; |
| @@ -1904,7 +1904,7 @@ fail: | |||
| 1904 | * and will try to get the correct fid eventually. */ | 1904 | * and will try to get the correct fid eventually. */ |
| 1905 | #define EXTRA_FID_READ_TESTS | 1905 | #define EXTRA_FID_READ_TESTS |
| 1906 | 1906 | ||
| 1907 | static inline u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) | 1907 | static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) |
| 1908 | { | 1908 | { |
| 1909 | #ifdef EXTRA_FID_READ_TESTS | 1909 | #ifdef EXTRA_FID_READ_TESTS |
| 1910 | u16 val, val2, val3; | 1910 | u16 val, val2, val3; |
| @@ -2581,7 +2581,7 @@ static void prism2_ev_tick(struct net_device *dev) | |||
| 2581 | 2581 | ||
| 2582 | 2582 | ||
| 2583 | /* Called only from hardware IRQ */ | 2583 | /* Called only from hardware IRQ */ |
| 2584 | static inline void prism2_check_magic(local_info_t *local) | 2584 | static void prism2_check_magic(local_info_t *local) |
| 2585 | { | 2585 | { |
| 2586 | /* at least PCI Prism2.5 with bus mastering seems to sometimes | 2586 | /* at least PCI Prism2.5 with bus mastering seems to sometimes |
| 2587 | * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the | 2587 | * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the |
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index cf05661fb1bd..7518384f34d9 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c | |||
| @@ -411,7 +411,7 @@ static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val) | |||
| 411 | write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val); | 411 | write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val); |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, | 414 | static void write_nic_memory(struct net_device *dev, u32 addr, u32 len, |
| 415 | const u8 * buf) | 415 | const u8 * buf) |
| 416 | { | 416 | { |
| 417 | u32 aligned_addr; | 417 | u32 aligned_addr; |
| @@ -449,7 +449,7 @@ static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, | |||
| 449 | *buf); | 449 | *buf); |
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, | 452 | static void read_nic_memory(struct net_device *dev, u32 addr, u32 len, |
| 453 | u8 * buf) | 453 | u8 * buf) |
| 454 | { | 454 | { |
| 455 | u32 aligned_addr; | 455 | u32 aligned_addr; |
| @@ -657,7 +657,7 @@ static void printk_buf(int level, const u8 * data, u32 len) | |||
| 657 | 657 | ||
| 658 | #define MAX_RESET_BACKOFF 10 | 658 | #define MAX_RESET_BACKOFF 10 |
| 659 | 659 | ||
| 660 | static inline void schedule_reset(struct ipw2100_priv *priv) | 660 | static void schedule_reset(struct ipw2100_priv *priv) |
| 661 | { | 661 | { |
| 662 | unsigned long now = get_seconds(); | 662 | unsigned long now = get_seconds(); |
| 663 | 663 | ||
| @@ -1130,7 +1130,7 @@ static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv) | |||
| 1130 | write_register(priv->net_dev, IPW_REG_GPIO, reg); | 1130 | write_register(priv->net_dev, IPW_REG_GPIO, reg); |
| 1131 | } | 1131 | } |
| 1132 | 1132 | ||
| 1133 | static inline int rf_kill_active(struct ipw2100_priv *priv) | 1133 | static int rf_kill_active(struct ipw2100_priv *priv) |
| 1134 | { | 1134 | { |
| 1135 | #define MAX_RF_KILL_CHECKS 5 | 1135 | #define MAX_RF_KILL_CHECKS 5 |
| 1136 | #define RF_KILL_CHECK_DELAY 40 | 1136 | #define RF_KILL_CHECK_DELAY 40 |
| @@ -2177,7 +2177,7 @@ static const char *frame_types[] = { | |||
| 2177 | }; | 2177 | }; |
| 2178 | #endif | 2178 | #endif |
| 2179 | 2179 | ||
| 2180 | static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, | 2180 | static int ipw2100_alloc_skb(struct ipw2100_priv *priv, |
| 2181 | struct ipw2100_rx_packet *packet) | 2181 | struct ipw2100_rx_packet *packet) |
| 2182 | { | 2182 | { |
| 2183 | packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); | 2183 | packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); |
| @@ -2201,7 +2201,7 @@ static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, | |||
| 2201 | #define SEARCH_SNAPSHOT 1 | 2201 | #define SEARCH_SNAPSHOT 1 |
| 2202 | 2202 | ||
| 2203 | #define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) | 2203 | #define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) |
| 2204 | static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) | 2204 | static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) |
| 2205 | { | 2205 | { |
| 2206 | int i; | 2206 | int i; |
| 2207 | if (priv->snapshot[0]) | 2207 | if (priv->snapshot[0]) |
| @@ -2221,7 +2221,7 @@ static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) | |||
| 2221 | return 1; | 2221 | return 1; |
| 2222 | } | 2222 | } |
| 2223 | 2223 | ||
| 2224 | static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) | 2224 | static void ipw2100_snapshot_free(struct ipw2100_priv *priv) |
| 2225 | { | 2225 | { |
| 2226 | int i; | 2226 | int i; |
| 2227 | if (!priv->snapshot[0]) | 2227 | if (!priv->snapshot[0]) |
| @@ -2231,7 +2231,7 @@ static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) | |||
| 2231 | priv->snapshot[0] = NULL; | 2231 | priv->snapshot[0] = NULL; |
| 2232 | } | 2232 | } |
| 2233 | 2233 | ||
| 2234 | static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, | 2234 | static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, |
| 2235 | size_t len, int mode) | 2235 | size_t len, int mode) |
| 2236 | { | 2236 | { |
| 2237 | u32 i, j; | 2237 | u32 i, j; |
| @@ -2288,7 +2288,7 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, | |||
| 2288 | static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; | 2288 | static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; |
| 2289 | #endif | 2289 | #endif |
| 2290 | 2290 | ||
| 2291 | static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) | 2291 | static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) |
| 2292 | { | 2292 | { |
| 2293 | #ifdef CONFIG_IPW2100_DEBUG_C3 | 2293 | #ifdef CONFIG_IPW2100_DEBUG_C3 |
| 2294 | struct ipw2100_status *status = &priv->status_queue.drv[i]; | 2294 | struct ipw2100_status *status = &priv->status_queue.drv[i]; |
| @@ -2346,7 +2346,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) | |||
| 2346 | schedule_reset(priv); | 2346 | schedule_reset(priv); |
| 2347 | } | 2347 | } |
| 2348 | 2348 | ||
| 2349 | static inline void isr_rx(struct ipw2100_priv *priv, int i, | 2349 | static void isr_rx(struct ipw2100_priv *priv, int i, |
| 2350 | struct ieee80211_rx_stats *stats) | 2350 | struct ieee80211_rx_stats *stats) |
| 2351 | { | 2351 | { |
| 2352 | struct ipw2100_status *status = &priv->status_queue.drv[i]; | 2352 | struct ipw2100_status *status = &priv->status_queue.drv[i]; |
| @@ -2425,7 +2425,7 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i, | |||
| 2425 | priv->rx_queue.drv[i].host_addr = packet->dma_addr; | 2425 | priv->rx_queue.drv[i].host_addr = packet->dma_addr; |
| 2426 | } | 2426 | } |
| 2427 | 2427 | ||
| 2428 | static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) | 2428 | static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) |
| 2429 | { | 2429 | { |
| 2430 | struct ipw2100_status *status = &priv->status_queue.drv[i]; | 2430 | struct ipw2100_status *status = &priv->status_queue.drv[i]; |
| 2431 | struct ipw2100_rx *u = priv->rx_buffers[i].rxp; | 2431 | struct ipw2100_rx *u = priv->rx_buffers[i].rxp; |
| @@ -2481,7 +2481,7 @@ static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) | |||
| 2481 | * The WRITE index is cached in the variable 'priv->rx_queue.next'. | 2481 | * The WRITE index is cached in the variable 'priv->rx_queue.next'. |
| 2482 | * | 2482 | * |
| 2483 | */ | 2483 | */ |
| 2484 | static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) | 2484 | static void __ipw2100_rx_process(struct ipw2100_priv *priv) |
| 2485 | { | 2485 | { |
| 2486 | struct ipw2100_bd_queue *rxq = &priv->rx_queue; | 2486 | struct ipw2100_bd_queue *rxq = &priv->rx_queue; |
| 2487 | struct ipw2100_status_queue *sq = &priv->status_queue; | 2487 | struct ipw2100_status_queue *sq = &priv->status_queue; |
| @@ -2634,7 +2634,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) | |||
| 2634 | * for use by future command and data packets. | 2634 | * for use by future command and data packets. |
| 2635 | * | 2635 | * |
| 2636 | */ | 2636 | */ |
| 2637 | static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) | 2637 | static int __ipw2100_tx_process(struct ipw2100_priv *priv) |
| 2638 | { | 2638 | { |
| 2639 | struct ipw2100_bd_queue *txq = &priv->tx_queue; | 2639 | struct ipw2100_bd_queue *txq = &priv->tx_queue; |
| 2640 | struct ipw2100_bd *tbd; | 2640 | struct ipw2100_bd *tbd; |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index cdfe50207757..819be2b6b7df 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
| @@ -813,7 +813,7 @@ static void ipw_bg_led_link_off(void *data) | |||
| 813 | up(&priv->sem); | 813 | up(&priv->sem); |
| 814 | } | 814 | } |
| 815 | 815 | ||
| 816 | static inline void __ipw_led_activity_on(struct ipw_priv *priv) | 816 | static void __ipw_led_activity_on(struct ipw_priv *priv) |
| 817 | { | 817 | { |
| 818 | u32 led; | 818 | u32 led; |
| 819 | 819 | ||
| @@ -1508,7 +1508,7 @@ static ssize_t store_direct_dword(struct device *d, | |||
| 1508 | static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, | 1508 | static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, |
| 1509 | show_direct_dword, store_direct_dword); | 1509 | show_direct_dword, store_direct_dword); |
| 1510 | 1510 | ||
| 1511 | static inline int rf_kill_active(struct ipw_priv *priv) | 1511 | static int rf_kill_active(struct ipw_priv *priv) |
| 1512 | { | 1512 | { |
| 1513 | if (0 == (ipw_read32(priv, 0x30) & 0x10000)) | 1513 | if (0 == (ipw_read32(priv, 0x30) & 0x10000)) |
| 1514 | priv->status |= STATUS_RF_KILL_HW; | 1514 | priv->status |= STATUS_RF_KILL_HW; |
| @@ -2359,7 +2359,7 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data) | |||
| 2359 | } | 2359 | } |
| 2360 | 2360 | ||
| 2361 | /* perform a chip select operation */ | 2361 | /* perform a chip select operation */ |
| 2362 | static inline void eeprom_cs(struct ipw_priv *priv) | 2362 | static void eeprom_cs(struct ipw_priv *priv) |
| 2363 | { | 2363 | { |
| 2364 | eeprom_write_reg(priv, 0); | 2364 | eeprom_write_reg(priv, 0); |
| 2365 | eeprom_write_reg(priv, EEPROM_BIT_CS); | 2365 | eeprom_write_reg(priv, EEPROM_BIT_CS); |
| @@ -2368,7 +2368,7 @@ static inline void eeprom_cs(struct ipw_priv *priv) | |||
| 2368 | } | 2368 | } |
| 2369 | 2369 | ||
| 2370 | /* perform a chip select operation */ | 2370 | /* perform a chip select operation */ |
| 2371 | static inline void eeprom_disable_cs(struct ipw_priv *priv) | 2371 | static void eeprom_disable_cs(struct ipw_priv *priv) |
| 2372 | { | 2372 | { |
| 2373 | eeprom_write_reg(priv, EEPROM_BIT_CS); | 2373 | eeprom_write_reg(priv, EEPROM_BIT_CS); |
| 2374 | eeprom_write_reg(priv, 0); | 2374 | eeprom_write_reg(priv, 0); |
| @@ -2475,7 +2475,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) | |||
| 2475 | IPW_DEBUG_TRACE("<<\n"); | 2475 | IPW_DEBUG_TRACE("<<\n"); |
| 2476 | } | 2476 | } |
| 2477 | 2477 | ||
| 2478 | static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) | 2478 | static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) |
| 2479 | { | 2479 | { |
| 2480 | count >>= 2; | 2480 | count >>= 2; |
| 2481 | if (!count) | 2481 | if (!count) |
| @@ -2772,7 +2772,7 @@ static inline int ipw_alive(struct ipw_priv *priv) | |||
| 2772 | return ipw_read32(priv, 0x90) == 0xd55555d5; | 2772 | return ipw_read32(priv, 0x90) == 0xd55555d5; |
| 2773 | } | 2773 | } |
| 2774 | 2774 | ||
| 2775 | static inline int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, | 2775 | static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, |
| 2776 | int timeout) | 2776 | int timeout) |
| 2777 | { | 2777 | { |
| 2778 | int i = 0; | 2778 | int i = 0; |
| @@ -3150,7 +3150,7 @@ static int ipw_get_fw(struct ipw_priv *priv, | |||
| 3150 | 3150 | ||
| 3151 | #define IPW_RX_BUF_SIZE (3000) | 3151 | #define IPW_RX_BUF_SIZE (3000) |
| 3152 | 3152 | ||
| 3153 | static inline void ipw_rx_queue_reset(struct ipw_priv *priv, | 3153 | static void ipw_rx_queue_reset(struct ipw_priv *priv, |
| 3154 | struct ipw_rx_queue *rxq) | 3154 | struct ipw_rx_queue *rxq) |
| 3155 | { | 3155 | { |
| 3156 | unsigned long flags; | 3156 | unsigned long flags; |
| @@ -3608,7 +3608,7 @@ static void ipw_tx_queue_free(struct ipw_priv *priv) | |||
| 3608 | ipw_queue_tx_free(priv, &priv->txq[3]); | 3608 | ipw_queue_tx_free(priv, &priv->txq[3]); |
| 3609 | } | 3609 | } |
| 3610 | 3610 | ||
| 3611 | static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) | 3611 | static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) |
| 3612 | { | 3612 | { |
| 3613 | /* First 3 bytes are manufacturer */ | 3613 | /* First 3 bytes are manufacturer */ |
| 3614 | bssid[0] = priv->mac_addr[0]; | 3614 | bssid[0] = priv->mac_addr[0]; |
| @@ -3622,7 +3622,7 @@ static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) | |||
| 3622 | bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */ | 3622 | bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */ |
| 3623 | } | 3623 | } |
| 3624 | 3624 | ||
| 3625 | static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) | 3625 | static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) |
| 3626 | { | 3626 | { |
| 3627 | struct ipw_station_entry entry; | 3627 | struct ipw_station_entry entry; |
| 3628 | int i; | 3628 | int i; |
| @@ -3655,7 +3655,7 @@ static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) | |||
| 3655 | return i; | 3655 | return i; |
| 3656 | } | 3656 | } |
| 3657 | 3657 | ||
| 3658 | static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) | 3658 | static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) |
| 3659 | { | 3659 | { |
| 3660 | int i; | 3660 | int i; |
| 3661 | 3661 | ||
| @@ -3794,7 +3794,7 @@ static void inline average_init(struct average *avg) | |||
| 3794 | memset(avg, 0, sizeof(*avg)); | 3794 | memset(avg, 0, sizeof(*avg)); |
| 3795 | } | 3795 | } |
| 3796 | 3796 | ||
| 3797 | static void inline average_add(struct average *avg, s16 val) | 3797 | static void average_add(struct average *avg, s16 val) |
| 3798 | { | 3798 | { |
| 3799 | avg->sum -= avg->entries[avg->pos]; | 3799 | avg->sum -= avg->entries[avg->pos]; |
| 3800 | avg->sum += val; | 3800 | avg->sum += val; |
| @@ -3805,7 +3805,7 @@ static void inline average_add(struct average *avg, s16 val) | |||
| 3805 | } | 3805 | } |
| 3806 | } | 3806 | } |
| 3807 | 3807 | ||
| 3808 | static s16 inline average_value(struct average *avg) | 3808 | static s16 average_value(struct average *avg) |
| 3809 | { | 3809 | { |
| 3810 | if (!unlikely(avg->init)) { | 3810 | if (!unlikely(avg->init)) { |
| 3811 | if (avg->pos) | 3811 | if (avg->pos) |
| @@ -3847,7 +3847,7 @@ static void ipw_reset_stats(struct ipw_priv *priv) | |||
| 3847 | 3847 | ||
| 3848 | } | 3848 | } |
| 3849 | 3849 | ||
| 3850 | static inline u32 ipw_get_max_rate(struct ipw_priv *priv) | 3850 | static u32 ipw_get_max_rate(struct ipw_priv *priv) |
| 3851 | { | 3851 | { |
| 3852 | u32 i = 0x80000000; | 3852 | u32 i = 0x80000000; |
| 3853 | u32 mask = priv->rates_mask; | 3853 | u32 mask = priv->rates_mask; |
| @@ -4087,7 +4087,7 @@ static void ipw_bg_gather_stats(void *data) | |||
| 4087 | * roaming_threshold -> disassociate_threshold, scan and roam for better signal. | 4087 | * roaming_threshold -> disassociate_threshold, scan and roam for better signal. |
| 4088 | * Above disassociate threshold, give up and stop scanning. | 4088 | * Above disassociate threshold, give up and stop scanning. |
| 4089 | * Roaming is disabled if disassociate_threshold <= roaming_threshold */ | 4089 | * Roaming is disabled if disassociate_threshold <= roaming_threshold */ |
| 4090 | static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, | 4090 | static void ipw_handle_missed_beacon(struct ipw_priv *priv, |
| 4091 | int missed_count) | 4091 | int missed_count) |
| 4092 | { | 4092 | { |
| 4093 | priv->notif_missed_beacons = missed_count; | 4093 | priv->notif_missed_beacons = missed_count; |
| @@ -4157,7 +4157,7 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, | |||
| 4157 | * Handle host notification packet. | 4157 | * Handle host notification packet. |
| 4158 | * Called from interrupt routine | 4158 | * Called from interrupt routine |
| 4159 | */ | 4159 | */ |
| 4160 | static inline void ipw_rx_notification(struct ipw_priv *priv, | 4160 | static void ipw_rx_notification(struct ipw_priv *priv, |
| 4161 | struct ipw_rx_notification *notif) | 4161 | struct ipw_rx_notification *notif) |
| 4162 | { | 4162 | { |
| 4163 | notif->size = le16_to_cpu(notif->size); | 4163 | notif->size = le16_to_cpu(notif->size); |
| @@ -5095,7 +5095,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv, | |||
| 5095 | return 1; | 5095 | return 1; |
| 5096 | } | 5096 | } |
| 5097 | 5097 | ||
| 5098 | static inline void ipw_copy_rates(struct ipw_supported_rates *dest, | 5098 | static void ipw_copy_rates(struct ipw_supported_rates *dest, |
| 5099 | const struct ipw_supported_rates *src) | 5099 | const struct ipw_supported_rates *src) |
| 5100 | { | 5100 | { |
| 5101 | u8 i; | 5101 | u8 i; |
| @@ -5856,7 +5856,7 @@ static void ipw_debug_config(struct ipw_priv *priv) | |||
| 5856 | #define ipw_debug_config(x) do {} while (0) | 5856 | #define ipw_debug_config(x) do {} while (0) |
| 5857 | #endif | 5857 | #endif |
| 5858 | 5858 | ||
| 5859 | static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) | 5859 | static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) |
| 5860 | { | 5860 | { |
| 5861 | /* TODO: Verify that this works... */ | 5861 | /* TODO: Verify that this works... */ |
| 5862 | struct ipw_fixed_rate fr = { | 5862 | struct ipw_fixed_rate fr = { |
| @@ -7634,7 +7634,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7634 | } | 7634 | } |
| 7635 | #endif | 7635 | #endif |
| 7636 | 7636 | ||
| 7637 | static inline int is_network_packet(struct ipw_priv *priv, | 7637 | static int is_network_packet(struct ipw_priv *priv, |
| 7638 | struct ieee80211_hdr_4addr *header) | 7638 | struct ieee80211_hdr_4addr *header) |
| 7639 | { | 7639 | { |
| 7640 | /* Filter incoming packets to determine if they are targetted toward | 7640 | /* Filter incoming packets to determine if they are targetted toward |
| @@ -7672,7 +7672,7 @@ static inline int is_network_packet(struct ipw_priv *priv, | |||
| 7672 | 7672 | ||
| 7673 | #define IPW_PACKET_RETRY_TIME HZ | 7673 | #define IPW_PACKET_RETRY_TIME HZ |
| 7674 | 7674 | ||
| 7675 | static inline int is_duplicate_packet(struct ipw_priv *priv, | 7675 | static int is_duplicate_packet(struct ipw_priv *priv, |
| 7676 | struct ieee80211_hdr_4addr *header) | 7676 | struct ieee80211_hdr_4addr *header) |
| 7677 | { | 7677 | { |
| 7678 | u16 sc = le16_to_cpu(header->seq_ctl); | 7678 | u16 sc = le16_to_cpu(header->seq_ctl); |
| @@ -9581,7 +9581,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) | |||
| 9581 | 9581 | ||
| 9582 | /* net device stuff */ | 9582 | /* net device stuff */ |
| 9583 | 9583 | ||
| 9584 | static inline void init_sys_config(struct ipw_sys_config *sys_config) | 9584 | static void init_sys_config(struct ipw_sys_config *sys_config) |
| 9585 | { | 9585 | { |
| 9586 | memset(sys_config, 0, sizeof(struct ipw_sys_config)); | 9586 | memset(sys_config, 0, sizeof(struct ipw_sys_config)); |
| 9587 | sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ | 9587 | sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ |
| @@ -9627,7 +9627,7 @@ modify to send one tfd per fragment instead of using chunking. otherwise | |||
| 9627 | we need to heavily modify the ieee80211_skb_to_txb. | 9627 | we need to heavily modify the ieee80211_skb_to_txb. |
| 9628 | */ | 9628 | */ |
| 9629 | 9629 | ||
| 9630 | static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | 9630 | static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, |
| 9631 | int pri) | 9631 | int pri) |
| 9632 | { | 9632 | { |
| 9633 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) | 9633 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) |
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index b0d8b5b03152..ff192e96268a 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c | |||
| @@ -102,7 +102,7 @@ static inline void hacr_write(unsigned long ioaddr, u16 hacr) | |||
| 102 | * Write to card's Host Adapter Command Register. Include a delay for | 102 | * Write to card's Host Adapter Command Register. Include a delay for |
| 103 | * those times when it is needed. | 103 | * those times when it is needed. |
| 104 | */ | 104 | */ |
| 105 | static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr) | 105 | static void hacr_write_slow(unsigned long ioaddr, u16 hacr) |
| 106 | { | 106 | { |
| 107 | hacr_write(ioaddr, hacr); | 107 | hacr_write(ioaddr, hacr); |
| 108 | /* delay might only be needed sometimes */ | 108 | /* delay might only be needed sometimes */ |
| @@ -242,7 +242,7 @@ static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */ | |||
| 242 | * The Windows drivers don't use the CRC, but the AP and the PtP tool | 242 | * The Windows drivers don't use the CRC, but the AP and the PtP tool |
| 243 | * depend on it. | 243 | * depend on it. |
| 244 | */ | 244 | */ |
| 245 | static inline u16 psa_crc(u8 * psa, /* The PSA */ | 245 | static u16 psa_crc(u8 * psa, /* The PSA */ |
| 246 | int size) | 246 | int size) |
| 247 | { /* Number of short for CRC */ | 247 | { /* Number of short for CRC */ |
| 248 | int byte_cnt; /* Loop on the PSA */ | 248 | int byte_cnt; /* Loop on the PSA */ |
| @@ -310,7 +310,7 @@ static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u | |||
| 310 | /* | 310 | /* |
| 311 | * Write 1 byte to the MMC. | 311 | * Write 1 byte to the MMC. |
| 312 | */ | 312 | */ |
| 313 | static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) | 313 | static void mmc_out(unsigned long ioaddr, u16 o, u8 d) |
| 314 | { | 314 | { |
| 315 | int count = 0; | 315 | int count = 0; |
| 316 | 316 | ||
| @@ -326,7 +326,7 @@ static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) | |||
| 326 | * Routine to write bytes to the Modem Management Controller. | 326 | * Routine to write bytes to the Modem Management Controller. |
| 327 | * We start at the end because it is the way it should be! | 327 | * We start at the end because it is the way it should be! |
| 328 | */ | 328 | */ |
| 329 | static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) | 329 | static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) |
| 330 | { | 330 | { |
| 331 | o += n; | 331 | o += n; |
| 332 | b += n; | 332 | b += n; |
| @@ -340,7 +340,7 @@ static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) | |||
| 340 | * Read a byte from the MMC. | 340 | * Read a byte from the MMC. |
| 341 | * Optimised version for 1 byte, avoid using memory. | 341 | * Optimised version for 1 byte, avoid using memory. |
| 342 | */ | 342 | */ |
| 343 | static inline u8 mmc_in(unsigned long ioaddr, u16 o) | 343 | static u8 mmc_in(unsigned long ioaddr, u16 o) |
| 344 | { | 344 | { |
| 345 | int count = 0; | 345 | int count = 0; |
| 346 | 346 | ||
| @@ -587,7 +587,7 @@ static void wv_ack(struct net_device * dev) | |||
| 587 | * Set channel attention bit and busy wait until command has | 587 | * Set channel attention bit and busy wait until command has |
| 588 | * completed, then acknowledge completion of the command. | 588 | * completed, then acknowledge completion of the command. |
| 589 | */ | 589 | */ |
| 590 | static inline int wv_synchronous_cmd(struct net_device * dev, const char *str) | 590 | static int wv_synchronous_cmd(struct net_device * dev, const char *str) |
| 591 | { | 591 | { |
| 592 | net_local *lp = (net_local *) dev->priv; | 592 | net_local *lp = (net_local *) dev->priv; |
| 593 | unsigned long ioaddr = dev->base_addr; | 593 | unsigned long ioaddr = dev->base_addr; |
| @@ -633,7 +633,7 @@ static inline int wv_synchronous_cmd(struct net_device * dev, const char *str) | |||
| 633 | * Configuration commands completion interrupt. | 633 | * Configuration commands completion interrupt. |
| 634 | * Check if done, and if OK. | 634 | * Check if done, and if OK. |
| 635 | */ | 635 | */ |
| 636 | static inline int | 636 | static int |
| 637 | wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) | 637 | wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) |
| 638 | { | 638 | { |
| 639 | unsigned short mcs_addr; | 639 | unsigned short mcs_addr; |
| @@ -843,7 +843,7 @@ if (lp->tx_n_in_use > 0) | |||
| 843 | * wavelan_interrupt is not an option), so you may experience | 843 | * wavelan_interrupt is not an option), so you may experience |
| 844 | * delays sometimes. | 844 | * delays sometimes. |
| 845 | */ | 845 | */ |
| 846 | static inline void wv_82586_reconfig(struct net_device * dev) | 846 | static void wv_82586_reconfig(struct net_device * dev) |
| 847 | { | 847 | { |
| 848 | net_local *lp = (net_local *) dev->priv; | 848 | net_local *lp = (net_local *) dev->priv; |
| 849 | unsigned long flags; | 849 | unsigned long flags; |
| @@ -1281,7 +1281,7 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */ | |||
| 1281 | * This is the information which is displayed by the driver at startup. | 1281 | * This is the information which is displayed by the driver at startup. |
| 1282 | * There are lots of flags for configuring it to your liking. | 1282 | * There are lots of flags for configuring it to your liking. |
| 1283 | */ | 1283 | */ |
| 1284 | static inline void wv_init_info(struct net_device * dev) | 1284 | static void wv_init_info(struct net_device * dev) |
| 1285 | { | 1285 | { |
| 1286 | short ioaddr = dev->base_addr; | 1286 | short ioaddr = dev->base_addr; |
| 1287 | net_local *lp = (net_local *) dev->priv; | 1287 | net_local *lp = (net_local *) dev->priv; |
| @@ -1502,7 +1502,7 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr) | |||
| 1502 | * It's a bit complicated and you don't really want to look into it. | 1502 | * It's a bit complicated and you don't really want to look into it. |
| 1503 | * (called in wavelan_ioctl) | 1503 | * (called in wavelan_ioctl) |
| 1504 | */ | 1504 | */ |
| 1505 | static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ | 1505 | static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ |
| 1506 | iw_freq * frequency) | 1506 | iw_freq * frequency) |
| 1507 | { | 1507 | { |
| 1508 | const int BAND_NUM = 10; /* Number of bands */ | 1508 | const int BAND_NUM = 10; /* Number of bands */ |
| @@ -1677,7 +1677,7 @@ static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card | |||
| 1677 | /* | 1677 | /* |
| 1678 | * Give the list of available frequencies. | 1678 | * Give the list of available frequencies. |
| 1679 | */ | 1679 | */ |
| 1680 | static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ | 1680 | static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ |
| 1681 | iw_freq * list, /* List of frequencies to fill */ | 1681 | iw_freq * list, /* List of frequencies to fill */ |
| 1682 | int max) | 1682 | int max) |
| 1683 | { /* Maximum number of frequencies */ | 1683 | { /* Maximum number of frequencies */ |
| @@ -2489,7 +2489,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev) | |||
| 2489 | * Note: if any errors occur, the packet is "dropped on the floor". | 2489 | * Note: if any errors occur, the packet is "dropped on the floor". |
| 2490 | * (called by wv_packet_rcv()) | 2490 | * (called by wv_packet_rcv()) |
| 2491 | */ | 2491 | */ |
| 2492 | static inline void | 2492 | static void |
| 2493 | wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) | 2493 | wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) |
| 2494 | { | 2494 | { |
| 2495 | net_local *lp = (net_local *) dev->priv; | 2495 | net_local *lp = (net_local *) dev->priv; |
| @@ -2585,7 +2585,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) | |||
| 2585 | * (called in wavelan_interrupt()). | 2585 | * (called in wavelan_interrupt()). |
| 2586 | * Note : the spinlock is already grabbed for us. | 2586 | * Note : the spinlock is already grabbed for us. |
| 2587 | */ | 2587 | */ |
| 2588 | static inline void wv_receive(struct net_device * dev) | 2588 | static void wv_receive(struct net_device * dev) |
| 2589 | { | 2589 | { |
| 2590 | unsigned long ioaddr = dev->base_addr; | 2590 | unsigned long ioaddr = dev->base_addr; |
| 2591 | net_local *lp = (net_local *) dev->priv; | 2591 | net_local *lp = (net_local *) dev->priv; |
| @@ -2768,7 +2768,7 @@ static inline void wv_receive(struct net_device * dev) | |||
| 2768 | * | 2768 | * |
| 2769 | * (called in wavelan_packet_xmit()) | 2769 | * (called in wavelan_packet_xmit()) |
| 2770 | */ | 2770 | */ |
| 2771 | static inline int wv_packet_write(struct net_device * dev, void *buf, short length) | 2771 | static int wv_packet_write(struct net_device * dev, void *buf, short length) |
| 2772 | { | 2772 | { |
| 2773 | net_local *lp = (net_local *) dev->priv; | 2773 | net_local *lp = (net_local *) dev->priv; |
| 2774 | unsigned long ioaddr = dev->base_addr; | 2774 | unsigned long ioaddr = dev->base_addr; |
| @@ -2964,7 +2964,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) | |||
| 2964 | * Routine to initialize the Modem Management Controller. | 2964 | * Routine to initialize the Modem Management Controller. |
| 2965 | * (called by wv_hw_reset()) | 2965 | * (called by wv_hw_reset()) |
| 2966 | */ | 2966 | */ |
| 2967 | static inline int wv_mmc_init(struct net_device * dev) | 2967 | static int wv_mmc_init(struct net_device * dev) |
| 2968 | { | 2968 | { |
| 2969 | unsigned long ioaddr = dev->base_addr; | 2969 | unsigned long ioaddr = dev->base_addr; |
| 2970 | net_local *lp = (net_local *) dev->priv; | 2970 | net_local *lp = (net_local *) dev->priv; |
| @@ -3136,7 +3136,7 @@ static inline int wv_mmc_init(struct net_device * dev) | |||
| 3136 | * Start the receive unit. | 3136 | * Start the receive unit. |
| 3137 | * (called by wv_hw_reset()) | 3137 | * (called by wv_hw_reset()) |
| 3138 | */ | 3138 | */ |
| 3139 | static inline int wv_ru_start(struct net_device * dev) | 3139 | static int wv_ru_start(struct net_device * dev) |
| 3140 | { | 3140 | { |
| 3141 | net_local *lp = (net_local *) dev->priv; | 3141 | net_local *lp = (net_local *) dev->priv; |
| 3142 | unsigned long ioaddr = dev->base_addr; | 3142 | unsigned long ioaddr = dev->base_addr; |
| @@ -3228,7 +3228,7 @@ static inline int wv_ru_start(struct net_device * dev) | |||
| 3228 | * | 3228 | * |
| 3229 | * (called by wv_hw_reset()) | 3229 | * (called by wv_hw_reset()) |
| 3230 | */ | 3230 | */ |
| 3231 | static inline int wv_cu_start(struct net_device * dev) | 3231 | static int wv_cu_start(struct net_device * dev) |
| 3232 | { | 3232 | { |
| 3233 | net_local *lp = (net_local *) dev->priv; | 3233 | net_local *lp = (net_local *) dev->priv; |
| 3234 | unsigned long ioaddr = dev->base_addr; | 3234 | unsigned long ioaddr = dev->base_addr; |
| @@ -3329,7 +3329,7 @@ static inline int wv_cu_start(struct net_device * dev) | |||
| 3329 | * | 3329 | * |
| 3330 | * (called by wv_hw_reset()) | 3330 | * (called by wv_hw_reset()) |
| 3331 | */ | 3331 | */ |
| 3332 | static inline int wv_82586_start(struct net_device * dev) | 3332 | static int wv_82586_start(struct net_device * dev) |
| 3333 | { | 3333 | { |
| 3334 | net_local *lp = (net_local *) dev->priv; | 3334 | net_local *lp = (net_local *) dev->priv; |
| 3335 | unsigned long ioaddr = dev->base_addr; | 3335 | unsigned long ioaddr = dev->base_addr; |
| @@ -3641,7 +3641,7 @@ static void wv_82586_config(struct net_device * dev) | |||
| 3641 | * WaveLAN controller (i82586). | 3641 | * WaveLAN controller (i82586). |
| 3642 | * (called by wavelan_close()) | 3642 | * (called by wavelan_close()) |
| 3643 | */ | 3643 | */ |
| 3644 | static inline void wv_82586_stop(struct net_device * dev) | 3644 | static void wv_82586_stop(struct net_device * dev) |
| 3645 | { | 3645 | { |
| 3646 | net_local *lp = (net_local *) dev->priv; | 3646 | net_local *lp = (net_local *) dev->priv; |
| 3647 | unsigned long ioaddr = dev->base_addr; | 3647 | unsigned long ioaddr = dev->base_addr; |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7146b69b812c..0aa14c92b570 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) | |||
| 380 | /* initialize common driver fields */ | 380 | /* initialize common driver fields */ |
| 381 | drv->driver.name = drv->name; | 381 | drv->driver.name = drv->name; |
| 382 | drv->driver.bus = &pci_bus_type; | 382 | drv->driver.bus = &pci_bus_type; |
| 383 | drv->driver.probe = pci_device_probe; | ||
| 384 | drv->driver.remove = pci_device_remove; | ||
| 385 | /* FIXME, once all of the existing PCI drivers have been fixed to set | 383 | /* FIXME, once all of the existing PCI drivers have been fixed to set |
| 386 | * the pci shutdown function, this test can go away. */ | 384 | * the pci shutdown function, this test can go away. */ |
| 387 | if (!drv->driver.shutdown) | 385 | if (!drv->driver.shutdown) |
| @@ -513,6 +511,8 @@ struct bus_type pci_bus_type = { | |||
| 513 | .name = "pci", | 511 | .name = "pci", |
| 514 | .match = pci_bus_match, | 512 | .match = pci_bus_match, |
| 515 | .uevent = pci_uevent, | 513 | .uevent = pci_uevent, |
| 514 | .probe = pci_device_probe, | ||
| 515 | .remove = pci_device_remove, | ||
| 516 | .suspend = pci_device_suspend, | 516 | .suspend = pci_device_suspend, |
| 517 | .resume = pci_device_resume, | 517 | .resume = pci_device_resume, |
| 518 | .dev_attrs = pci_dev_attrs, | 518 | .dev_attrs = pci_dev_attrs, |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 621ec459d27a..0a424a4e8187 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -311,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) | |||
| 311 | /* initialize common fields */ | 311 | /* initialize common fields */ |
| 312 | driver->drv.bus = &pcmcia_bus_type; | 312 | driver->drv.bus = &pcmcia_bus_type; |
| 313 | driver->drv.owner = driver->owner; | 313 | driver->drv.owner = driver->owner; |
| 314 | driver->drv.probe = pcmcia_device_probe; | ||
| 315 | driver->drv.remove = pcmcia_device_remove; | ||
| 316 | 314 | ||
| 317 | return driver_register(&driver->drv); | 315 | return driver_register(&driver->drv); |
| 318 | } | 316 | } |
| @@ -1200,6 +1198,8 @@ struct bus_type pcmcia_bus_type = { | |||
| 1200 | .uevent = pcmcia_bus_uevent, | 1198 | .uevent = pcmcia_bus_uevent, |
| 1201 | .match = pcmcia_bus_match, | 1199 | .match = pcmcia_bus_match, |
| 1202 | .dev_attrs = pcmcia_dev_attrs, | 1200 | .dev_attrs = pcmcia_dev_attrs, |
| 1201 | .probe = pcmcia_device_probe, | ||
| 1202 | .remove = pcmcia_device_remove, | ||
| 1203 | .suspend = pcmcia_dev_suspend, | 1203 | .suspend = pcmcia_dev_suspend, |
| 1204 | .resume = pcmcia_dev_resume, | 1204 | .resume = pcmcia_dev_resume, |
| 1205 | }; | 1205 | }; |
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 15fb758a9e52..7cafacdd12b0 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
| @@ -195,6 +195,8 @@ static int pnp_bus_resume(struct device *dev) | |||
| 195 | struct bus_type pnp_bus_type = { | 195 | struct bus_type pnp_bus_type = { |
| 196 | .name = "pnp", | 196 | .name = "pnp", |
| 197 | .match = pnp_bus_match, | 197 | .match = pnp_bus_match, |
| 198 | .probe = pnp_device_probe, | ||
| 199 | .remove = pnp_device_remove, | ||
| 198 | .suspend = pnp_bus_suspend, | 200 | .suspend = pnp_bus_suspend, |
| 199 | .resume = pnp_bus_resume, | 201 | .resume = pnp_bus_resume, |
| 200 | }; | 202 | }; |
| @@ -215,8 +217,6 @@ int pnp_register_driver(struct pnp_driver *drv) | |||
| 215 | 217 | ||
| 216 | drv->driver.name = drv->name; | 218 | drv->driver.name = drv->name; |
| 217 | drv->driver.bus = &pnp_bus_type; | 219 | drv->driver.bus = &pnp_bus_type; |
| 218 | drv->driver.probe = pnp_device_probe; | ||
| 219 | drv->driver.remove = pnp_device_remove; | ||
| 220 | 220 | ||
| 221 | count = driver_register(&drv->driver); | 221 | count = driver_register(&drv->driver); |
| 222 | 222 | ||
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index dc749609699a..5480119ff9d3 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c | |||
| @@ -147,8 +147,6 @@ int rio_register_driver(struct rio_driver *rdrv) | |||
| 147 | /* initialize common driver fields */ | 147 | /* initialize common driver fields */ |
| 148 | rdrv->driver.name = rdrv->name; | 148 | rdrv->driver.name = rdrv->name; |
| 149 | rdrv->driver.bus = &rio_bus_type; | 149 | rdrv->driver.bus = &rio_bus_type; |
| 150 | rdrv->driver.probe = rio_device_probe; | ||
| 151 | rdrv->driver.remove = rio_device_remove; | ||
| 152 | 150 | ||
| 153 | /* register with core */ | 151 | /* register with core */ |
| 154 | return driver_register(&rdrv->driver); | 152 | return driver_register(&rdrv->driver); |
| @@ -204,7 +202,9 @@ static struct device rio_bus = { | |||
| 204 | struct bus_type rio_bus_type = { | 202 | struct bus_type rio_bus_type = { |
| 205 | .name = "rapidio", | 203 | .name = "rapidio", |
| 206 | .match = rio_match_bus, | 204 | .match = rio_match_bus, |
| 207 | .dev_attrs = rio_dev_attrs | 205 | .dev_attrs = rio_dev_attrs, |
| 206 | .probe = rio_device_probe, | ||
| 207 | .remove = rio_device_remove, | ||
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | /** | 210 | /** |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 9c25654b1e75..ef4c687e7c01 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -1635,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device) | |||
| 1635 | blk_queue_max_hw_segments(device->request_queue, -1L); | 1635 | blk_queue_max_hw_segments(device->request_queue, -1L); |
| 1636 | blk_queue_max_segment_size(device->request_queue, -1L); | 1636 | blk_queue_max_segment_size(device->request_queue, -1L); |
| 1637 | blk_queue_segment_boundary(device->request_queue, -1L); | 1637 | blk_queue_segment_boundary(device->request_queue, -1L); |
| 1638 | blk_queue_ordered(device->request_queue, 1); | 1638 | blk_queue_ordered(device->request_queue, QUEUE_ORDERED_TAG, NULL); |
| 1639 | } | 1639 | } |
| 1640 | 1640 | ||
| 1641 | /* | 1641 | /* |
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 83e6a060668e..cd2cc28e16a7 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c | |||
| @@ -2,12 +2,12 @@ | |||
| 2 | * drivers/s390/cio/airq.c | 2 | * drivers/s390/cio/airq.c |
| 3 | * S/390 common I/O routines -- support for adapter interruptions | 3 | * S/390 common I/O routines -- support for adapter interruptions |
| 4 | * | 4 | * |
| 5 | * $Revision: 1.12 $ | 5 | * $Revision: 1.15 $ |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, | 7 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, |
| 8 | * IBM Corporation | 8 | * IBM Corporation |
| 9 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 9 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
| 10 | * Cornelia Huck (cohuck@de.ibm.com) | 10 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 11 | * Arnd Bergmann (arndb@de.ibm.com) | 11 | * Arnd Bergmann (arndb@de.ibm.com) |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index daf21e03b21d..72f27c151c09 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/blacklist.c | 2 | * drivers/s390/cio/blacklist.c |
| 3 | * S/390 common I/O routines -- blacklisting of specific devices | 3 | * S/390 common I/O routines -- blacklisting of specific devices |
| 4 | * $Revision: 1.39 $ | 4 | * $Revision: 1.42 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 8 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | * Arnd Bergmann (arndb@de.ibm.com) | 10 | * Arnd Bergmann (arndb@de.ibm.com) |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e849289d4f3c..6c077ad71edc 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/ccwgroup.c | 2 | * drivers/s390/cio/ccwgroup.c |
| 3 | * bus driver for ccwgroup | 3 | * bus driver for ccwgroup |
| 4 | * $Revision: 1.33 $ | 4 | * $Revision: 1.35 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) | 8 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | */ | 10 | */ |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| @@ -52,11 +52,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, | |||
| 52 | return 0; | 52 | return 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static struct bus_type ccwgroup_bus_type = { | 55 | static struct bus_type ccwgroup_bus_type; |
| 56 | .name = "ccwgroup", | ||
| 57 | .match = ccwgroup_bus_match, | ||
| 58 | .uevent = ccwgroup_uevent, | ||
| 59 | }; | ||
| 60 | 56 | ||
| 61 | static inline void | 57 | static inline void |
| 62 | __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) | 58 | __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) |
| @@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev) | |||
| 389 | return 0; | 385 | return 0; |
| 390 | } | 386 | } |
| 391 | 387 | ||
| 388 | static struct bus_type ccwgroup_bus_type = { | ||
| 389 | .name = "ccwgroup", | ||
| 390 | .match = ccwgroup_bus_match, | ||
| 391 | .uevent = ccwgroup_uevent, | ||
| 392 | .probe = ccwgroup_probe, | ||
| 393 | .remove = ccwgroup_remove, | ||
| 394 | }; | ||
| 395 | |||
| 392 | int | 396 | int |
| 393 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | 397 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) |
| 394 | { | 398 | { |
| @@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | |||
| 396 | cdriver->driver = (struct device_driver) { | 400 | cdriver->driver = (struct device_driver) { |
| 397 | .bus = &ccwgroup_bus_type, | 401 | .bus = &ccwgroup_bus_type, |
| 398 | .name = cdriver->name, | 402 | .name = cdriver->name, |
| 399 | .probe = ccwgroup_probe, | ||
| 400 | .remove = ccwgroup_remove, | ||
| 401 | }; | 403 | }; |
| 402 | 404 | ||
| 403 | return driver_register(&cdriver->driver); | 405 | return driver_register(&cdriver->driver); |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 7270808c02d1..2cbb724791a8 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/chsc.c | 2 | * drivers/s390/cio/chsc.c |
| 3 | * S/390 common I/O routines -- channel subsystem call | 3 | * S/390 common I/O routines -- channel subsystem call |
| 4 | * $Revision: 1.126 $ | 4 | * $Revision: 1.128 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 8 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | * Arnd Bergmann (arndb@de.ibm.com) | 10 | * Arnd Bergmann (arndb@de.ibm.com) |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 7376bc87206d..6223b06d27d5 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/cio.c | 2 | * drivers/s390/cio/cio.c |
| 3 | * S/390 common I/O routines -- low level i/o calls | 3 | * S/390 common I/O routines -- low level i/o calls |
| 4 | * $Revision: 1.138 $ | 4 | * $Revision: 1.140 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 8 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | * Arnd Bergmann (arndb@de.ibm.com) | 10 | * Arnd Bergmann (arndb@de.ibm.com) |
| 11 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 11 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 12 | */ | 12 | */ |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index e565193650c7..516108779f60 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/css.c | 2 | * drivers/s390/cio/css.c |
| 3 | * driver for channel subsystem | 3 | * driver for channel subsystem |
| 4 | * $Revision: 1.93 $ | 4 | * $Revision: 1.96 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) | 8 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | */ | 10 | */ |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| @@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struct device_driver *drv) | |||
| 542 | return 0; | 542 | return 0; |
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | static int | ||
| 546 | css_probe (struct device *dev) | ||
| 547 | { | ||
| 548 | struct subchannel *sch; | ||
| 549 | |||
| 550 | sch = to_subchannel(dev); | ||
| 551 | sch->driver = container_of (dev->driver, struct css_driver, drv); | ||
| 552 | return (sch->driver->probe ? sch->driver->probe(sch) : 0); | ||
| 553 | } | ||
| 554 | |||
| 555 | static int | ||
| 556 | css_remove (struct device *dev) | ||
| 557 | { | ||
| 558 | struct subchannel *sch; | ||
| 559 | |||
| 560 | sch = to_subchannel(dev); | ||
| 561 | return (sch->driver->remove ? sch->driver->remove(sch) : 0); | ||
| 562 | } | ||
| 563 | |||
| 564 | static void | ||
| 565 | css_shutdown (struct device *dev) | ||
| 566 | { | ||
| 567 | struct subchannel *sch; | ||
| 568 | |||
| 569 | sch = to_subchannel(dev); | ||
| 570 | if (sch->driver->shutdown) | ||
| 571 | sch->driver->shutdown(sch); | ||
| 572 | } | ||
| 573 | |||
| 545 | struct bus_type css_bus_type = { | 574 | struct bus_type css_bus_type = { |
| 546 | .name = "css", | 575 | .name = "css", |
| 547 | .match = &css_bus_match, | 576 | .match = css_bus_match, |
| 577 | .probe = css_probe, | ||
| 578 | .remove = css_remove, | ||
| 579 | .shutdown = css_shutdown, | ||
| 548 | }; | 580 | }; |
| 549 | 581 | ||
| 550 | subsys_initcall(init_channel_subsystem); | 582 | subsys_initcall(init_channel_subsystem); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 251ebd7a7d3a..b6375861cb37 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
| @@ -115,6 +115,7 @@ struct ccw_device_private { | |||
| 115 | * Currently, we only care about I/O subchannels (type 0), these | 115 | * Currently, we only care about I/O subchannels (type 0), these |
| 116 | * have a ccw_device connected to them. | 116 | * have a ccw_device connected to them. |
| 117 | */ | 117 | */ |
| 118 | struct subchannel; | ||
| 118 | struct css_driver { | 119 | struct css_driver { |
| 119 | unsigned int subchannel_type; | 120 | unsigned int subchannel_type; |
| 120 | struct device_driver drv; | 121 | struct device_driver drv; |
| @@ -122,6 +123,9 @@ struct css_driver { | |||
| 122 | int (*notify)(struct device *, int); | 123 | int (*notify)(struct device *, int); |
| 123 | void (*verify)(struct device *); | 124 | void (*verify)(struct device *); |
| 124 | void (*termination)(struct device *); | 125 | void (*termination)(struct device *); |
| 126 | int (*probe)(struct subchannel *); | ||
| 127 | int (*remove)(struct subchannel *); | ||
| 128 | void (*shutdown)(struct subchannel *); | ||
| 125 | }; | 129 | }; |
| 126 | 130 | ||
| 127 | /* | 131 | /* |
| @@ -143,7 +147,7 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); | |||
| 143 | struct channel_subsystem { | 147 | struct channel_subsystem { |
| 144 | u8 cssid; | 148 | u8 cssid; |
| 145 | int valid; | 149 | int valid; |
| 146 | struct channel_path *chps[__MAX_CHPID]; | 150 | struct channel_path *chps[__MAX_CHPID + 1]; |
| 147 | struct device device; | 151 | struct device device; |
| 148 | struct pgid global_pgid; | 152 | struct pgid global_pgid; |
| 149 | }; | 153 | }; |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fa3e4c0a2536..a67e7e60e330 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/device.c | 2 | * drivers/s390/cio/device.c |
| 3 | * bus driver for ccw devices | 3 | * bus driver for ccw devices |
| 4 | * $Revision: 1.137 $ | 4 | * $Revision: 1.140 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) | 8 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 10 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 11 | */ | 11 | */ |
| 12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
| @@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **envp, int num_envp, | |||
| 107 | return 0; | 107 | return 0; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | struct bus_type ccw_bus_type = { | 110 | struct bus_type ccw_bus_type; |
| 111 | .name = "ccw", | ||
| 112 | .match = &ccw_bus_match, | ||
| 113 | .uevent = &ccw_uevent, | ||
| 114 | }; | ||
| 115 | 111 | ||
| 116 | static int io_subchannel_probe (struct device *); | 112 | static int io_subchannel_probe (struct subchannel *); |
| 117 | static int io_subchannel_remove (struct device *); | 113 | static int io_subchannel_remove (struct subchannel *); |
| 118 | void io_subchannel_irq (struct device *); | 114 | void io_subchannel_irq (struct device *); |
| 119 | static int io_subchannel_notify(struct device *, int); | 115 | static int io_subchannel_notify(struct device *, int); |
| 120 | static void io_subchannel_verify(struct device *); | 116 | static void io_subchannel_verify(struct device *); |
| 121 | static void io_subchannel_ioterm(struct device *); | 117 | static void io_subchannel_ioterm(struct device *); |
| 122 | static void io_subchannel_shutdown(struct device *); | 118 | static void io_subchannel_shutdown(struct subchannel *); |
| 123 | 119 | ||
| 124 | struct css_driver io_subchannel_driver = { | 120 | struct css_driver io_subchannel_driver = { |
| 125 | .subchannel_type = SUBCHANNEL_TYPE_IO, | 121 | .subchannel_type = SUBCHANNEL_TYPE_IO, |
| 126 | .drv = { | 122 | .drv = { |
| 127 | .name = "io_subchannel", | 123 | .name = "io_subchannel", |
| 128 | .bus = &css_bus_type, | 124 | .bus = &css_bus_type, |
| 129 | .probe = &io_subchannel_probe, | ||
| 130 | .remove = &io_subchannel_remove, | ||
| 131 | .shutdown = &io_subchannel_shutdown, | ||
| 132 | }, | 125 | }, |
| 133 | .irq = io_subchannel_irq, | 126 | .irq = io_subchannel_irq, |
| 134 | .notify = io_subchannel_notify, | 127 | .notify = io_subchannel_notify, |
| 135 | .verify = io_subchannel_verify, | 128 | .verify = io_subchannel_verify, |
| 136 | .termination = io_subchannel_ioterm, | 129 | .termination = io_subchannel_ioterm, |
| 130 | .probe = io_subchannel_probe, | ||
| 131 | .remove = io_subchannel_remove, | ||
| 132 | .shutdown = io_subchannel_shutdown, | ||
| 137 | }; | 133 | }; |
| 138 | 134 | ||
| 139 | struct workqueue_struct *ccw_device_work; | 135 | struct workqueue_struct *ccw_device_work; |
| @@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | |||
| 803 | } | 799 | } |
| 804 | 800 | ||
| 805 | static int | 801 | static int |
| 806 | io_subchannel_probe (struct device *pdev) | 802 | io_subchannel_probe (struct subchannel *sch) |
| 807 | { | 803 | { |
| 808 | struct subchannel *sch; | ||
| 809 | struct ccw_device *cdev; | 804 | struct ccw_device *cdev; |
| 810 | int rc; | 805 | int rc; |
| 811 | unsigned long flags; | 806 | unsigned long flags; |
| 812 | 807 | ||
| 813 | sch = to_subchannel(pdev); | ||
| 814 | if (sch->dev.driver_data) { | 808 | if (sch->dev.driver_data) { |
| 815 | /* | 809 | /* |
| 816 | * This subchannel already has an associated ccw_device. | 810 | * This subchannel already has an associated ccw_device. |
| @@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev) | |||
| 846 | memset(cdev->private, 0, sizeof(struct ccw_device_private)); | 840 | memset(cdev->private, 0, sizeof(struct ccw_device_private)); |
| 847 | atomic_set(&cdev->private->onoff, 0); | 841 | atomic_set(&cdev->private->onoff, 0); |
| 848 | cdev->dev = (struct device) { | 842 | cdev->dev = (struct device) { |
| 849 | .parent = pdev, | 843 | .parent = &sch->dev, |
| 850 | .release = ccw_device_release, | 844 | .release = ccw_device_release, |
| 851 | }; | 845 | }; |
| 852 | INIT_LIST_HEAD(&cdev->private->kick_work.entry); | 846 | INIT_LIST_HEAD(&cdev->private->kick_work.entry); |
| @@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev) | |||
| 859 | return -ENODEV; | 853 | return -ENODEV; |
| 860 | } | 854 | } |
| 861 | 855 | ||
| 862 | rc = io_subchannel_recog(cdev, to_subchannel(pdev)); | 856 | rc = io_subchannel_recog(cdev, sch); |
| 863 | if (rc) { | 857 | if (rc) { |
| 864 | spin_lock_irqsave(&sch->lock, flags); | 858 | spin_lock_irqsave(&sch->lock, flags); |
| 865 | sch->dev.driver_data = NULL; | 859 | sch->dev.driver_data = NULL; |
| @@ -883,17 +877,17 @@ ccw_device_unregister(void *data) | |||
| 883 | } | 877 | } |
| 884 | 878 | ||
| 885 | static int | 879 | static int |
| 886 | io_subchannel_remove (struct device *dev) | 880 | io_subchannel_remove (struct subchannel *sch) |
| 887 | { | 881 | { |
| 888 | struct ccw_device *cdev; | 882 | struct ccw_device *cdev; |
| 889 | unsigned long flags; | 883 | unsigned long flags; |
| 890 | 884 | ||
| 891 | if (!dev->driver_data) | 885 | if (!sch->dev.driver_data) |
| 892 | return 0; | 886 | return 0; |
| 893 | cdev = dev->driver_data; | 887 | cdev = sch->dev.driver_data; |
| 894 | /* Set ccw device to not operational and drop reference. */ | 888 | /* Set ccw device to not operational and drop reference. */ |
| 895 | spin_lock_irqsave(cdev->ccwlock, flags); | 889 | spin_lock_irqsave(cdev->ccwlock, flags); |
| 896 | dev->driver_data = NULL; | 890 | sch->dev.driver_data = NULL; |
| 897 | cdev->private->state = DEV_STATE_NOT_OPER; | 891 | cdev->private->state = DEV_STATE_NOT_OPER; |
| 898 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 892 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
| 899 | /* | 893 | /* |
| @@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev) | |||
| 948 | } | 942 | } |
| 949 | 943 | ||
| 950 | static void | 944 | static void |
| 951 | io_subchannel_shutdown(struct device *dev) | 945 | io_subchannel_shutdown(struct subchannel *sch) |
| 952 | { | 946 | { |
| 953 | struct subchannel *sch; | ||
| 954 | struct ccw_device *cdev; | 947 | struct ccw_device *cdev; |
| 955 | int ret; | 948 | int ret; |
| 956 | 949 | ||
| 957 | sch = to_subchannel(dev); | 950 | cdev = sch->dev.driver_data; |
| 958 | cdev = dev->driver_data; | ||
| 959 | 951 | ||
| 960 | if (cio_is_console(sch->schid)) | 952 | if (cio_is_console(sch->schid)) |
| 961 | return; | 953 | return; |
| @@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev) | |||
| 1129 | return 0; | 1121 | return 0; |
| 1130 | } | 1122 | } |
| 1131 | 1123 | ||
| 1124 | struct bus_type ccw_bus_type = { | ||
| 1125 | .name = "ccw", | ||
| 1126 | .match = ccw_bus_match, | ||
| 1127 | .uevent = ccw_uevent, | ||
| 1128 | .probe = ccw_device_probe, | ||
| 1129 | .remove = ccw_device_remove, | ||
| 1130 | }; | ||
| 1131 | |||
| 1132 | int | 1132 | int |
| 1133 | ccw_driver_register (struct ccw_driver *cdriver) | 1133 | ccw_driver_register (struct ccw_driver *cdriver) |
| 1134 | { | 1134 | { |
| @@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
| 1136 | 1136 | ||
| 1137 | drv->bus = &ccw_bus_type; | 1137 | drv->bus = &ccw_bus_type; |
| 1138 | drv->name = cdriver->name; | 1138 | drv->name = cdriver->name; |
| 1139 | drv->probe = ccw_device_probe; | ||
| 1140 | drv->remove = ccw_device_remove; | ||
| 1141 | 1139 | ||
| 1142 | return driver_register(drv); | 1140 | return driver_register(drv); |
| 1143 | } | 1141 | } |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 23d12b65e5fa..b302779e7cff 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 5 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 6 | * IBM Corporation | 6 | * IBM Corporation |
| 7 | * Author(s): Cornelia Huck(cohuck@de.ibm.com) | 7 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) |
| 8 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 8 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 04ceba343db8..e60b2d8103b8 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 5 | * IBM Corporation | 5 | * IBM Corporation |
| 6 | * Author(s): Cornelia Huck(cohuck@de.ibm.com) | 6 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) |
| 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 8 | * | 8 | * |
| 9 | * Sense ID functions. | 9 | * Sense ID functions. |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 143b6c25a4e6..8b0218949b62 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/cio/device_ops.c | 2 | * drivers/s390/cio/device_ops.c |
| 3 | * | 3 | * |
| 4 | * $Revision: 1.58 $ | 4 | * $Revision: 1.61 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | 8 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 9 | * Cornelia Huck (cohuck@de.ibm.com) | 9 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
| 10 | */ | 10 | */ |
| 11 | #include <linux/config.h> | 11 | #include <linux/config.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 052832d03d38..d2a5b04d7cba 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 5 | * IBM Corporation | 5 | * IBM Corporation |
| 6 | * Author(s): Cornelia Huck(cohuck@de.ibm.com) | 6 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) |
| 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 8 | * | 8 | * |
| 9 | * Path Group ID functions. | 9 | * Path Group ID functions. |
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index db09c209098b..dad4dd9887c9 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, | 4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, |
| 5 | * IBM Corporation | 5 | * IBM Corporation |
| 6 | * Author(s): Cornelia Huck(cohuck@de.ibm.com) | 6 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) |
| 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
| 8 | * | 8 | * |
| 9 | * Status accumulation and basic sense functions. | 9 | * Status accumulation and basic sense functions. |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 30a836ffc31f..77be2c39bfe4 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright 2000,2002 IBM Corporation | 8 | * Copyright 2000,2002 IBM Corporation |
| 9 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com> | 9 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com> |
| 10 | * 2.6 cio integration by Cornelia Huck <cohuck@de.ibm.com> | 10 | * 2.6 cio integration by Cornelia Huck <cornelia.huck@de.ibm.com> |
| 11 | * | 11 | * |
| 12 | * Restriction: only 63 iqdio subchannels would have its own indicator, | 12 | * Restriction: only 63 iqdio subchannels would have its own indicator, |
| 13 | * after that, subsequent subchannels share one indicator | 13 | * after that, subsequent subchannels share one indicator |
| @@ -56,7 +56,7 @@ | |||
| 56 | #include "ioasm.h" | 56 | #include "ioasm.h" |
| 57 | #include "chsc.h" | 57 | #include "chsc.h" |
| 58 | 58 | ||
| 59 | #define VERSION_QDIO_C "$Revision: 1.114 $" | 59 | #define VERSION_QDIO_C "$Revision: 1.117 $" |
| 60 | 60 | ||
| 61 | /****************** MODULE PARAMETER VARIABLES ********************/ | 61 | /****************** MODULE PARAMETER VARIABLES ********************/ |
| 62 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); | 62 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); |
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 0db4f57a6a95..1901feef07d9 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ | 2 | * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $ |
| 3 | * | 3 | * |
| 4 | * CTC / ESCON network driver | 4 | * CTC / ESCON network driver |
| 5 | * | 5 | * |
| @@ -8,7 +8,7 @@ | |||
| 8 | * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) | 8 | * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) |
| 9 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 9 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
| 10 | Peter Tiedemann (ptiedem@de.ibm.com) | 10 | Peter Tiedemann (ptiedem@de.ibm.com) |
| 11 | * Driver Model stuff by : Cornelia Huck <cohuck@de.ibm.com> | 11 | * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com> |
| 12 | * | 12 | * |
| 13 | * Documentation used: | 13 | * Documentation used: |
| 14 | * - Principles of Operation (IBM doc#: SA22-7201-06) | 14 | * - Principles of Operation (IBM doc#: SA22-7201-06) |
| @@ -37,7 +37,7 @@ | |||
| 37 | * along with this program; if not, write to the Free Software | 37 | * along with this program; if not, write to the Free Software |
| 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 39 | * | 39 | * |
| 40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ | 40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $ |
| 41 | * | 41 | * |
| 42 | */ | 42 | */ |
| 43 | #undef DEBUG | 43 | #undef DEBUG |
| @@ -248,7 +248,7 @@ static void | |||
| 248 | print_banner(void) | 248 | print_banner(void) |
| 249 | { | 249 | { |
| 250 | static int printed = 0; | 250 | static int printed = 0; |
| 251 | char vbuf[] = "$Revision: 1.78 $"; | 251 | char vbuf[] = "$Revision: 1.79 $"; |
| 252 | char *version = vbuf; | 252 | char *version = vbuf; |
| 253 | 253 | ||
| 254 | if (printed) | 254 | if (printed) |
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index 77dacb465732..2014fb7a4881 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $ | 2 | * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $ |
| 3 | * | 3 | * |
| 4 | * CTC / LCS ccw_device driver | 4 | * CTC / LCS ccw_device driver |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation | 6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation |
| 7 | * Author(s): Arnd Bergmann <arndb@de.ibm.com> | 7 | * Author(s): Arnd Bergmann <arndb@de.ibm.com> |
| 8 | * Cornelia Huck <cohuck@de.ibm.com> | 8 | * Cornelia Huck <cornelia.huck@de.ibm.com> |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 69425a7a6e98..ac4c4b83fe17 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $ | 2 | * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $ |
| 3 | * | 3 | * |
| 4 | * IUCV network driver | 4 | * IUCV network driver |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation | 6 | * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation |
| 7 | * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) | 7 | * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) |
| 8 | * | 8 | * |
| 9 | * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com) | 9 | * Sysfs integration and all bugs therein by Cornelia Huck |
| 10 | * (cornelia.huck@de.ibm.com) | ||
| 10 | * | 11 | * |
| 11 | * Documentation used: | 12 | * Documentation used: |
| 12 | * the source of the original IUCV driver by: | 13 | * the source of the original IUCV driver by: |
| @@ -30,7 +31,7 @@ | |||
| 30 | * along with this program; if not, write to the Free Software | 31 | * along with this program; if not, write to the Free Software |
| 31 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 32 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 32 | * | 33 | * |
| 33 | * RELEASE-TAG: IUCV network driver $Revision: 1.66 $ | 34 | * RELEASE-TAG: IUCV network driver $Revision: 1.69 $ |
| 34 | * | 35 | * |
| 35 | */ | 36 | */ |
| 36 | 37 | ||
| @@ -2076,7 +2077,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write); | |||
| 2076 | static void | 2077 | static void |
| 2077 | netiucv_banner(void) | 2078 | netiucv_banner(void) |
| 2078 | { | 2079 | { |
| 2079 | char vbuf[] = "$Revision: 1.66 $"; | 2080 | char vbuf[] = "$Revision: 1.69 $"; |
| 2080 | char *version = vbuf; | 2081 | char *version = vbuf; |
| 2081 | 2082 | ||
| 2082 | if ((version = strchr(version, ':'))) { | 2083 | if ((version = strchr(version, ':'))) { |
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c index 566cc3d185b6..206518c7d332 100644 --- a/drivers/s390/s390_rdev.c +++ b/drivers/s390/s390_rdev.c | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/s390/s390_rdev.c | 2 | * drivers/s390/s390_rdev.c |
| 3 | * s390 root device | 3 | * s390 root device |
| 4 | * $Revision: 1.2 $ | 4 | * $Revision: 1.4 $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, |
| 7 | * IBM Corporation | 7 | * IBM Corporation |
| 8 | * Author(s): Cornelia Huck (cohuck@de.ibm.com) | 8 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) |
| 9 | * Carsten Otte (cotte@de.ibm.com) | 9 | * Carsten Otte (cotte@de.ibm.com) |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 5e84c5aa7779..167fef39d8a7 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
| @@ -1125,6 +1125,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
| 1125 | zfcp_free_low_mem_buffers(adapter); | 1125 | zfcp_free_low_mem_buffers(adapter); |
| 1126 | /* free memory of adapter data structure and queues */ | 1126 | /* free memory of adapter data structure and queues */ |
| 1127 | zfcp_qdio_free_queues(adapter); | 1127 | zfcp_qdio_free_queues(adapter); |
| 1128 | kfree(adapter->fc_stats); | ||
| 1129 | kfree(adapter->stats_reset_data); | ||
| 1128 | ZFCP_LOG_TRACE("freeing adapter structure\n"); | 1130 | ZFCP_LOG_TRACE("freeing adapter structure\n"); |
| 1129 | kfree(adapter); | 1131 | kfree(adapter); |
| 1130 | out: | 1132 | out: |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index d81b737d68cc..9bb511083a26 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
| @@ -921,7 +921,6 @@ struct zfcp_adapter { | |||
| 921 | u32 physical_s_id; /* local FC port ID */ | 921 | u32 physical_s_id; /* local FC port ID */ |
| 922 | struct ccw_device *ccw_device; /* S/390 ccw device */ | 922 | struct ccw_device *ccw_device; /* S/390 ccw device */ |
| 923 | u8 fc_service_class; | 923 | u8 fc_service_class; |
| 924 | u32 fc_topology; /* FC topology */ | ||
| 925 | u32 hydra_version; /* Hydra version */ | 924 | u32 hydra_version; /* Hydra version */ |
| 926 | u32 fsf_lic_version; | 925 | u32 fsf_lic_version; |
| 927 | u32 adapter_features; /* FCP channel features */ | 926 | u32 adapter_features; /* FCP channel features */ |
| @@ -978,6 +977,9 @@ struct zfcp_adapter { | |||
| 978 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ | 977 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ |
| 979 | struct qdio_initialize qdio_init_data; /* for qdio_establish */ | 978 | struct qdio_initialize qdio_init_data; /* for qdio_establish */ |
| 980 | struct device generic_services; /* directory for WKA ports */ | 979 | struct device generic_services; /* directory for WKA ports */ |
| 980 | struct fc_host_statistics *fc_stats; | ||
| 981 | struct fsf_qtcb_bottom_port *stats_reset_data; | ||
| 982 | unsigned long stats_reset; | ||
| 981 | }; | 983 | }; |
| 982 | 984 | ||
| 983 | /* | 985 | /* |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index ee7314d8c2da..7bdb00b5aeb2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -2613,7 +2613,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) | |||
| 2613 | case ZFCP_ERP_STEP_UNINITIALIZED: | 2613 | case ZFCP_ERP_STEP_UNINITIALIZED: |
| 2614 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: | 2614 | case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: |
| 2615 | case ZFCP_ERP_STEP_PORT_CLOSING: | 2615 | case ZFCP_ERP_STEP_PORT_CLOSING: |
| 2616 | if (adapter->fc_topology == FSF_TOPO_P2P) { | 2616 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) { |
| 2617 | if (port->wwpn != adapter->peer_wwpn) { | 2617 | if (port->wwpn != adapter->peer_wwpn) { |
| 2618 | ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx " | 2618 | ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx " |
| 2619 | "on adapter %s.\nPeer WWPN " | 2619 | "on adapter %s.\nPeer WWPN " |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 59587951c847..cbfab09899c8 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -964,6 +964,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
| 964 | | ZFCP_STATUS_COMMON_ERP_FAILED); | 964 | | ZFCP_STATUS_COMMON_ERP_FAILED); |
| 965 | break; | 965 | break; |
| 966 | 966 | ||
| 967 | case FSF_STATUS_READ_NOTIFICATION_LOST: | ||
| 968 | ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: " | ||
| 969 | "adapter %s%s%s%s%s%s%s%s%s\n", | ||
| 970 | zfcp_get_busid_by_adapter(adapter), | ||
| 971 | (status_buffer->status_subtype & | ||
| 972 | FSF_STATUS_READ_SUB_INCOMING_ELS) ? | ||
| 973 | ", incoming ELS" : "", | ||
| 974 | (status_buffer->status_subtype & | ||
| 975 | FSF_STATUS_READ_SUB_SENSE_DATA) ? | ||
| 976 | ", sense data" : "", | ||
| 977 | (status_buffer->status_subtype & | ||
| 978 | FSF_STATUS_READ_SUB_LINK_STATUS) ? | ||
| 979 | ", link status change" : "", | ||
| 980 | (status_buffer->status_subtype & | ||
| 981 | FSF_STATUS_READ_SUB_PORT_CLOSED) ? | ||
| 982 | ", port close" : "", | ||
| 983 | (status_buffer->status_subtype & | ||
| 984 | FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ? | ||
| 985 | ", bit error exception" : "", | ||
| 986 | (status_buffer->status_subtype & | ||
| 987 | FSF_STATUS_READ_SUB_ACT_UPDATED) ? | ||
| 988 | ", ACT update" : "", | ||
| 989 | (status_buffer->status_subtype & | ||
| 990 | FSF_STATUS_READ_SUB_ACT_HARDENED) ? | ||
| 991 | ", ACT hardening" : "", | ||
| 992 | (status_buffer->status_subtype & | ||
| 993 | FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ? | ||
| 994 | ", adapter feature change" : ""); | ||
| 995 | |||
| 996 | if (status_buffer->status_subtype & | ||
| 997 | FSF_STATUS_READ_SUB_ACT_UPDATED) | ||
| 998 | zfcp_erp_adapter_access_changed(adapter); | ||
| 999 | break; | ||
| 1000 | |||
| 967 | case FSF_STATUS_READ_CFDC_UPDATED: | 1001 | case FSF_STATUS_READ_CFDC_UPDATED: |
| 968 | ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", | 1002 | ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", |
| 969 | zfcp_get_busid_by_adapter(adapter)); | 1003 | zfcp_get_busid_by_adapter(adapter)); |
| @@ -1954,6 +1988,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
| 1954 | erp_action->fsf_req->qtcb->bottom.config.feature_selection = | 1988 | erp_action->fsf_req->qtcb->bottom.config.feature_selection = |
| 1955 | FSF_FEATURE_CFDC | | 1989 | FSF_FEATURE_CFDC | |
| 1956 | FSF_FEATURE_LUN_SHARING | | 1990 | FSF_FEATURE_LUN_SHARING | |
| 1991 | FSF_FEATURE_NOTIFICATION_LOST | | ||
| 1957 | FSF_FEATURE_UPDATE_ALERT; | 1992 | FSF_FEATURE_UPDATE_ALERT; |
| 1958 | 1993 | ||
| 1959 | /* start QDIO request for this FSF request */ | 1994 | /* start QDIO request for this FSF request */ |
| @@ -2008,27 +2043,30 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
| 2008 | fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; | 2043 | fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; |
| 2009 | fc_host_speed(shost) = bottom->fc_link_speed; | 2044 | fc_host_speed(shost) = bottom->fc_link_speed; |
| 2010 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; | 2045 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; |
| 2011 | adapter->fc_topology = bottom->fc_topology; | ||
| 2012 | adapter->hydra_version = bottom->adapter_type; | 2046 | adapter->hydra_version = bottom->adapter_type; |
| 2013 | if (adapter->physical_wwpn == 0) | 2047 | if (fc_host_permanent_port_name(shost) == -1) |
| 2014 | adapter->physical_wwpn = fc_host_port_name(shost); | 2048 | fc_host_permanent_port_name(shost) = |
| 2015 | if (adapter->physical_s_id == 0) | 2049 | fc_host_port_name(shost); |
| 2016 | adapter->physical_s_id = fc_host_port_id(shost); | 2050 | if (bottom->fc_topology == FSF_TOPO_P2P) { |
| 2051 | adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; | ||
| 2052 | adapter->peer_wwpn = bottom->plogi_payload.wwpn; | ||
| 2053 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; | ||
| 2054 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; | ||
| 2055 | } else if (bottom->fc_topology == FSF_TOPO_FABRIC) | ||
| 2056 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; | ||
| 2057 | else if (bottom->fc_topology == FSF_TOPO_AL) | ||
| 2058 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; | ||
| 2059 | else | ||
| 2060 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; | ||
| 2017 | } else { | 2061 | } else { |
| 2018 | fc_host_node_name(shost) = 0; | 2062 | fc_host_node_name(shost) = 0; |
| 2019 | fc_host_port_name(shost) = 0; | 2063 | fc_host_port_name(shost) = 0; |
| 2020 | fc_host_port_id(shost) = 0; | 2064 | fc_host_port_id(shost) = 0; |
| 2021 | fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; | 2065 | fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; |
| 2022 | adapter->fc_topology = 0; | 2066 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; |
| 2023 | adapter->hydra_version = 0; | 2067 | adapter->hydra_version = 0; |
| 2024 | } | 2068 | } |
| 2025 | 2069 | ||
| 2026 | if (adapter->fc_topology == FSF_TOPO_P2P) { | ||
| 2027 | adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; | ||
| 2028 | adapter->peer_wwpn = bottom->plogi_payload.wwpn; | ||
| 2029 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { | 2070 | if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { |
| 2033 | adapter->hardware_version = bottom->hardware_version; | 2071 | adapter->hardware_version = bottom->hardware_version; |
| 2034 | memcpy(fc_host_serial_number(shost), bottom->serial_number, | 2072 | memcpy(fc_host_serial_number(shost), bottom->serial_number, |
| @@ -2097,8 +2135,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
| 2097 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) | 2135 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) |
| 2098 | return -EIO; | 2136 | return -EIO; |
| 2099 | 2137 | ||
| 2100 | switch (adapter->fc_topology) { | 2138 | switch (fc_host_port_type(adapter->scsi_host)) { |
| 2101 | case FSF_TOPO_P2P: | 2139 | case FC_PORTTYPE_PTP: |
| 2102 | ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " | 2140 | ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " |
| 2103 | "configuration detected at adapter %s\n" | 2141 | "configuration detected at adapter %s\n" |
| 2104 | "Peer WWNN 0x%016llx, " | 2142 | "Peer WWNN 0x%016llx, " |
| @@ -2111,7 +2149,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
| 2111 | debug_text_event(fsf_req->adapter->erp_dbf, 0, | 2149 | debug_text_event(fsf_req->adapter->erp_dbf, 0, |
| 2112 | "top-p-to-p"); | 2150 | "top-p-to-p"); |
| 2113 | break; | 2151 | break; |
| 2114 | case FSF_TOPO_AL: | 2152 | case FC_PORTTYPE_NLPORT: |
| 2115 | ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " | 2153 | ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " |
| 2116 | "topology detected at adapter %s " | 2154 | "topology detected at adapter %s " |
| 2117 | "unsupported, shutting down adapter\n", | 2155 | "unsupported, shutting down adapter\n", |
| @@ -2120,7 +2158,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
| 2120 | "top-al"); | 2158 | "top-al"); |
| 2121 | zfcp_erp_adapter_shutdown(adapter, 0); | 2159 | zfcp_erp_adapter_shutdown(adapter, 0); |
| 2122 | return -EIO; | 2160 | return -EIO; |
| 2123 | case FSF_TOPO_FABRIC: | 2161 | case FC_PORTTYPE_NPORT: |
| 2124 | ZFCP_LOG_NORMAL("Switched fabric fibrechannel " | 2162 | ZFCP_LOG_NORMAL("Switched fabric fibrechannel " |
| 2125 | "network detected at adapter %s.\n", | 2163 | "network detected at adapter %s.\n", |
| 2126 | zfcp_get_busid_by_adapter(adapter)); | 2164 | zfcp_get_busid_by_adapter(adapter)); |
| @@ -2133,7 +2171,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
| 2133 | "of a type known to the zfcp " | 2171 | "of a type known to the zfcp " |
| 2134 | "driver, shutting down adapter\n", | 2172 | "driver, shutting down adapter\n", |
| 2135 | zfcp_get_busid_by_adapter(adapter)); | 2173 | zfcp_get_busid_by_adapter(adapter)); |
| 2136 | adapter->fc_topology = FSF_TOPO_ERROR; | ||
| 2137 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, | 2174 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, |
| 2138 | "unknown-topo"); | 2175 | "unknown-topo"); |
| 2139 | zfcp_erp_adapter_shutdown(adapter, 0); | 2176 | zfcp_erp_adapter_shutdown(adapter, 0); |
| @@ -2293,14 +2330,13 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) | |||
| 2293 | data = (struct fsf_qtcb_bottom_port*) fsf_req->data; | 2330 | data = (struct fsf_qtcb_bottom_port*) fsf_req->data; |
| 2294 | if (data) | 2331 | if (data) |
| 2295 | memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); | 2332 | memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); |
| 2296 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { | 2333 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) |
| 2297 | adapter->physical_wwpn = bottom->wwpn; | 2334 | fc_host_permanent_port_name(shost) = bottom->wwpn; |
| 2298 | adapter->physical_s_id = bottom->fc_port_id; | 2335 | else |
| 2299 | } else { | 2336 | fc_host_permanent_port_name(shost) = |
| 2300 | adapter->physical_wwpn = fc_host_port_name(shost); | 2337 | fc_host_port_name(shost); |
| 2301 | adapter->physical_s_id = fc_host_port_id(shost); | ||
| 2302 | } | ||
| 2303 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; | 2338 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; |
| 2339 | fc_host_supported_speeds(shost) = bottom->supported_speed; | ||
| 2304 | break; | 2340 | break; |
| 2305 | 2341 | ||
| 2306 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: | 2342 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: |
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 48719f055952..e734415cae6d 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
| @@ -166,6 +166,7 @@ | |||
| 166 | #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 | 166 | #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 |
| 167 | #define FSF_STATUS_READ_LINK_DOWN 0x00000005 | 167 | #define FSF_STATUS_READ_LINK_DOWN 0x00000005 |
| 168 | #define FSF_STATUS_READ_LINK_UP 0x00000006 | 168 | #define FSF_STATUS_READ_LINK_UP 0x00000006 |
| 169 | #define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 | ||
| 169 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A | 170 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A |
| 170 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B | 171 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B |
| 171 | #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C | 172 | #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C |
| @@ -179,6 +180,16 @@ | |||
| 179 | #define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 | 180 | #define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 |
| 180 | #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 | 181 | #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 |
| 181 | 182 | ||
| 183 | /* status subtypes for unsolicited status notification lost */ | ||
| 184 | #define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 | ||
| 185 | #define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002 | ||
| 186 | #define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004 | ||
| 187 | #define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008 | ||
| 188 | #define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010 | ||
| 189 | #define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020 | ||
| 190 | #define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040 | ||
| 191 | #define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080 | ||
| 192 | |||
| 182 | /* status subtypes for CFDC */ | 193 | /* status subtypes for CFDC */ |
| 183 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 | 194 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 |
| 184 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F | 195 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F |
| @@ -188,7 +199,6 @@ | |||
| 188 | #define FSF_TOPO_P2P 0x00000001 | 199 | #define FSF_TOPO_P2P 0x00000001 |
| 189 | #define FSF_TOPO_FABRIC 0x00000002 | 200 | #define FSF_TOPO_FABRIC 0x00000002 |
| 190 | #define FSF_TOPO_AL 0x00000003 | 201 | #define FSF_TOPO_AL 0x00000003 |
| 191 | #define FSF_TOPO_FABRIC_VIRT 0x00000004 | ||
| 192 | 202 | ||
| 193 | /* data direction for FCP commands */ | 203 | /* data direction for FCP commands */ |
| 194 | #define FSF_DATADIR_WRITE 0x00000001 | 204 | #define FSF_DATADIR_WRITE 0x00000001 |
| @@ -211,6 +221,7 @@ | |||
| 211 | /* channel features */ | 221 | /* channel features */ |
| 212 | #define FSF_FEATURE_CFDC 0x00000002 | 222 | #define FSF_FEATURE_CFDC 0x00000002 |
| 213 | #define FSF_FEATURE_LUN_SHARING 0x00000004 | 223 | #define FSF_FEATURE_LUN_SHARING 0x00000004 |
| 224 | #define FSF_FEATURE_NOTIFICATION_LOST 0x00000008 | ||
| 214 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 | 225 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 |
| 215 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 | 226 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 |
| 216 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 | 227 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 66608d13a634..3c2cbcccbf54 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
| @@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8, | |||
| 49 | 49 | ||
| 50 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, | 50 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, |
| 51 | scsi_lun_t); | 51 | scsi_lun_t); |
| 52 | static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int, | ||
| 53 | scsi_id_t); | ||
| 54 | 52 | ||
| 55 | static struct device_attribute *zfcp_sysfs_sdev_attrs[]; | 53 | static struct device_attribute *zfcp_sysfs_sdev_attrs[]; |
| 56 | 54 | ||
| @@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, | |||
| 406 | return retval; | 404 | return retval; |
| 407 | } | 405 | } |
| 408 | 406 | ||
| 409 | static struct zfcp_port * | ||
| 410 | zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) | ||
| 411 | { | ||
| 412 | struct zfcp_port *port; | ||
| 413 | |||
| 414 | list_for_each_entry(port, &adapter->port_list_head, list) { | ||
| 415 | if (port->rport && (id == port->rport->scsi_target_id)) | ||
| 416 | return port; | ||
| 417 | } | ||
| 418 | return (struct zfcp_port *) NULL; | ||
| 419 | } | ||
| 420 | |||
| 421 | /** | 407 | /** |
| 422 | * zfcp_scsi_eh_abort_handler - abort the specified SCSI command | 408 | * zfcp_scsi_eh_abort_handler - abort the specified SCSI command |
| 423 | * @scpnt: pointer to scsi_cmnd to be aborted | 409 | * @scpnt: pointer to scsi_cmnd to be aborted |
| @@ -731,70 +717,164 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) | |||
| 731 | /* | 717 | /* |
| 732 | * Support functions for FC transport class | 718 | * Support functions for FC transport class |
| 733 | */ | 719 | */ |
| 734 | static void | 720 | static struct fc_host_statistics* |
| 735 | zfcp_get_port_id(struct scsi_target *starget) | 721 | zfcp_init_fc_host_stats(struct zfcp_adapter *adapter) |
| 736 | { | 722 | { |
| 737 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 723 | struct fc_host_statistics *fc_stats; |
| 738 | struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
| 739 | struct zfcp_port *port; | ||
| 740 | unsigned long flags; | ||
| 741 | 724 | ||
| 742 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 725 | if (!adapter->fc_stats) { |
| 743 | port = zfcp_port_lookup(adapter, starget->channel, starget->id); | 726 | fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL); |
| 744 | if (port) | 727 | if (!fc_stats) |
| 745 | fc_starget_port_id(starget) = port->d_id; | 728 | return NULL; |
| 746 | else | 729 | adapter->fc_stats = fc_stats; /* freed in adater_dequeue */ |
| 747 | fc_starget_port_id(starget) = -1; | 730 | } |
| 748 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 731 | memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats)); |
| 732 | return adapter->fc_stats; | ||
| 749 | } | 733 | } |
| 750 | 734 | ||
| 751 | static void | 735 | static void |
| 752 | zfcp_get_port_name(struct scsi_target *starget) | 736 | zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats, |
| 737 | struct fsf_qtcb_bottom_port *data, | ||
| 738 | struct fsf_qtcb_bottom_port *old) | ||
| 753 | { | 739 | { |
| 754 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 740 | fc_stats->seconds_since_last_reset = data->seconds_since_last_reset - |
| 755 | struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; | 741 | old->seconds_since_last_reset; |
| 756 | struct zfcp_port *port; | 742 | fc_stats->tx_frames = data->tx_frames - old->tx_frames; |
| 757 | unsigned long flags; | 743 | fc_stats->tx_words = data->tx_words - old->tx_words; |
| 744 | fc_stats->rx_frames = data->rx_frames - old->rx_frames; | ||
| 745 | fc_stats->rx_words = data->rx_words - old->rx_words; | ||
| 746 | fc_stats->lip_count = data->lip - old->lip; | ||
| 747 | fc_stats->nos_count = data->nos - old->nos; | ||
| 748 | fc_stats->error_frames = data->error_frames - old->error_frames; | ||
| 749 | fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames; | ||
| 750 | fc_stats->link_failure_count = data->link_failure - old->link_failure; | ||
| 751 | fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync; | ||
| 752 | fc_stats->loss_of_signal_count = data->loss_of_signal - | ||
| 753 | old->loss_of_signal; | ||
| 754 | fc_stats->prim_seq_protocol_err_count = data->psp_error_counts - | ||
| 755 | old->psp_error_counts; | ||
| 756 | fc_stats->invalid_tx_word_count = data->invalid_tx_words - | ||
| 757 | old->invalid_tx_words; | ||
| 758 | fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs; | ||
| 759 | fc_stats->fcp_input_requests = data->input_requests - | ||
| 760 | old->input_requests; | ||
| 761 | fc_stats->fcp_output_requests = data->output_requests - | ||
| 762 | old->output_requests; | ||
| 763 | fc_stats->fcp_control_requests = data->control_requests - | ||
| 764 | old->control_requests; | ||
| 765 | fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb; | ||
| 766 | fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb; | ||
| 767 | } | ||
| 758 | 768 | ||
| 759 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 769 | static void |
| 760 | port = zfcp_port_lookup(adapter, starget->channel, starget->id); | 770 | zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats, |
| 761 | if (port) | 771 | struct fsf_qtcb_bottom_port *data) |
| 762 | fc_starget_port_name(starget) = port->wwpn; | 772 | { |
| 763 | else | 773 | fc_stats->seconds_since_last_reset = data->seconds_since_last_reset; |
| 764 | fc_starget_port_name(starget) = -1; | 774 | fc_stats->tx_frames = data->tx_frames; |
| 765 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 775 | fc_stats->tx_words = data->tx_words; |
| 776 | fc_stats->rx_frames = data->rx_frames; | ||
| 777 | fc_stats->rx_words = data->rx_words; | ||
| 778 | fc_stats->lip_count = data->lip; | ||
| 779 | fc_stats->nos_count = data->nos; | ||
| 780 | fc_stats->error_frames = data->error_frames; | ||
| 781 | fc_stats->dumped_frames = data->dumped_frames; | ||
| 782 | fc_stats->link_failure_count = data->link_failure; | ||
| 783 | fc_stats->loss_of_sync_count = data->loss_of_sync; | ||
| 784 | fc_stats->loss_of_signal_count = data->loss_of_signal; | ||
| 785 | fc_stats->prim_seq_protocol_err_count = data->psp_error_counts; | ||
| 786 | fc_stats->invalid_tx_word_count = data->invalid_tx_words; | ||
| 787 | fc_stats->invalid_crc_count = data->invalid_crcs; | ||
| 788 | fc_stats->fcp_input_requests = data->input_requests; | ||
| 789 | fc_stats->fcp_output_requests = data->output_requests; | ||
| 790 | fc_stats->fcp_control_requests = data->control_requests; | ||
| 791 | fc_stats->fcp_input_megabytes = data->input_mb; | ||
| 792 | fc_stats->fcp_output_megabytes = data->output_mb; | ||
| 793 | } | ||
| 794 | |||
| 795 | /** | ||
| 796 | * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc | ||
| 797 | * | ||
| 798 | * assumption: scsi_transport_fc synchronizes calls of | ||
| 799 | * get_fc_host_stats and reset_fc_host_stats | ||
| 800 | * (XXX to be checked otherwise introduce locking) | ||
| 801 | */ | ||
| 802 | static struct fc_host_statistics * | ||
| 803 | zfcp_get_fc_host_stats(struct Scsi_Host *shost) | ||
| 804 | { | ||
| 805 | struct zfcp_adapter *adapter; | ||
| 806 | struct fc_host_statistics *fc_stats; | ||
| 807 | struct fsf_qtcb_bottom_port *data; | ||
| 808 | int ret; | ||
| 809 | |||
| 810 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
| 811 | fc_stats = zfcp_init_fc_host_stats(adapter); | ||
| 812 | if (!fc_stats) | ||
| 813 | return NULL; | ||
| 814 | |||
| 815 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
| 816 | if (!data) | ||
| 817 | return NULL; | ||
| 818 | memset(data, 0, sizeof(*data)); | ||
| 819 | |||
| 820 | ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); | ||
| 821 | if (ret) { | ||
| 822 | kfree(data); | ||
| 823 | return NULL; /* XXX return zeroed fc_stats? */ | ||
| 824 | } | ||
| 825 | |||
| 826 | if (adapter->stats_reset && | ||
| 827 | ((jiffies/HZ - adapter->stats_reset) < | ||
| 828 | data->seconds_since_last_reset)) { | ||
| 829 | zfcp_adjust_fc_host_stats(fc_stats, data, | ||
| 830 | adapter->stats_reset_data); | ||
| 831 | } else | ||
| 832 | zfcp_set_fc_host_stats(fc_stats, data); | ||
| 833 | |||
| 834 | kfree(data); | ||
| 835 | return fc_stats; | ||
| 766 | } | 836 | } |
| 767 | 837 | ||
| 768 | static void | 838 | static void |
| 769 | zfcp_get_node_name(struct scsi_target *starget) | 839 | zfcp_reset_fc_host_stats(struct Scsi_Host *shost) |
| 770 | { | 840 | { |
| 771 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 841 | struct zfcp_adapter *adapter; |
| 772 | struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; | 842 | struct fsf_qtcb_bottom_port *data, *old_data; |
| 773 | struct zfcp_port *port; | 843 | int ret; |
| 774 | unsigned long flags; | ||
| 775 | 844 | ||
| 776 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 845 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; |
| 777 | port = zfcp_port_lookup(adapter, starget->channel, starget->id); | 846 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
| 778 | if (port) | 847 | if (!data) |
| 779 | fc_starget_node_name(starget) = port->wwnn; | 848 | return; |
| 780 | else | 849 | memset(data, 0, sizeof(*data)); |
| 781 | fc_starget_node_name(starget) = -1; | 850 | |
| 782 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 851 | ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); |
| 852 | if (ret == 0) { | ||
| 853 | adapter->stats_reset = jiffies/HZ; | ||
| 854 | old_data = adapter->stats_reset_data; | ||
| 855 | adapter->stats_reset_data = data; /* finally freed in | ||
| 856 | adater_dequeue */ | ||
| 857 | kfree(old_data); | ||
| 858 | } | ||
| 783 | } | 859 | } |
| 784 | 860 | ||
| 785 | struct fc_function_template zfcp_transport_functions = { | 861 | struct fc_function_template zfcp_transport_functions = { |
| 786 | .get_starget_port_id = zfcp_get_port_id, | ||
| 787 | .get_starget_port_name = zfcp_get_port_name, | ||
| 788 | .get_starget_node_name = zfcp_get_node_name, | ||
| 789 | .show_starget_port_id = 1, | 862 | .show_starget_port_id = 1, |
| 790 | .show_starget_port_name = 1, | 863 | .show_starget_port_name = 1, |
| 791 | .show_starget_node_name = 1, | 864 | .show_starget_node_name = 1, |
| 792 | .show_rport_supported_classes = 1, | 865 | .show_rport_supported_classes = 1, |
| 793 | .show_host_node_name = 1, | 866 | .show_host_node_name = 1, |
| 794 | .show_host_port_name = 1, | 867 | .show_host_port_name = 1, |
| 868 | .show_host_permanent_port_name = 1, | ||
| 795 | .show_host_supported_classes = 1, | 869 | .show_host_supported_classes = 1, |
| 870 | .show_host_supported_speeds = 1, | ||
| 796 | .show_host_maxframe_size = 1, | 871 | .show_host_maxframe_size = 1, |
| 797 | .show_host_serial_number = 1, | 872 | .show_host_serial_number = 1, |
| 873 | .get_fc_host_stats = zfcp_get_fc_host_stats, | ||
| 874 | .reset_fc_host_stats = zfcp_reset_fc_host_stats, | ||
| 875 | /* no functions registered for following dynamic attributes but | ||
| 876 | directly set by LLDD */ | ||
| 877 | .show_host_port_type = 1, | ||
| 798 | .show_host_speed = 1, | 878 | .show_host_speed = 1, |
| 799 | .show_host_port_id = 1, | 879 | .show_host_port_id = 1, |
| 800 | }; | 880 | }; |
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index 0cd435280e7d..9f262250043a 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c | |||
| @@ -33,14 +33,6 @@ | |||
| 33 | 33 | ||
| 34 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG | 34 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG |
| 35 | 35 | ||
| 36 | static const char fc_topologies[5][25] = { | ||
| 37 | "<error>", | ||
| 38 | "point-to-point", | ||
| 39 | "fabric", | ||
| 40 | "arbitrated loop", | ||
| 41 | "fabric (virt. adapter)" | ||
| 42 | }; | ||
| 43 | |||
| 44 | /** | 36 | /** |
| 45 | * ZFCP_DEFINE_ADAPTER_ATTR | 37 | * ZFCP_DEFINE_ADAPTER_ATTR |
| 46 | * @_name: name of show attribute | 38 | * @_name: name of show attribute |
| @@ -69,12 +61,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); | |||
| 69 | ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); | 61 | ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); |
| 70 | ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); | 62 | ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); |
| 71 | ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); | 63 | ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); |
| 72 | ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class); | ||
| 73 | ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", | ||
| 74 | fc_topologies[adapter->fc_topology]); | ||
| 75 | ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", | 64 | ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", |
| 76 | adapter->hardware_version); | 65 | adapter->hardware_version); |
| 77 | ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); | ||
| 78 | ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask | 66 | ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask |
| 79 | (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); | 67 | (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); |
| 80 | 68 | ||
| @@ -259,9 +247,6 @@ static struct attribute *zfcp_adapter_attrs[] = { | |||
| 259 | &dev_attr_physical_s_id.attr, | 247 | &dev_attr_physical_s_id.attr, |
| 260 | &dev_attr_card_version.attr, | 248 | &dev_attr_card_version.attr, |
| 261 | &dev_attr_lic_version.attr, | 249 | &dev_attr_lic_version.attr, |
| 262 | &dev_attr_fc_service_class.attr, | ||
| 263 | &dev_attr_fc_topology.attr, | ||
| 264 | &dev_attr_scsi_host_no.attr, | ||
| 265 | &dev_attr_status.attr, | 250 | &dev_attr_status.attr, |
| 266 | &dev_attr_hardware_version.attr, | 251 | &dev_attr_hardware_version.attr, |
| 267 | NULL | 252 | NULL |
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index c55e82d91deb..3924eb38805c 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c | |||
| @@ -65,8 +65,6 @@ static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_ | |||
| 65 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL); | 65 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL); |
| 66 | 66 | ||
| 67 | ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status)); | 67 | ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status)); |
| 68 | ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn); | ||
| 69 | ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id); | ||
| 70 | ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask | 68 | ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask |
| 71 | (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)); | 69 | (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)); |
| 72 | ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask | 70 | ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask |
| @@ -245,8 +243,6 @@ static struct attribute *zfcp_port_common_attrs[] = { | |||
| 245 | &dev_attr_failed.attr, | 243 | &dev_attr_failed.attr, |
| 246 | &dev_attr_in_recovery.attr, | 244 | &dev_attr_in_recovery.attr, |
| 247 | &dev_attr_status.attr, | 245 | &dev_attr_status.attr, |
| 248 | &dev_attr_wwnn.attr, | ||
| 249 | &dev_attr_d_id.attr, | ||
| 250 | &dev_attr_access_denied.attr, | 246 | &dev_attr_access_denied.attr, |
| 251 | NULL | 247 | NULL |
| 252 | }; | 248 | }; |
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index 0556642c9e1d..2f50815f65c7 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c | |||
| @@ -65,7 +65,6 @@ static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_ | |||
| 65 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL); | 65 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL); |
| 66 | 66 | ||
| 67 | ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status)); | 67 | ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status)); |
| 68 | ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun); | ||
| 69 | ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask | 68 | ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask |
| 70 | (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)); | 69 | (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)); |
| 71 | ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask | 70 | ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask |
| @@ -138,7 +137,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show, | |||
| 138 | zfcp_sysfs_unit_failed_store); | 137 | zfcp_sysfs_unit_failed_store); |
| 139 | 138 | ||
| 140 | static struct attribute *zfcp_unit_attrs[] = { | 139 | static struct attribute *zfcp_unit_attrs[] = { |
| 141 | &dev_attr_scsi_lun.attr, | ||
| 142 | &dev_attr_failed.attr, | 140 | &dev_attr_failed.attr, |
| 143 | &dev_attr_in_recovery.attr, | 141 | &dev_attr_in_recovery.attr, |
| 144 | &dev_attr_status.attr, | 142 | &dev_attr_status.attr, |
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index 92e6c5639dd3..015db40ad8a4 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c | |||
| @@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = { | |||
| 92 | 92 | ||
| 93 | /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ | 93 | /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ |
| 94 | static unsigned char * tmp_buf = NULL; | 94 | static unsigned char * tmp_buf = NULL; |
| 95 | static DECLARE_MUTEX(tmp_buf_sem); | ||
| 96 | 95 | ||
| 97 | DECLARE_TASK_QUEUE(tq_aurora); | 96 | DECLARE_TASK_QUEUE(tq_aurora); |
| 98 | 97 | ||
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 3ff74f472249..31c497542272 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
| @@ -73,6 +73,7 @@ | |||
| 73 | #include <linux/delay.h> | 73 | #include <linux/delay.h> |
| 74 | #include <linux/pci.h> | 74 | #include <linux/pci.h> |
| 75 | #include <linux/time.h> | 75 | #include <linux/time.h> |
| 76 | #include <linux/mutex.h> | ||
| 76 | #include <asm/io.h> | 77 | #include <asm/io.h> |
| 77 | #include <asm/irq.h> | 78 | #include <asm/irq.h> |
| 78 | #include <asm/uaccess.h> | 79 | #include <asm/uaccess.h> |
| @@ -615,7 +616,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int | |||
| 615 | void __user *argp = (void __user *)arg; | 616 | void __user *argp = (void __user *)arg; |
| 616 | 617 | ||
| 617 | /* Only let one of these through at a time */ | 618 | /* Only let one of these through at a time */ |
| 618 | if (down_interruptible(&tw_dev->ioctl_sem)) { | 619 | if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) { |
| 619 | retval = TW_IOCTL_ERROR_OS_EINTR; | 620 | retval = TW_IOCTL_ERROR_OS_EINTR; |
| 620 | goto out; | 621 | goto out; |
| 621 | } | 622 | } |
| @@ -852,7 +853,7 @@ out3: | |||
| 852 | /* Now free ioctl buf memory */ | 853 | /* Now free ioctl buf memory */ |
| 853 | dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle); | 854 | dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle); |
| 854 | out2: | 855 | out2: |
| 855 | up(&tw_dev->ioctl_sem); | 856 | mutex_unlock(&tw_dev->ioctl_lock); |
| 856 | out: | 857 | out: |
| 857 | return retval; | 858 | return retval; |
| 858 | } /* End twa_chrdev_ioctl() */ | 859 | } /* End twa_chrdev_ioctl() */ |
| @@ -1182,7 +1183,7 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev) | |||
| 1182 | tw_dev->error_sequence_id = 1; | 1183 | tw_dev->error_sequence_id = 1; |
| 1183 | tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; | 1184 | tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; |
| 1184 | 1185 | ||
| 1185 | init_MUTEX(&tw_dev->ioctl_sem); | 1186 | mutex_init(&tw_dev->ioctl_lock); |
| 1186 | init_waitqueue_head(&tw_dev->ioctl_wqueue); | 1187 | init_waitqueue_head(&tw_dev->ioctl_wqueue); |
| 1187 | 1188 | ||
| 1188 | retval = 0; | 1189 | retval = 0; |
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 46f22cdc8298..1b16d57f0314 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h | |||
| @@ -672,7 +672,7 @@ typedef struct TAG_TW_Device_Extension { | |||
| 672 | u32 ioctl_msec; | 672 | u32 ioctl_msec; |
| 673 | int chrdev_request_id; | 673 | int chrdev_request_id; |
| 674 | wait_queue_head_t ioctl_wqueue; | 674 | wait_queue_head_t ioctl_wqueue; |
| 675 | struct semaphore ioctl_sem; | 675 | struct mutex ioctl_lock; |
| 676 | char aen_clobber; | 676 | char aen_clobber; |
| 677 | unsigned short working_srl; | 677 | unsigned short working_srl; |
| 678 | unsigned short working_branch; | 678 | unsigned short working_branch; |
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 283f6d25892b..25f678d0780b 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c | |||
| @@ -203,6 +203,7 @@ | |||
| 203 | #include <linux/delay.h> | 203 | #include <linux/delay.h> |
| 204 | #include <linux/pci.h> | 204 | #include <linux/pci.h> |
| 205 | #include <linux/time.h> | 205 | #include <linux/time.h> |
| 206 | #include <linux/mutex.h> | ||
| 206 | #include <asm/io.h> | 207 | #include <asm/io.h> |
| 207 | #include <asm/irq.h> | 208 | #include <asm/irq.h> |
| 208 | #include <asm/uaccess.h> | 209 | #include <asm/uaccess.h> |
| @@ -888,7 +889,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int | |||
| 888 | dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n"); | 889 | dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n"); |
| 889 | 890 | ||
| 890 | /* Only let one of these through at a time */ | 891 | /* Only let one of these through at a time */ |
| 891 | if (down_interruptible(&tw_dev->ioctl_sem)) | 892 | if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) |
| 892 | return -EINTR; | 893 | return -EINTR; |
| 893 | 894 | ||
| 894 | /* First copy down the buffer length */ | 895 | /* First copy down the buffer length */ |
| @@ -1029,7 +1030,7 @@ out2: | |||
| 1029 | /* Now free ioctl buf memory */ | 1030 | /* Now free ioctl buf memory */ |
| 1030 | dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); | 1031 | dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); |
| 1031 | out: | 1032 | out: |
| 1032 | up(&tw_dev->ioctl_sem); | 1033 | mutex_unlock(&tw_dev->ioctl_lock); |
| 1033 | return retval; | 1034 | return retval; |
| 1034 | } /* End tw_chrdev_ioctl() */ | 1035 | } /* End tw_chrdev_ioctl() */ |
| 1035 | 1036 | ||
| @@ -1270,7 +1271,7 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev) | |||
| 1270 | tw_dev->pending_tail = TW_Q_START; | 1271 | tw_dev->pending_tail = TW_Q_START; |
| 1271 | tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; | 1272 | tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; |
| 1272 | 1273 | ||
| 1273 | init_MUTEX(&tw_dev->ioctl_sem); | 1274 | mutex_init(&tw_dev->ioctl_lock); |
| 1274 | init_waitqueue_head(&tw_dev->ioctl_wqueue); | 1275 | init_waitqueue_head(&tw_dev->ioctl_wqueue); |
| 1275 | 1276 | ||
| 1276 | return 0; | 1277 | return 0; |
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 4f81fc39ec57..31fe5ea15920 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h | |||
| @@ -420,7 +420,7 @@ typedef struct TAG_TW_Device_Extension { | |||
| 420 | u32 max_sector_count; | 420 | u32 max_sector_count; |
| 421 | u32 aen_count; | 421 | u32 aen_count; |
| 422 | struct Scsi_Host *host; | 422 | struct Scsi_Host *host; |
| 423 | struct semaphore ioctl_sem; | 423 | struct mutex ioctl_lock; |
| 424 | unsigned short aen_queue[TW_Q_LENGTH]; | 424 | unsigned short aen_queue[TW_Q_LENGTH]; |
| 425 | unsigned char aen_head; | 425 | unsigned char aen_head; |
| 426 | unsigned char aen_tail; | 426 | unsigned char aen_tail; |
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 9d6040bfa064..1c459343292b 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c | |||
| @@ -2216,6 +2216,7 @@ static int __init BusLogic_init(void) | |||
| 2216 | HostAdapter->PCI_Address = ProbeInfo->PCI_Address; | 2216 | HostAdapter->PCI_Address = ProbeInfo->PCI_Address; |
| 2217 | HostAdapter->Bus = ProbeInfo->Bus; | 2217 | HostAdapter->Bus = ProbeInfo->Bus; |
| 2218 | HostAdapter->Device = ProbeInfo->Device; | 2218 | HostAdapter->Device = ProbeInfo->Device; |
| 2219 | HostAdapter->PCI_Device = ProbeInfo->PCI_Device; | ||
| 2219 | HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; | 2220 | HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; |
| 2220 | HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; | 2221 | HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; |
| 2221 | /* | 2222 | /* |
| @@ -2296,7 +2297,7 @@ static int __init BusLogic_init(void) | |||
| 2296 | scsi_host_put(Host); | 2297 | scsi_host_put(Host); |
| 2297 | } else { | 2298 | } else { |
| 2298 | BusLogic_InitializeHostStructure(HostAdapter, Host); | 2299 | BusLogic_InitializeHostStructure(HostAdapter, Host); |
| 2299 | scsi_add_host(Host, NULL); | 2300 | scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL); |
| 2300 | scsi_scan_host(Host); | 2301 | scsi_scan_host(Host); |
| 2301 | BusLogicHostAdapterCount++; | 2302 | BusLogicHostAdapterCount++; |
| 2302 | } | 2303 | } |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 6e0c059df6a5..320e765fa0cd 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
| @@ -80,7 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o | |||
| 80 | obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o | 80 | obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o |
| 81 | obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o | 81 | obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o |
| 82 | obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o | 82 | obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o |
| 83 | obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx/ | 83 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/ |
| 84 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ | 84 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ |
| 85 | obj-$(CONFIG_SCSI_PAS16) += pas16.o | 85 | obj-$(CONFIG_SCSI_PAS16) += pas16.o |
| 86 | obj-$(CONFIG_SCSI_SEAGATE) += seagate.o | 86 | obj-$(CONFIG_SCSI_SEAGATE) += seagate.o |
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README deleted file mode 100644 index 4193865d419c..000000000000 --- a/drivers/scsi/aacraid/README +++ /dev/null | |||
| @@ -1,74 +0,0 @@ | |||
| 1 | AACRAID Driver for Linux (take two) | ||
| 2 | |||
| 3 | Introduction | ||
| 4 | ------------------------- | ||
| 5 | The aacraid driver adds support for Adaptec (http://www.adaptec.com) | ||
| 6 | RAID controllers. This is a major rewrite from the original | ||
| 7 | Adaptec supplied driver. It has signficantly cleaned up both the code | ||
| 8 | and the running binary size (the module is less than half the size of | ||
| 9 | the original). | ||
| 10 | |||
| 11 | Supported Cards/Chipsets | ||
| 12 | ------------------------- | ||
| 13 | Adaptec 2020S | ||
| 14 | Adaptec 2025S | ||
| 15 | Adaptec 2120S | ||
| 16 | Adaptec 2130S | ||
| 17 | Adaptec 2200S | ||
| 18 | Adaptec 2230S | ||
| 19 | Adaptec 2240S | ||
| 20 | Adaptec 2410SA | ||
| 21 | Adaptec 2610SA | ||
| 22 | Adaptec 2810SA | ||
| 23 | Adaptec 21610SA | ||
| 24 | Adaptec 3230S | ||
| 25 | Adaptec 3240S | ||
| 26 | Adaptec 4000SAS | ||
| 27 | Adaptec 4005SAS | ||
| 28 | Adaptec 4800SAS | ||
| 29 | Adaptec 4805SAS | ||
| 30 | Adaptec 5400S | ||
| 31 | Dell PERC 2 Quad Channel | ||
| 32 | Dell PERC 2/Si | ||
| 33 | Dell PERC 3/Si | ||
| 34 | Dell PERC 3/Di | ||
| 35 | Dell CERC 2 | ||
| 36 | HP NetRAID-4M | ||
| 37 | Legend S220 | ||
| 38 | Legend S230 | ||
| 39 | IBM ServeRAID 8i | ||
| 40 | ICP 9014R0 | ||
| 41 | ICP 9024R0 | ||
| 42 | ICP 9047MA | ||
| 43 | ICP 9087MA | ||
| 44 | ICP 9085LI | ||
| 45 | ICP 5085AU | ||
| 46 | |||
| 47 | People | ||
| 48 | ------------------------- | ||
| 49 | Alan Cox <alan@redhat.com> | ||
| 50 | Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration, | ||
| 51 | small cleanups/fixes) | ||
| 52 | Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages) | ||
| 53 | Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers | ||
| 54 | added new ioctls, changed scsi interface to use new error handler, | ||
| 55 | increased the number of fibs and outstanding commands to a container) | ||
| 56 | |||
| 57 | (fixed 64bit and 64G memory model, changed confusing naming convention | ||
| 58 | where fibs that go to the hardware are consistently called hw_fibs and | ||
| 59 | not just fibs like the name of the driver tracking structure) | ||
| 60 | Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations. | ||
| 61 | |||
| 62 | Original Driver | ||
| 63 | ------------------------- | ||
| 64 | Adaptec Unix OEM Product Group | ||
| 65 | |||
| 66 | Mailing List | ||
| 67 | ------------------------- | ||
| 68 | linux-scsi@vger.kernel.org (Interested parties troll here) | ||
| 69 | Also note this is very different to Brian's original driver | ||
| 70 | so don't expect him to support it. | ||
| 71 | Adaptec does support this driver. Contact either tech support or Mark Salyzyn. | ||
| 72 | |||
| 73 | Original by Brian Boerner February 2001 | ||
| 74 | Rewritten by Alan Cox, November 2001 | ||
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 30fd8d6e3f31..66dbb6d2c506 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
| @@ -532,6 +532,13 @@ struct aac_driver_ident | |||
| 532 | #define AAC_QUIRK_MASTER 0x0008 | 532 | #define AAC_QUIRK_MASTER 0x0008 |
| 533 | 533 | ||
| 534 | /* | 534 | /* |
| 535 | * Some adapter firmware perform poorly when it must split up scatter gathers | ||
| 536 | * in order to deal with the limits of the underlying CHIM. This limit in this | ||
| 537 | * class of adapters is 17 scatter gather elements. | ||
| 538 | */ | ||
| 539 | #define AAC_QUIRK_17SG 0x0010 | ||
| 540 | |||
| 541 | /* | ||
| 535 | * The adapter interface specs all queues to be located in the same | 542 | * The adapter interface specs all queues to be located in the same |
| 536 | * physically contigous block. The host structure that defines the | 543 | * physically contigous block. The host structure that defines the |
| 537 | * commuication queues will assume they are each a separate physically | 544 | * commuication queues will assume they are each a separate physically |
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index ef623bd965f5..4fe79cd7c957 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
| @@ -85,6 +85,10 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) | |||
| 85 | if (size < le16_to_cpu(kfib->header.SenderSize)) | 85 | if (size < le16_to_cpu(kfib->header.SenderSize)) |
| 86 | size = le16_to_cpu(kfib->header.SenderSize); | 86 | size = le16_to_cpu(kfib->header.SenderSize); |
| 87 | if (size > dev->max_fib_size) { | 87 | if (size > dev->max_fib_size) { |
| 88 | if (size > 2048) { | ||
| 89 | retval = -EINVAL; | ||
| 90 | goto cleanup; | ||
| 91 | } | ||
| 88 | /* Highjack the hw_fib */ | 92 | /* Highjack the hw_fib */ |
| 89 | hw_fib = fibptr->hw_fib; | 93 | hw_fib = fibptr->hw_fib; |
| 90 | hw_fib_pa = fibptr->hw_fib_pa; | 94 | hw_fib_pa = fibptr->hw_fib_pa; |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 9b9062f02462..0bf5f9a943e8 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
| @@ -200,10 +200,10 @@ static struct aac_driver_ident aac_drivers[] = { | |||
| 200 | { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ | 200 | { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ |
| 201 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ | 201 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ |
| 202 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ | 202 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ |
| 203 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ | 203 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ |
| 204 | { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ | 204 | { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ |
| 205 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ | 205 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ |
| 206 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ | 206 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ |
| 207 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ | 207 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ |
| 208 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */ | 208 | { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */ |
| 209 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ | 209 | { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ |
| @@ -574,7 +574,15 @@ static ssize_t aac_show_model(struct class_device *class_dev, | |||
| 574 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; | 574 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; |
| 575 | int len; | 575 | int len; |
| 576 | 576 | ||
| 577 | len = snprintf(buf, PAGE_SIZE, "%s\n", | 577 | if (dev->supplement_adapter_info.AdapterTypeText[0]) { |
| 578 | char * cp = dev->supplement_adapter_info.AdapterTypeText; | ||
| 579 | while (*cp && *cp != ' ') | ||
| 580 | ++cp; | ||
| 581 | while (*cp == ' ') | ||
| 582 | ++cp; | ||
| 583 | len = snprintf(buf, PAGE_SIZE, "%s\n", cp); | ||
| 584 | } else | ||
| 585 | len = snprintf(buf, PAGE_SIZE, "%s\n", | ||
| 578 | aac_drivers[dev->cardtype].model); | 586 | aac_drivers[dev->cardtype].model); |
| 579 | return len; | 587 | return len; |
| 580 | } | 588 | } |
| @@ -585,7 +593,15 @@ static ssize_t aac_show_vendor(struct class_device *class_dev, | |||
| 585 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; | 593 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; |
| 586 | int len; | 594 | int len; |
| 587 | 595 | ||
| 588 | len = snprintf(buf, PAGE_SIZE, "%s\n", | 596 | if (dev->supplement_adapter_info.AdapterTypeText[0]) { |
| 597 | char * cp = dev->supplement_adapter_info.AdapterTypeText; | ||
| 598 | while (*cp && *cp != ' ') | ||
| 599 | ++cp; | ||
| 600 | len = snprintf(buf, PAGE_SIZE, "%.*s\n", | ||
| 601 | (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText), | ||
| 602 | dev->supplement_adapter_info.AdapterTypeText); | ||
| 603 | } else | ||
| 604 | len = snprintf(buf, PAGE_SIZE, "%s\n", | ||
| 589 | aac_drivers[dev->cardtype].vname); | 605 | aac_drivers[dev->cardtype].vname); |
| 590 | return len; | 606 | return len; |
| 591 | } | 607 | } |
| @@ -837,6 +853,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
| 837 | = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; | 853 | = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; |
| 838 | } | 854 | } |
| 839 | 855 | ||
| 856 | if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && | ||
| 857 | (aac->scsi_host_ptr->sg_tablesize > 17)) { | ||
| 858 | aac->scsi_host_ptr->sg_tablesize = 17; | ||
| 859 | aac->scsi_host_ptr->max_sectors | ||
| 860 | = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; | ||
| 861 | } | ||
| 862 | |||
| 840 | /* | 863 | /* |
| 841 | * Firware printf works only with older firmware. | 864 | * Firware printf works only with older firmware. |
| 842 | */ | 865 | */ |
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index ac8de03c9fa2..6c2c395554ff 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx | |||
| @@ -42,13 +42,13 @@ config AIC7XXX_CMDS_PER_DEVICE | |||
| 42 | config AIC7XXX_RESET_DELAY_MS | 42 | config AIC7XXX_RESET_DELAY_MS |
| 43 | int "Initial bus reset delay in milli-seconds" | 43 | int "Initial bus reset delay in milli-seconds" |
| 44 | depends on SCSI_AIC7XXX | 44 | depends on SCSI_AIC7XXX |
| 45 | default "15000" | 45 | default "5000" |
| 46 | ---help--- | 46 | ---help--- |
| 47 | The number of milliseconds to delay after an initial bus reset. | 47 | The number of milliseconds to delay after an initial bus reset. |
| 48 | The bus settle delay following all error recovery actions is | 48 | The bus settle delay following all error recovery actions is |
| 49 | dictated by the SCSI layer and is not affected by this value. | 49 | dictated by the SCSI layer and is not affected by this value. |
| 50 | 50 | ||
| 51 | Default: 15000 (15 seconds) | 51 | Default: 5000 (5 seconds) |
| 52 | 52 | ||
| 53 | config AIC7XXX_PROBE_EISA_VL | 53 | config AIC7XXX_PROBE_EISA_VL |
| 54 | bool "Probe for EISA and VL AIC7XXX Adapters" | 54 | bool "Probe for EISA and VL AIC7XXX Adapters" |
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 653fb0b42aea..2cfdbef447db 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 38 | * POSSIBILITY OF SUCH DAMAGES. | 38 | * POSSIBILITY OF SUCH DAMAGES. |
| 39 | * | 39 | * |
| 40 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $ | 40 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $ |
| 41 | * | 41 | * |
| 42 | * $FreeBSD$ | 42 | * $FreeBSD$ |
| 43 | */ | 43 | */ |
| @@ -75,8 +75,7 @@ struct scb_platform_data; | |||
| 75 | #define INITIATOR_WILDCARD (~0) | 75 | #define INITIATOR_WILDCARD (~0) |
| 76 | #define SCB_LIST_NULL 0xFF00 | 76 | #define SCB_LIST_NULL 0xFF00 |
| 77 | #define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) | 77 | #define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) |
| 78 | #define QOUTFIFO_ENTRY_VALID 0x8000 | 78 | #define QOUTFIFO_ENTRY_VALID 0x80 |
| 79 | #define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000)) | ||
| 80 | #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) | 79 | #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) |
| 81 | 80 | ||
| 82 | #define SCSIID_TARGET(ahd, scsiid) \ | 81 | #define SCSIID_TARGET(ahd, scsiid) \ |
| @@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state; | |||
| 1053 | 1052 | ||
| 1054 | typedef void ahd_callback_t (void *); | 1053 | typedef void ahd_callback_t (void *); |
| 1055 | 1054 | ||
| 1055 | struct ahd_completion | ||
| 1056 | { | ||
| 1057 | uint16_t tag; | ||
| 1058 | uint8_t sg_status; | ||
| 1059 | uint8_t valid_tag; | ||
| 1060 | }; | ||
| 1061 | |||
| 1056 | struct ahd_softc { | 1062 | struct ahd_softc { |
| 1057 | bus_space_tag_t tags[2]; | 1063 | bus_space_tag_t tags[2]; |
| 1058 | bus_space_handle_t bshs[2]; | 1064 | bus_space_handle_t bshs[2]; |
| @@ -1062,6 +1068,7 @@ struct ahd_softc { | |||
| 1062 | struct scb_data scb_data; | 1068 | struct scb_data scb_data; |
| 1063 | 1069 | ||
| 1064 | struct hardware_scb *next_queued_hscb; | 1070 | struct hardware_scb *next_queued_hscb; |
| 1071 | struct map_node *next_queued_hscb_map; | ||
| 1065 | 1072 | ||
| 1066 | /* | 1073 | /* |
| 1067 | * SCBs that have been sent to the controller | 1074 | * SCBs that have been sent to the controller |
| @@ -1140,16 +1147,23 @@ struct ahd_softc { | |||
| 1140 | ahd_flag flags; | 1147 | ahd_flag flags; |
| 1141 | struct seeprom_config *seep_config; | 1148 | struct seeprom_config *seep_config; |
| 1142 | 1149 | ||
| 1143 | /* Values to store in the SEQCTL register for pause and unpause */ | ||
| 1144 | uint8_t unpause; | ||
| 1145 | uint8_t pause; | ||
| 1146 | |||
| 1147 | /* Command Queues */ | 1150 | /* Command Queues */ |
| 1151 | struct ahd_completion *qoutfifo; | ||
| 1148 | uint16_t qoutfifonext; | 1152 | uint16_t qoutfifonext; |
| 1149 | uint16_t qoutfifonext_valid_tag; | 1153 | uint16_t qoutfifonext_valid_tag; |
| 1150 | uint16_t qinfifonext; | 1154 | uint16_t qinfifonext; |
| 1151 | uint16_t qinfifo[AHD_SCB_MAX]; | 1155 | uint16_t qinfifo[AHD_SCB_MAX]; |
| 1152 | uint16_t *qoutfifo; | 1156 | |
| 1157 | /* | ||
| 1158 | * Our qfreeze count. The sequencer compares | ||
| 1159 | * this value with its own counter to determine | ||
| 1160 | * whether to allow selections to occur. | ||
| 1161 | */ | ||
| 1162 | uint16_t qfreeze_cnt; | ||
| 1163 | |||
| 1164 | /* Values to store in the SEQCTL register for pause and unpause */ | ||
| 1165 | uint8_t unpause; | ||
| 1166 | uint8_t pause; | ||
| 1153 | 1167 | ||
| 1154 | /* Critical Section Data */ | 1168 | /* Critical Section Data */ |
| 1155 | struct cs *critical_sections; | 1169 | struct cs *critical_sections; |
| @@ -1197,8 +1211,7 @@ struct ahd_softc { | |||
| 1197 | */ | 1211 | */ |
| 1198 | bus_dma_tag_t parent_dmat; | 1212 | bus_dma_tag_t parent_dmat; |
| 1199 | bus_dma_tag_t shared_data_dmat; | 1213 | bus_dma_tag_t shared_data_dmat; |
| 1200 | bus_dmamap_t shared_data_dmamap; | 1214 | struct map_node shared_data_map; |
| 1201 | dma_addr_t shared_data_busaddr; | ||
| 1202 | 1215 | ||
| 1203 | /* Information saved through suspend/resume cycles */ | 1216 | /* Information saved through suspend/resume cycles */ |
| 1204 | struct ahd_suspend_state suspend_state; | 1217 | struct ahd_suspend_state suspend_state; |
| @@ -1296,9 +1309,9 @@ struct ahd_devinfo { | |||
| 1296 | }; | 1309 | }; |
| 1297 | 1310 | ||
| 1298 | /****************************** PCI Structures ********************************/ | 1311 | /****************************** PCI Structures ********************************/ |
| 1299 | #define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/ | 1312 | #define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/ |
| 1300 | #define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */ | 1313 | #define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */ |
| 1301 | #define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */ | 1314 | #define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */ |
| 1302 | 1315 | ||
| 1303 | typedef int (ahd_device_setup_t)(struct ahd_softc *); | 1316 | typedef int (ahd_device_setup_t)(struct ahd_softc *); |
| 1304 | 1317 | ||
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg index cca58edc8648..3a3204703b15 100644 --- a/drivers/scsi/aic7xxx/aic79xx.reg +++ b/drivers/scsi/aic7xxx/aic79xx.reg | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | * | 39 | * |
| 40 | * $FreeBSD$ | 40 | * $FreeBSD$ |
| 41 | */ | 41 | */ |
| 42 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" | 42 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $" |
| 43 | 43 | ||
| 44 | /* | 44 | /* |
| 45 | * This file is processed by the aic7xxx_asm utility for use in assembling | 45 | * This file is processed by the aic7xxx_asm utility for use in assembling |
| @@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" | |||
| 65 | mvi MODE_PTR, MK_MODE(src, dst); \ | 65 | mvi MODE_PTR, MK_MODE(src, dst); \ |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | #define TOGGLE_DFF_MODE \ | ||
| 69 | if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ | ||
| 70 | call toggle_dff_mode_work_around; \ | ||
| 71 | } else { \ | ||
| 72 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \ | ||
| 73 | } | ||
| 74 | |||
| 75 | #define RESTORE_MODE(mode) \ | 68 | #define RESTORE_MODE(mode) \ |
| 76 | if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ | 69 | if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ |
| 77 | mov mode call set_mode_work_around; \ | 70 | mov mode call set_mode_work_around; \ |
| @@ -1199,7 +1192,7 @@ register TARGPCISTAT { | |||
| 1199 | 1192 | ||
| 1200 | /* | 1193 | /* |
| 1201 | * LQ Packet In | 1194 | * LQ Packet In |
| 1202 | * The last LQ Packet received | 1195 | * The last LQ Packet recieved |
| 1203 | */ | 1196 | */ |
| 1204 | register LQIN { | 1197 | register LQIN { |
| 1205 | address 0x020 | 1198 | address 0x020 |
| @@ -3542,10 +3535,34 @@ scratch_ram { | |||
| 3542 | COMPLETE_DMA_SCB_HEAD { | 3535 | COMPLETE_DMA_SCB_HEAD { |
| 3543 | size 2 | 3536 | size 2 |
| 3544 | } | 3537 | } |
| 3545 | /* Counting semaphore to prevent new select-outs */ | 3538 | /* |
| 3539 | * tail of list of SCBs that have | ||
| 3540 | * completed but need to be uploaded | ||
| 3541 | * to the host prior to being completed. | ||
| 3542 | */ | ||
| 3543 | COMPLETE_DMA_SCB_TAIL { | ||
| 3544 | size 2 | ||
| 3545 | } | ||
| 3546 | /* | ||
| 3547 | * head of list of SCBs that have | ||
| 3548 | * been uploaded to the host, but cannot | ||
| 3549 | * be completed until the QFREEZE is in | ||
| 3550 | * full effect (i.e. no selections pending). | ||
| 3551 | */ | ||
| 3552 | COMPLETE_ON_QFREEZE_HEAD { | ||
| 3553 | size 2 | ||
| 3554 | } | ||
| 3555 | /* | ||
| 3556 | * Counting semaphore to prevent new select-outs | ||
| 3557 | * The queue is frozen so long as the sequencer | ||
| 3558 | * and kernel freeze counts differ. | ||
| 3559 | */ | ||
| 3546 | QFREEZE_COUNT { | 3560 | QFREEZE_COUNT { |
| 3547 | size 2 | 3561 | size 2 |
| 3548 | } | 3562 | } |
| 3563 | KERNEL_QFREEZE_COUNT { | ||
| 3564 | size 2 | ||
| 3565 | } | ||
| 3549 | /* | 3566 | /* |
| 3550 | * Mode to restore on legacy idle loop exit. | 3567 | * Mode to restore on legacy idle loop exit. |
| 3551 | */ | 3568 | */ |
| @@ -3625,6 +3642,17 @@ scratch_ram { | |||
| 3625 | size 1 | 3642 | size 1 |
| 3626 | } | 3643 | } |
| 3627 | /* | 3644 | /* |
| 3645 | * Kernel and sequencer offsets into the queue of | ||
| 3646 | * incoming target mode command descriptors. The | ||
| 3647 | * queue is full when the KERNEL_TQINPOS == TQINPOS. | ||
| 3648 | */ | ||
| 3649 | KERNEL_TQINPOS { | ||
| 3650 | size 1 | ||
| 3651 | } | ||
| 3652 | TQINPOS { | ||
| 3653 | size 1 | ||
| 3654 | } | ||
| 3655 | /* | ||
| 3628 | * Base address of our shared data with the kernel driver in host | 3656 | * Base address of our shared data with the kernel driver in host |
| 3629 | * memory. This includes the qoutfifo and target mode | 3657 | * memory. This includes the qoutfifo and target mode |
| 3630 | * incoming command queue. | 3658 | * incoming command queue. |
| @@ -3639,17 +3667,6 @@ scratch_ram { | |||
| 3639 | QOUTFIFO_NEXT_ADDR { | 3667 | QOUTFIFO_NEXT_ADDR { |
| 3640 | size 4 | 3668 | size 4 |
| 3641 | } | 3669 | } |
| 3642 | /* | ||
| 3643 | * Kernel and sequencer offsets into the queue of | ||
| 3644 | * incoming target mode command descriptors. The | ||
| 3645 | * queue is full when the KERNEL_TQINPOS == TQINPOS. | ||
| 3646 | */ | ||
| 3647 | KERNEL_TQINPOS { | ||
| 3648 | size 1 | ||
| 3649 | } | ||
| 3650 | TQINPOS { | ||
| 3651 | size 1 | ||
| 3652 | } | ||
| 3653 | ARG_1 { | 3670 | ARG_1 { |
| 3654 | size 1 | 3671 | size 1 |
| 3655 | mask SEND_MSG 0x80 | 3672 | mask SEND_MSG 0x80 |
| @@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download | |||
| 3951 | const SG_SIZEOF download | 3968 | const SG_SIZEOF download |
| 3952 | const PKT_OVERRUN_BUFOFFSET download | 3969 | const PKT_OVERRUN_BUFOFFSET download |
| 3953 | const SCB_TRANSFER_SIZE download | 3970 | const SCB_TRANSFER_SIZE download |
| 3971 | const CACHELINE_MASK download | ||
| 3954 | 3972 | ||
| 3955 | /* | 3973 | /* |
| 3956 | * BIOS SCB offsets | 3974 | * BIOS SCB offsets |
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index 65339bc1ca99..bef1f9d369b6 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | * $FreeBSD$ | 40 | * $FreeBSD$ |
| 41 | */ | 41 | */ |
| 42 | 42 | ||
| 43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $" | 43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $" |
| 44 | PATCH_ARG_LIST = "struct ahd_softc *ahd" | 44 | PATCH_ARG_LIST = "struct ahd_softc *ahd" |
| 45 | PREFIX = "ahd_" | 45 | PREFIX = "ahd_" |
| 46 | 46 | ||
| @@ -68,13 +68,47 @@ no_error_set: | |||
| 68 | } | 68 | } |
| 69 | SET_MODE(M_SCSI, M_SCSI) | 69 | SET_MODE(M_SCSI, M_SCSI) |
| 70 | test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; | 70 | test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; |
| 71 | test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; | 71 | test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list; |
| 72 | /* | ||
| 73 | * If the kernel has caught up with us, thaw the queue. | ||
| 74 | */ | ||
| 75 | mov A, KERNEL_QFREEZE_COUNT; | ||
| 76 | cmp QFREEZE_COUNT, A jne check_frozen_completions; | ||
| 77 | mov A, KERNEL_QFREEZE_COUNT[1]; | ||
| 78 | cmp QFREEZE_COUNT[1], A jne check_frozen_completions; | ||
| 79 | and SEQ_FLAGS2, ~SELECTOUT_QFROZEN; | ||
| 80 | jmp check_waiting_list; | ||
| 81 | check_frozen_completions: | ||
| 82 | test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus; | ||
| 83 | BEGIN_CRITICAL; | ||
| 84 | /* | ||
| 85 | * If we have completions stalled waiting for the qfreeze | ||
| 86 | * to take effect, move them over to the complete_scb list | ||
| 87 | * now that no selections are pending. | ||
| 88 | */ | ||
| 89 | cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus; | ||
| 90 | /* | ||
| 91 | * Find the end of the qfreeze list. The first element has | ||
| 92 | * to be treated specially. | ||
| 93 | */ | ||
| 94 | bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2; | ||
| 95 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists; | ||
| 96 | /* | ||
| 97 | * Now the normal loop. | ||
| 98 | */ | ||
| 99 | bmov SCBPTR, SCB_NEXT_COMPLETE, 2; | ||
| 100 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1; | ||
| 101 | join_lists: | ||
| 102 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; | ||
| 103 | bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2; | ||
| 104 | mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL; | ||
| 105 | jmp idle_loop_checkbus; | ||
| 106 | check_waiting_list: | ||
| 72 | cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; | 107 | cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; |
| 73 | /* | 108 | /* |
| 74 | * ENSELO is cleared by a SELDO, so we must test for SELDO | 109 | * ENSELO is cleared by a SELDO, so we must test for SELDO |
| 75 | * one last time. | 110 | * one last time. |
| 76 | */ | 111 | */ |
| 77 | BEGIN_CRITICAL; | ||
| 78 | test SSTAT0, SELDO jnz select_out; | 112 | test SSTAT0, SELDO jnz select_out; |
| 79 | END_CRITICAL; | 113 | END_CRITICAL; |
| 80 | call start_selection; | 114 | call start_selection; |
| @@ -90,6 +124,13 @@ idle_loop_check_nonpackreq: | |||
| 90 | test SSTAT2, NONPACKREQ jz . + 2; | 124 | test SSTAT2, NONPACKREQ jz . + 2; |
| 91 | call unexpected_nonpkt_phase_find_ctxt; | 125 | call unexpected_nonpkt_phase_find_ctxt; |
| 92 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { | 126 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { |
| 127 | /* | ||
| 128 | * On Rev A. hardware, the busy LED is only | ||
| 129 | * turned on automaically during selections | ||
| 130 | * and re-selections. Make the LED status | ||
| 131 | * more useful by forcing it to be on so | ||
| 132 | * long as one of our data FIFOs is active. | ||
| 133 | */ | ||
| 93 | and A, FIFO0FREE|FIFO1FREE, DFFSTAT; | 134 | and A, FIFO0FREE|FIFO1FREE, DFFSTAT; |
| 94 | cmp A, FIFO0FREE|FIFO1FREE jne . + 3; | 135 | cmp A, FIFO0FREE|FIFO1FREE jne . + 3; |
| 95 | and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; | 136 | and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; |
| @@ -101,9 +142,9 @@ idle_loop_check_nonpackreq: | |||
| 101 | call idle_loop_cchan; | 142 | call idle_loop_cchan; |
| 102 | jmp idle_loop; | 143 | jmp idle_loop; |
| 103 | 144 | ||
| 104 | BEGIN_CRITICAL; | ||
| 105 | idle_loop_gsfifo: | 145 | idle_loop_gsfifo: |
| 106 | SET_MODE(M_SCSI, M_SCSI) | 146 | SET_MODE(M_SCSI, M_SCSI) |
| 147 | BEGIN_CRITICAL; | ||
| 107 | idle_loop_gsfifo_in_scsi_mode: | 148 | idle_loop_gsfifo_in_scsi_mode: |
| 108 | test LQISTAT2, LQIGSAVAIL jz return; | 149 | test LQISTAT2, LQIGSAVAIL jz return; |
| 109 | /* | 150 | /* |
| @@ -152,11 +193,15 @@ END_CRITICAL; | |||
| 152 | 193 | ||
| 153 | idle_loop_service_fifos: | 194 | idle_loop_service_fifos: |
| 154 | SET_MODE(M_DFF0, M_DFF0) | 195 | SET_MODE(M_DFF0, M_DFF0) |
| 196 | BEGIN_CRITICAL; | ||
| 155 | test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; | 197 | test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; |
| 156 | call longjmp; | 198 | call longjmp; |
| 199 | END_CRITICAL; | ||
| 157 | idle_loop_next_fifo: | 200 | idle_loop_next_fifo: |
| 158 | SET_MODE(M_DFF1, M_DFF1) | 201 | SET_MODE(M_DFF1, M_DFF1) |
| 202 | BEGIN_CRITICAL; | ||
| 159 | test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; | 203 | test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; |
| 204 | END_CRITICAL; | ||
| 160 | return: | 205 | return: |
| 161 | ret; | 206 | ret; |
| 162 | 207 | ||
| @@ -170,7 +215,6 @@ BEGIN_CRITICAL; | |||
| 170 | test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; | 215 | test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; |
| 171 | test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; | 216 | test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; |
| 172 | test CCSCBCTL, CCSCBDONE jz return; | 217 | test CCSCBCTL, CCSCBDONE jz return; |
| 173 | END_CRITICAL; | ||
| 174 | /* FALLTHROUGH */ | 218 | /* FALLTHROUGH */ |
| 175 | scbdma_tohost_done: | 219 | scbdma_tohost_done: |
| 176 | test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; | 220 | test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; |
| @@ -180,26 +224,18 @@ scbdma_tohost_done: | |||
| 180 | * bad SCSI status (currently only for underruns), we | 224 | * bad SCSI status (currently only for underruns), we |
| 181 | * queue the SCB for normal completion. Otherwise, we | 225 | * queue the SCB for normal completion. Otherwise, we |
| 182 | * wait until any select-out activity has halted, and | 226 | * wait until any select-out activity has halted, and |
| 183 | * then notify the host so that the transaction can be | 227 | * then queue the completion. |
| 184 | * dealt with. | ||
| 185 | */ | 228 | */ |
| 186 | test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; | ||
| 187 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | 229 | and CCSCBCTL, ~(CCARREN|CCSCBEN); |
| 188 | bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; | 230 | bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; |
| 231 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2; | ||
| 232 | mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL; | ||
| 233 | test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; | ||
| 234 | bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2; | ||
| 235 | bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret; | ||
| 236 | scbdma_queue_completion: | ||
| 189 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; | 237 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; |
| 190 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; | 238 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; |
| 191 | scbdma_notify_host: | ||
| 192 | SET_MODE(M_SCSI, M_SCSI) | ||
| 193 | test SCSISEQ0, ENSELO jnz return; | ||
| 194 | test SSTAT0, (SELDO|SELINGO) jnz return; | ||
| 195 | SET_MODE(M_CCHAN, M_CCHAN) | ||
| 196 | /* | ||
| 197 | * Remove SCB and notify host. | ||
| 198 | */ | ||
| 199 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | ||
| 200 | bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; | ||
| 201 | SET_SEQINTCODE(BAD_SCB_STATUS) | ||
| 202 | ret; | ||
| 203 | fill_qoutfifo_dmadone: | 239 | fill_qoutfifo_dmadone: |
| 204 | and CCSCBCTL, ~(CCARREN|CCSCBEN); | 240 | and CCSCBCTL, ~(CCARREN|CCSCBEN); |
| 205 | call qoutfifo_updated; | 241 | call qoutfifo_updated; |
| @@ -208,6 +244,7 @@ fill_qoutfifo_dmadone: | |||
| 208 | test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; | 244 | test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; |
| 209 | bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; | 245 | bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; |
| 210 | xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; | 246 | xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; |
| 247 | END_CRITICAL; | ||
| 211 | 248 | ||
| 212 | qoutfifo_updated: | 249 | qoutfifo_updated: |
| 213 | /* | 250 | /* |
| @@ -324,14 +361,15 @@ fill_qoutfifo: | |||
| 324 | * Keep track of the SCBs we are dmaing just | 361 | * Keep track of the SCBs we are dmaing just |
| 325 | * in case the DMA fails or is aborted. | 362 | * in case the DMA fails or is aborted. |
| 326 | */ | 363 | */ |
| 327 | mov A, QOUTFIFO_ENTRY_VALID_TAG; | ||
| 328 | bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; | 364 | bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; |
| 329 | mvi CCSCBCTL, CCSCBRESET; | 365 | mvi CCSCBCTL, CCSCBRESET; |
| 330 | bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; | 366 | bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; |
| 367 | mov A, QOUTFIFO_NEXT_ADDR; | ||
| 331 | bmov SCBPTR, COMPLETE_SCB_HEAD, 2; | 368 | bmov SCBPTR, COMPLETE_SCB_HEAD, 2; |
| 332 | fill_qoutfifo_loop: | 369 | fill_qoutfifo_loop: |
| 333 | mov CCSCBRAM, SCBPTR; | 370 | bmov CCSCBRAM, SCBPTR, 2; |
| 334 | or CCSCBRAM, A, SCBPTR[1]; | 371 | mov CCSCBRAM, SCB_SGPTR[0]; |
| 372 | mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG; | ||
| 335 | mov NONE, SDSCB_QOFF; | 373 | mov NONE, SDSCB_QOFF; |
| 336 | inc INT_COALESCING_CMDCOUNT; | 374 | inc INT_COALESCING_CMDCOUNT; |
| 337 | add CMDS_PENDING, -1; | 375 | add CMDS_PENDING, -1; |
| @@ -339,6 +377,18 @@ fill_qoutfifo_loop: | |||
| 339 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; | 377 | cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; |
| 340 | cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; | 378 | cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; |
| 341 | test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; | 379 | test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; |
| 380 | /* | ||
| 381 | * Don't cross an ADB or Cachline boundary when DMA'ing | ||
| 382 | * completion entries. In PCI mode, at least in 32/33 | ||
| 383 | * configurations, the SCB DMA engine may lose its place | ||
| 384 | * in the data-stream should the target force a retry on | ||
| 385 | * something other than an 8byte aligned boundary. In | ||
| 386 | * PCI-X mode, we do this to avoid split transactions since | ||
| 387 | * many chipsets seem to be unable to format proper split | ||
| 388 | * completions to continue the data transfer. | ||
| 389 | */ | ||
| 390 | add SINDEX, A, CCSCBADDR; | ||
| 391 | test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done; | ||
| 342 | bmov SCBPTR, SCB_NEXT_COMPLETE, 2; | 392 | bmov SCBPTR, SCB_NEXT_COMPLETE, 2; |
| 343 | jmp fill_qoutfifo_loop; | 393 | jmp fill_qoutfifo_loop; |
| 344 | fill_qoutfifo_done: | 394 | fill_qoutfifo_done: |
| @@ -354,7 +404,6 @@ dma_complete_scb: | |||
| 354 | bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; | 404 | bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; |
| 355 | bmov SCBHADDR, SCB_BUSADDR, 4; | 405 | bmov SCBHADDR, SCB_BUSADDR, 4; |
| 356 | mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; | 406 | mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; |
| 357 | END_CRITICAL; | ||
| 358 | 407 | ||
| 359 | /* | 408 | /* |
| 360 | * Either post or fetch an SCB from host memory. The caller | 409 | * Either post or fetch an SCB from host memory. The caller |
| @@ -371,9 +420,19 @@ dma_scb: | |||
| 371 | mvi SCBHCNT, SCB_TRANSFER_SIZE; | 420 | mvi SCBHCNT, SCB_TRANSFER_SIZE; |
| 372 | mov CCSCBCTL, SINDEX ret; | 421 | mov CCSCBCTL, SINDEX ret; |
| 373 | 422 | ||
| 374 | BEGIN_CRITICAL; | ||
| 375 | setjmp: | 423 | setjmp: |
| 376 | bmov LONGJMP_ADDR, STACK, 2 ret; | 424 | /* |
| 425 | * At least on the A, a return in the same | ||
| 426 | * instruction as the bmov results in a return | ||
| 427 | * to the caller, not to the new address at the | ||
| 428 | * top of the stack. Since we want the latter | ||
| 429 | * (we use setjmp to register a handler from an | ||
| 430 | * interrupt context but not invoke that handler | ||
| 431 | * until we return to our idle loop), use a | ||
| 432 | * separate ret instruction. | ||
| 433 | */ | ||
| 434 | bmov LONGJMP_ADDR, STACK, 2; | ||
| 435 | ret; | ||
| 377 | setjmp_inline: | 436 | setjmp_inline: |
| 378 | bmov LONGJMP_ADDR, STACK, 2; | 437 | bmov LONGJMP_ADDR, STACK, 2; |
| 379 | longjmp: | 438 | longjmp: |
| @@ -392,11 +451,6 @@ set_mode_work_around: | |||
| 392 | mvi SEQINTCTL, INTVEC1DSL; | 451 | mvi SEQINTCTL, INTVEC1DSL; |
| 393 | mov MODE_PTR, SINDEX; | 452 | mov MODE_PTR, SINDEX; |
| 394 | clr SEQINTCTL ret; | 453 | clr SEQINTCTL ret; |
| 395 | |||
| 396 | toggle_dff_mode_work_around: | ||
| 397 | mvi SEQINTCTL, INTVEC1DSL; | ||
| 398 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); | ||
| 399 | clr SEQINTCTL ret; | ||
| 400 | } | 454 | } |
| 401 | 455 | ||
| 402 | 456 | ||
| @@ -490,6 +544,21 @@ allocate_fifo1: | |||
| 490 | SET_SRC_MODE M_SCSI; | 544 | SET_SRC_MODE M_SCSI; |
| 491 | SET_DST_MODE M_SCSI; | 545 | SET_DST_MODE M_SCSI; |
| 492 | select_in: | 546 | select_in: |
| 547 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { | ||
| 548 | /* | ||
| 549 | * On Rev A. hardware, the busy LED is only | ||
| 550 | * turned on automaically during selections | ||
| 551 | * and re-selections. Make the LED status | ||
| 552 | * more useful by forcing it to be on from | ||
| 553 | * the point of selection until our idle | ||
| 554 | * loop determines that neither of our FIFOs | ||
| 555 | * are busy. This handles the non-packetized | ||
| 556 | * case nicely as we will not return to the | ||
| 557 | * idle loop until the busfree at the end of | ||
| 558 | * each transaction. | ||
| 559 | */ | ||
| 560 | or SBLKCTL, DIAGLEDEN|DIAGLEDON; | ||
| 561 | } | ||
| 493 | if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { | 562 | if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { |
| 494 | /* | 563 | /* |
| 495 | * Test to ensure that the bus has not | 564 | * Test to ensure that the bus has not |
| @@ -528,6 +597,21 @@ SET_SRC_MODE M_SCSI; | |||
| 528 | SET_DST_MODE M_SCSI; | 597 | SET_DST_MODE M_SCSI; |
| 529 | select_out: | 598 | select_out: |
| 530 | BEGIN_CRITICAL; | 599 | BEGIN_CRITICAL; |
| 600 | if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { | ||
| 601 | /* | ||
| 602 | * On Rev A. hardware, the busy LED is only | ||
| 603 | * turned on automaically during selections | ||
| 604 | * and re-selections. Make the LED status | ||
| 605 | * more useful by forcing it to be on from | ||
| 606 | * the point of re-selection until our idle | ||
| 607 | * loop determines that neither of our FIFOs | ||
| 608 | * are busy. This handles the non-packetized | ||
| 609 | * case nicely as we will not return to the | ||
| 610 | * idle loop until the busfree at the end of | ||
| 611 | * each transaction. | ||
| 612 | */ | ||
| 613 | or SBLKCTL, DIAGLEDEN|DIAGLEDON; | ||
| 614 | } | ||
| 531 | /* Clear out all SCBs that have been successfully sent. */ | 615 | /* Clear out all SCBs that have been successfully sent. */ |
| 532 | if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { | 616 | if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { |
| 533 | /* | 617 | /* |
| @@ -1000,15 +1084,9 @@ not_found_ITloop: | |||
| 1000 | /* | 1084 | /* |
| 1001 | * We received a "command complete" message. Put the SCB on the complete | 1085 | * We received a "command complete" message. Put the SCB on the complete |
| 1002 | * queue and trigger a completion interrupt via the idle loop. Before doing | 1086 | * queue and trigger a completion interrupt via the idle loop. Before doing |
| 1003 | * so, check to see if there | 1087 | * so, check to see if there is a residual or the status byte is something |
| 1004 | * is a residual or the status byte is something other than STATUS_GOOD (0). | 1088 | * other than STATUS_GOOD (0). In either of these conditions, we upload the |
| 1005 | * In either of these conditions, we upload the SCB back to the host so it can | 1089 | * SCB back to the host so it can process this information. |
| 1006 | * process this information. In the case of a non zero status byte, we | ||
| 1007 | * additionally interrupt the kernel driver synchronously, allowing it to | ||
| 1008 | * decide if sense should be retrieved. If the kernel driver wishes to request | ||
| 1009 | * sense, it will fill the kernel SCB with a request sense command, requeue | ||
| 1010 | * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting | ||
| 1011 | * RETURN_1 to SEND_SENSE. | ||
| 1012 | */ | 1090 | */ |
| 1013 | mesgin_complete: | 1091 | mesgin_complete: |
| 1014 | 1092 | ||
| @@ -1053,6 +1131,7 @@ complete_nomsg: | |||
| 1053 | call queue_scb_completion; | 1131 | call queue_scb_completion; |
| 1054 | jmp await_busfree; | 1132 | jmp await_busfree; |
| 1055 | 1133 | ||
| 1134 | BEGIN_CRITICAL; | ||
| 1056 | freeze_queue: | 1135 | freeze_queue: |
| 1057 | /* Cancel any pending select-out. */ | 1136 | /* Cancel any pending select-out. */ |
| 1058 | test SSTAT0, SELDO|SELINGO jnz . + 2; | 1137 | test SSTAT0, SELDO|SELINGO jnz . + 2; |
| @@ -1063,6 +1142,7 @@ freeze_queue: | |||
| 1063 | adc QFREEZE_COUNT[1], A; | 1142 | adc QFREEZE_COUNT[1], A; |
| 1064 | or SEQ_FLAGS2, SELECTOUT_QFROZEN; | 1143 | or SEQ_FLAGS2, SELECTOUT_QFROZEN; |
| 1065 | mov A, ACCUM_SAVE ret; | 1144 | mov A, ACCUM_SAVE ret; |
| 1145 | END_CRITICAL; | ||
| 1066 | 1146 | ||
| 1067 | /* | 1147 | /* |
| 1068 | * Complete the current FIFO's SCB if data for this same | 1148 | * Complete the current FIFO's SCB if data for this same |
| @@ -1085,8 +1165,10 @@ queue_scb_completion: | |||
| 1085 | test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ | 1165 | test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ |
| 1086 | test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; | 1166 | test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; |
| 1087 | complete: | 1167 | complete: |
| 1168 | BEGIN_CRITICAL; | ||
| 1088 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; | 1169 | bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; |
| 1089 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; | 1170 | bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; |
| 1171 | END_CRITICAL; | ||
| 1090 | bad_status: | 1172 | bad_status: |
| 1091 | cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; | 1173 | cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; |
| 1092 | call freeze_queue; | 1174 | call freeze_queue; |
| @@ -1097,9 +1179,18 @@ upload_scb: | |||
| 1097 | * it on the host. | 1179 | * it on the host. |
| 1098 | */ | 1180 | */ |
| 1099 | bmov SCB_TAG, SCBPTR, 2; | 1181 | bmov SCB_TAG, SCBPTR, 2; |
| 1100 | bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; | 1182 | BEGIN_CRITICAL; |
| 1183 | or SCB_SGPTR, SG_STATUS_VALID; | ||
| 1184 | mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL; | ||
| 1185 | cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail; | ||
| 1101 | bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; | 1186 | bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; |
| 1102 | or SCB_SGPTR, SG_STATUS_VALID ret; | 1187 | bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret; |
| 1188 | add_dma_scb_tail: | ||
| 1189 | bmov REG0, SCBPTR, 2; | ||
| 1190 | bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2; | ||
| 1191 | bmov SCB_NEXT_COMPLETE, REG0, 2; | ||
| 1192 | bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret; | ||
| 1193 | END_CRITICAL; | ||
| 1103 | 1194 | ||
| 1104 | /* | 1195 | /* |
| 1105 | * Is it a disconnect message? Set a flag in the SCB to remind us | 1196 | * Is it a disconnect message? Set a flag in the SCB to remind us |
| @@ -1146,8 +1237,18 @@ SET_DST_MODE M_DFF1; | |||
| 1146 | await_busfree_clrchn: | 1237 | await_busfree_clrchn: |
| 1147 | mvi DFFSXFRCTL, CLRCHN; | 1238 | mvi DFFSXFRCTL, CLRCHN; |
| 1148 | await_busfree_not_m_dff: | 1239 | await_busfree_not_m_dff: |
| 1149 | call clear_target_state; | 1240 | /* clear target specific flags */ |
| 1241 | mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; | ||
| 1150 | test SSTAT1,REQINIT|BUSFREE jz .; | 1242 | test SSTAT1,REQINIT|BUSFREE jz .; |
| 1243 | /* | ||
| 1244 | * We only set BUSFREE status once either a new | ||
| 1245 | * phase has been detected or we are really | ||
| 1246 | * BUSFREE. This allows the driver to know | ||
| 1247 | * that we are active on the bus even though | ||
| 1248 | * no identified transaction exists should a | ||
| 1249 | * timeout occur while awaiting busfree. | ||
| 1250 | */ | ||
| 1251 | mvi LASTPHASE, P_BUSFREE; | ||
| 1151 | test SSTAT1, BUSFREE jnz idle_loop; | 1252 | test SSTAT1, BUSFREE jnz idle_loop; |
| 1152 | SET_SEQINTCODE(MISSED_BUSFREE) | 1253 | SET_SEQINTCODE(MISSED_BUSFREE) |
| 1153 | 1254 | ||
| @@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo: | |||
| 1202 | call allocate_fifo; | 1303 | call allocate_fifo; |
| 1203 | jmp mesgin_done; | 1304 | jmp mesgin_done; |
| 1204 | 1305 | ||
| 1205 | clear_target_state: | ||
| 1206 | mvi LASTPHASE, P_BUSFREE; | ||
| 1207 | /* clear target specific flags */ | ||
| 1208 | mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; | ||
| 1209 | |||
| 1210 | phase_lock: | 1306 | phase_lock: |
| 1211 | if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { | 1307 | if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { |
| 1212 | /* | 1308 | /* |
| @@ -1298,6 +1394,47 @@ service_fifo: | |||
| 1298 | test CCSGCTL, CCSGENACK jnz return; | 1394 | test CCSGCTL, CCSGENACK jnz return; |
| 1299 | 1395 | ||
| 1300 | /* | 1396 | /* |
| 1397 | * Should the other FIFO get the S/G cache first? If | ||
| 1398 | * both FIFOs have been allocated since we last checked | ||
| 1399 | * any FIFO, it is important that we service a FIFO | ||
| 1400 | * that is not actively on the bus first. This guarantees | ||
| 1401 | * that a FIFO will be freed to handle snapshot requests for | ||
| 1402 | * any FIFO that is still on the bus. Chips with RTI do not | ||
| 1403 | * perform snapshots, so don't bother with this test there. | ||
| 1404 | */ | ||
| 1405 | if ((ahd->features & AHD_RTI) == 0) { | ||
| 1406 | /* | ||
| 1407 | * If we're not still receiving SCSI data, | ||
| 1408 | * it is safe to allocate the S/G cache to | ||
| 1409 | * this FIFO. | ||
| 1410 | */ | ||
| 1411 | test DFCNTRL, SCSIEN jz idle_sgfetch_start; | ||
| 1412 | |||
| 1413 | /* | ||
| 1414 | * Switch to the other FIFO. Non-RTI chips | ||
| 1415 | * also have the "set mode" bug, so we must | ||
| 1416 | * disable interrupts during the switch. | ||
| 1417 | */ | ||
| 1418 | mvi SEQINTCTL, INTVEC1DSL; | ||
| 1419 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); | ||
| 1420 | |||
| 1421 | /* | ||
| 1422 | * If the other FIFO needs loading, then it | ||
| 1423 | * must not have claimed the S/G cache yet | ||
| 1424 | * (SG_CACHE_AVAIL would have been cleared in | ||
| 1425 | * the orginal FIFO mode and we test this above). | ||
| 1426 | * Return to the idle loop so we can process the | ||
| 1427 | * FIFO not currently on the bus first. | ||
| 1428 | */ | ||
| 1429 | test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay; | ||
| 1430 | clr SEQINTCTL ret; | ||
| 1431 | idle_sgfetch_okay: | ||
| 1432 | xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); | ||
| 1433 | clr SEQINTCTL; | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | idle_sgfetch_start: | ||
| 1437 | /* | ||
| 1301 | * We fetch a "cacheline aligned" and sized amount of data | 1438 | * We fetch a "cacheline aligned" and sized amount of data |
| 1302 | * so we don't end up referencing a non-existant page. | 1439 | * so we don't end up referencing a non-existant page. |
| 1303 | * Cacheline aligned is in quotes because the kernel will | 1440 | * Cacheline aligned is in quotes because the kernel will |
| @@ -1308,7 +1445,7 @@ service_fifo: | |||
| 1308 | mvi SGHCNT, SG_PREFETCH_CNT; | 1445 | mvi SGHCNT, SG_PREFETCH_CNT; |
| 1309 | if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { | 1446 | if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { |
| 1310 | /* | 1447 | /* |
| 1311 | * Need two instruction between "touches" of SGHADDR. | 1448 | * Need two instructions between "touches" of SGHADDR. |
| 1312 | */ | 1449 | */ |
| 1313 | nop; | 1450 | nop; |
| 1314 | } | 1451 | } |
| @@ -1658,7 +1795,7 @@ export seq_isr: | |||
| 1658 | * savepointer in the current FIFO. We do this so that | 1795 | * savepointer in the current FIFO. We do this so that |
| 1659 | * a pending CTXTDONE or SAVEPTR is visible in the active | 1796 | * a pending CTXTDONE or SAVEPTR is visible in the active |
| 1660 | * FIFO. This status is the only way we can detect if we | 1797 | * FIFO. This status is the only way we can detect if we |
| 1661 | * have lost the race (e.g. host paused us) and our attepts | 1798 | * have lost the race (e.g. host paused us) and our attempts |
| 1662 | * to disable the channel occurred after all REQs were | 1799 | * to disable the channel occurred after all REQs were |
| 1663 | * already seen and acked (REQINIT never comes true). | 1800 | * already seen and acked (REQINIT never comes true). |
| 1664 | */ | 1801 | */ |
| @@ -1667,7 +1804,7 @@ export seq_isr: | |||
| 1667 | test DFCNTRL, DIRECTION jz interrupt_return; | 1804 | test DFCNTRL, DIRECTION jz interrupt_return; |
| 1668 | and DFCNTRL, ~SCSIEN; | 1805 | and DFCNTRL, ~SCSIEN; |
| 1669 | snapshot_wait_data_valid: | 1806 | snapshot_wait_data_valid: |
| 1670 | test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; | 1807 | test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; |
| 1671 | test SSTAT1, REQINIT jz snapshot_wait_data_valid; | 1808 | test SSTAT1, REQINIT jz snapshot_wait_data_valid; |
| 1672 | snapshot_data_valid: | 1809 | snapshot_data_valid: |
| 1673 | or DFCNTRL, SCSIEN; | 1810 | or DFCNTRL, SCSIEN; |
| @@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status: | |||
| 1834 | dec SCB_FIFO_USE_COUNT; | 1971 | dec SCB_FIFO_USE_COUNT; |
| 1835 | test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; | 1972 | test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; |
| 1836 | mvi DFFSXFRCTL, CLRCHN ret; | 1973 | mvi DFFSXFRCTL, CLRCHN ret; |
| 1837 | END_CRITICAL; | ||
| 1838 | 1974 | ||
| 1839 | /* | 1975 | /* |
| 1840 | * LAST_SEG_DONE status has been seen in the current FIFO. | 1976 | * LAST_SEG_DONE status has been seen in the current FIFO. |
| @@ -1843,7 +1979,6 @@ END_CRITICAL; | |||
| 1843 | * Check for overrun and see if we can complete this command. | 1979 | * Check for overrun and see if we can complete this command. |
| 1844 | */ | 1980 | */ |
| 1845 | pkt_last_seg_done: | 1981 | pkt_last_seg_done: |
| 1846 | BEGIN_CRITICAL; | ||
| 1847 | /* | 1982 | /* |
| 1848 | * Mark transfer as completed. | 1983 | * Mark transfer as completed. |
| 1849 | */ | 1984 | */ |
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 4e8f00df978d..db8f5ce99ee3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c | |||
| @@ -37,9 +37,7 @@ | |||
| 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 38 | * POSSIBILITY OF SUCH DAMAGES. | 38 | * POSSIBILITY OF SUCH DAMAGES. |
| 39 | * | 39 | * |
| 40 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $ | 40 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $ |
| 41 | * | ||
| 42 | * $FreeBSD$ | ||
| 43 | */ | 41 | */ |
| 44 | 42 | ||
| 45 | #ifdef __linux__ | 43 | #ifdef __linux__ |
| @@ -332,6 +330,14 @@ ahd_restart(struct ahd_softc *ahd) | |||
| 332 | ahd_outb(ahd, SCSISEQ1, | 330 | ahd_outb(ahd, SCSISEQ1, |
| 333 | ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); | 331 | ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); |
| 334 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); | 332 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
| 333 | |||
| 334 | /* | ||
| 335 | * Clear any pending sequencer interrupt. It is no | ||
| 336 | * longer relevant since we're resetting the Program | ||
| 337 | * Counter. | ||
| 338 | */ | ||
| 339 | ahd_outb(ahd, CLRINT, CLRSEQINT); | ||
| 340 | |||
| 335 | ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); | 341 | ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); |
| 336 | ahd_unpause(ahd); | 342 | ahd_unpause(ahd); |
| 337 | } | 343 | } |
| @@ -373,13 +379,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
| 373 | saved_modes = ahd_save_modes(ahd); | 379 | saved_modes = ahd_save_modes(ahd); |
| 374 | 380 | ||
| 375 | /* | 381 | /* |
| 376 | * Complete any SCBs that just finished being | 382 | * Flush the good status FIFO for completed packetized commands. |
| 377 | * DMA'ed into the qoutfifo. | ||
| 378 | */ | ||
| 379 | ahd_run_qoutfifo(ahd); | ||
| 380 | |||
| 381 | /* | ||
| 382 | * Flush the good status FIFO for compelted packetized commands. | ||
| 383 | */ | 383 | */ |
| 384 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | 384 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
| 385 | saved_scbptr = ahd_get_scbptr(ahd); | 385 | saved_scbptr = ahd_get_scbptr(ahd); |
| @@ -387,8 +387,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
| 387 | u_int fifo_mode; | 387 | u_int fifo_mode; |
| 388 | u_int i; | 388 | u_int i; |
| 389 | 389 | ||
| 390 | scbid = (ahd_inb(ahd, GSFIFO+1) << 8) | 390 | scbid = ahd_inw(ahd, GSFIFO); |
| 391 | | ahd_inb(ahd, GSFIFO); | ||
| 392 | scb = ahd_lookup_scb(ahd, scbid); | 391 | scb = ahd_lookup_scb(ahd, scbid); |
| 393 | if (scb == NULL) { | 392 | if (scb == NULL) { |
| 394 | printf("%s: Warning - GSFIFO SCB %d invalid\n", | 393 | printf("%s: Warning - GSFIFO SCB %d invalid\n", |
| @@ -401,22 +400,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
| 401 | * the host before completing the command. | 400 | * the host before completing the command. |
| 402 | */ | 401 | */ |
| 403 | fifo_mode = 0; | 402 | fifo_mode = 0; |
| 403 | rescan_fifos: | ||
| 404 | for (i = 0; i < 2; i++) { | 404 | for (i = 0; i < 2; i++) { |
| 405 | /* Toggle to the other mode. */ | 405 | /* Toggle to the other mode. */ |
| 406 | fifo_mode ^= 1; | 406 | fifo_mode ^= 1; |
| 407 | ahd_set_modes(ahd, fifo_mode, fifo_mode); | 407 | ahd_set_modes(ahd, fifo_mode, fifo_mode); |
| 408 | |||
| 408 | if (ahd_scb_active_in_fifo(ahd, scb) == 0) | 409 | if (ahd_scb_active_in_fifo(ahd, scb) == 0) |
| 409 | continue; | 410 | continue; |
| 410 | 411 | ||
| 411 | ahd_run_data_fifo(ahd, scb); | 412 | ahd_run_data_fifo(ahd, scb); |
| 412 | 413 | ||
| 413 | /* | 414 | /* |
| 414 | * Clearing this transaction in this FIFO may | 415 | * Running this FIFO may cause a CFG4DATA for |
| 415 | * cause a CFG4DATA for this same transaction | 416 | * this same transaction to assert in the other |
| 416 | * to assert in the other FIFO. Make sure we | 417 | * FIFO or a new snapshot SAVEPTRS interrupt |
| 417 | * loop one more time and check the other FIFO. | 418 | * in this FIFO. Even running a FIFO may not |
| 419 | * clear the transaction if we are still waiting | ||
| 420 | * for data to drain to the host. We must loop | ||
| 421 | * until the transaction is not active in either | ||
| 422 | * FIFO just to be sure. Reset our loop counter | ||
| 423 | * so we will visit both FIFOs again before | ||
| 424 | * declaring this transaction finished. We | ||
| 425 | * also delay a bit so that status has a chance | ||
| 426 | * to change before we look at this FIFO again. | ||
| 418 | */ | 427 | */ |
| 419 | i = 0; | 428 | ahd_delay(200); |
| 429 | goto rescan_fifos; | ||
| 420 | } | 430 | } |
| 421 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | 431 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
| 422 | ahd_set_scbptr(ahd, scbid); | 432 | ahd_set_scbptr(ahd, scbid); |
| @@ -429,19 +439,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
| 429 | /* | 439 | /* |
| 430 | * The transfer completed with a residual. | 440 | * The transfer completed with a residual. |
| 431 | * Place this SCB on the complete DMA list | 441 | * Place this SCB on the complete DMA list |
| 432 | * so that we Update our in-core copy of the | 442 | * so that we update our in-core copy of the |
| 433 | * SCB before completing the command. | 443 | * SCB before completing the command. |
| 434 | */ | 444 | */ |
| 435 | ahd_outb(ahd, SCB_SCSI_STATUS, 0); | 445 | ahd_outb(ahd, SCB_SCSI_STATUS, 0); |
| 436 | ahd_outb(ahd, SCB_SGPTR, | 446 | ahd_outb(ahd, SCB_SGPTR, |
| 437 | ahd_inb_scbram(ahd, SCB_SGPTR) | 447 | ahd_inb_scbram(ahd, SCB_SGPTR) |
| 438 | | SG_STATUS_VALID); | 448 | | SG_STATUS_VALID); |
| 439 | ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb)); | 449 | ahd_outw(ahd, SCB_TAG, scbid); |
| 450 | ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL); | ||
| 440 | comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); | 451 | comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); |
| 441 | ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head); | 452 | if (SCBID_IS_NULL(comp_head)) { |
| 442 | if (SCBID_IS_NULL(comp_head)) | 453 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid); |
| 443 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, | 454 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); |
| 444 | SCB_GET_TAG(scb)); | 455 | } else { |
| 456 | u_int tail; | ||
| 457 | |||
| 458 | tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL); | ||
| 459 | ahd_set_scbptr(ahd, tail); | ||
| 460 | ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid); | ||
| 461 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); | ||
| 462 | ahd_set_scbptr(ahd, scbid); | ||
| 463 | } | ||
| 445 | } else | 464 | } else |
| 446 | ahd_complete_scb(ahd, scb); | 465 | ahd_complete_scb(ahd, scb); |
| 447 | } | 466 | } |
| @@ -465,9 +484,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
| 465 | break; | 484 | break; |
| 466 | ahd_delay(200); | 485 | ahd_delay(200); |
| 467 | } | 486 | } |
| 468 | if ((ccscbctl & CCSCBDIR) != 0) | 487 | /* |
| 488 | * We leave the sequencer to cleanup in the case of DMA's to | ||
| 489 | * update the qoutfifo. In all other cases (DMA's to the | ||
| 490 | * chip or a push of an SCB from the COMPLETE_DMA_SCB list), | ||
| 491 | * we disable the DMA engine so that the sequencer will not | ||
| 492 | * attempt to handle the DMA completion. | ||
| 493 | */ | ||
| 494 | if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0) | ||
| 469 | ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); | 495 | ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); |
| 470 | 496 | ||
| 497 | /* | ||
| 498 | * Complete any SCBs that just finished | ||
| 499 | * being DMA'ed into the qoutfifo. | ||
| 500 | */ | ||
| 501 | ahd_run_qoutfifo(ahd); | ||
| 502 | |||
| 471 | saved_scbptr = ahd_get_scbptr(ahd); | 503 | saved_scbptr = ahd_get_scbptr(ahd); |
| 472 | /* | 504 | /* |
| 473 | * Manually update/complete any completed SCBs that are waiting to be | 505 | * Manually update/complete any completed SCBs that are waiting to be |
| @@ -494,6 +526,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
| 494 | scbid = next_scbid; | 526 | scbid = next_scbid; |
| 495 | } | 527 | } |
| 496 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); | 528 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); |
| 529 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); | ||
| 530 | |||
| 531 | scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); | ||
| 532 | while (!SCBID_IS_NULL(scbid)) { | ||
| 533 | |||
| 534 | ahd_set_scbptr(ahd, scbid); | ||
| 535 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); | ||
| 536 | scb = ahd_lookup_scb(ahd, scbid); | ||
| 537 | if (scb == NULL) { | ||
| 538 | printf("%s: Warning - Complete Qfrz SCB %d invalid\n", | ||
| 539 | ahd_name(ahd), scbid); | ||
| 540 | continue; | ||
| 541 | } | ||
| 542 | |||
| 543 | ahd_complete_scb(ahd, scb); | ||
| 544 | scbid = next_scbid; | ||
| 545 | } | ||
| 546 | ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); | ||
| 497 | 547 | ||
| 498 | scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); | 548 | scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); |
| 499 | while (!SCBID_IS_NULL(scbid)) { | 549 | while (!SCBID_IS_NULL(scbid)) { |
| @@ -558,150 +608,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) | |||
| 558 | { | 608 | { |
| 559 | u_int seqintsrc; | 609 | u_int seqintsrc; |
| 560 | 610 | ||
| 561 | while (1) { | 611 | seqintsrc = ahd_inb(ahd, SEQINTSRC); |
| 562 | seqintsrc = ahd_inb(ahd, SEQINTSRC); | 612 | if ((seqintsrc & CFG4DATA) != 0) { |
| 563 | if ((seqintsrc & CFG4DATA) != 0) { | 613 | uint32_t datacnt; |
| 564 | uint32_t datacnt; | 614 | uint32_t sgptr; |
| 565 | uint32_t sgptr; | ||
| 566 | |||
| 567 | /* | ||
| 568 | * Clear full residual flag. | ||
| 569 | */ | ||
| 570 | sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; | ||
| 571 | ahd_outb(ahd, SCB_SGPTR, sgptr); | ||
| 572 | 615 | ||
| 573 | /* | 616 | /* |
| 574 | * Load datacnt and address. | 617 | * Clear full residual flag. |
| 575 | */ | 618 | */ |
| 576 | datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); | 619 | sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; |
| 577 | if ((datacnt & AHD_DMA_LAST_SEG) != 0) { | 620 | ahd_outb(ahd, SCB_SGPTR, sgptr); |
| 578 | sgptr |= LAST_SEG; | ||
| 579 | ahd_outb(ahd, SG_STATE, 0); | ||
| 580 | } else | ||
| 581 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED); | ||
| 582 | ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); | ||
| 583 | ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); | ||
| 584 | ahd_outb(ahd, SG_CACHE_PRE, sgptr); | ||
| 585 | ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); | ||
| 586 | 621 | ||
| 587 | /* | 622 | /* |
| 588 | * Initialize Residual Fields. | 623 | * Load datacnt and address. |
| 589 | */ | 624 | */ |
| 590 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); | 625 | datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); |
| 591 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); | 626 | if ((datacnt & AHD_DMA_LAST_SEG) != 0) { |
| 627 | sgptr |= LAST_SEG; | ||
| 628 | ahd_outb(ahd, SG_STATE, 0); | ||
| 629 | } else | ||
| 630 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED); | ||
| 631 | ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); | ||
| 632 | ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); | ||
| 633 | ahd_outb(ahd, SG_CACHE_PRE, sgptr); | ||
| 634 | ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); | ||
| 592 | 635 | ||
| 593 | /* | 636 | /* |
| 594 | * Mark the SCB as having a FIFO in use. | 637 | * Initialize Residual Fields. |
| 595 | */ | 638 | */ |
| 596 | ahd_outb(ahd, SCB_FIFO_USE_COUNT, | 639 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); |
| 597 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); | 640 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); |
| 598 | 641 | ||
| 599 | /* | 642 | /* |
| 600 | * Install a "fake" handler for this FIFO. | 643 | * Mark the SCB as having a FIFO in use. |
| 601 | */ | 644 | */ |
| 602 | ahd_outw(ahd, LONGJMP_ADDR, 0); | 645 | ahd_outb(ahd, SCB_FIFO_USE_COUNT, |
| 646 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); | ||
| 603 | 647 | ||
| 604 | /* | 648 | /* |
| 605 | * Notify the hardware that we have satisfied | 649 | * Install a "fake" handler for this FIFO. |
| 606 | * this sequencer interrupt. | 650 | */ |
| 607 | */ | 651 | ahd_outw(ahd, LONGJMP_ADDR, 0); |
| 608 | ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); | ||
| 609 | } else if ((seqintsrc & SAVEPTRS) != 0) { | ||
| 610 | uint32_t sgptr; | ||
| 611 | uint32_t resid; | ||
| 612 | 652 | ||
| 613 | if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { | 653 | /* |
| 614 | /* | 654 | * Notify the hardware that we have satisfied |
| 615 | * Snapshot Save Pointers. Clear | 655 | * this sequencer interrupt. |
| 616 | * the snapshot and continue. | 656 | */ |
| 617 | */ | 657 | ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); |
| 618 | ahd_outb(ahd, DFFSXFRCTL, CLRCHN); | 658 | } else if ((seqintsrc & SAVEPTRS) != 0) { |
| 619 | continue; | 659 | uint32_t sgptr; |
| 620 | } | 660 | uint32_t resid; |
| 621 | 661 | ||
| 662 | if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { | ||
| 622 | /* | 663 | /* |
| 623 | * Disable S/G fetch so the DMA engine | 664 | * Snapshot Save Pointers. All that |
| 624 | * is available to future users. | 665 | * is necessary to clear the snapshot |
| 666 | * is a CLRCHN. | ||
| 625 | */ | 667 | */ |
| 626 | if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) | 668 | goto clrchn; |
| 627 | ahd_outb(ahd, CCSGCTL, 0); | 669 | } |
| 628 | ahd_outb(ahd, SG_STATE, 0); | ||
| 629 | 670 | ||
| 630 | /* | 671 | /* |
| 631 | * Flush the data FIFO. Strickly only | 672 | * Disable S/G fetch so the DMA engine |
| 632 | * necessary for Rev A parts. | 673 | * is available to future users. |
| 633 | */ | 674 | */ |
| 634 | ahd_outb(ahd, DFCNTRL, | 675 | if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) |
| 635 | ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); | 676 | ahd_outb(ahd, CCSGCTL, 0); |
| 677 | ahd_outb(ahd, SG_STATE, 0); | ||
| 636 | 678 | ||
| 637 | /* | 679 | /* |
| 638 | * Calculate residual. | 680 | * Flush the data FIFO. Strickly only |
| 639 | */ | 681 | * necessary for Rev A parts. |
| 640 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); | 682 | */ |
| 641 | resid = ahd_inl(ahd, SHCNT); | 683 | ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); |
| 642 | resid |= | ||
| 643 | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; | ||
| 644 | ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); | ||
| 645 | if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { | ||
| 646 | /* | ||
| 647 | * Must back up to the correct S/G element. | ||
| 648 | * Typically this just means resetting our | ||
| 649 | * low byte to the offset in the SG_CACHE, | ||
| 650 | * but if we wrapped, we have to correct | ||
| 651 | * the other bytes of the sgptr too. | ||
| 652 | */ | ||
| 653 | if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 | ||
| 654 | && (sgptr & 0x80) == 0) | ||
| 655 | sgptr -= 0x100; | ||
| 656 | sgptr &= ~0xFF; | ||
| 657 | sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) | ||
| 658 | & SG_ADDR_MASK; | ||
| 659 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); | ||
| 660 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); | ||
| 661 | } else if ((resid & AHD_SG_LEN_MASK) == 0) { | ||
| 662 | ahd_outb(ahd, SCB_RESIDUAL_SGPTR, | ||
| 663 | sgptr | SG_LIST_NULL); | ||
| 664 | } | ||
| 665 | /* | ||
| 666 | * Save Pointers. | ||
| 667 | */ | ||
| 668 | ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); | ||
| 669 | ahd_outl(ahd, SCB_DATACNT, resid); | ||
| 670 | ahd_outl(ahd, SCB_SGPTR, sgptr); | ||
| 671 | ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); | ||
| 672 | ahd_outb(ahd, SEQIMODE, | ||
| 673 | ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); | ||
| 674 | /* | ||
| 675 | * If the data is to the SCSI bus, we are | ||
| 676 | * done, otherwise wait for FIFOEMP. | ||
| 677 | */ | ||
| 678 | if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) | ||
| 679 | break; | ||
| 680 | } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { | ||
| 681 | uint32_t sgptr; | ||
| 682 | uint64_t data_addr; | ||
| 683 | uint32_t data_len; | ||
| 684 | u_int dfcntrl; | ||
| 685 | 684 | ||
| 685 | /* | ||
| 686 | * Calculate residual. | ||
| 687 | */ | ||
| 688 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); | ||
| 689 | resid = ahd_inl(ahd, SHCNT); | ||
| 690 | resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; | ||
| 691 | ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); | ||
| 692 | if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { | ||
| 686 | /* | 693 | /* |
| 687 | * Disable S/G fetch so the DMA engine | 694 | * Must back up to the correct S/G element. |
| 688 | * is available to future users. | 695 | * Typically this just means resetting our |
| 696 | * low byte to the offset in the SG_CACHE, | ||
| 697 | * but if we wrapped, we have to correct | ||
| 698 | * the other bytes of the sgptr too. | ||
| 689 | */ | 699 | */ |
| 690 | if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { | 700 | if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 |
| 691 | ahd_outb(ahd, CCSGCTL, 0); | 701 | && (sgptr & 0x80) == 0) |
| 692 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED); | 702 | sgptr -= 0x100; |
| 693 | } | 703 | sgptr &= ~0xFF; |
| 704 | sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) | ||
| 705 | & SG_ADDR_MASK; | ||
| 706 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); | ||
| 707 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); | ||
| 708 | } else if ((resid & AHD_SG_LEN_MASK) == 0) { | ||
| 709 | ahd_outb(ahd, SCB_RESIDUAL_SGPTR, | ||
| 710 | sgptr | SG_LIST_NULL); | ||
| 711 | } | ||
| 712 | /* | ||
| 713 | * Save Pointers. | ||
| 714 | */ | ||
| 715 | ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); | ||
| 716 | ahd_outl(ahd, SCB_DATACNT, resid); | ||
| 717 | ahd_outl(ahd, SCB_SGPTR, sgptr); | ||
| 718 | ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); | ||
| 719 | ahd_outb(ahd, SEQIMODE, | ||
| 720 | ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); | ||
| 721 | /* | ||
| 722 | * If the data is to the SCSI bus, we are | ||
| 723 | * done, otherwise wait for FIFOEMP. | ||
| 724 | */ | ||
| 725 | if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) | ||
| 726 | goto clrchn; | ||
| 727 | } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { | ||
| 728 | uint32_t sgptr; | ||
| 729 | uint64_t data_addr; | ||
| 730 | uint32_t data_len; | ||
| 731 | u_int dfcntrl; | ||
| 694 | 732 | ||
| 695 | /* | 733 | /* |
| 696 | * Wait for the DMA engine to notice that the | 734 | * Disable S/G fetch so the DMA engine |
| 697 | * host transfer is enabled and that there is | 735 | * is available to future users. We won't |
| 698 | * space in the S/G FIFO for new segments before | 736 | * be using the DMA engine to load segments. |
| 699 | * loading more segments. | 737 | */ |
| 700 | */ | 738 | if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { |
| 701 | if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0) | 739 | ahd_outb(ahd, CCSGCTL, 0); |
| 702 | continue; | 740 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED); |
| 703 | if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0) | 741 | } |
| 704 | continue; | 742 | |
| 743 | /* | ||
| 744 | * Wait for the DMA engine to notice that the | ||
| 745 | * host transfer is enabled and that there is | ||
| 746 | * space in the S/G FIFO for new segments before | ||
| 747 | * loading more segments. | ||
| 748 | */ | ||
| 749 | if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0 | ||
| 750 | && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) { | ||
| 705 | 751 | ||
| 706 | /* | 752 | /* |
| 707 | * Determine the offset of the next S/G | 753 | * Determine the offset of the next S/G |
| @@ -748,7 +794,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) | |||
| 748 | * Advertise the segment to the hardware. | 794 | * Advertise the segment to the hardware. |
| 749 | */ | 795 | */ |
| 750 | dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; | 796 | dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; |
| 751 | if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) { | 797 | if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { |
| 752 | /* | 798 | /* |
| 753 | * Use SCSIENWRDIS so that SCSIEN | 799 | * Use SCSIENWRDIS so that SCSIEN |
| 754 | * is never modified by this | 800 | * is never modified by this |
| @@ -757,35 +803,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) | |||
| 757 | dfcntrl |= SCSIENWRDIS; | 803 | dfcntrl |= SCSIENWRDIS; |
| 758 | } | 804 | } |
| 759 | ahd_outb(ahd, DFCNTRL, dfcntrl); | 805 | ahd_outb(ahd, DFCNTRL, dfcntrl); |
| 760 | } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) | ||
| 761 | & LAST_SEG_DONE) != 0) { | ||
| 762 | |||
| 763 | /* | ||
| 764 | * Transfer completed to the end of SG list | ||
| 765 | * and has flushed to the host. | ||
| 766 | */ | ||
| 767 | ahd_outb(ahd, SCB_SGPTR, | ||
| 768 | ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); | ||
| 769 | break; | ||
| 770 | } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { | ||
| 771 | break; | ||
| 772 | } | 806 | } |
| 773 | ahd_delay(200); | 807 | } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) { |
| 808 | |||
| 809 | /* | ||
| 810 | * Transfer completed to the end of SG list | ||
| 811 | * and has flushed to the host. | ||
| 812 | */ | ||
| 813 | ahd_outb(ahd, SCB_SGPTR, | ||
| 814 | ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); | ||
| 815 | goto clrchn; | ||
| 816 | } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { | ||
| 817 | clrchn: | ||
| 818 | /* | ||
| 819 | * Clear any handler for this FIFO, decrement | ||
| 820 | * the FIFO use count for the SCB, and release | ||
| 821 | * the FIFO. | ||
| 822 | */ | ||
| 823 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); | ||
| 824 | ahd_outb(ahd, SCB_FIFO_USE_COUNT, | ||
| 825 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); | ||
| 826 | ahd_outb(ahd, DFFSXFRCTL, CLRCHN); | ||
| 774 | } | 827 | } |
| 775 | /* | ||
| 776 | * Clear any handler for this FIFO, decrement | ||
| 777 | * the FIFO use count for the SCB, and release | ||
| 778 | * the FIFO. | ||
| 779 | */ | ||
| 780 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); | ||
| 781 | ahd_outb(ahd, SCB_FIFO_USE_COUNT, | ||
| 782 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); | ||
| 783 | ahd_outb(ahd, DFFSXFRCTL, CLRCHN); | ||
| 784 | } | 828 | } |
| 785 | 829 | ||
| 830 | /* | ||
| 831 | * Look for entries in the QoutFIFO that have completed. | ||
| 832 | * The valid_tag completion field indicates the validity | ||
| 833 | * of the entry - the valid value toggles each time through | ||
| 834 | * the queue. We use the sg_status field in the completion | ||
| 835 | * entry to avoid referencing the hscb if the completion | ||
| 836 | * occurred with no errors and no residual. sg_status is | ||
| 837 | * a copy of the first byte (little endian) of the sgptr | ||
| 838 | * hscb field. | ||
| 839 | */ | ||
| 786 | void | 840 | void |
| 787 | ahd_run_qoutfifo(struct ahd_softc *ahd) | 841 | ahd_run_qoutfifo(struct ahd_softc *ahd) |
| 788 | { | 842 | { |
| 843 | struct ahd_completion *completion; | ||
| 789 | struct scb *scb; | 844 | struct scb *scb; |
| 790 | u_int scb_index; | 845 | u_int scb_index; |
| 791 | 846 | ||
| @@ -793,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) | |||
| 793 | panic("ahd_run_qoutfifo recursion"); | 848 | panic("ahd_run_qoutfifo recursion"); |
| 794 | ahd->flags |= AHD_RUNNING_QOUTFIFO; | 849 | ahd->flags |= AHD_RUNNING_QOUTFIFO; |
| 795 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); | 850 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); |
| 796 | while ((ahd->qoutfifo[ahd->qoutfifonext] | 851 | for (;;) { |
| 797 | & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { | 852 | completion = &ahd->qoutfifo[ahd->qoutfifonext]; |
| 798 | 853 | ||
| 799 | scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] | 854 | if (completion->valid_tag != ahd->qoutfifonext_valid_tag) |
| 800 | & ~QOUTFIFO_ENTRY_VALID_LE); | 855 | break; |
| 856 | |||
| 857 | scb_index = ahd_le16toh(completion->tag); | ||
| 801 | scb = ahd_lookup_scb(ahd, scb_index); | 858 | scb = ahd_lookup_scb(ahd, scb_index); |
| 802 | if (scb == NULL) { | 859 | if (scb == NULL) { |
| 803 | printf("%s: WARNING no command for scb %d " | 860 | printf("%s: WARNING no command for scb %d " |
| @@ -805,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) | |||
| 805 | ahd_name(ahd), scb_index, | 862 | ahd_name(ahd), scb_index, |
| 806 | ahd->qoutfifonext); | 863 | ahd->qoutfifonext); |
| 807 | ahd_dump_card_state(ahd); | 864 | ahd_dump_card_state(ahd); |
| 808 | } else | 865 | } else if ((completion->sg_status & SG_STATUS_VALID) != 0) { |
| 809 | ahd_complete_scb(ahd, scb); | 866 | ahd_handle_scb_status(ahd, scb); |
| 867 | } else { | ||
| 868 | ahd_done(ahd, scb); | ||
| 869 | } | ||
| 810 | 870 | ||
| 811 | ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); | 871 | ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); |
| 812 | if (ahd->qoutfifonext == 0) | 872 | if (ahd->qoutfifonext == 0) |
| 813 | ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE; | 873 | ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID; |
| 814 | } | 874 | } |
| 815 | ahd->flags &= ~AHD_RUNNING_QOUTFIFO; | 875 | ahd->flags &= ~AHD_RUNNING_QOUTFIFO; |
| 816 | } | 876 | } |
| @@ -876,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) | |||
| 876 | ahd_name(ahd), seqintcode); | 936 | ahd_name(ahd), seqintcode); |
| 877 | #endif | 937 | #endif |
| 878 | switch (seqintcode) { | 938 | switch (seqintcode) { |
| 879 | case BAD_SCB_STATUS: | ||
| 880 | { | ||
| 881 | struct scb *scb; | ||
| 882 | u_int scbid; | ||
| 883 | int cmds_pending; | ||
| 884 | |||
| 885 | scbid = ahd_get_scbptr(ahd); | ||
| 886 | scb = ahd_lookup_scb(ahd, scbid); | ||
| 887 | if (scb != NULL) { | ||
| 888 | ahd_complete_scb(ahd, scb); | ||
| 889 | } else { | ||
| 890 | printf("%s: WARNING no command for scb %d " | ||
| 891 | "(bad status)\n", ahd_name(ahd), scbid); | ||
| 892 | ahd_dump_card_state(ahd); | ||
| 893 | } | ||
| 894 | cmds_pending = ahd_inw(ahd, CMDS_PENDING); | ||
| 895 | if (cmds_pending > 0) | ||
| 896 | ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); | ||
| 897 | break; | ||
| 898 | } | ||
| 899 | case ENTERING_NONPACK: | 939 | case ENTERING_NONPACK: |
| 900 | { | 940 | { |
| 901 | struct scb *scb; | 941 | struct scb *scb; |
| @@ -1060,7 +1100,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) | |||
| 1060 | ahd_outb(ahd, SAVED_LUN, 0); | 1100 | ahd_outb(ahd, SAVED_LUN, 0); |
| 1061 | ahd_outb(ahd, SEQ_FLAGS, 0); | 1101 | ahd_outb(ahd, SEQ_FLAGS, 0); |
| 1062 | ahd_assert_atn(ahd); | 1102 | ahd_assert_atn(ahd); |
| 1063 | scb->flags &= ~(SCB_PACKETIZED); | 1103 | scb->flags &= ~SCB_PACKETIZED; |
| 1064 | scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; | 1104 | scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; |
| 1065 | ahd_freeze_devq(ahd, scb); | 1105 | ahd_freeze_devq(ahd, scb); |
| 1066 | ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); | 1106 | ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); |
| @@ -1503,9 +1543,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1503 | && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) | 1543 | && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) |
| 1504 | scb = NULL; | 1544 | scb = NULL; |
| 1505 | 1545 | ||
| 1506 | /* Make sure the sequencer is in a safe location. */ | ||
| 1507 | ahd_clear_critical_section(ahd); | ||
| 1508 | |||
| 1509 | if ((status0 & IOERR) != 0) { | 1546 | if ((status0 & IOERR) != 0) { |
| 1510 | u_int now_lvd; | 1547 | u_int now_lvd; |
| 1511 | 1548 | ||
| @@ -1521,26 +1558,35 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1521 | ahd_setup_iocell_workaround(ahd); | 1558 | ahd_setup_iocell_workaround(ahd); |
| 1522 | ahd_unpause(ahd); | 1559 | ahd_unpause(ahd); |
| 1523 | } else if ((status0 & OVERRUN) != 0) { | 1560 | } else if ((status0 & OVERRUN) != 0) { |
| 1561 | |||
| 1524 | printf("%s: SCSI offset overrun detected. Resetting bus.\n", | 1562 | printf("%s: SCSI offset overrun detected. Resetting bus.\n", |
| 1525 | ahd_name(ahd)); | 1563 | ahd_name(ahd)); |
| 1526 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); | 1564 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); |
| 1527 | } else if ((status & SCSIRSTI) != 0) { | 1565 | } else if ((status & SCSIRSTI) != 0) { |
| 1566 | |||
| 1528 | printf("%s: Someone reset channel A\n", ahd_name(ahd)); | 1567 | printf("%s: Someone reset channel A\n", ahd_name(ahd)); |
| 1529 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); | 1568 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); |
| 1530 | } else if ((status & SCSIPERR) != 0) { | 1569 | } else if ((status & SCSIPERR) != 0) { |
| 1570 | |||
| 1571 | /* Make sure the sequencer is in a safe location. */ | ||
| 1572 | ahd_clear_critical_section(ahd); | ||
| 1573 | |||
| 1531 | ahd_handle_transmission_error(ahd); | 1574 | ahd_handle_transmission_error(ahd); |
| 1532 | } else if (lqostat0 != 0) { | 1575 | } else if (lqostat0 != 0) { |
| 1576 | |||
| 1533 | printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); | 1577 | printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); |
| 1534 | ahd_outb(ahd, CLRLQOINT0, lqostat0); | 1578 | ahd_outb(ahd, CLRLQOINT0, lqostat0); |
| 1535 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { | 1579 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) |
| 1536 | ahd_outb(ahd, CLRLQOINT1, 0); | 1580 | ahd_outb(ahd, CLRLQOINT1, 0); |
| 1537 | } | ||
| 1538 | } else if ((status & SELTO) != 0) { | 1581 | } else if ((status & SELTO) != 0) { |
| 1539 | u_int scbid; | 1582 | u_int scbid; |
| 1540 | 1583 | ||
| 1541 | /* Stop the selection */ | 1584 | /* Stop the selection */ |
| 1542 | ahd_outb(ahd, SCSISEQ0, 0); | 1585 | ahd_outb(ahd, SCSISEQ0, 0); |
| 1543 | 1586 | ||
| 1587 | /* Make sure the sequencer is in a safe location. */ | ||
| 1588 | ahd_clear_critical_section(ahd); | ||
| 1589 | |||
| 1544 | /* No more pending messages */ | 1590 | /* No more pending messages */ |
| 1545 | ahd_clear_msg_state(ahd); | 1591 | ahd_clear_msg_state(ahd); |
| 1546 | 1592 | ||
| @@ -1573,24 +1619,27 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1573 | scbid); | 1619 | scbid); |
| 1574 | } | 1620 | } |
| 1575 | #endif | 1621 | #endif |
| 1576 | /* | ||
| 1577 | * Force a renegotiation with this target just in | ||
| 1578 | * case the cable was pulled and will later be | ||
| 1579 | * re-attached. The target may forget its negotiation | ||
| 1580 | * settings with us should it attempt to reselect | ||
| 1581 | * during the interruption. The target will not issue | ||
| 1582 | * a unit attention in this case, so we must always | ||
| 1583 | * renegotiate. | ||
| 1584 | */ | ||
| 1585 | ahd_scb_devinfo(ahd, &devinfo, scb); | 1622 | ahd_scb_devinfo(ahd, &devinfo, scb); |
| 1586 | ahd_force_renegotiation(ahd, &devinfo); | ||
| 1587 | ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); | 1623 | ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); |
| 1588 | ahd_freeze_devq(ahd, scb); | 1624 | ahd_freeze_devq(ahd, scb); |
| 1625 | |||
| 1626 | /* | ||
| 1627 | * Cancel any pending transactions on the device | ||
| 1628 | * now that it seems to be missing. This will | ||
| 1629 | * also revert us to async/narrow transfers until | ||
| 1630 | * we can renegotiate with the device. | ||
| 1631 | */ | ||
| 1632 | ahd_handle_devreset(ahd, &devinfo, | ||
| 1633 | CAM_LUN_WILDCARD, | ||
| 1634 | CAM_SEL_TIMEOUT, | ||
| 1635 | "Selection Timeout", | ||
| 1636 | /*verbose_level*/1); | ||
| 1589 | } | 1637 | } |
| 1590 | ahd_outb(ahd, CLRINT, CLRSCSIINT); | 1638 | ahd_outb(ahd, CLRINT, CLRSCSIINT); |
| 1591 | ahd_iocell_first_selection(ahd); | 1639 | ahd_iocell_first_selection(ahd); |
| 1592 | ahd_unpause(ahd); | 1640 | ahd_unpause(ahd); |
| 1593 | } else if ((status0 & (SELDI|SELDO)) != 0) { | 1641 | } else if ((status0 & (SELDI|SELDO)) != 0) { |
| 1642 | |||
| 1594 | ahd_iocell_first_selection(ahd); | 1643 | ahd_iocell_first_selection(ahd); |
| 1595 | ahd_unpause(ahd); | 1644 | ahd_unpause(ahd); |
| 1596 | } else if (status3 != 0) { | 1645 | } else if (status3 != 0) { |
| @@ -1598,6 +1647,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1598 | ahd_name(ahd), status3); | 1647 | ahd_name(ahd), status3); |
| 1599 | ahd_outb(ahd, CLRSINT3, status3); | 1648 | ahd_outb(ahd, CLRSINT3, status3); |
| 1600 | } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { | 1649 | } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { |
| 1650 | |||
| 1651 | /* Make sure the sequencer is in a safe location. */ | ||
| 1652 | ahd_clear_critical_section(ahd); | ||
| 1653 | |||
| 1601 | ahd_handle_lqiphase_error(ahd, lqistat1); | 1654 | ahd_handle_lqiphase_error(ahd, lqistat1); |
| 1602 | } else if ((lqistat1 & LQICRCI_NLQ) != 0) { | 1655 | } else if ((lqistat1 & LQICRCI_NLQ) != 0) { |
| 1603 | /* | 1656 | /* |
| @@ -1622,6 +1675,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1622 | */ | 1675 | */ |
| 1623 | ahd_outb(ahd, SCSISEQ0, 0); | 1676 | ahd_outb(ahd, SCSISEQ0, 0); |
| 1624 | 1677 | ||
| 1678 | /* Make sure the sequencer is in a safe location. */ | ||
| 1679 | ahd_clear_critical_section(ahd); | ||
| 1680 | |||
| 1625 | /* | 1681 | /* |
| 1626 | * Determine what we were up to at the time of | 1682 | * Determine what we were up to at the time of |
| 1627 | * the busfree. | 1683 | * the busfree. |
| @@ -1659,7 +1715,16 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
| 1659 | clear_fifo = 0; | 1715 | clear_fifo = 0; |
| 1660 | packetized = (lqostat1 & LQOBUSFREE) != 0; | 1716 | packetized = (lqostat1 & LQOBUSFREE) != 0; |
| 1661 | if (!packetized | 1717 | if (!packetized |
| 1662 | && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) | 1718 | && ahd_inb(ahd, LASTPHASE) == P_BUSFREE |
| 1719 | && (ahd_inb(ahd, SSTAT0) & SELDI) == 0 | ||
| 1720 | && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0 | ||
| 1721 | || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0)) | ||
| 1722 | /* | ||
| 1723 | * Assume packetized if we are not | ||
| 1724 | * on the bus in a non-packetized | ||
| 1725 | * capacity and any pending selection | ||
| 1726 | * was a packetized selection. | ||
| 1727 | */ | ||
| 1663 | packetized = 1; | 1728 | packetized = 1; |
| 1664 | break; | 1729 | break; |
| 1665 | } | 1730 | } |
| @@ -2310,8 +2375,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) | |||
| 2310 | "PRGMCNT == 0x%x\n", | 2375 | "PRGMCNT == 0x%x\n", |
| 2311 | ahd_lookup_phase_entry(lastphase)->phasemsg, | 2376 | ahd_lookup_phase_entry(lastphase)->phasemsg, |
| 2312 | aborted, | 2377 | aborted, |
| 2313 | ahd_inb(ahd, PRGMCNT) | 2378 | ahd_inw(ahd, PRGMCNT)); |
| 2314 | | (ahd_inb(ahd, PRGMCNT+1) << 8)); | ||
| 2315 | ahd_dump_card_state(ahd); | 2379 | ahd_dump_card_state(ahd); |
| 2316 | } | 2380 | } |
| 2317 | /* Always restart the sequencer. */ | 2381 | /* Always restart the sequencer. */ |
| @@ -2474,8 +2538,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) | |||
| 2474 | u_int i; | 2538 | u_int i; |
| 2475 | 2539 | ||
| 2476 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | 2540 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
| 2477 | seqaddr = ahd_inb(ahd, CURADDR) | 2541 | seqaddr = ahd_inw(ahd, CURADDR); |
| 2478 | | (ahd_inb(ahd, CURADDR+1) << 8); | ||
| 2479 | 2542 | ||
| 2480 | cs = ahd->critical_sections; | 2543 | cs = ahd->critical_sections; |
| 2481 | for (i = 0; i < ahd->num_critical_sections; i++, cs++) { | 2544 | for (i = 0; i < ahd->num_critical_sections; i++, cs++) { |
| @@ -3196,14 +3259,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | |||
| 3196 | iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; | 3259 | iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; |
| 3197 | 3260 | ||
| 3198 | if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 | 3261 | if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 |
| 3199 | && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { | 3262 | && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0 |
| 3263 | && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) { | ||
| 3200 | /* | 3264 | /* |
| 3201 | * Slow down our CRC interval to be | 3265 | * Slow down our CRC interval to be |
| 3202 | * compatible with devices that can't | 3266 | * compatible with non-packetized |
| 3203 | * handle a CRC at full speed. | 3267 | * U160 devices that can't handle a |
| 3268 | * CRC at full speed. | ||
| 3204 | */ | 3269 | */ |
| 3205 | con_opts |= ENSLOWCRC; | 3270 | con_opts |= ENSLOWCRC; |
| 3206 | } | 3271 | } |
| 3272 | |||
| 3273 | if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { | ||
| 3274 | /* | ||
| 3275 | * On H2A4, revert to a slower slewrate | ||
| 3276 | * on non-paced transfers. | ||
| 3277 | */ | ||
| 3278 | iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= | ||
| 3279 | ~AHD_SLEWRATE_MASK; | ||
| 3280 | } | ||
| 3207 | } | 3281 | } |
| 3208 | 3282 | ||
| 3209 | ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); | 3283 | ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); |
| @@ -3292,11 +3366,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) | |||
| 3292 | * Force the sequencer to reinitialize the selection for | 3366 | * Force the sequencer to reinitialize the selection for |
| 3293 | * the command at the head of the execution queue if it | 3367 | * the command at the head of the execution queue if it |
| 3294 | * has already been setup. The negotiation changes may | 3368 | * has already been setup. The negotiation changes may |
| 3295 | * effect whether we select-out with ATN. | 3369 | * effect whether we select-out with ATN. It is only |
| 3370 | * safe to clear ENSELO when the bus is not free and no | ||
| 3371 | * selection is in progres or completed. | ||
| 3296 | */ | 3372 | */ |
| 3297 | saved_modes = ahd_save_modes(ahd); | 3373 | saved_modes = ahd_save_modes(ahd); |
| 3298 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | 3374 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
| 3299 | ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); | 3375 | if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0 |
| 3376 | && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) | ||
| 3377 | ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); | ||
| 3300 | saved_scbptr = ahd_get_scbptr(ahd); | 3378 | saved_scbptr = ahd_get_scbptr(ahd); |
| 3301 | /* Ensure that the hscbs down on the card match the new information */ | 3379 | /* Ensure that the hscbs down on the card match the new information */ |
| 3302 | for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { | 3380 | for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { |
| @@ -4909,10 +4987,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) | |||
| 4909 | * Determine initial values for data_addr and data_cnt | 4987 | * Determine initial values for data_addr and data_cnt |
| 4910 | * for resuming the data phase. | 4988 | * for resuming the data phase. |
| 4911 | */ | 4989 | */ |
| 4912 | sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) | 4990 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); |
| 4913 | | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) | ||
| 4914 | | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) | ||
| 4915 | | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); | ||
| 4916 | sgptr &= SG_PTR_MASK; | 4991 | sgptr &= SG_PTR_MASK; |
| 4917 | 4992 | ||
| 4918 | resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) | 4993 | resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) |
| @@ -4930,10 +5005,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) | |||
| 4930 | dataptr = ahd_le64toh(sg->addr) | 5005 | dataptr = ahd_le64toh(sg->addr) |
| 4931 | + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) | 5006 | + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) |
| 4932 | - resid; | 5007 | - resid; |
| 4933 | ahd_outb(ahd, HADDR + 7, dataptr >> 56); | 5008 | ahd_outl(ahd, HADDR + 4, dataptr >> 32); |
| 4934 | ahd_outb(ahd, HADDR + 6, dataptr >> 48); | ||
| 4935 | ahd_outb(ahd, HADDR + 5, dataptr >> 40); | ||
| 4936 | ahd_outb(ahd, HADDR + 4, dataptr >> 32); | ||
| 4937 | } else { | 5009 | } else { |
| 4938 | struct ahd_dma_seg *sg; | 5010 | struct ahd_dma_seg *sg; |
| 4939 | 5011 | ||
| @@ -4948,10 +5020,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) | |||
| 4948 | ahd_outb(ahd, HADDR + 4, | 5020 | ahd_outb(ahd, HADDR + 4, |
| 4949 | (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); | 5021 | (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); |
| 4950 | } | 5022 | } |
| 4951 | ahd_outb(ahd, HADDR + 3, dataptr >> 24); | 5023 | ahd_outl(ahd, HADDR, dataptr); |
| 4952 | ahd_outb(ahd, HADDR + 2, dataptr >> 16); | ||
| 4953 | ahd_outb(ahd, HADDR + 1, dataptr >> 8); | ||
| 4954 | ahd_outb(ahd, HADDR, dataptr); | ||
| 4955 | ahd_outb(ahd, HCNT + 2, resid >> 16); | 5024 | ahd_outb(ahd, HCNT + 2, resid >> 16); |
| 4956 | ahd_outb(ahd, HCNT + 1, resid >> 8); | 5025 | ahd_outb(ahd, HCNT + 1, resid >> 8); |
| 4957 | ahd_outb(ahd, HCNT, resid); | 5026 | ahd_outb(ahd, HCNT, resid); |
| @@ -5011,13 +5080,14 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | |||
| 5011 | ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, | 5080 | ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, |
| 5012 | AHD_TRANS_CUR, /*paused*/TRUE); | 5081 | AHD_TRANS_CUR, /*paused*/TRUE); |
| 5013 | ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, | 5082 | ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, |
| 5014 | /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE); | 5083 | /*ppr_options*/0, AHD_TRANS_CUR, |
| 5084 | /*paused*/TRUE); | ||
| 5015 | 5085 | ||
| 5016 | ahd_send_async(ahd, devinfo->channel, devinfo->target, | 5086 | if (status != CAM_SEL_TIMEOUT) |
| 5017 | lun, AC_SENT_BDR, NULL); | 5087 | ahd_send_async(ahd, devinfo->channel, devinfo->target, |
| 5088 | CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); | ||
| 5018 | 5089 | ||
| 5019 | if (message != NULL | 5090 | if (message != NULL && bootverbose) |
| 5020 | && (verbose_level <= bootverbose)) | ||
| 5021 | printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), | 5091 | printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), |
| 5022 | message, devinfo->channel, devinfo->target, found); | 5092 | message, devinfo->channel, devinfo->target, found); |
| 5023 | } | 5093 | } |
| @@ -5203,13 +5273,13 @@ ahd_free(struct ahd_softc *ahd) | |||
| 5203 | /* FALLTHROUGH */ | 5273 | /* FALLTHROUGH */ |
| 5204 | case 4: | 5274 | case 4: |
| 5205 | ahd_dmamap_unload(ahd, ahd->shared_data_dmat, | 5275 | ahd_dmamap_unload(ahd, ahd->shared_data_dmat, |
| 5206 | ahd->shared_data_dmamap); | 5276 | ahd->shared_data_map.dmamap); |
| 5207 | /* FALLTHROUGH */ | 5277 | /* FALLTHROUGH */ |
| 5208 | case 3: | 5278 | case 3: |
| 5209 | ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, | 5279 | ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, |
| 5210 | ahd->shared_data_dmamap); | 5280 | ahd->shared_data_map.dmamap); |
| 5211 | ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, | 5281 | ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, |
| 5212 | ahd->shared_data_dmamap); | 5282 | ahd->shared_data_map.dmamap); |
| 5213 | /* FALLTHROUGH */ | 5283 | /* FALLTHROUGH */ |
| 5214 | case 2: | 5284 | case 2: |
| 5215 | ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); | 5285 | ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); |
| @@ -5975,16 +6045,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd) | |||
| 5975 | newcount = MIN(scb_data->sense_left, scb_data->scbs_left); | 6045 | newcount = MIN(scb_data->sense_left, scb_data->scbs_left); |
| 5976 | newcount = MIN(newcount, scb_data->sgs_left); | 6046 | newcount = MIN(newcount, scb_data->sgs_left); |
| 5977 | newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); | 6047 | newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); |
| 5978 | scb_data->sense_left -= newcount; | ||
| 5979 | scb_data->scbs_left -= newcount; | ||
| 5980 | scb_data->sgs_left -= newcount; | ||
| 5981 | for (i = 0; i < newcount; i++) { | 6048 | for (i = 0; i < newcount; i++) { |
| 5982 | u_int col_tag; | ||
| 5983 | |||
| 5984 | struct scb_platform_data *pdata; | 6049 | struct scb_platform_data *pdata; |
| 6050 | u_int col_tag; | ||
| 5985 | #ifndef __linux__ | 6051 | #ifndef __linux__ |
| 5986 | int error; | 6052 | int error; |
| 5987 | #endif | 6053 | #endif |
| 6054 | |||
| 5988 | next_scb = (struct scb *)malloc(sizeof(*next_scb), | 6055 | next_scb = (struct scb *)malloc(sizeof(*next_scb), |
| 5989 | M_DEVBUF, M_NOWAIT); | 6056 | M_DEVBUF, M_NOWAIT); |
| 5990 | if (next_scb == NULL) | 6057 | if (next_scb == NULL) |
| @@ -6041,6 +6108,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd) | |||
| 6041 | sense_data += AHD_SENSE_BUFSIZE; | 6108 | sense_data += AHD_SENSE_BUFSIZE; |
| 6042 | sense_busaddr += AHD_SENSE_BUFSIZE; | 6109 | sense_busaddr += AHD_SENSE_BUFSIZE; |
| 6043 | scb_data->numscbs++; | 6110 | scb_data->numscbs++; |
| 6111 | scb_data->sense_left--; | ||
| 6112 | scb_data->scbs_left--; | ||
| 6113 | scb_data->sgs_left--; | ||
| 6044 | } | 6114 | } |
| 6045 | } | 6115 | } |
| 6046 | 6116 | ||
| @@ -6088,7 +6158,6 @@ static const char *termstat_strings[] = { | |||
| 6088 | int | 6158 | int |
| 6089 | ahd_init(struct ahd_softc *ahd) | 6159 | ahd_init(struct ahd_softc *ahd) |
| 6090 | { | 6160 | { |
| 6091 | uint8_t *base_vaddr; | ||
| 6092 | uint8_t *next_vaddr; | 6161 | uint8_t *next_vaddr; |
| 6093 | dma_addr_t next_baddr; | 6162 | dma_addr_t next_baddr; |
| 6094 | size_t driver_data_size; | 6163 | size_t driver_data_size; |
| @@ -6156,7 +6225,7 @@ ahd_init(struct ahd_softc *ahd) | |||
| 6156 | * for the target mode role, we must additionally provide space for | 6225 | * for the target mode role, we must additionally provide space for |
| 6157 | * the incoming target command fifo. | 6226 | * the incoming target command fifo. |
| 6158 | */ | 6227 | */ |
| 6159 | driver_data_size = AHD_SCB_MAX * sizeof(uint16_t) | 6228 | driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo) |
| 6160 | + sizeof(struct hardware_scb); | 6229 | + sizeof(struct hardware_scb); |
| 6161 | if ((ahd->features & AHD_TARGETMODE) != 0) | 6230 | if ((ahd->features & AHD_TARGETMODE) != 0) |
| 6162 | driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); | 6231 | driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); |
| @@ -6178,20 +6247,23 @@ ahd_init(struct ahd_softc *ahd) | |||
| 6178 | 6247 | ||
| 6179 | /* Allocation of driver data */ | 6248 | /* Allocation of driver data */ |
| 6180 | if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, | 6249 | if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, |
| 6181 | (void **)&base_vaddr, | 6250 | (void **)&ahd->shared_data_map.vaddr, |
| 6182 | BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { | 6251 | BUS_DMA_NOWAIT, |
| 6252 | &ahd->shared_data_map.dmamap) != 0) { | ||
| 6183 | return (ENOMEM); | 6253 | return (ENOMEM); |
| 6184 | } | 6254 | } |
| 6185 | 6255 | ||
| 6186 | ahd->init_level++; | 6256 | ahd->init_level++; |
| 6187 | 6257 | ||
| 6188 | /* And permanently map it in */ | 6258 | /* And permanently map it in */ |
| 6189 | ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, | 6259 | ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, |
| 6190 | base_vaddr, driver_data_size, ahd_dmamap_cb, | 6260 | ahd->shared_data_map.vaddr, driver_data_size, |
| 6191 | &ahd->shared_data_busaddr, /*flags*/0); | 6261 | ahd_dmamap_cb, &ahd->shared_data_map.physaddr, |
| 6192 | ahd->qoutfifo = (uint16_t *)base_vaddr; | 6262 | /*flags*/0); |
| 6263 | ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr; | ||
| 6193 | next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; | 6264 | next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; |
| 6194 | next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); | 6265 | next_baddr = ahd->shared_data_map.physaddr |
| 6266 | + AHD_QOUT_SIZE*sizeof(struct ahd_completion); | ||
| 6195 | if ((ahd->features & AHD_TARGETMODE) != 0) { | 6267 | if ((ahd->features & AHD_TARGETMODE) != 0) { |
| 6196 | ahd->targetcmds = (struct target_cmd *)next_vaddr; | 6268 | ahd->targetcmds = (struct target_cmd *)next_vaddr; |
| 6197 | next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); | 6269 | next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); |
| @@ -6212,6 +6284,7 @@ ahd_init(struct ahd_softc *ahd) | |||
| 6212 | * specially from the DMA safe memory chunk used for the QOUTFIFO. | 6284 | * specially from the DMA safe memory chunk used for the QOUTFIFO. |
| 6213 | */ | 6285 | */ |
| 6214 | ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; | 6286 | ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; |
| 6287 | ahd->next_queued_hscb_map = &ahd->shared_data_map; | ||
| 6215 | ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); | 6288 | ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); |
| 6216 | 6289 | ||
| 6217 | ahd->init_level++; | 6290 | ahd->init_level++; |
| @@ -6517,10 +6590,10 @@ ahd_chip_init(struct ahd_softc *ahd) | |||
| 6517 | 6590 | ||
| 6518 | /* All of our queues are empty */ | 6591 | /* All of our queues are empty */ |
| 6519 | ahd->qoutfifonext = 0; | 6592 | ahd->qoutfifonext = 0; |
| 6520 | ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE; | 6593 | ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID; |
| 6521 | ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8); | 6594 | ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID); |
| 6522 | for (i = 0; i < AHD_QOUT_SIZE; i++) | 6595 | for (i = 0; i < AHD_QOUT_SIZE; i++) |
| 6523 | ahd->qoutfifo[i] = 0; | 6596 | ahd->qoutfifo[i].valid_tag = 0; |
| 6524 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); | 6597 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); |
| 6525 | 6598 | ||
| 6526 | ahd->qinfifonext = 0; | 6599 | ahd->qinfifonext = 0; |
| @@ -6553,24 +6626,22 @@ ahd_chip_init(struct ahd_softc *ahd) | |||
| 6553 | ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); | 6626 | ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); |
| 6554 | ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); | 6627 | ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); |
| 6555 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); | 6628 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); |
| 6629 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); | ||
| 6630 | ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); | ||
| 6556 | 6631 | ||
| 6557 | /* | 6632 | /* |
| 6558 | * The Freeze Count is 0. | 6633 | * The Freeze Count is 0. |
| 6559 | */ | 6634 | */ |
| 6635 | ahd->qfreeze_cnt = 0; | ||
| 6560 | ahd_outw(ahd, QFREEZE_COUNT, 0); | 6636 | ahd_outw(ahd, QFREEZE_COUNT, 0); |
| 6637 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0); | ||
| 6561 | 6638 | ||
| 6562 | /* | 6639 | /* |
| 6563 | * Tell the sequencer where it can find our arrays in memory. | 6640 | * Tell the sequencer where it can find our arrays in memory. |
| 6564 | */ | 6641 | */ |
| 6565 | busaddr = ahd->shared_data_busaddr; | 6642 | busaddr = ahd->shared_data_map.physaddr; |
| 6566 | ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); | 6643 | ahd_outl(ahd, SHARED_DATA_ADDR, busaddr); |
| 6567 | ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); | 6644 | ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr); |
| 6568 | ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); | ||
| 6569 | ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); | ||
| 6570 | ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); | ||
| 6571 | ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); | ||
| 6572 | ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); | ||
| 6573 | ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); | ||
| 6574 | 6645 | ||
| 6575 | /* | 6646 | /* |
| 6576 | * Setup the allowed SCSI Sequences based on operational mode. | 6647 | * Setup the allowed SCSI Sequences based on operational mode. |
| @@ -6619,10 +6690,7 @@ ahd_chip_init(struct ahd_softc *ahd) | |||
| 6619 | * Tell the sequencer which SCB will be the next one it receives. | 6690 | * Tell the sequencer which SCB will be the next one it receives. |
| 6620 | */ | 6691 | */ |
| 6621 | busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); | 6692 | busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); |
| 6622 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); | 6693 | ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); |
| 6623 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); | ||
| 6624 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); | ||
| 6625 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); | ||
| 6626 | 6694 | ||
| 6627 | /* | 6695 | /* |
| 6628 | * Default to coalescing disabled. | 6696 | * Default to coalescing disabled. |
| @@ -6926,43 +6994,34 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) | |||
| 6926 | { | 6994 | { |
| 6927 | u_int intstat; | 6995 | u_int intstat; |
| 6928 | u_int maxloops; | 6996 | u_int maxloops; |
| 6929 | u_int qfreeze_cnt; | ||
| 6930 | 6997 | ||
| 6931 | maxloops = 1000; | 6998 | maxloops = 1000; |
| 6932 | ahd->flags |= AHD_ALL_INTERRUPTS; | 6999 | ahd->flags |= AHD_ALL_INTERRUPTS; |
| 6933 | ahd_pause(ahd); | 7000 | ahd_pause(ahd); |
| 6934 | /* | 7001 | /* |
| 6935 | * Increment the QFreeze Count so that the sequencer | 7002 | * Freeze the outgoing selections. We do this only |
| 6936 | * will not start new selections. We do this only | ||
| 6937 | * until we are safely paused without further selections | 7003 | * until we are safely paused without further selections |
| 6938 | * pending. | 7004 | * pending. |
| 6939 | */ | 7005 | */ |
| 6940 | ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); | 7006 | ahd->qfreeze_cnt--; |
| 7007 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); | ||
| 6941 | ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); | 7008 | ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); |
| 6942 | do { | 7009 | do { |
| 6943 | struct scb *waiting_scb; | ||
| 6944 | 7010 | ||
| 6945 | ahd_unpause(ahd); | 7011 | ahd_unpause(ahd); |
| 7012 | /* | ||
| 7013 | * Give the sequencer some time to service | ||
| 7014 | * any active selections. | ||
| 7015 | */ | ||
| 7016 | ahd_delay(500); | ||
| 7017 | |||
| 6946 | ahd_intr(ahd); | 7018 | ahd_intr(ahd); |
| 6947 | ahd_pause(ahd); | 7019 | ahd_pause(ahd); |
| 6948 | ahd_clear_critical_section(ahd); | ||
| 6949 | intstat = ahd_inb(ahd, INTSTAT); | 7020 | intstat = ahd_inb(ahd, INTSTAT); |
| 6950 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | 7021 | if ((intstat & INT_PEND) == 0) { |
| 6951 | if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) | 7022 | ahd_clear_critical_section(ahd); |
| 6952 | ahd_outb(ahd, SCSISEQ0, | 7023 | intstat = ahd_inb(ahd, INTSTAT); |
| 6953 | ahd_inb(ahd, SCSISEQ0) & ~ENSELO); | 7024 | } |
| 6954 | /* | ||
| 6955 | * In the non-packetized case, the sequencer (for Rev A), | ||
| 6956 | * relies on ENSELO remaining set after SELDO. The hardware | ||
| 6957 | * auto-clears ENSELO in the packetized case. | ||
| 6958 | */ | ||
| 6959 | waiting_scb = ahd_lookup_scb(ahd, | ||
| 6960 | ahd_inw(ahd, WAITING_TID_HEAD)); | ||
| 6961 | if (waiting_scb != NULL | ||
| 6962 | && (waiting_scb->flags & SCB_PACKETIZED) == 0 | ||
| 6963 | && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0) | ||
| 6964 | ahd_outb(ahd, SCSISEQ0, | ||
| 6965 | ahd_inb(ahd, SCSISEQ0) | ENSELO); | ||
| 6966 | } while (--maxloops | 7025 | } while (--maxloops |
| 6967 | && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) | 7026 | && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) |
| 6968 | && ((intstat & INT_PEND) != 0 | 7027 | && ((intstat & INT_PEND) != 0 |
| @@ -6973,17 +7032,8 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) | |||
| 6973 | printf("Infinite interrupt loop, INTSTAT = %x", | 7032 | printf("Infinite interrupt loop, INTSTAT = %x", |
| 6974 | ahd_inb(ahd, INTSTAT)); | 7033 | ahd_inb(ahd, INTSTAT)); |
| 6975 | } | 7034 | } |
| 6976 | qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); | 7035 | ahd->qfreeze_cnt++; |
| 6977 | if (qfreeze_cnt == 0) { | 7036 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); |
| 6978 | printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n", | ||
| 6979 | ahd_name(ahd)); | ||
| 6980 | } else { | ||
| 6981 | qfreeze_cnt--; | ||
| 6982 | } | ||
| 6983 | ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); | ||
| 6984 | if (qfreeze_cnt == 0) | ||
| 6985 | ahd_outb(ahd, SEQ_FLAGS2, | ||
| 6986 | ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); | ||
| 6987 | 7037 | ||
| 6988 | ahd_flush_qoutfifo(ahd); | 7038 | ahd_flush_qoutfifo(ahd); |
| 6989 | 7039 | ||
| @@ -7155,10 +7205,7 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb, | |||
| 7155 | uint32_t busaddr; | 7205 | uint32_t busaddr; |
| 7156 | 7206 | ||
| 7157 | busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); | 7207 | busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); |
| 7158 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); | 7208 | ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); |
| 7159 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); | ||
| 7160 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); | ||
| 7161 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); | ||
| 7162 | } else { | 7209 | } else { |
| 7163 | prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; | 7210 | prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; |
| 7164 | ahd_sync_scb(ahd, prev_scb, | 7211 | ahd_sync_scb(ahd, prev_scb, |
| @@ -7265,10 +7312,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, | |||
| 7265 | */ | 7312 | */ |
| 7266 | ahd->qinfifonext = qinstart; | 7313 | ahd->qinfifonext = qinstart; |
| 7267 | busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); | 7314 | busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); |
| 7268 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); | 7315 | ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); |
| 7269 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); | ||
| 7270 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); | ||
| 7271 | ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); | ||
| 7272 | 7316 | ||
| 7273 | while (qinpos != qintail) { | 7317 | while (qinpos != qintail) { |
| 7274 | scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); | 7318 | scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); |
| @@ -7330,6 +7374,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, | |||
| 7330 | * appropriate, traverse the SCBs of each "their id" | 7374 | * appropriate, traverse the SCBs of each "their id" |
| 7331 | * looking for matches. | 7375 | * looking for matches. |
| 7332 | */ | 7376 | */ |
| 7377 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
| 7333 | savedscbptr = ahd_get_scbptr(ahd); | 7378 | savedscbptr = ahd_get_scbptr(ahd); |
| 7334 | tid_next = ahd_inw(ahd, WAITING_TID_HEAD); | 7379 | tid_next = ahd_inw(ahd, WAITING_TID_HEAD); |
| 7335 | tid_prev = SCB_LIST_NULL; | 7380 | tid_prev = SCB_LIST_NULL; |
| @@ -7399,7 +7444,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, | |||
| 7399 | u_int prev; | 7444 | u_int prev; |
| 7400 | int found; | 7445 | int found; |
| 7401 | 7446 | ||
| 7402 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); | 7447 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); |
| 7403 | found = 0; | 7448 | found = 0; |
| 7404 | prev = SCB_LIST_NULL; | 7449 | prev = SCB_LIST_NULL; |
| 7405 | next = *list_head; | 7450 | next = *list_head; |
| @@ -7466,7 +7511,7 @@ static void | |||
| 7466 | ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, | 7511 | ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, |
| 7467 | u_int tid_cur, u_int tid_next) | 7512 | u_int tid_cur, u_int tid_next) |
| 7468 | { | 7513 | { |
| 7469 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); | 7514 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); |
| 7470 | 7515 | ||
| 7471 | if (SCBID_IS_NULL(tid_cur)) { | 7516 | if (SCBID_IS_NULL(tid_cur)) { |
| 7472 | 7517 | ||
| @@ -7506,7 +7551,7 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, | |||
| 7506 | { | 7551 | { |
| 7507 | u_int tail_offset; | 7552 | u_int tail_offset; |
| 7508 | 7553 | ||
| 7509 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); | 7554 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); |
| 7510 | if (!SCBID_IS_NULL(prev)) { | 7555 | if (!SCBID_IS_NULL(prev)) { |
| 7511 | ahd_set_scbptr(ahd, prev); | 7556 | ahd_set_scbptr(ahd, prev); |
| 7512 | ahd_outw(ahd, SCB_NEXT, next); | 7557 | ahd_outw(ahd, SCB_NEXT, next); |
| @@ -7739,7 +7784,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) | |||
| 7739 | */ | 7784 | */ |
| 7740 | ahd_clear_msg_state(ahd); | 7785 | ahd_clear_msg_state(ahd); |
| 7741 | ahd_outb(ahd, SIMODE1, | 7786 | ahd_outb(ahd, SIMODE1, |
| 7742 | ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); | 7787 | ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); |
| 7743 | 7788 | ||
| 7744 | if (initiate_reset) | 7789 | if (initiate_reset) |
| 7745 | ahd_reset_current_bus(ahd); | 7790 | ahd_reset_current_bus(ahd); |
| @@ -7910,30 +7955,35 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) | |||
| 7910 | void | 7955 | void |
| 7911 | ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) | 7956 | ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) |
| 7912 | { | 7957 | { |
| 7913 | struct hardware_scb *hscb; | 7958 | struct hardware_scb *hscb; |
| 7914 | u_int qfreeze_cnt; | 7959 | int paused; |
| 7915 | 7960 | ||
| 7916 | /* | 7961 | /* |
| 7917 | * The sequencer freezes its select-out queue | 7962 | * The sequencer freezes its select-out queue |
| 7918 | * anytime a SCSI status error occurs. We must | 7963 | * anytime a SCSI status error occurs. We must |
| 7919 | * handle the error and decrement the QFREEZE count | 7964 | * handle the error and increment our qfreeze count |
| 7920 | * to allow the sequencer to continue. | 7965 | * to allow the sequencer to continue. We don't |
| 7966 | * bother clearing critical sections here since all | ||
| 7967 | * operations are on data structures that the sequencer | ||
| 7968 | * is not touching once the queue is frozen. | ||
| 7921 | */ | 7969 | */ |
| 7922 | hscb = scb->hscb; | 7970 | hscb = scb->hscb; |
| 7923 | 7971 | ||
| 7972 | if (ahd_is_paused(ahd)) { | ||
| 7973 | paused = 1; | ||
| 7974 | } else { | ||
| 7975 | paused = 0; | ||
| 7976 | ahd_pause(ahd); | ||
| 7977 | } | ||
| 7978 | |||
| 7924 | /* Freeze the queue until the client sees the error. */ | 7979 | /* Freeze the queue until the client sees the error. */ |
| 7925 | ahd_freeze_devq(ahd, scb); | 7980 | ahd_freeze_devq(ahd, scb); |
| 7926 | ahd_freeze_scb(scb); | 7981 | ahd_freeze_scb(scb); |
| 7927 | qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); | 7982 | ahd->qfreeze_cnt++; |
| 7928 | if (qfreeze_cnt == 0) { | 7983 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); |
| 7929 | printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); | 7984 | |
| 7930 | } else { | 7985 | if (paused == 0) |
| 7931 | qfreeze_cnt--; | 7986 | ahd_unpause(ahd); |
| 7932 | ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); | ||
| 7933 | } | ||
| 7934 | if (qfreeze_cnt == 0) | ||
| 7935 | ahd_outb(ahd, SEQ_FLAGS2, | ||
| 7936 | ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); | ||
| 7937 | 7987 | ||
| 7938 | /* Don't want to clobber the original sense code */ | 7988 | /* Don't want to clobber the original sense code */ |
| 7939 | if ((scb->flags & SCB_SENSE) != 0) { | 7989 | if ((scb->flags & SCB_SENSE) != 0) { |
| @@ -8317,8 +8367,7 @@ ahd_dumpseq(struct ahd_softc* ahd) | |||
| 8317 | max_prog = 2048; | 8367 | max_prog = 2048; |
| 8318 | 8368 | ||
| 8319 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); | 8369 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); |
| 8320 | ahd_outb(ahd, PRGMCNT, 0); | 8370 | ahd_outw(ahd, PRGMCNT, 0); |
| 8321 | ahd_outb(ahd, PRGMCNT+1, 0); | ||
| 8322 | for (i = 0; i < max_prog; i++) { | 8371 | for (i = 0; i < max_prog; i++) { |
| 8323 | uint8_t ins_bytes[4]; | 8372 | uint8_t ins_bytes[4]; |
| 8324 | 8373 | ||
| @@ -8347,13 +8396,14 @@ ahd_loadseq(struct ahd_softc *ahd) | |||
| 8347 | u_int sg_prefetch_cnt_limit; | 8396 | u_int sg_prefetch_cnt_limit; |
| 8348 | u_int sg_prefetch_align; | 8397 | u_int sg_prefetch_align; |
| 8349 | u_int sg_size; | 8398 | u_int sg_size; |
| 8399 | u_int cacheline_mask; | ||
| 8350 | uint8_t download_consts[DOWNLOAD_CONST_COUNT]; | 8400 | uint8_t download_consts[DOWNLOAD_CONST_COUNT]; |
| 8351 | 8401 | ||
| 8352 | if (bootverbose) | 8402 | if (bootverbose) |
| 8353 | printf("%s: Downloading Sequencer Program...", | 8403 | printf("%s: Downloading Sequencer Program...", |
| 8354 | ahd_name(ahd)); | 8404 | ahd_name(ahd)); |
| 8355 | 8405 | ||
| 8356 | #if DOWNLOAD_CONST_COUNT != 7 | 8406 | #if DOWNLOAD_CONST_COUNT != 8 |
| 8357 | #error "Download Const Mismatch" | 8407 | #error "Download Const Mismatch" |
| 8358 | #endif | 8408 | #endif |
| 8359 | /* | 8409 | /* |
| @@ -8389,6 +8439,9 @@ ahd_loadseq(struct ahd_softc *ahd) | |||
| 8389 | /* Round down to the nearest power of 2. */ | 8439 | /* Round down to the nearest power of 2. */ |
| 8390 | while (powerof2(sg_prefetch_align) == 0) | 8440 | while (powerof2(sg_prefetch_align) == 0) |
| 8391 | sg_prefetch_align--; | 8441 | sg_prefetch_align--; |
| 8442 | |||
| 8443 | cacheline_mask = sg_prefetch_align - 1; | ||
| 8444 | |||
| 8392 | /* | 8445 | /* |
| 8393 | * If the cacheline boundary is greater than half our prefetch RAM | 8446 | * If the cacheline boundary is greater than half our prefetch RAM |
| 8394 | * we risk not being able to fetch even a single complete S/G | 8447 | * we risk not being able to fetch even a single complete S/G |
| @@ -8429,12 +8482,12 @@ ahd_loadseq(struct ahd_softc *ahd) | |||
| 8429 | download_consts[PKT_OVERRUN_BUFOFFSET] = | 8482 | download_consts[PKT_OVERRUN_BUFOFFSET] = |
| 8430 | (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256; | 8483 | (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256; |
| 8431 | download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN; | 8484 | download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN; |
| 8485 | download_consts[CACHELINE_MASK] = cacheline_mask; | ||
| 8432 | cur_patch = patches; | 8486 | cur_patch = patches; |
| 8433 | downloaded = 0; | 8487 | downloaded = 0; |
| 8434 | skip_addr = 0; | 8488 | skip_addr = 0; |
| 8435 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); | 8489 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); |
| 8436 | ahd_outb(ahd, PRGMCNT, 0); | 8490 | ahd_outw(ahd, PRGMCNT, 0); |
| 8437 | ahd_outb(ahd, PRGMCNT+1, 0); | ||
| 8438 | 8491 | ||
| 8439 | for (i = 0; i < sizeof(seqprog)/4; i++) { | 8492 | for (i = 0; i < sizeof(seqprog)/4; i++) { |
| 8440 | if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { | 8493 | if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { |
| @@ -8727,7 +8780,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) | |||
| 8727 | printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" | 8780 | printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" |
| 8728 | "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", | 8781 | "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", |
| 8729 | ahd_name(ahd), | 8782 | ahd_name(ahd), |
| 8730 | ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), | 8783 | ahd_inw(ahd, CURADDR), |
| 8731 | ahd_build_mode_state(ahd, ahd->saved_src_mode, | 8784 | ahd_build_mode_state(ahd, ahd->saved_src_mode, |
| 8732 | ahd->saved_dst_mode)); | 8785 | ahd->saved_dst_mode)); |
| 8733 | if (paused) | 8786 | if (paused) |
| @@ -8843,6 +8896,15 @@ ahd_dump_card_state(struct ahd_softc *ahd) | |||
| 8843 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); | 8896 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); |
| 8844 | } | 8897 | } |
| 8845 | printf("\n"); | 8898 | printf("\n"); |
| 8899 | printf("Sequencer On QFreeze and Complete list: "); | ||
| 8900 | scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); | ||
| 8901 | i = 0; | ||
| 8902 | while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { | ||
| 8903 | ahd_set_scbptr(ahd, scb_index); | ||
| 8904 | printf("%d ", scb_index); | ||
| 8905 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); | ||
| 8906 | } | ||
| 8907 | printf("\n"); | ||
| 8846 | ahd_set_scbptr(ahd, saved_scb_index); | 8908 | ahd_set_scbptr(ahd, saved_scb_index); |
| 8847 | dffstat = ahd_inb(ahd, DFFSTAT); | 8909 | dffstat = ahd_inb(ahd, DFFSTAT); |
| 8848 | for (i = 0; i < 2; i++) { | 8910 | for (i = 0; i < 2; i++) { |
| @@ -9077,7 +9139,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd) | |||
| 9077 | { | 9139 | { |
| 9078 | int cnt; | 9140 | int cnt; |
| 9079 | 9141 | ||
| 9080 | cnt = 20; | 9142 | cnt = 5000; |
| 9081 | while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) | 9143 | while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) |
| 9082 | ahd_delay(5); | 9144 | ahd_delay(5); |
| 9083 | 9145 | ||
| @@ -9423,13 +9485,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) | |||
| 9423 | if ((ahd->features & AHD_MULTI_TID) != 0) { | 9485 | if ((ahd->features & AHD_MULTI_TID) != 0) { |
| 9424 | u_int targid_mask; | 9486 | u_int targid_mask; |
| 9425 | 9487 | ||
| 9426 | targid_mask = ahd_inb(ahd, TARGID) | 9488 | targid_mask = ahd_inw(ahd, TARGID); |
| 9427 | | (ahd_inb(ahd, TARGID + 1) << 8); | ||
| 9428 | |||
| 9429 | targid_mask |= target_mask; | 9489 | targid_mask |= target_mask; |
| 9430 | ahd_outb(ahd, TARGID, targid_mask); | 9490 | ahd_outw(ahd, TARGID, targid_mask); |
| 9431 | ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); | ||
| 9432 | |||
| 9433 | ahd_update_scsiid(ahd, targid_mask); | 9491 | ahd_update_scsiid(ahd, targid_mask); |
| 9434 | } else { | 9492 | } else { |
| 9435 | u_int our_id; | 9493 | u_int our_id; |
| @@ -9543,14 +9601,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) | |||
| 9543 | if (ahd->features & AHD_MULTI_TID) { | 9601 | if (ahd->features & AHD_MULTI_TID) { |
| 9544 | u_int targid_mask; | 9602 | u_int targid_mask; |
| 9545 | 9603 | ||
| 9546 | targid_mask = ahd_inb(ahd, TARGID) | 9604 | targid_mask = ahd_inw(ahd, TARGID); |
| 9547 | | (ahd_inb(ahd, TARGID + 1) | ||
| 9548 | << 8); | ||
| 9549 | |||
| 9550 | targid_mask &= ~target_mask; | 9605 | targid_mask &= ~target_mask; |
| 9551 | ahd_outb(ahd, TARGID, targid_mask); | 9606 | ahd_outw(ahd, TARGID, targid_mask); |
| 9552 | ahd_outb(ahd, TARGID+1, | ||
| 9553 | (targid_mask >> 8)); | ||
| 9554 | ahd_update_scsiid(ahd, targid_mask); | 9607 | ahd_update_scsiid(ahd, targid_mask); |
| 9555 | } | 9608 | } |
| 9556 | } | 9609 | } |
| @@ -9651,7 +9704,7 @@ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused) | |||
| 9651 | 9704 | ||
| 9652 | cmd->cmd_valid = 0; | 9705 | cmd->cmd_valid = 0; |
| 9653 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, | 9706 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, |
| 9654 | ahd->shared_data_dmamap, | 9707 | ahd->shared_data_map.dmamap, |
| 9655 | ahd_targetcmd_offset(ahd, ahd->tqinfifonext), | 9708 | ahd_targetcmd_offset(ahd, ahd->tqinfifonext), |
| 9656 | sizeof(struct target_cmd), | 9709 | sizeof(struct target_cmd), |
| 9657 | BUS_DMASYNC_PREREAD); | 9710 | BUS_DMASYNC_PREREAD); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index d80bc5161fb1..91c4f7f484b1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 37 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 38 | * POSSIBILITY OF SUCH DAMAGES. | 38 | * POSSIBILITY OF SUCH DAMAGES. |
| 39 | * | 39 | * |
| 40 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $ | 40 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $ |
| 41 | * | 41 | * |
| 42 | * $FreeBSD$ | 42 | * $FreeBSD$ |
| 43 | */ | 43 | */ |
| @@ -522,12 +522,21 @@ do { \ | |||
| 522 | static __inline uint16_t | 522 | static __inline uint16_t |
| 523 | ahd_inw(struct ahd_softc *ahd, u_int port) | 523 | ahd_inw(struct ahd_softc *ahd, u_int port) |
| 524 | { | 524 | { |
| 525 | /* | ||
| 526 | * Read high byte first as some registers increment | ||
| 527 | * or have other side effects when the low byte is | ||
| 528 | * read. | ||
| 529 | */ | ||
| 525 | return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); | 530 | return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); |
| 526 | } | 531 | } |
| 527 | 532 | ||
| 528 | static __inline void | 533 | static __inline void |
| 529 | ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) | 534 | ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) |
| 530 | { | 535 | { |
| 536 | /* | ||
| 537 | * Write low byte first to accomodate registers | ||
| 538 | * such as PRGMCNT where the order maters. | ||
| 539 | */ | ||
| 531 | ahd_outb(ahd, port, value & 0xFF); | 540 | ahd_outb(ahd, port, value & 0xFF); |
| 532 | ahd_outb(ahd, port+1, (value >> 8) & 0xFF); | 541 | ahd_outb(ahd, port+1, (value >> 8) & 0xFF); |
| 533 | } | 542 | } |
| @@ -684,7 +693,7 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) | |||
| 684 | * Razor #528 | 693 | * Razor #528 |
| 685 | */ | 694 | */ |
| 686 | value = ahd_inb(ahd, offset); | 695 | value = ahd_inb(ahd, offset); |
| 687 | if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0) | 696 | if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0) |
| 688 | ahd_inb(ahd, MODE_PTR); | 697 | ahd_inb(ahd, MODE_PTR); |
| 689 | return (value); | 698 | return (value); |
| 690 | } | 699 | } |
| @@ -727,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) | |||
| 727 | static __inline void | 736 | static __inline void |
| 728 | ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) | 737 | ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) |
| 729 | { | 738 | { |
| 730 | struct hardware_scb *q_hscb; | 739 | struct hardware_scb *q_hscb; |
| 740 | struct map_node *q_hscb_map; | ||
| 731 | uint32_t saved_hscb_busaddr; | 741 | uint32_t saved_hscb_busaddr; |
| 732 | 742 | ||
| 733 | /* | 743 | /* |
| @@ -743,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) | |||
| 743 | * locate the correct SCB by SCB_TAG. | 753 | * locate the correct SCB by SCB_TAG. |
| 744 | */ | 754 | */ |
| 745 | q_hscb = ahd->next_queued_hscb; | 755 | q_hscb = ahd->next_queued_hscb; |
| 756 | q_hscb_map = ahd->next_queued_hscb_map; | ||
| 746 | saved_hscb_busaddr = q_hscb->hscb_busaddr; | 757 | saved_hscb_busaddr = q_hscb->hscb_busaddr; |
| 747 | memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); | 758 | memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); |
| 748 | q_hscb->hscb_busaddr = saved_hscb_busaddr; | 759 | q_hscb->hscb_busaddr = saved_hscb_busaddr; |
| @@ -750,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) | |||
| 750 | 761 | ||
| 751 | /* Now swap HSCB pointers. */ | 762 | /* Now swap HSCB pointers. */ |
| 752 | ahd->next_queued_hscb = scb->hscb; | 763 | ahd->next_queued_hscb = scb->hscb; |
| 764 | ahd->next_queued_hscb_map = scb->hscb_map; | ||
| 753 | scb->hscb = q_hscb; | 765 | scb->hscb = q_hscb; |
| 766 | scb->hscb_map = q_hscb_map; | ||
| 754 | 767 | ||
| 755 | /* Now define the mapping from tag to SCB in the scbindex */ | 768 | /* Now define the mapping from tag to SCB in the scbindex */ |
| 756 | ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; | 769 | ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; |
| @@ -824,8 +837,9 @@ static __inline int ahd_intr(struct ahd_softc *ahd); | |||
| 824 | static __inline void | 837 | static __inline void |
| 825 | ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) | 838 | ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) |
| 826 | { | 839 | { |
| 827 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, | 840 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, |
| 828 | /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); | 841 | /*offset*/0, |
| 842 | /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op); | ||
| 829 | } | 843 | } |
| 830 | 844 | ||
| 831 | static __inline void | 845 | static __inline void |
| @@ -834,7 +848,7 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) | |||
| 834 | #ifdef AHD_TARGET_MODE | 848 | #ifdef AHD_TARGET_MODE |
| 835 | if ((ahd->flags & AHD_TARGETROLE) != 0) { | 849 | if ((ahd->flags & AHD_TARGETROLE) != 0) { |
| 836 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, | 850 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, |
| 837 | ahd->shared_data_dmamap, | 851 | ahd->shared_data_map.dmamap, |
| 838 | ahd_targetcmd_offset(ahd, 0), | 852 | ahd_targetcmd_offset(ahd, 0), |
| 839 | sizeof(struct target_cmd) * AHD_TMODE_CMDS, | 853 | sizeof(struct target_cmd) * AHD_TMODE_CMDS, |
| 840 | op); | 854 | op); |
| @@ -854,17 +868,17 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) | |||
| 854 | u_int retval; | 868 | u_int retval; |
| 855 | 869 | ||
| 856 | retval = 0; | 870 | retval = 0; |
| 857 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, | 871 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, |
| 858 | /*offset*/ahd->qoutfifonext, /*len*/2, | 872 | /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), |
| 859 | BUS_DMASYNC_POSTREAD); | 873 | /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); |
| 860 | if ((ahd->qoutfifo[ahd->qoutfifonext] | 874 | if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag |
| 861 | & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) | 875 | == ahd->qoutfifonext_valid_tag) |
| 862 | retval |= AHD_RUN_QOUTFIFO; | 876 | retval |= AHD_RUN_QOUTFIFO; |
| 863 | #ifdef AHD_TARGET_MODE | 877 | #ifdef AHD_TARGET_MODE |
| 864 | if ((ahd->flags & AHD_TARGETROLE) != 0 | 878 | if ((ahd->flags & AHD_TARGETROLE) != 0 |
| 865 | && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { | 879 | && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { |
| 866 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, | 880 | ahd_dmamap_sync(ahd, ahd->shared_data_dmat, |
| 867 | ahd->shared_data_dmamap, | 881 | ahd->shared_data_map.dmamap, |
| 868 | ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), | 882 | ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), |
| 869 | /*len*/sizeof(struct target_cmd), | 883 | /*len*/sizeof(struct target_cmd), |
| 870 | BUS_DMASYNC_POSTREAD); | 884 | BUS_DMASYNC_POSTREAD); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 1c8f872e2dd4..2567e29960bd 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
| @@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, | |||
| 1468 | if ((tstate->auto_negotiate & mask) != 0) { | 1468 | if ((tstate->auto_negotiate & mask) != 0) { |
| 1469 | scb->flags |= SCB_AUTO_NEGOTIATE; | 1469 | scb->flags |= SCB_AUTO_NEGOTIATE; |
| 1470 | scb->hscb->control |= MK_MESSAGE; | 1470 | scb->hscb->control |= MK_MESSAGE; |
| 1471 | } else if (cmd->cmnd[0] == INQUIRY | ||
| 1472 | && (tinfo->curr.offset != 0 | ||
| 1473 | || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT | ||
| 1474 | || tinfo->curr.ppr_options != 0) | ||
| 1475 | && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) { | ||
| 1476 | /* | ||
| 1477 | * The SCSI spec requires inquiry | ||
| 1478 | * commands to complete without | ||
| 1479 | * reporting unit attention conditions. | ||
| 1480 | * Because of this, an inquiry command | ||
| 1481 | * that occurs just after a device is | ||
| 1482 | * reset will result in a data phase | ||
| 1483 | * with mismatched negotiated rates. | ||
| 1484 | * The core already forces a renegotiation | ||
| 1485 | * for reset events that are visible to | ||
| 1486 | * our controller or that we initiate, | ||
| 1487 | * but a third party device reset or a | ||
| 1488 | * hot-plug insertion can still cause this | ||
| 1489 | * issue. Therefore, we force a re-negotiation | ||
| 1490 | * for every inquiry command unless we | ||
| 1491 | * are async. | ||
| 1492 | */ | ||
| 1493 | scb->flags |= SCB_NEGOTIATE; | ||
| 1494 | scb->hscb->control |= MK_MESSAGE; | ||
| 1471 | } | 1495 | } |
| 1472 | 1496 | ||
| 1473 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { | 1497 | if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { |
| @@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
| 2058 | int paused; | 2082 | int paused; |
| 2059 | int wait; | 2083 | int wait; |
| 2060 | int disconnected; | 2084 | int disconnected; |
| 2085 | int found; | ||
| 2061 | ahd_mode_state saved_modes; | 2086 | ahd_mode_state saved_modes; |
| 2062 | unsigned long flags; | 2087 | unsigned long flags; |
| 2063 | 2088 | ||
| @@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
| 2176 | last_phase = ahd_inb(ahd, LASTPHASE); | 2201 | last_phase = ahd_inb(ahd, LASTPHASE); |
| 2177 | saved_scbptr = ahd_get_scbptr(ahd); | 2202 | saved_scbptr = ahd_get_scbptr(ahd); |
| 2178 | active_scbptr = saved_scbptr; | 2203 | active_scbptr = saved_scbptr; |
| 2179 | if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { | 2204 | if (disconnected && ((last_phase != P_BUSFREE) || |
| 2205 | (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) { | ||
| 2180 | struct scb *bus_scb; | 2206 | struct scb *bus_scb; |
| 2181 | 2207 | ||
| 2182 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); | 2208 | bus_scb = ahd_lookup_scb(ahd, active_scbptr); |
| @@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
| 2194 | * bus or is in the disconnected state. | 2220 | * bus or is in the disconnected state. |
| 2195 | */ | 2221 | */ |
| 2196 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); | 2222 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); |
| 2197 | if (last_phase != P_BUSFREE | 2223 | if (SCB_GET_TAG(pending_scb) == active_scbptr |
| 2198 | && (SCB_GET_TAG(pending_scb) == active_scbptr | ||
| 2199 | || (flag == SCB_DEVICE_RESET | 2224 | || (flag == SCB_DEVICE_RESET |
| 2200 | && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) { | 2225 | && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) { |
| 2201 | 2226 | ||
| 2202 | /* | 2227 | /* |
| 2203 | * We're active on the bus, so assert ATN | 2228 | * We're active on the bus, so assert ATN |
| 2204 | * and hope that the target responds. | 2229 | * and hope that the target responds. |
| 2205 | */ | 2230 | */ |
| 2206 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); | 2231 | pending_scb = ahd_lookup_scb(ahd, active_scbptr); |
| 2207 | pending_scb->flags |= SCB_RECOVERY_SCB|flag; | 2232 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; |
| 2208 | ahd_outb(ahd, MSG_OUT, HOST_MSG); | 2233 | ahd_outb(ahd, MSG_OUT, HOST_MSG); |
| 2209 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); | 2234 | ahd_outb(ahd, SCSISIGO, last_phase|ATNO); |
| 2210 | scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); | 2235 | scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n"); |
| 2211 | wait = TRUE; | 2236 | wait = TRUE; |
| 2237 | } else if (last_phase != P_BUSFREE | ||
| 2238 | && ahd_inb(ahd, SCSIPHASE) == 0) { | ||
| 2239 | /* | ||
| 2240 | * SCB is not identified, there | ||
| 2241 | * is no pending REQ, and the sequencer | ||
| 2242 | * has not seen a busfree. Looks like | ||
| 2243 | * a stuck connection waiting to | ||
| 2244 | * go busfree. Reset the bus. | ||
| 2245 | */ | ||
| 2246 | found = ahd_reset_channel(ahd, cmd->device->channel + 'A', | ||
| 2247 | /*Initiate Reset*/TRUE); | ||
| 2248 | printf("%s: Issued Channel %c Bus Reset. " | ||
| 2249 | "%d SCBs aborted\n", ahd_name(ahd), | ||
| 2250 | cmd->device->channel + 'A', found); | ||
| 2212 | } else if (disconnected) { | 2251 | } else if (disconnected) { |
| 2213 | 2252 | ||
| 2214 | /* | 2253 | /* |
| 2215 | * Actually re-queue this SCB in an attempt | 2254 | * Actually re-queue this SCB in an attempt |
| 2216 | * to select the device before it reconnects. | 2255 | * to select the device before it reconnects. |
| 2217 | */ | 2256 | */ |
| 2218 | pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; | 2257 | pending_scb->flags |= SCB_RECOVERY_SCB|flag; |
| 2219 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); | 2258 | ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); |
| 2220 | pending_scb->hscb->cdb_len = 0; | 2259 | pending_scb->hscb->cdb_len = 0; |
| 2221 | pending_scb->hscb->task_attribute = 0; | 2260 | pending_scb->hscb->task_attribute = 0; |
| @@ -2296,16 +2335,17 @@ done: | |||
| 2296 | timer.expires = jiffies + (5 * HZ); | 2335 | timer.expires = jiffies + (5 * HZ); |
| 2297 | timer.function = ahd_linux_sem_timeout; | 2336 | timer.function = ahd_linux_sem_timeout; |
| 2298 | add_timer(&timer); | 2337 | add_timer(&timer); |
| 2299 | printf("Recovery code sleeping\n"); | 2338 | printf("%s: Recovery code sleeping\n", ahd_name(ahd)); |
| 2300 | down(&ahd->platform_data->eh_sem); | 2339 | down(&ahd->platform_data->eh_sem); |
| 2301 | printf("Recovery code awake\n"); | 2340 | printf("%s: Recovery code awake\n", ahd_name(ahd)); |
| 2302 | ret = del_timer_sync(&timer); | 2341 | ret = del_timer_sync(&timer); |
| 2303 | if (ret == 0) { | 2342 | if (ret == 0) { |
| 2304 | printf("Timer Expired\n"); | 2343 | printf("%s: Timer Expired (active %d)\n", |
| 2344 | ahd_name(ahd), dev->active); | ||
| 2305 | retval = FAILED; | 2345 | retval = FAILED; |
| 2306 | } | 2346 | } |
| 2307 | } | 2347 | } |
| 2308 | ahd_unlock(ahd, &flags); | 2348 | ahd_unlock(ahd, &flags); |
| 2309 | return (retval); | 2349 | return (retval); |
| 2310 | } | 2350 | } |
| 2311 | 2351 | ||
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index bc44222d6cc3..cb74fccc8100 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h | |||
| @@ -252,7 +252,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec) | |||
| 252 | /***************************** SMP support ************************************/ | 252 | /***************************** SMP support ************************************/ |
| 253 | #include <linux/spinlock.h> | 253 | #include <linux/spinlock.h> |
| 254 | 254 | ||
| 255 | #define AIC79XX_DRIVER_VERSION "1.3.11" | 255 | #define AIC79XX_DRIVER_VERSION "3.0" |
| 256 | 256 | ||
| 257 | /*************************** Device Data Structures ***************************/ | 257 | /*************************** Device Data Structures ***************************/ |
| 258 | /* | 258 | /* |
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 2131db60018a..196a6344b037 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c | |||
| @@ -38,9 +38,7 @@ | |||
| 38 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 38 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 39 | * POSSIBILITY OF SUCH DAMAGES. | 39 | * POSSIBILITY OF SUCH DAMAGES. |
| 40 | * | 40 | * |
| 41 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $ | 41 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $ |
| 42 | * | ||
| 43 | * $FreeBSD$ | ||
| 44 | */ | 42 | */ |
| 45 | 43 | ||
| 46 | #ifdef __linux__ | 44 | #ifdef __linux__ |
| @@ -114,6 +112,13 @@ struct ahd_pci_identity ahd_pci_ident_table [] = | |||
| 114 | "Adaptec 29320ALP Ultra320 SCSI adapter", | 112 | "Adaptec 29320ALP Ultra320 SCSI adapter", |
| 115 | ahd_aic7901_setup | 113 | ahd_aic7901_setup |
| 116 | }, | 114 | }, |
| 115 | /* aic7901A based controllers */ | ||
| 116 | { | ||
| 117 | ID_AHA_29320LP, | ||
| 118 | ID_ALL_MASK, | ||
| 119 | "Adaptec 29320LP Ultra320 SCSI adapter", | ||
| 120 | ahd_aic7901A_setup | ||
| 121 | }, | ||
| 117 | /* aic7902 based controllers */ | 122 | /* aic7902 based controllers */ |
| 118 | { | 123 | { |
| 119 | ID_AHA_29320, | 124 | ID_AHA_29320, |
| @@ -128,12 +133,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] = | |||
| 128 | ahd_aic7902_setup | 133 | ahd_aic7902_setup |
| 129 | }, | 134 | }, |
| 130 | { | 135 | { |
| 131 | ID_AHA_29320LP, | ||
| 132 | ID_ALL_MASK, | ||
| 133 | "Adaptec 29320LP Ultra320 SCSI adapter", | ||
| 134 | ahd_aic7901A_setup | ||
| 135 | }, | ||
| 136 | { | ||
| 137 | ID_AHA_39320, | 136 | ID_AHA_39320, |
| 138 | ID_ALL_MASK, | 137 | ID_ALL_MASK, |
| 139 | "Adaptec 39320 Ultra320 SCSI adapter", | 138 | "Adaptec 39320 Ultra320 SCSI adapter", |
| @@ -146,6 +145,12 @@ struct ahd_pci_identity ahd_pci_ident_table [] = | |||
| 146 | ahd_aic7902_setup | 145 | ahd_aic7902_setup |
| 147 | }, | 146 | }, |
| 148 | { | 147 | { |
| 148 | ID_AHA_39320_B_DELL, | ||
| 149 | ID_ALL_MASK, | ||
| 150 | "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter", | ||
| 151 | ahd_aic7902_setup | ||
| 152 | }, | ||
| 153 | { | ||
| 149 | ID_AHA_39320A, | 154 | ID_AHA_39320A, |
| 150 | ID_ALL_MASK, | 155 | ID_ALL_MASK, |
| 151 | "Adaptec 39320A Ultra320 SCSI adapter", | 156 | "Adaptec 39320A Ultra320 SCSI adapter", |
| @@ -668,6 +673,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) | |||
| 668 | * Now set the termination based on what we found. | 673 | * Now set the termination based on what we found. |
| 669 | */ | 674 | */ |
| 670 | sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; | 675 | sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; |
| 676 | ahd->flags &= ~AHD_TERM_ENB_A; | ||
| 671 | if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { | 677 | if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { |
| 672 | ahd->flags |= AHD_TERM_ENB_A; | 678 | ahd->flags |= AHD_TERM_ENB_A; |
| 673 | sxfrctl1 |= STPWEN; | 679 | sxfrctl1 |= STPWEN; |
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h index b5cfeabdfecf..da45153668c7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.h +++ b/drivers/scsi/aic7xxx/aic79xx_pci.h | |||
| @@ -53,14 +53,15 @@ | |||
| 53 | #define ID_AHA_29320ALP 0x8017900500449005ull | 53 | #define ID_AHA_29320ALP 0x8017900500449005ull |
| 54 | 54 | ||
| 55 | #define ID_AIC7901A 0x801E9005FFFF9005ull | 55 | #define ID_AIC7901A 0x801E9005FFFF9005ull |
| 56 | #define ID_AHA_29320 0x8012900500429005ull | ||
| 57 | #define ID_AHA_29320B 0x8013900500439005ull | ||
| 58 | #define ID_AHA_29320LP 0x8014900500449005ull | 56 | #define ID_AHA_29320LP 0x8014900500449005ull |
| 59 | 57 | ||
| 60 | #define ID_AIC7902 0x801F9005FFFF9005ull | 58 | #define ID_AIC7902 0x801F9005FFFF9005ull |
| 61 | #define ID_AIC7902_B 0x801D9005FFFF9005ull | 59 | #define ID_AIC7902_B 0x801D9005FFFF9005ull |
| 62 | #define ID_AHA_39320 0x8010900500409005ull | 60 | #define ID_AHA_39320 0x8010900500409005ull |
| 61 | #define ID_AHA_29320 0x8012900500429005ull | ||
| 62 | #define ID_AHA_29320B 0x8013900500439005ull | ||
| 63 | #define ID_AHA_39320_B 0x8015900500409005ull | 63 | #define ID_AHA_39320_B 0x8015900500409005ull |
| 64 | #define ID_AHA_39320_B_DELL 0x8015900501681028ull | ||
| 64 | #define ID_AHA_39320A 0x8016900500409005ull | 65 | #define ID_AHA_39320A 0x8016900500409005ull |
| 65 | #define ID_AHA_39320D 0x8011900500419005ull | 66 | #define ID_AHA_39320D 0x8011900500419005ull |
| 66 | #define ID_AHA_39320D_B 0x801C900500419005ull | 67 | #define ID_AHA_39320D_B 0x801C900500419005ull |
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped index c01ac39090d9..8763b158856b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | * DO NOT EDIT - This file is automatically generated | 2 | * DO NOT EDIT - This file is automatically generated |
| 3 | * from the following source files: | 3 | * from the following source files: |
| 4 | * | 4 | * |
| 5 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ | 5 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $ |
| 6 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ | 6 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $ |
| 7 | */ | 7 | */ |
| 8 | typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); | 8 | typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); |
| 9 | typedef struct ahd_reg_parse_entry { | 9 | typedef struct ahd_reg_parse_entry { |
| @@ -83,17 +83,17 @@ ahd_reg_print_t ahd_hs_mailbox_print; | |||
| 83 | #endif | 83 | #endif |
| 84 | 84 | ||
| 85 | #if AIC_DEBUG_REGISTERS | 85 | #if AIC_DEBUG_REGISTERS |
| 86 | ahd_reg_print_t ahd_clrseqintstat_print; | 86 | ahd_reg_print_t ahd_seqintstat_print; |
| 87 | #else | 87 | #else |
| 88 | #define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ | 88 | #define ahd_seqintstat_print(regvalue, cur_col, wrap) \ |
| 89 | ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) | 89 | ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) |
| 90 | #endif | 90 | #endif |
| 91 | 91 | ||
| 92 | #if AIC_DEBUG_REGISTERS | 92 | #if AIC_DEBUG_REGISTERS |
| 93 | ahd_reg_print_t ahd_seqintstat_print; | 93 | ahd_reg_print_t ahd_clrseqintstat_print; |
| 94 | #else | 94 | #else |
| 95 | #define ahd_seqintstat_print(regvalue, cur_col, wrap) \ | 95 | #define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ |
| 96 | ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) | 96 | ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) |
| 97 | #endif | 97 | #endif |
| 98 | 98 | ||
| 99 | #if AIC_DEBUG_REGISTERS | 99 | #if AIC_DEBUG_REGISTERS |
| @@ -412,17 +412,17 @@ ahd_reg_print_t ahd_sxfrctl0_print; | |||
| 412 | #endif | 412 | #endif |
| 413 | 413 | ||
| 414 | #if AIC_DEBUG_REGISTERS | 414 | #if AIC_DEBUG_REGISTERS |
| 415 | ahd_reg_print_t ahd_businitid_print; | 415 | ahd_reg_print_t ahd_dlcount_print; |
| 416 | #else | 416 | #else |
| 417 | #define ahd_businitid_print(regvalue, cur_col, wrap) \ | 417 | #define ahd_dlcount_print(regvalue, cur_col, wrap) \ |
| 418 | ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) | 418 | ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) |
| 419 | #endif | 419 | #endif |
| 420 | 420 | ||
| 421 | #if AIC_DEBUG_REGISTERS | 421 | #if AIC_DEBUG_REGISTERS |
| 422 | ahd_reg_print_t ahd_dlcount_print; | 422 | ahd_reg_print_t ahd_businitid_print; |
| 423 | #else | 423 | #else |
| 424 | #define ahd_dlcount_print(regvalue, cur_col, wrap) \ | 424 | #define ahd_businitid_print(regvalue, cur_col, wrap) \ |
| 425 | ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) | 425 | ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) |
| 426 | #endif | 426 | #endif |
| 427 | 427 | ||
| 428 | #if AIC_DEBUG_REGISTERS | 428 | #if AIC_DEBUG_REGISTERS |
| @@ -517,13 +517,6 @@ ahd_reg_print_t ahd_selid_print; | |||
| 517 | #endif | 517 | #endif |
| 518 | 518 | ||
| 519 | #if AIC_DEBUG_REGISTERS | 519 | #if AIC_DEBUG_REGISTERS |
| 520 | ahd_reg_print_t ahd_sblkctl_print; | ||
| 521 | #else | ||
| 522 | #define ahd_sblkctl_print(regvalue, cur_col, wrap) \ | ||
| 523 | ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) | ||
| 524 | #endif | ||
| 525 | |||
| 526 | #if AIC_DEBUG_REGISTERS | ||
| 527 | ahd_reg_print_t ahd_optionmode_print; | 520 | ahd_reg_print_t ahd_optionmode_print; |
| 528 | #else | 521 | #else |
| 529 | #define ahd_optionmode_print(regvalue, cur_col, wrap) \ | 522 | #define ahd_optionmode_print(regvalue, cur_col, wrap) \ |
| @@ -531,10 +524,10 @@ ahd_reg_print_t ahd_optionmode_print; | |||
| 531 | #endif | 524 | #endif |
| 532 | 525 | ||
| 533 | #if AIC_DEBUG_REGISTERS | 526 | #if AIC_DEBUG_REGISTERS |
| 534 | ahd_reg_print_t ahd_sstat0_print; | 527 | ahd_reg_print_t ahd_sblkctl_print; |
| 535 | #else | 528 | #else |
| 536 | #define ahd_sstat0_print(regvalue, cur_col, wrap) \ | 529 | #define ahd_sblkctl_print(regvalue, cur_col, wrap) \ |
| 537 | ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) | 530 | ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) |
| 538 | #endif | 531 | #endif |
| 539 | 532 | ||
| 540 | #if AIC_DEBUG_REGISTERS | 533 | #if AIC_DEBUG_REGISTERS |
| @@ -545,6 +538,13 @@ ahd_reg_print_t ahd_clrsint0_print; | |||
| 545 | #endif | 538 | #endif |
| 546 | 539 | ||
| 547 | #if AIC_DEBUG_REGISTERS | 540 | #if AIC_DEBUG_REGISTERS |
| 541 | ahd_reg_print_t ahd_sstat0_print; | ||
| 542 | #else | ||
| 543 | #define ahd_sstat0_print(regvalue, cur_col, wrap) \ | ||
| 544 | ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) | ||
| 545 | #endif | ||
| 546 | |||
| 547 | #if AIC_DEBUG_REGISTERS | ||
| 548 | ahd_reg_print_t ahd_simode0_print; | 548 | ahd_reg_print_t ahd_simode0_print; |
| 549 | #else | 549 | #else |
| 550 | #define ahd_simode0_print(regvalue, cur_col, wrap) \ | 550 | #define ahd_simode0_print(regvalue, cur_col, wrap) \ |
| @@ -573,17 +573,17 @@ ahd_reg_print_t ahd_sstat2_print; | |||
| 573 | #endif | 573 | #endif |
| 574 | 574 | ||
| 575 | #if AIC_DEBUG_REGISTERS | 575 | #if AIC_DEBUG_REGISTERS |
| 576 | ahd_reg_print_t ahd_clrsint2_print; | 576 | ahd_reg_print_t ahd_simode2_print; |
| 577 | #else | 577 | #else |
| 578 | #define ahd_clrsint2_print(regvalue, cur_col, wrap) \ | 578 | #define ahd_simode2_print(regvalue, cur_col, wrap) \ |
| 579 | ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) | 579 | ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) |
| 580 | #endif | 580 | #endif |
| 581 | 581 | ||
| 582 | #if AIC_DEBUG_REGISTERS | 582 | #if AIC_DEBUG_REGISTERS |
| 583 | ahd_reg_print_t ahd_simode2_print; | 583 | ahd_reg_print_t ahd_clrsint2_print; |
| 584 | #else | 584 | #else |
| 585 | #define ahd_simode2_print(regvalue, cur_col, wrap) \ | 585 | #define ahd_clrsint2_print(regvalue, cur_col, wrap) \ |
| 586 | ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) | 586 | ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) |
| 587 | #endif | 587 | #endif |
| 588 | 588 | ||
| 589 | #if AIC_DEBUG_REGISTERS | 589 | #if AIC_DEBUG_REGISTERS |
| @@ -685,13 +685,6 @@ ahd_reg_print_t ahd_clrsint3_print; | |||
| 685 | #endif | 685 | #endif |
| 686 | 686 | ||
| 687 | #if AIC_DEBUG_REGISTERS | 687 | #if AIC_DEBUG_REGISTERS |
| 688 | ahd_reg_print_t ahd_lqomode0_print; | ||
| 689 | #else | ||
| 690 | #define ahd_lqomode0_print(regvalue, cur_col, wrap) \ | ||
| 691 | ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) | ||
| 692 | #endif | ||
| 693 | |||
| 694 | #if AIC_DEBUG_REGISTERS | ||
| 695 | ahd_reg_print_t ahd_lqostat0_print; | 688 | ahd_reg_print_t ahd_lqostat0_print; |
| 696 | #else | 689 | #else |
| 697 | #define ahd_lqostat0_print(regvalue, cur_col, wrap) \ | 690 | #define ahd_lqostat0_print(regvalue, cur_col, wrap) \ |
| @@ -706,6 +699,20 @@ ahd_reg_print_t ahd_clrlqoint0_print; | |||
| 706 | #endif | 699 | #endif |
| 707 | 700 | ||
| 708 | #if AIC_DEBUG_REGISTERS | 701 | #if AIC_DEBUG_REGISTERS |
| 702 | ahd_reg_print_t ahd_lqomode0_print; | ||
| 703 | #else | ||
| 704 | #define ahd_lqomode0_print(regvalue, cur_col, wrap) \ | ||
| 705 | ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) | ||
| 706 | #endif | ||
| 707 | |||
| 708 | #if AIC_DEBUG_REGISTERS | ||
| 709 | ahd_reg_print_t ahd_lqomode1_print; | ||
| 710 | #else | ||
| 711 | #define ahd_lqomode1_print(regvalue, cur_col, wrap) \ | ||
| 712 | ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) | ||
| 713 | #endif | ||
| 714 | |||
| 715 | #if AIC_DEBUG_REGISTERS | ||
| 709 | ahd_reg_print_t ahd_lqostat1_print; | 716 | ahd_reg_print_t ahd_lqostat1_print; |
| 710 | #else | 717 | #else |
| 711 | #define ahd_lqostat1_print(regvalue, cur_col, wrap) \ | 718 | #define ahd_lqostat1_print(regvalue, cur_col, wrap) \ |
| @@ -720,13 +727,6 @@ ahd_reg_print_t ahd_clrlqoint1_print; | |||
| 720 | #endif | 727 | #endif |
| 721 | 728 | ||
| 722 | #if AIC_DEBUG_REGISTERS | 729 | #if AIC_DEBUG_REGISTERS |
| 723 | ahd_reg_print_t ahd_lqomode1_print; | ||
| 724 | #else | ||
| 725 | #define ahd_lqomode1_print(regvalue, cur_col, wrap) \ | ||
| 726 | ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) | ||
| 727 | #endif | ||
| 728 | |||
| 729 | #if AIC_DEBUG_REGISTERS | ||
| 730 | ahd_reg_print_t ahd_lqostat2_print; | 730 | ahd_reg_print_t ahd_lqostat2_print; |
| 731 | #else | 731 | #else |
| 732 | #define ahd_lqostat2_print(regvalue, cur_col, wrap) \ | 732 | #define ahd_lqostat2_print(regvalue, cur_col, wrap) \ |
| @@ -909,17 +909,17 @@ ahd_reg_print_t ahd_annexcol_print; | |||
| 909 | #endif | 909 | #endif |
| 910 | 910 | ||
| 911 | #if AIC_DEBUG_REGISTERS | 911 | #if AIC_DEBUG_REGISTERS |
| 912 | ahd_reg_print_t ahd_scschkn_print; | 912 | ahd_reg_print_t ahd_annexdat_print; |
| 913 | #else | 913 | #else |
| 914 | #define ahd_scschkn_print(regvalue, cur_col, wrap) \ | 914 | #define ahd_annexdat_print(regvalue, cur_col, wrap) \ |
| 915 | ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) | 915 | ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) |
| 916 | #endif | 916 | #endif |
| 917 | 917 | ||
| 918 | #if AIC_DEBUG_REGISTERS | 918 | #if AIC_DEBUG_REGISTERS |
| 919 | ahd_reg_print_t ahd_annexdat_print; | 919 | ahd_reg_print_t ahd_scschkn_print; |
| 920 | #else | 920 | #else |
| 921 | #define ahd_annexdat_print(regvalue, cur_col, wrap) \ | 921 | #define ahd_scschkn_print(regvalue, cur_col, wrap) \ |
| 922 | ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) | 922 | ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) |
| 923 | #endif | 923 | #endif |
| 924 | 924 | ||
| 925 | #if AIC_DEBUG_REGISTERS | 925 | #if AIC_DEBUG_REGISTERS |
| @@ -1000,17 +1000,17 @@ ahd_reg_print_t ahd_pll400ctl1_print; | |||
| 1000 | #endif | 1000 | #endif |
| 1001 | 1001 | ||
| 1002 | #if AIC_DEBUG_REGISTERS | 1002 | #if AIC_DEBUG_REGISTERS |
| 1003 | ahd_reg_print_t ahd_pll400cnt0_print; | 1003 | ahd_reg_print_t ahd_unfairness_print; |
| 1004 | #else | 1004 | #else |
| 1005 | #define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ | 1005 | #define ahd_unfairness_print(regvalue, cur_col, wrap) \ |
| 1006 | ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) | 1006 | ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) |
| 1007 | #endif | 1007 | #endif |
| 1008 | 1008 | ||
| 1009 | #if AIC_DEBUG_REGISTERS | 1009 | #if AIC_DEBUG_REGISTERS |
| 1010 | ahd_reg_print_t ahd_unfairness_print; | 1010 | ahd_reg_print_t ahd_pll400cnt0_print; |
| 1011 | #else | 1011 | #else |
| 1012 | #define ahd_unfairness_print(regvalue, cur_col, wrap) \ | 1012 | #define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ |
| 1013 | ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) | 1013 | ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) |
| 1014 | #endif | 1014 | #endif |
| 1015 | 1015 | ||
| 1016 | #if AIC_DEBUG_REGISTERS | 1016 | #if AIC_DEBUG_REGISTERS |
| @@ -1056,13 +1056,6 @@ ahd_reg_print_t ahd_hodmaen_print; | |||
| 1056 | #endif | 1056 | #endif |
| 1057 | 1057 | ||
| 1058 | #if AIC_DEBUG_REGISTERS | 1058 | #if AIC_DEBUG_REGISTERS |
| 1059 | ahd_reg_print_t ahd_sghaddr_print; | ||
| 1060 | #else | ||
| 1061 | #define ahd_sghaddr_print(regvalue, cur_col, wrap) \ | ||
| 1062 | ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) | ||
| 1063 | #endif | ||
| 1064 | |||
| 1065 | #if AIC_DEBUG_REGISTERS | ||
| 1066 | ahd_reg_print_t ahd_scbhaddr_print; | 1059 | ahd_reg_print_t ahd_scbhaddr_print; |
| 1067 | #else | 1060 | #else |
| 1068 | #define ahd_scbhaddr_print(regvalue, cur_col, wrap) \ | 1061 | #define ahd_scbhaddr_print(regvalue, cur_col, wrap) \ |
| @@ -1070,10 +1063,10 @@ ahd_reg_print_t ahd_scbhaddr_print; | |||
| 1070 | #endif | 1063 | #endif |
| 1071 | 1064 | ||
| 1072 | #if AIC_DEBUG_REGISTERS | 1065 | #if AIC_DEBUG_REGISTERS |
| 1073 | ahd_reg_print_t ahd_sghcnt_print; | 1066 | ahd_reg_print_t ahd_sghaddr_print; |
| 1074 | #else | 1067 | #else |
| 1075 | #define ahd_sghcnt_print(regvalue, cur_col, wrap) \ | 1068 | #define ahd_sghaddr_print(regvalue, cur_col, wrap) \ |
| 1076 | ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) | 1069 | ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) |
| 1077 | #endif | 1070 | #endif |
| 1078 | 1071 | ||
| 1079 | #if AIC_DEBUG_REGISTERS | 1072 | #if AIC_DEBUG_REGISTERS |
| @@ -1084,6 +1077,13 @@ ahd_reg_print_t ahd_scbhcnt_print; | |||
| 1084 | #endif | 1077 | #endif |
| 1085 | 1078 | ||
| 1086 | #if AIC_DEBUG_REGISTERS | 1079 | #if AIC_DEBUG_REGISTERS |
| 1080 | ahd_reg_print_t ahd_sghcnt_print; | ||
| 1081 | #else | ||
| 1082 | #define ahd_sghcnt_print(regvalue, cur_col, wrap) \ | ||
| 1083 | ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) | ||
| 1084 | #endif | ||
| 1085 | |||
| 1086 | #if AIC_DEBUG_REGISTERS | ||
| 1087 | ahd_reg_print_t ahd_dff_thrsh_print; | 1087 | ahd_reg_print_t ahd_dff_thrsh_print; |
| 1088 | #else | 1088 | #else |
| 1089 | #define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \ | 1089 | #define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \ |
| @@ -1154,13 +1154,6 @@ ahd_reg_print_t ahd_nsenable_print; | |||
| 1154 | #endif | 1154 | #endif |
| 1155 | 1155 | ||
| 1156 | #if AIC_DEBUG_REGISTERS | 1156 | #if AIC_DEBUG_REGISTERS |
| 1157 | ahd_reg_print_t ahd_dchrxmsg1_print; | ||
| 1158 | #else | ||
| 1159 | #define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ | ||
| 1160 | ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) | ||
| 1161 | #endif | ||
| 1162 | |||
| 1163 | #if AIC_DEBUG_REGISTERS | ||
| 1164 | ahd_reg_print_t ahd_cmcrxmsg1_print; | 1157 | ahd_reg_print_t ahd_cmcrxmsg1_print; |
| 1165 | #else | 1158 | #else |
| 1166 | #define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \ | 1159 | #define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \ |
| @@ -1168,17 +1161,17 @@ ahd_reg_print_t ahd_cmcrxmsg1_print; | |||
| 1168 | #endif | 1161 | #endif |
| 1169 | 1162 | ||
| 1170 | #if AIC_DEBUG_REGISTERS | 1163 | #if AIC_DEBUG_REGISTERS |
| 1171 | ahd_reg_print_t ahd_dchrxmsg2_print; | 1164 | ahd_reg_print_t ahd_dchrxmsg1_print; |
| 1172 | #else | 1165 | #else |
| 1173 | #define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ | 1166 | #define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ |
| 1174 | ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) | 1167 | ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) |
| 1175 | #endif | 1168 | #endif |
| 1176 | 1169 | ||
| 1177 | #if AIC_DEBUG_REGISTERS | 1170 | #if AIC_DEBUG_REGISTERS |
| 1178 | ahd_reg_print_t ahd_ovlyrxmsg2_print; | 1171 | ahd_reg_print_t ahd_dchrxmsg2_print; |
| 1179 | #else | 1172 | #else |
| 1180 | #define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ | 1173 | #define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ |
| 1181 | ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) | 1174 | ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) |
| 1182 | #endif | 1175 | #endif |
| 1183 | 1176 | ||
| 1184 | #if AIC_DEBUG_REGISTERS | 1177 | #if AIC_DEBUG_REGISTERS |
| @@ -1196,6 +1189,13 @@ ahd_reg_print_t ahd_ost_print; | |||
| 1196 | #endif | 1189 | #endif |
| 1197 | 1190 | ||
| 1198 | #if AIC_DEBUG_REGISTERS | 1191 | #if AIC_DEBUG_REGISTERS |
| 1192 | ahd_reg_print_t ahd_ovlyrxmsg2_print; | ||
| 1193 | #else | ||
| 1194 | #define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ | ||
| 1195 | ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) | ||
| 1196 | #endif | ||
| 1197 | |||
| 1198 | #if AIC_DEBUG_REGISTERS | ||
| 1199 | ahd_reg_print_t ahd_dchrxmsg3_print; | 1199 | ahd_reg_print_t ahd_dchrxmsg3_print; |
| 1200 | #else | 1200 | #else |
| 1201 | #define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \ | 1201 | #define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \ |
| @@ -1203,6 +1203,13 @@ ahd_reg_print_t ahd_dchrxmsg3_print; | |||
| 1203 | #endif | 1203 | #endif |
| 1204 | 1204 | ||
| 1205 | #if AIC_DEBUG_REGISTERS | 1205 | #if AIC_DEBUG_REGISTERS |
| 1206 | ahd_reg_print_t ahd_ovlyrxmsg3_print; | ||
| 1207 | #else | ||
| 1208 | #define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ | ||
| 1209 | ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) | ||
| 1210 | #endif | ||
| 1211 | |||
| 1212 | #if AIC_DEBUG_REGISTERS | ||
| 1206 | ahd_reg_print_t ahd_cmcrxmsg3_print; | 1213 | ahd_reg_print_t ahd_cmcrxmsg3_print; |
| 1207 | #else | 1214 | #else |
| 1208 | #define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \ | 1215 | #define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \ |
| @@ -1217,13 +1224,6 @@ ahd_reg_print_t ahd_pcixctl_print; | |||
| 1217 | #endif | 1224 | #endif |
| 1218 | 1225 | ||
| 1219 | #if AIC_DEBUG_REGISTERS | 1226 | #if AIC_DEBUG_REGISTERS |
| 1220 | ahd_reg_print_t ahd_ovlyrxmsg3_print; | ||
| 1221 | #else | ||
| 1222 | #define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ | ||
| 1223 | ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) | ||
| 1224 | #endif | ||
| 1225 | |||
| 1226 | #if AIC_DEBUG_REGISTERS | ||
| 1227 | ahd_reg_print_t ahd_ovlyseqbcnt_print; | 1227 | ahd_reg_print_t ahd_ovlyseqbcnt_print; |
| 1228 | #else | 1228 | #else |
| 1229 | #define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \ | 1229 | #define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \ |
| @@ -1231,13 +1231,6 @@ ahd_reg_print_t ahd_ovlyseqbcnt_print; | |||
| 1231 | #endif | 1231 | #endif |
| 1232 | 1232 | ||
| 1233 | #if AIC_DEBUG_REGISTERS | 1233 | #if AIC_DEBUG_REGISTERS |
| 1234 | ahd_reg_print_t ahd_cmcseqbcnt_print; | ||
| 1235 | #else | ||
| 1236 | #define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ | ||
| 1237 | ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) | ||
| 1238 | #endif | ||
| 1239 | |||
| 1240 | #if AIC_DEBUG_REGISTERS | ||
| 1241 | ahd_reg_print_t ahd_dchseqbcnt_print; | 1234 | ahd_reg_print_t ahd_dchseqbcnt_print; |
| 1242 | #else | 1235 | #else |
| 1243 | #define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \ | 1236 | #define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \ |
| @@ -1245,17 +1238,17 @@ ahd_reg_print_t ahd_dchseqbcnt_print; | |||
| 1245 | #endif | 1238 | #endif |
| 1246 | 1239 | ||
| 1247 | #if AIC_DEBUG_REGISTERS | 1240 | #if AIC_DEBUG_REGISTERS |
| 1248 | ahd_reg_print_t ahd_cmcspltstat0_print; | 1241 | ahd_reg_print_t ahd_cmcseqbcnt_print; |
| 1249 | #else | 1242 | #else |
| 1250 | #define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ | 1243 | #define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ |
| 1251 | ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) | 1244 | ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) |
| 1252 | #endif | 1245 | #endif |
| 1253 | 1246 | ||
| 1254 | #if AIC_DEBUG_REGISTERS | 1247 | #if AIC_DEBUG_REGISTERS |
| 1255 | ahd_reg_print_t ahd_ovlyspltstat0_print; | 1248 | ahd_reg_print_t ahd_cmcspltstat0_print; |
| 1256 | #else | 1249 | #else |
| 1257 | #define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ | 1250 | #define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ |
| 1258 | ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) | 1251 | ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) |
| 1259 | #endif | 1252 | #endif |
| 1260 | 1253 | ||
| 1261 | #if AIC_DEBUG_REGISTERS | 1254 | #if AIC_DEBUG_REGISTERS |
| @@ -1266,10 +1259,10 @@ ahd_reg_print_t ahd_dchspltstat0_print; | |||
| 1266 | #endif | 1259 | #endif |
| 1267 | 1260 | ||
| 1268 | #if AIC_DEBUG_REGISTERS | 1261 | #if AIC_DEBUG_REGISTERS |
| 1269 | ahd_reg_print_t ahd_dchspltstat1_print; | 1262 | ahd_reg_print_t ahd_ovlyspltstat0_print; |
| 1270 | #else | 1263 | #else |
| 1271 | #define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ | 1264 | #define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ |
| 1272 | ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) | 1265 | ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) |
| 1273 | #endif | 1266 | #endif |
| 1274 | 1267 | ||
| 1275 | #if AIC_DEBUG_REGISTERS | 1268 | #if AIC_DEBUG_REGISTERS |
| @@ -1287,6 +1280,13 @@ ahd_reg_print_t ahd_ovlyspltstat1_print; | |||
| 1287 | #endif | 1280 | #endif |
| 1288 | 1281 | ||
| 1289 | #if AIC_DEBUG_REGISTERS | 1282 | #if AIC_DEBUG_REGISTERS |
| 1283 | ahd_reg_print_t ahd_dchspltstat1_print; | ||
| 1284 | #else | ||
| 1285 | #define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ | ||
| 1286 | ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) | ||
| 1287 | #endif | ||
| 1288 | |||
| 1289 | #if AIC_DEBUG_REGISTERS | ||
| 1290 | ahd_reg_print_t ahd_sgrxmsg0_print; | 1290 | ahd_reg_print_t ahd_sgrxmsg0_print; |
| 1291 | #else | 1291 | #else |
| 1292 | #define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \ | 1292 | #define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \ |
| @@ -1378,17 +1378,17 @@ ahd_reg_print_t ahd_sgspltstat0_print; | |||
| 1378 | #endif | 1378 | #endif |
| 1379 | 1379 | ||
| 1380 | #if AIC_DEBUG_REGISTERS | 1380 | #if AIC_DEBUG_REGISTERS |
| 1381 | ahd_reg_print_t ahd_sfunct_print; | 1381 | ahd_reg_print_t ahd_sgspltstat1_print; |
| 1382 | #else | 1382 | #else |
| 1383 | #define ahd_sfunct_print(regvalue, cur_col, wrap) \ | 1383 | #define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ |
| 1384 | ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) | 1384 | ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) |
| 1385 | #endif | 1385 | #endif |
| 1386 | 1386 | ||
| 1387 | #if AIC_DEBUG_REGISTERS | 1387 | #if AIC_DEBUG_REGISTERS |
| 1388 | ahd_reg_print_t ahd_sgspltstat1_print; | 1388 | ahd_reg_print_t ahd_sfunct_print; |
| 1389 | #else | 1389 | #else |
| 1390 | #define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ | 1390 | #define ahd_sfunct_print(regvalue, cur_col, wrap) \ |
| 1391 | ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) | 1391 | ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) |
| 1392 | #endif | 1392 | #endif |
| 1393 | 1393 | ||
| 1394 | #if AIC_DEBUG_REGISTERS | 1394 | #if AIC_DEBUG_REGISTERS |
| @@ -1504,17 +1504,17 @@ ahd_reg_print_t ahd_ccsgaddr_print; | |||
| 1504 | #endif | 1504 | #endif |
| 1505 | 1505 | ||
| 1506 | #if AIC_DEBUG_REGISTERS | 1506 | #if AIC_DEBUG_REGISTERS |
| 1507 | ahd_reg_print_t ahd_ccscbaddr_print; | 1507 | ahd_reg_print_t ahd_ccscbadr_bk_print; |
| 1508 | #else | 1508 | #else |
| 1509 | #define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ | 1509 | #define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ |
| 1510 | ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) | 1510 | ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) |
| 1511 | #endif | 1511 | #endif |
| 1512 | 1512 | ||
| 1513 | #if AIC_DEBUG_REGISTERS | 1513 | #if AIC_DEBUG_REGISTERS |
| 1514 | ahd_reg_print_t ahd_ccscbadr_bk_print; | 1514 | ahd_reg_print_t ahd_ccscbaddr_print; |
| 1515 | #else | 1515 | #else |
| 1516 | #define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ | 1516 | #define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ |
| 1517 | ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) | 1517 | ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) |
| 1518 | #endif | 1518 | #endif |
| 1519 | 1519 | ||
| 1520 | #if AIC_DEBUG_REGISTERS | 1520 | #if AIC_DEBUG_REGISTERS |
| @@ -1525,17 +1525,17 @@ ahd_reg_print_t ahd_cmc_rambist_print; | |||
| 1525 | #endif | 1525 | #endif |
| 1526 | 1526 | ||
| 1527 | #if AIC_DEBUG_REGISTERS | 1527 | #if AIC_DEBUG_REGISTERS |
| 1528 | ahd_reg_print_t ahd_ccsgctl_print; | 1528 | ahd_reg_print_t ahd_ccscbctl_print; |
| 1529 | #else | 1529 | #else |
| 1530 | #define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ | 1530 | #define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ |
| 1531 | ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) | 1531 | ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) |
| 1532 | #endif | 1532 | #endif |
| 1533 | 1533 | ||
| 1534 | #if AIC_DEBUG_REGISTERS | 1534 | #if AIC_DEBUG_REGISTERS |
| 1535 | ahd_reg_print_t ahd_ccscbctl_print; | 1535 | ahd_reg_print_t ahd_ccsgctl_print; |
| 1536 | #else | 1536 | #else |
| 1537 | #define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ | 1537 | #define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ |
| 1538 | ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) | 1538 | ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) |
| 1539 | #endif | 1539 | #endif |
| 1540 | 1540 | ||
| 1541 | #if AIC_DEBUG_REGISTERS | 1541 | #if AIC_DEBUG_REGISTERS |
| @@ -1707,13 +1707,6 @@ ahd_reg_print_t ahd_wrtbiascalc_print; | |||
| 1707 | #endif | 1707 | #endif |
| 1708 | 1708 | ||
| 1709 | #if AIC_DEBUG_REGISTERS | 1709 | #if AIC_DEBUG_REGISTERS |
| 1710 | ahd_reg_print_t ahd_dfptrs_print; | ||
| 1711 | #else | ||
| 1712 | #define ahd_dfptrs_print(regvalue, cur_col, wrap) \ | ||
| 1713 | ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) | ||
| 1714 | #endif | ||
| 1715 | |||
| 1716 | #if AIC_DEBUG_REGISTERS | ||
| 1717 | ahd_reg_print_t ahd_rcvrbiascalc_print; | 1710 | ahd_reg_print_t ahd_rcvrbiascalc_print; |
| 1718 | #else | 1711 | #else |
| 1719 | #define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \ | 1712 | #define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \ |
| @@ -1721,10 +1714,10 @@ ahd_reg_print_t ahd_rcvrbiascalc_print; | |||
| 1721 | #endif | 1714 | #endif |
| 1722 | 1715 | ||
| 1723 | #if AIC_DEBUG_REGISTERS | 1716 | #if AIC_DEBUG_REGISTERS |
| 1724 | ahd_reg_print_t ahd_dfbkptr_print; | 1717 | ahd_reg_print_t ahd_dfptrs_print; |
| 1725 | #else | 1718 | #else |
| 1726 | #define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ | 1719 | #define ahd_dfptrs_print(regvalue, cur_col, wrap) \ |
| 1727 | ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) | 1720 | ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) |
| 1728 | #endif | 1721 | #endif |
| 1729 | 1722 | ||
| 1730 | #if AIC_DEBUG_REGISTERS | 1723 | #if AIC_DEBUG_REGISTERS |
| @@ -1735,6 +1728,13 @@ ahd_reg_print_t ahd_skewcalc_print; | |||
| 1735 | #endif | 1728 | #endif |
| 1736 | 1729 | ||
| 1737 | #if AIC_DEBUG_REGISTERS | 1730 | #if AIC_DEBUG_REGISTERS |
| 1731 | ahd_reg_print_t ahd_dfbkptr_print; | ||
| 1732 | #else | ||
| 1733 | #define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ | ||
| 1734 | ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) | ||
| 1735 | #endif | ||
| 1736 | |||
| 1737 | #if AIC_DEBUG_REGISTERS | ||
| 1738 | ahd_reg_print_t ahd_dfdbctl_print; | 1738 | ahd_reg_print_t ahd_dfdbctl_print; |
| 1739 | #else | 1739 | #else |
| 1740 | #define ahd_dfdbctl_print(regvalue, cur_col, wrap) \ | 1740 | #define ahd_dfdbctl_print(regvalue, cur_col, wrap) \ |
| @@ -1826,17 +1826,17 @@ ahd_reg_print_t ahd_dindex_print; | |||
| 1826 | #endif | 1826 | #endif |
| 1827 | 1827 | ||
| 1828 | #if AIC_DEBUG_REGISTERS | 1828 | #if AIC_DEBUG_REGISTERS |
| 1829 | ahd_reg_print_t ahd_brkaddr1_print; | 1829 | ahd_reg_print_t ahd_brkaddr0_print; |
| 1830 | #else | 1830 | #else |
| 1831 | #define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ | 1831 | #define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ |
| 1832 | ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) | 1832 | ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) |
| 1833 | #endif | 1833 | #endif |
| 1834 | 1834 | ||
| 1835 | #if AIC_DEBUG_REGISTERS | 1835 | #if AIC_DEBUG_REGISTERS |
| 1836 | ahd_reg_print_t ahd_brkaddr0_print; | 1836 | ahd_reg_print_t ahd_brkaddr1_print; |
| 1837 | #else | 1837 | #else |
| 1838 | #define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ | 1838 | #define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ |
| 1839 | ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) | 1839 | ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) |
| 1840 | #endif | 1840 | #endif |
| 1841 | 1841 | ||
| 1842 | #if AIC_DEBUG_REGISTERS | 1842 | #if AIC_DEBUG_REGISTERS |
| @@ -1889,13 +1889,6 @@ ahd_reg_print_t ahd_stack_print; | |||
| 1889 | #endif | 1889 | #endif |
| 1890 | 1890 | ||
| 1891 | #if AIC_DEBUG_REGISTERS | 1891 | #if AIC_DEBUG_REGISTERS |
| 1892 | ahd_reg_print_t ahd_curaddr_print; | ||
| 1893 | #else | ||
| 1894 | #define ahd_curaddr_print(regvalue, cur_col, wrap) \ | ||
| 1895 | ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) | ||
| 1896 | #endif | ||
| 1897 | |||
| 1898 | #if AIC_DEBUG_REGISTERS | ||
| 1899 | ahd_reg_print_t ahd_intvec1_addr_print; | 1892 | ahd_reg_print_t ahd_intvec1_addr_print; |
| 1900 | #else | 1893 | #else |
| 1901 | #define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \ | 1894 | #define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \ |
| @@ -1903,10 +1896,10 @@ ahd_reg_print_t ahd_intvec1_addr_print; | |||
| 1903 | #endif | 1896 | #endif |
| 1904 | 1897 | ||
| 1905 | #if AIC_DEBUG_REGISTERS | 1898 | #if AIC_DEBUG_REGISTERS |
| 1906 | ahd_reg_print_t ahd_intvec2_addr_print; | 1899 | ahd_reg_print_t ahd_curaddr_print; |
| 1907 | #else | 1900 | #else |
| 1908 | #define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ | 1901 | #define ahd_curaddr_print(regvalue, cur_col, wrap) \ |
| 1909 | ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) | 1902 | ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) |
| 1910 | #endif | 1903 | #endif |
| 1911 | 1904 | ||
| 1912 | #if AIC_DEBUG_REGISTERS | 1905 | #if AIC_DEBUG_REGISTERS |
| @@ -1917,6 +1910,13 @@ ahd_reg_print_t ahd_lastaddr_print; | |||
| 1917 | #endif | 1910 | #endif |
| 1918 | 1911 | ||
| 1919 | #if AIC_DEBUG_REGISTERS | 1912 | #if AIC_DEBUG_REGISTERS |
| 1913 | ahd_reg_print_t ahd_intvec2_addr_print; | ||
| 1914 | #else | ||
| 1915 | #define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ | ||
| 1916 | ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) | ||
| 1917 | #endif | ||
| 1918 | |||
| 1919 | #if AIC_DEBUG_REGISTERS | ||
| 1920 | ahd_reg_print_t ahd_longjmp_addr_print; | 1920 | ahd_reg_print_t ahd_longjmp_addr_print; |
| 1921 | #else | 1921 | #else |
| 1922 | #define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \ | 1922 | #define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \ |
| @@ -1994,192 +1994,213 @@ ahd_reg_print_t ahd_complete_dma_scb_head_print; | |||
| 1994 | #endif | 1994 | #endif |
| 1995 | 1995 | ||
| 1996 | #if AIC_DEBUG_REGISTERS | 1996 | #if AIC_DEBUG_REGISTERS |
| 1997 | ahd_reg_print_t ahd_complete_dma_scb_tail_print; | ||
| 1998 | #else | ||
| 1999 | #define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \ | ||
| 2000 | ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap) | ||
| 2001 | #endif | ||
| 2002 | |||
| 2003 | #if AIC_DEBUG_REGISTERS | ||
| 2004 | ahd_reg_print_t ahd_complete_on_qfreeze_head_print; | ||
| 2005 | #else | ||
| 2006 | #define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \ | ||
| 2007 | ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap) | ||
| 2008 | #endif | ||
| 2009 | |||
| 2010 | #if AIC_DEBUG_REGISTERS | ||
| 1997 | ahd_reg_print_t ahd_qfreeze_count_print; | 2011 | ahd_reg_print_t ahd_qfreeze_count_print; |
| 1998 | #else | 2012 | #else |
| 1999 | #define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \ | 2013 | #define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \ |
| 2000 | ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap) | 2014 | ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap) |
| 2015 | #endif | ||
| 2016 | |||
| 2017 | #if AIC_DEBUG_REGISTERS | ||
| 2018 | ahd_reg_print_t ahd_kernel_qfreeze_count_print; | ||
| 2019 | #else | ||
| 2020 | #define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \ | ||
| 2021 | ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap) | ||
| 2001 | #endif | 2022 | #endif |
| 2002 | 2023 | ||
| 2003 | #if AIC_DEBUG_REGISTERS | 2024 | #if AIC_DEBUG_REGISTERS |
| 2004 | ahd_reg_print_t ahd_saved_mode_print; | 2025 | ahd_reg_print_t ahd_saved_mode_print; |
| 2005 | #else | 2026 | #else |
| 2006 | #define ahd_saved_mode_print(regvalue, cur_col, wrap) \ | 2027 | #define ahd_saved_mode_print(regvalue, cur_col, wrap) \ |
| 2007 | ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap) | 2028 | ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap) |
| 2008 | #endif | 2029 | #endif |
| 2009 | 2030 | ||
| 2010 | #if AIC_DEBUG_REGISTERS | 2031 | #if AIC_DEBUG_REGISTERS |
| 2011 | ahd_reg_print_t ahd_msg_out_print; | 2032 | ahd_reg_print_t ahd_msg_out_print; |
| 2012 | #else | 2033 | #else |
| 2013 | #define ahd_msg_out_print(regvalue, cur_col, wrap) \ | 2034 | #define ahd_msg_out_print(regvalue, cur_col, wrap) \ |
| 2014 | ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap) | 2035 | ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap) |
| 2015 | #endif | 2036 | #endif |
| 2016 | 2037 | ||
| 2017 | #if AIC_DEBUG_REGISTERS | 2038 | #if AIC_DEBUG_REGISTERS |
| 2018 | ahd_reg_print_t ahd_dmaparams_print; | 2039 | ahd_reg_print_t ahd_dmaparams_print; |
| 2019 | #else | 2040 | #else |
| 2020 | #define ahd_dmaparams_print(regvalue, cur_col, wrap) \ | 2041 | #define ahd_dmaparams_print(regvalue, cur_col, wrap) \ |
| 2021 | ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap) | 2042 | ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap) |
| 2022 | #endif | 2043 | #endif |
| 2023 | 2044 | ||
| 2024 | #if AIC_DEBUG_REGISTERS | 2045 | #if AIC_DEBUG_REGISTERS |
| 2025 | ahd_reg_print_t ahd_seq_flags_print; | 2046 | ahd_reg_print_t ahd_seq_flags_print; |
| 2026 | #else | 2047 | #else |
| 2027 | #define ahd_seq_flags_print(regvalue, cur_col, wrap) \ | 2048 | #define ahd_seq_flags_print(regvalue, cur_col, wrap) \ |
| 2028 | ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap) | 2049 | ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap) |
| 2029 | #endif | 2050 | #endif |
| 2030 | 2051 | ||
| 2031 | #if AIC_DEBUG_REGISTERS | 2052 | #if AIC_DEBUG_REGISTERS |
| 2032 | ahd_reg_print_t ahd_saved_scsiid_print; | 2053 | ahd_reg_print_t ahd_saved_scsiid_print; |
| 2033 | #else | 2054 | #else |
| 2034 | #define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \ | 2055 | #define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \ |
| 2035 | ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap) | 2056 | ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap) |
| 2036 | #endif | 2057 | #endif |
| 2037 | 2058 | ||
| 2038 | #if AIC_DEBUG_REGISTERS | 2059 | #if AIC_DEBUG_REGISTERS |
| 2039 | ahd_reg_print_t ahd_saved_lun_print; | 2060 | ahd_reg_print_t ahd_saved_lun_print; |
| 2040 | #else | 2061 | #else |
| 2041 | #define ahd_saved_lun_print(regvalue, cur_col, wrap) \ | 2062 | #define ahd_saved_lun_print(regvalue, cur_col, wrap) \ |
| 2042 | ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap) | 2063 | ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap) |
| 2043 | #endif | 2064 | #endif |
| 2044 | 2065 | ||
| 2045 | #if AIC_DEBUG_REGISTERS | 2066 | #if AIC_DEBUG_REGISTERS |
| 2046 | ahd_reg_print_t ahd_lastphase_print; | 2067 | ahd_reg_print_t ahd_lastphase_print; |
| 2047 | #else | 2068 | #else |
| 2048 | #define ahd_lastphase_print(regvalue, cur_col, wrap) \ | 2069 | #define ahd_lastphase_print(regvalue, cur_col, wrap) \ |
| 2049 | ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap) | 2070 | ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap) |
| 2050 | #endif | 2071 | #endif |
| 2051 | 2072 | ||
| 2052 | #if AIC_DEBUG_REGISTERS | 2073 | #if AIC_DEBUG_REGISTERS |
| 2053 | ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print; | 2074 | ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print; |
| 2054 | #else | 2075 | #else |
| 2055 | #define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \ | 2076 | #define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \ |
| 2056 | ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap) | 2077 | ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap) |
| 2057 | #endif | 2078 | #endif |
| 2058 | 2079 | ||
| 2059 | #if AIC_DEBUG_REGISTERS | 2080 | #if AIC_DEBUG_REGISTERS |
| 2060 | ahd_reg_print_t ahd_shared_data_addr_print; | 2081 | ahd_reg_print_t ahd_kernel_tqinpos_print; |
| 2061 | #else | 2082 | #else |
| 2062 | #define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ | 2083 | #define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ |
| 2063 | ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap) | 2084 | ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap) |
| 2064 | #endif | 2085 | #endif |
| 2065 | 2086 | ||
| 2066 | #if AIC_DEBUG_REGISTERS | 2087 | #if AIC_DEBUG_REGISTERS |
| 2067 | ahd_reg_print_t ahd_qoutfifo_next_addr_print; | 2088 | ahd_reg_print_t ahd_tqinpos_print; |
| 2068 | #else | 2089 | #else |
| 2069 | #define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ | 2090 | #define ahd_tqinpos_print(regvalue, cur_col, wrap) \ |
| 2070 | ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap) | 2091 | ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap) |
| 2071 | #endif | 2092 | #endif |
| 2072 | 2093 | ||
| 2073 | #if AIC_DEBUG_REGISTERS | 2094 | #if AIC_DEBUG_REGISTERS |
| 2074 | ahd_reg_print_t ahd_kernel_tqinpos_print; | 2095 | ahd_reg_print_t ahd_shared_data_addr_print; |
| 2075 | #else | 2096 | #else |
| 2076 | #define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ | 2097 | #define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ |
| 2077 | ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap) | 2098 | ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap) |
| 2078 | #endif | 2099 | #endif |
| 2079 | 2100 | ||
| 2080 | #if AIC_DEBUG_REGISTERS | 2101 | #if AIC_DEBUG_REGISTERS |
| 2081 | ahd_reg_print_t ahd_tqinpos_print; | 2102 | ahd_reg_print_t ahd_qoutfifo_next_addr_print; |
| 2082 | #else | 2103 | #else |
| 2083 | #define ahd_tqinpos_print(regvalue, cur_col, wrap) \ | 2104 | #define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ |
| 2084 | ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap) | 2105 | ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap) |
| 2085 | #endif | 2106 | #endif |
| 2086 | 2107 | ||
| 2087 | #if AIC_DEBUG_REGISTERS | 2108 | #if AIC_DEBUG_REGISTERS |
| 2088 | ahd_reg_print_t ahd_arg_1_print; | 2109 | ahd_reg_print_t ahd_arg_1_print; |
| 2089 | #else | 2110 | #else |
| 2090 | #define ahd_arg_1_print(regvalue, cur_col, wrap) \ | 2111 | #define ahd_arg_1_print(regvalue, cur_col, wrap) \ |
| 2091 | ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap) | 2112 | ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap) |
| 2092 | #endif | 2113 | #endif |
| 2093 | 2114 | ||
| 2094 | #if AIC_DEBUG_REGISTERS | 2115 | #if AIC_DEBUG_REGISTERS |
| 2095 | ahd_reg_print_t ahd_arg_2_print; | 2116 | ahd_reg_print_t ahd_arg_2_print; |
| 2096 | #else | 2117 | #else |
| 2097 | #define ahd_arg_2_print(regvalue, cur_col, wrap) \ | 2118 | #define ahd_arg_2_print(regvalue, cur_col, wrap) \ |
| 2098 | ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap) | 2119 | ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap) |
| 2099 | #endif | 2120 | #endif |
| 2100 | 2121 | ||
| 2101 | #if AIC_DEBUG_REGISTERS | 2122 | #if AIC_DEBUG_REGISTERS |
| 2102 | ahd_reg_print_t ahd_last_msg_print; | 2123 | ahd_reg_print_t ahd_last_msg_print; |
| 2103 | #else | 2124 | #else |
| 2104 | #define ahd_last_msg_print(regvalue, cur_col, wrap) \ | 2125 | #define ahd_last_msg_print(regvalue, cur_col, wrap) \ |
| 2105 | ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap) | 2126 | ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap) |
| 2106 | #endif | 2127 | #endif |
| 2107 | 2128 | ||
| 2108 | #if AIC_DEBUG_REGISTERS | 2129 | #if AIC_DEBUG_REGISTERS |
| 2109 | ahd_reg_print_t ahd_scsiseq_template_print; | 2130 | ahd_reg_print_t ahd_scsiseq_template_print; |
| 2110 | #else | 2131 | #else |
| 2111 | #define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \ | 2132 | #define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \ |
| 2112 | ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap) | 2133 | ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap) |
| 2113 | #endif | 2134 | #endif |
| 2114 | 2135 | ||
| 2115 | #if AIC_DEBUG_REGISTERS | 2136 | #if AIC_DEBUG_REGISTERS |
| 2116 | ahd_reg_print_t ahd_initiator_tag_print; | 2137 | ahd_reg_print_t ahd_initiator_tag_print; |
| 2117 | #else | 2138 | #else |
| 2118 | #define ahd_initiator_tag_print(regvalue, cur_col, wrap) \ | 2139 | #define ahd_initiator_tag_print(regvalue, cur_col, wrap) \ |
| 2119 | ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap) | 2140 | ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap) |
| 2120 | #endif | 2141 | #endif |
| 2121 | 2142 | ||
| 2122 | #if AIC_DEBUG_REGISTERS | 2143 | #if AIC_DEBUG_REGISTERS |
| 2123 | ahd_reg_print_t ahd_seq_flags2_print; | 2144 | ahd_reg_print_t ahd_seq_flags2_print; |
| 2124 | #else | 2145 | #else |
| 2125 | #define ahd_seq_flags2_print(regvalue, cur_col, wrap) \ | 2146 | #define ahd_seq_flags2_print(regvalue, cur_col, wrap) \ |
| 2126 | ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap) | 2147 | ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap) |
| 2127 | #endif | 2148 | #endif |
| 2128 | 2149 | ||
| 2129 | #if AIC_DEBUG_REGISTERS | 2150 | #if AIC_DEBUG_REGISTERS |
| 2130 | ahd_reg_print_t ahd_allocfifo_scbptr_print; | 2151 | ahd_reg_print_t ahd_allocfifo_scbptr_print; |
| 2131 | #else | 2152 | #else |
| 2132 | #define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \ | 2153 | #define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \ |
| 2133 | ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap) | 2154 | ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap) |
| 2134 | #endif | 2155 | #endif |
| 2135 | 2156 | ||
| 2136 | #if AIC_DEBUG_REGISTERS | 2157 | #if AIC_DEBUG_REGISTERS |
| 2137 | ahd_reg_print_t ahd_int_coalescing_timer_print; | 2158 | ahd_reg_print_t ahd_int_coalescing_timer_print; |
| 2138 | #else | 2159 | #else |
| 2139 | #define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \ | 2160 | #define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \ |
| 2140 | ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap) | 2161 | ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap) |
| 2141 | #endif | 2162 | #endif |
| 2142 | 2163 | ||
| 2143 | #if AIC_DEBUG_REGISTERS | 2164 | #if AIC_DEBUG_REGISTERS |
| 2144 | ahd_reg_print_t ahd_int_coalescing_maxcmds_print; | 2165 | ahd_reg_print_t ahd_int_coalescing_maxcmds_print; |
| 2145 | #else | 2166 | #else |
| 2146 | #define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \ | 2167 | #define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \ |
| 2147 | ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap) | 2168 | ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap) |
| 2148 | #endif | 2169 | #endif |
| 2149 | 2170 | ||
| 2150 | #if AIC_DEBUG_REGISTERS | 2171 | #if AIC_DEBUG_REGISTERS |
| 2151 | ahd_reg_print_t ahd_int_coalescing_mincmds_print; | 2172 | ahd_reg_print_t ahd_int_coalescing_mincmds_print; |
| 2152 | #else | 2173 | #else |
| 2153 | #define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \ | 2174 | #define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \ |
| 2154 | ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap) | 2175 | ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap) |
| 2155 | #endif | 2176 | #endif |
| 2156 | 2177 | ||
| 2157 | #if AIC_DEBUG_REGISTERS | 2178 | #if AIC_DEBUG_REGISTERS |
| 2158 | ahd_reg_print_t ahd_cmds_pending_print; | 2179 | ahd_reg_print_t ahd_cmds_pending_print; |
| 2159 | #else | 2180 | #else |
| 2160 | #define ahd_cmds_pending_print(regvalue, cur_col, wrap) \ | 2181 | #define ahd_cmds_pending_print(regvalue, cur_col, wrap) \ |
| 2161 | ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap) | 2182 | ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap) |
| 2162 | #endif | 2183 | #endif |
| 2163 | 2184 | ||
| 2164 | #if AIC_DEBUG_REGISTERS | 2185 | #if AIC_DEBUG_REGISTERS |
| 2165 | ahd_reg_print_t ahd_int_coalescing_cmdcount_print; | 2186 | ahd_reg_print_t ahd_int_coalescing_cmdcount_print; |
| 2166 | #else | 2187 | #else |
| 2167 | #define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \ | 2188 | #define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \ |
| 2168 | ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap) | 2189 | ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap) |
| 2169 | #endif | 2190 | #endif |
| 2170 | 2191 | ||
| 2171 | #if AIC_DEBUG_REGISTERS | 2192 | #if AIC_DEBUG_REGISTERS |
| 2172 | ahd_reg_print_t ahd_local_hs_mailbox_print; | 2193 | ahd_reg_print_t ahd_local_hs_mailbox_print; |
| 2173 | #else | 2194 | #else |
| 2174 | #define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \ | 2195 | #define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \ |
| 2175 | ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap) | 2196 | ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap) |
| 2176 | #endif | 2197 | #endif |
| 2177 | 2198 | ||
| 2178 | #if AIC_DEBUG_REGISTERS | 2199 | #if AIC_DEBUG_REGISTERS |
| 2179 | ahd_reg_print_t ahd_cmdsize_table_print; | 2200 | ahd_reg_print_t ahd_cmdsize_table_print; |
| 2180 | #else | 2201 | #else |
| 2181 | #define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \ | 2202 | #define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \ |
| 2182 | ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap) | 2203 | ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap) |
| 2183 | #endif | 2204 | #endif |
| 2184 | 2205 | ||
| 2185 | #if AIC_DEBUG_REGISTERS | 2206 | #if AIC_DEBUG_REGISTERS |
| @@ -2434,13 +2455,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2434 | #define HOST_TQINPOS 0x80 | 2455 | #define HOST_TQINPOS 0x80 |
| 2435 | #define ENINT_COALESCE 0x40 | 2456 | #define ENINT_COALESCE 0x40 |
| 2436 | 2457 | ||
| 2437 | #define CLRSEQINTSTAT 0x0c | ||
| 2438 | #define CLRSEQ_SWTMRTO 0x10 | ||
| 2439 | #define CLRSEQ_SEQINT 0x08 | ||
| 2440 | #define CLRSEQ_SCSIINT 0x04 | ||
| 2441 | #define CLRSEQ_PCIINT 0x02 | ||
| 2442 | #define CLRSEQ_SPLTINT 0x01 | ||
| 2443 | |||
| 2444 | #define SEQINTSTAT 0x0c | 2458 | #define SEQINTSTAT 0x0c |
| 2445 | #define SEQ_SWTMRTO 0x10 | 2459 | #define SEQ_SWTMRTO 0x10 |
| 2446 | #define SEQ_SEQINT 0x08 | 2460 | #define SEQ_SEQINT 0x08 |
| @@ -2448,6 +2462,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2448 | #define SEQ_PCIINT 0x02 | 2462 | #define SEQ_PCIINT 0x02 |
| 2449 | #define SEQ_SPLTINT 0x01 | 2463 | #define SEQ_SPLTINT 0x01 |
| 2450 | 2464 | ||
| 2465 | #define CLRSEQINTSTAT 0x0c | ||
| 2466 | #define CLRSEQ_SWTMRTO 0x10 | ||
| 2467 | #define CLRSEQ_SEQINT 0x08 | ||
| 2468 | #define CLRSEQ_SCSIINT 0x04 | ||
| 2469 | #define CLRSEQ_PCIINT 0x02 | ||
| 2470 | #define CLRSEQ_SPLTINT 0x01 | ||
| 2471 | |||
| 2451 | #define SWTIMER 0x0e | 2472 | #define SWTIMER 0x0e |
| 2452 | 2473 | ||
| 2453 | #define SNSCB_QOFF 0x10 | 2474 | #define SNSCB_QOFF 0x10 |
| @@ -2623,10 +2644,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2623 | #define BIOSCANCELEN 0x10 | 2644 | #define BIOSCANCELEN 0x10 |
| 2624 | #define SPIOEN 0x08 | 2645 | #define SPIOEN 0x08 |
| 2625 | 2646 | ||
| 2626 | #define BUSINITID 0x3c | ||
| 2627 | |||
| 2628 | #define DLCOUNT 0x3c | 2647 | #define DLCOUNT 0x3c |
| 2629 | 2648 | ||
| 2649 | #define BUSINITID 0x3c | ||
| 2650 | |||
| 2630 | #define SXFRCTL1 0x3d | 2651 | #define SXFRCTL1 0x3d |
| 2631 | #define BITBUCKET 0x80 | 2652 | #define BITBUCKET 0x80 |
| 2632 | #define ENSACHK 0x40 | 2653 | #define ENSACHK 0x40 |
| @@ -2693,13 +2714,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2693 | #define SELID_MASK 0xf0 | 2714 | #define SELID_MASK 0xf0 |
| 2694 | #define ONEBIT 0x08 | 2715 | #define ONEBIT 0x08 |
| 2695 | 2716 | ||
| 2696 | #define SBLKCTL 0x4a | ||
| 2697 | #define DIAGLEDEN 0x80 | ||
| 2698 | #define DIAGLEDON 0x40 | ||
| 2699 | #define ENAB40 0x08 | ||
| 2700 | #define ENAB20 0x04 | ||
| 2701 | #define SELWIDE 0x02 | ||
| 2702 | |||
| 2703 | #define OPTIONMODE 0x4a | 2717 | #define OPTIONMODE 0x4a |
| 2704 | #define OPTIONMODE_DEFAULTS 0x02 | 2718 | #define OPTIONMODE_DEFAULTS 0x02 |
| 2705 | #define BIOSCANCTL 0x80 | 2719 | #define BIOSCANCTL 0x80 |
| @@ -2709,15 +2723,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2709 | #define ENDGFORMCHK 0x04 | 2723 | #define ENDGFORMCHK 0x04 |
| 2710 | #define AUTO_MSGOUT_DE 0x02 | 2724 | #define AUTO_MSGOUT_DE 0x02 |
| 2711 | 2725 | ||
| 2712 | #define SSTAT0 0x4b | 2726 | #define SBLKCTL 0x4a |
| 2713 | #define TARGET 0x80 | 2727 | #define DIAGLEDEN 0x80 |
| 2714 | #define SELDO 0x40 | 2728 | #define DIAGLEDON 0x40 |
| 2715 | #define SELDI 0x20 | 2729 | #define ENAB40 0x08 |
| 2716 | #define SELINGO 0x10 | 2730 | #define ENAB20 0x04 |
| 2717 | #define IOERR 0x08 | 2731 | #define SELWIDE 0x02 |
| 2718 | #define OVERRUN 0x04 | ||
| 2719 | #define SPIORDY 0x02 | ||
| 2720 | #define ARBDO 0x01 | ||
| 2721 | 2732 | ||
| 2722 | #define CLRSINT0 0x4b | 2733 | #define CLRSINT0 0x4b |
| 2723 | #define CLRSELDO 0x40 | 2734 | #define CLRSELDO 0x40 |
| @@ -2728,6 +2739,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2728 | #define CLRSPIORDY 0x02 | 2739 | #define CLRSPIORDY 0x02 |
| 2729 | #define CLRARBDO 0x01 | 2740 | #define CLRARBDO 0x01 |
| 2730 | 2741 | ||
| 2742 | #define SSTAT0 0x4b | ||
| 2743 | #define TARGET 0x80 | ||
| 2744 | #define SELDO 0x40 | ||
| 2745 | #define SELDI 0x20 | ||
| 2746 | #define SELINGO 0x10 | ||
| 2747 | #define IOERR 0x08 | ||
| 2748 | #define OVERRUN 0x04 | ||
| 2749 | #define SPIORDY 0x02 | ||
| 2750 | #define ARBDO 0x01 | ||
| 2751 | |||
| 2731 | #define SIMODE0 0x4b | 2752 | #define SIMODE0 0x4b |
| 2732 | #define ENSELDO 0x40 | 2753 | #define ENSELDO 0x40 |
| 2733 | #define ENSELDI 0x20 | 2754 | #define ENSELDI 0x20 |
| @@ -2768,17 +2789,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2768 | #define BUSFREE_DFF0 0x80 | 2789 | #define BUSFREE_DFF0 0x80 |
| 2769 | #define BUSFREE_LQO 0x40 | 2790 | #define BUSFREE_LQO 0x40 |
| 2770 | 2791 | ||
| 2792 | #define SIMODE2 0x4d | ||
| 2793 | #define ENWIDE_RES 0x04 | ||
| 2794 | #define ENSDONE 0x02 | ||
| 2795 | #define ENDMADONE 0x01 | ||
| 2796 | |||
| 2771 | #define CLRSINT2 0x4d | 2797 | #define CLRSINT2 0x4d |
| 2772 | #define CLRNONPACKREQ 0x20 | 2798 | #define CLRNONPACKREQ 0x20 |
| 2773 | #define CLRWIDE_RES 0x04 | 2799 | #define CLRWIDE_RES 0x04 |
| 2774 | #define CLRSDONE 0x02 | 2800 | #define CLRSDONE 0x02 |
| 2775 | #define CLRDMADONE 0x01 | 2801 | #define CLRDMADONE 0x01 |
| 2776 | 2802 | ||
| 2777 | #define SIMODE2 0x4d | ||
| 2778 | #define ENWIDE_RES 0x04 | ||
| 2779 | #define ENSDONE 0x02 | ||
| 2780 | #define ENDMADONE 0x01 | ||
| 2781 | |||
| 2782 | #define PERRDIAG 0x4e | 2803 | #define PERRDIAG 0x4e |
| 2783 | #define HIZERO 0x80 | 2804 | #define HIZERO 0x80 |
| 2784 | #define HIPERR 0x40 | 2805 | #define HIPERR 0x40 |
| @@ -2871,13 +2892,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2871 | #define CLRNTRAMPERR 0x02 | 2892 | #define CLRNTRAMPERR 0x02 |
| 2872 | #define CLROSRAMPERR 0x01 | 2893 | #define CLROSRAMPERR 0x01 |
| 2873 | 2894 | ||
| 2874 | #define LQOMODE0 0x54 | ||
| 2875 | #define ENLQOTARGSCBPERR 0x10 | ||
| 2876 | #define ENLQOSTOPT2 0x08 | ||
| 2877 | #define ENLQOATNLQ 0x04 | ||
| 2878 | #define ENLQOATNPKT 0x02 | ||
| 2879 | #define ENLQOTCRC 0x01 | ||
| 2880 | |||
| 2881 | #define LQOSTAT0 0x54 | 2895 | #define LQOSTAT0 0x54 |
| 2882 | #define LQOTARGSCBPERR 0x10 | 2896 | #define LQOTARGSCBPERR 0x10 |
| 2883 | #define LQOSTOPT2 0x08 | 2897 | #define LQOSTOPT2 0x08 |
| @@ -2892,6 +2906,20 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2892 | #define CLRLQOATNPKT 0x02 | 2906 | #define CLRLQOATNPKT 0x02 |
| 2893 | #define CLRLQOTCRC 0x01 | 2907 | #define CLRLQOTCRC 0x01 |
| 2894 | 2908 | ||
| 2909 | #define LQOMODE0 0x54 | ||
| 2910 | #define ENLQOTARGSCBPERR 0x10 | ||
| 2911 | #define ENLQOSTOPT2 0x08 | ||
| 2912 | #define ENLQOATNLQ 0x04 | ||
| 2913 | #define ENLQOATNPKT 0x02 | ||
| 2914 | #define ENLQOTCRC 0x01 | ||
| 2915 | |||
| 2916 | #define LQOMODE1 0x55 | ||
| 2917 | #define ENLQOINITSCBPERR 0x10 | ||
| 2918 | #define ENLQOSTOPI2 0x08 | ||
| 2919 | #define ENLQOBADQAS 0x04 | ||
| 2920 | #define ENLQOBUSFREE 0x02 | ||
| 2921 | #define ENLQOPHACHGINPKT 0x01 | ||
| 2922 | |||
| 2895 | #define LQOSTAT1 0x55 | 2923 | #define LQOSTAT1 0x55 |
| 2896 | #define LQOINITSCBPERR 0x10 | 2924 | #define LQOINITSCBPERR 0x10 |
| 2897 | #define LQOSTOPI2 0x08 | 2925 | #define LQOSTOPI2 0x08 |
| @@ -2906,13 +2934,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 2906 | #define CLRLQOBUSFREE 0x02 | 2934 | #define CLRLQOBUSFREE 0x02 |
| 2907 | #define CLRLQOPHACHGINPKT 0x01 | 2935 | #define CLRLQOPHACHGINPKT 0x01 |
| 2908 | 2936 | ||
| 2909 | #define LQOMODE1 0x55 | ||
| 2910 | #define ENLQOINITSCBPERR 0x10 | ||
| 2911 | #define ENLQOSTOPI2 0x08 | ||
| 2912 | #define ENLQOBADQAS 0x04 | ||
| 2913 | #define ENLQOBUSFREE 0x02 | ||
| 2914 | #define ENLQOPHACHGINPKT 0x01 | ||
| 2915 | |||
| 2916 | #define LQOSTAT2 0x56 | 2937 | #define LQOSTAT2 0x56 |
| 2917 | #define LQOPKT 0xe0 | 2938 | #define LQOPKT 0xe0 |
| 2918 | #define LQOWAITFIFO 0x10 | 2939 | #define LQOWAITFIFO 0x10 |
| @@ -3028,6 +3049,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3028 | 3049 | ||
| 3029 | #define ANNEXCOL 0x65 | 3050 | #define ANNEXCOL 0x65 |
| 3030 | 3051 | ||
| 3052 | #define ANNEXDAT 0x66 | ||
| 3053 | |||
| 3031 | #define SCSCHKN 0x66 | 3054 | #define SCSCHKN 0x66 |
| 3032 | #define STSELSKIDDIS 0x40 | 3055 | #define STSELSKIDDIS 0x40 |
| 3033 | #define CURRFIFODEF 0x20 | 3056 | #define CURRFIFODEF 0x20 |
| @@ -3037,8 +3060,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3037 | #define SHVALIDSTDIS 0x02 | 3060 | #define SHVALIDSTDIS 0x02 |
| 3038 | #define LSTSGCLRDIS 0x01 | 3061 | #define LSTSGCLRDIS 0x01 |
| 3039 | 3062 | ||
| 3040 | #define ANNEXDAT 0x66 | ||
| 3041 | |||
| 3042 | #define IOWNID 0x67 | 3063 | #define IOWNID 0x67 |
| 3043 | 3064 | ||
| 3044 | #define PLL960CTL0 0x68 | 3065 | #define PLL960CTL0 0x68 |
| @@ -3071,10 +3092,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3071 | #define PLL_CNTCLR 0x40 | 3092 | #define PLL_CNTCLR 0x40 |
| 3072 | #define PLL_RST 0x01 | 3093 | #define PLL_RST 0x01 |
| 3073 | 3094 | ||
| 3074 | #define PLL400CNT0 0x6e | ||
| 3075 | |||
| 3076 | #define UNFAIRNESS 0x6e | 3095 | #define UNFAIRNESS 0x6e |
| 3077 | 3096 | ||
| 3097 | #define PLL400CNT0 0x6e | ||
| 3098 | |||
| 3078 | #define HADDR 0x70 | 3099 | #define HADDR 0x70 |
| 3079 | 3100 | ||
| 3080 | #define PLLDELAY 0x70 | 3101 | #define PLLDELAY 0x70 |
| @@ -3088,14 +3109,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3088 | 3109 | ||
| 3089 | #define HODMAEN 0x7a | 3110 | #define HODMAEN 0x7a |
| 3090 | 3111 | ||
| 3091 | #define SGHADDR 0x7c | ||
| 3092 | |||
| 3093 | #define SCBHADDR 0x7c | 3112 | #define SCBHADDR 0x7c |
| 3094 | 3113 | ||
| 3095 | #define SGHCNT 0x84 | 3114 | #define SGHADDR 0x7c |
| 3096 | 3115 | ||
| 3097 | #define SCBHCNT 0x84 | 3116 | #define SCBHCNT 0x84 |
| 3098 | 3117 | ||
| 3118 | #define SGHCNT 0x84 | ||
| 3119 | |||
| 3099 | #define DFF_THRSH 0x88 | 3120 | #define DFF_THRSH 0x88 |
| 3100 | #define WR_DFTHRSH 0x70 | 3121 | #define WR_DFTHRSH 0x70 |
| 3101 | #define RD_DFTHRSH 0x07 | 3122 | #define RD_DFTHRSH 0x07 |
| @@ -3113,8 +3134,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3113 | #define RD_DFTHRSH_63 0x03 | 3134 | #define RD_DFTHRSH_63 0x03 |
| 3114 | #define RD_DFTHRSH_50 0x02 | 3135 | #define RD_DFTHRSH_50 0x02 |
| 3115 | #define RD_DFTHRSH_25 0x01 | 3136 | #define RD_DFTHRSH_25 0x01 |
| 3116 | #define WR_DFTHRSH_MIN 0x00 | ||
| 3117 | #define RD_DFTHRSH_MIN 0x00 | 3137 | #define RD_DFTHRSH_MIN 0x00 |
| 3138 | #define WR_DFTHRSH_MIN 0x00 | ||
| 3118 | 3139 | ||
| 3119 | #define ROMADDR 0x8a | 3140 | #define ROMADDR 0x8a |
| 3120 | 3141 | ||
| @@ -3150,20 +3171,22 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3150 | #define DCH1NSEN 0x02 | 3171 | #define DCH1NSEN 0x02 |
| 3151 | #define DCH0NSEN 0x01 | 3172 | #define DCH0NSEN 0x01 |
| 3152 | 3173 | ||
| 3153 | #define DCHRXMSG1 0x91 | ||
| 3154 | |||
| 3155 | #define CMCRXMSG1 0x91 | 3174 | #define CMCRXMSG1 0x91 |
| 3156 | 3175 | ||
| 3157 | #define DCHRXMSG2 0x92 | 3176 | #define DCHRXMSG1 0x91 |
| 3158 | 3177 | ||
| 3159 | #define OVLYRXMSG2 0x92 | 3178 | #define DCHRXMSG2 0x92 |
| 3160 | 3179 | ||
| 3161 | #define CMCRXMSG2 0x92 | 3180 | #define CMCRXMSG2 0x92 |
| 3162 | 3181 | ||
| 3163 | #define OST 0x92 | 3182 | #define OST 0x92 |
| 3164 | 3183 | ||
| 3184 | #define OVLYRXMSG2 0x92 | ||
| 3185 | |||
| 3165 | #define DCHRXMSG3 0x93 | 3186 | #define DCHRXMSG3 0x93 |
| 3166 | 3187 | ||
| 3188 | #define OVLYRXMSG3 0x93 | ||
| 3189 | |||
| 3167 | #define CMCRXMSG3 0x93 | 3190 | #define CMCRXMSG3 0x93 |
| 3168 | 3191 | ||
| 3169 | #define PCIXCTL 0x93 | 3192 | #define PCIXCTL 0x93 |
| @@ -3175,26 +3198,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3175 | #define TSCSERREN 0x02 | 3198 | #define TSCSERREN 0x02 |
| 3176 | #define CMPABCDIS 0x01 | 3199 | #define CMPABCDIS 0x01 |
| 3177 | 3200 | ||
| 3178 | #define OVLYRXMSG3 0x93 | ||
| 3179 | |||
| 3180 | #define OVLYSEQBCNT 0x94 | 3201 | #define OVLYSEQBCNT 0x94 |
| 3181 | 3202 | ||
| 3182 | #define CMCSEQBCNT 0x94 | ||
| 3183 | |||
| 3184 | #define DCHSEQBCNT 0x94 | 3203 | #define DCHSEQBCNT 0x94 |
| 3185 | 3204 | ||
| 3186 | #define CMCSPLTSTAT0 0x96 | 3205 | #define CMCSEQBCNT 0x94 |
| 3187 | 3206 | ||
| 3188 | #define OVLYSPLTSTAT0 0x96 | 3207 | #define CMCSPLTSTAT0 0x96 |
| 3189 | 3208 | ||
| 3190 | #define DCHSPLTSTAT0 0x96 | 3209 | #define DCHSPLTSTAT0 0x96 |
| 3191 | 3210 | ||
| 3192 | #define DCHSPLTSTAT1 0x97 | 3211 | #define OVLYSPLTSTAT0 0x96 |
| 3193 | 3212 | ||
| 3194 | #define CMCSPLTSTAT1 0x97 | 3213 | #define CMCSPLTSTAT1 0x97 |
| 3195 | 3214 | ||
| 3196 | #define OVLYSPLTSTAT1 0x97 | 3215 | #define OVLYSPLTSTAT1 0x97 |
| 3197 | 3216 | ||
| 3217 | #define DCHSPLTSTAT1 0x97 | ||
| 3218 | |||
| 3198 | #define SGRXMSG0 0x98 | 3219 | #define SGRXMSG0 0x98 |
| 3199 | #define CDNUM 0xf8 | 3220 | #define CDNUM 0xf8 |
| 3200 | #define CFNUM 0x07 | 3221 | #define CFNUM 0x07 |
| @@ -3244,13 +3265,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3244 | #define RXSCEMSG 0x02 | 3265 | #define RXSCEMSG 0x02 |
| 3245 | #define RXSPLTRSP 0x01 | 3266 | #define RXSPLTRSP 0x01 |
| 3246 | 3267 | ||
| 3268 | #define SGSPLTSTAT1 0x9f | ||
| 3269 | #define RXDATABUCKET 0x01 | ||
| 3270 | |||
| 3247 | #define SFUNCT 0x9f | 3271 | #define SFUNCT 0x9f |
| 3248 | #define TEST_GROUP 0xf0 | 3272 | #define TEST_GROUP 0xf0 |
| 3249 | #define TEST_NUM 0x0f | 3273 | #define TEST_NUM 0x0f |
| 3250 | 3274 | ||
| 3251 | #define SGSPLTSTAT1 0x9f | ||
| 3252 | #define RXDATABUCKET 0x01 | ||
| 3253 | |||
| 3254 | #define DF0PCISTAT 0xa0 | 3275 | #define DF0PCISTAT 0xa0 |
| 3255 | 3276 | ||
| 3256 | #define REG0 0xa0 | 3277 | #define REG0 0xa0 |
| @@ -3299,10 +3320,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3299 | 3320 | ||
| 3300 | #define CCSGADDR 0xac | 3321 | #define CCSGADDR 0xac |
| 3301 | 3322 | ||
| 3302 | #define CCSCBADDR 0xac | ||
| 3303 | |||
| 3304 | #define CCSCBADR_BK 0xac | 3323 | #define CCSCBADR_BK 0xac |
| 3305 | 3324 | ||
| 3325 | #define CCSCBADDR 0xac | ||
| 3326 | |||
| 3306 | #define CMC_RAMBIST 0xad | 3327 | #define CMC_RAMBIST 0xad |
| 3307 | #define SG_ELEMENT_SIZE 0x80 | 3328 | #define SG_ELEMENT_SIZE 0x80 |
| 3308 | #define SCBRAMBIST_FAIL 0x40 | 3329 | #define SCBRAMBIST_FAIL 0x40 |
| @@ -3311,14 +3332,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3311 | #define CMC_BUFFER_BIST_FAIL 0x02 | 3332 | #define CMC_BUFFER_BIST_FAIL 0x02 |
| 3312 | #define CMC_BUFFER_BIST_EN 0x01 | 3333 | #define CMC_BUFFER_BIST_EN 0x01 |
| 3313 | 3334 | ||
| 3314 | #define CCSGCTL 0xad | ||
| 3315 | #define CCSGEN 0x0c | ||
| 3316 | #define CCSGDONE 0x80 | ||
| 3317 | #define SG_CACHE_AVAIL 0x10 | ||
| 3318 | #define CCSGENACK 0x08 | ||
| 3319 | #define SG_FETCH_REQ 0x02 | ||
| 3320 | #define CCSGRESET 0x01 | ||
| 3321 | |||
| 3322 | #define CCSCBCTL 0xad | 3335 | #define CCSCBCTL 0xad |
| 3323 | #define CCSCBDONE 0x80 | 3336 | #define CCSCBDONE 0x80 |
| 3324 | #define ARRDONE 0x40 | 3337 | #define ARRDONE 0x40 |
| @@ -3327,6 +3340,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3327 | #define CCSCBDIR 0x04 | 3340 | #define CCSCBDIR 0x04 |
| 3328 | #define CCSCBRESET 0x01 | 3341 | #define CCSCBRESET 0x01 |
| 3329 | 3342 | ||
| 3343 | #define CCSGCTL 0xad | ||
| 3344 | #define CCSGEN 0x0c | ||
| 3345 | #define CCSGDONE 0x80 | ||
| 3346 | #define SG_CACHE_AVAIL 0x10 | ||
| 3347 | #define CCSGENACK 0x08 | ||
| 3348 | #define SG_FETCH_REQ 0x02 | ||
| 3349 | #define CCSGRESET 0x01 | ||
| 3350 | |||
| 3330 | #define CCSGRAM 0xb0 | 3351 | #define CCSGRAM 0xb0 |
| 3331 | 3352 | ||
| 3332 | #define FLEXADR 0xb0 | 3353 | #define FLEXADR 0xb0 |
| @@ -3356,8 +3377,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3356 | #define SEEDAT 0xbc | 3377 | #define SEEDAT 0xbc |
| 3357 | 3378 | ||
| 3358 | #define SEECTL 0xbe | 3379 | #define SEECTL 0xbe |
| 3359 | #define SEEOP_EWEN 0x40 | ||
| 3360 | #define SEEOP_WALL 0x40 | 3380 | #define SEEOP_WALL 0x40 |
| 3381 | #define SEEOP_EWEN 0x40 | ||
| 3361 | #define SEEOP_EWDS 0x40 | 3382 | #define SEEOP_EWDS 0x40 |
| 3362 | #define SEEOPCODE 0x70 | 3383 | #define SEEOPCODE 0x70 |
| 3363 | #define SEERST 0x02 | 3384 | #define SEERST 0x02 |
| @@ -3414,14 +3435,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3414 | 3435 | ||
| 3415 | #define WRTBIASCALC 0xc7 | 3436 | #define WRTBIASCALC 0xc7 |
| 3416 | 3437 | ||
| 3417 | #define DFPTRS 0xc8 | ||
| 3418 | |||
| 3419 | #define RCVRBIASCALC 0xc8 | 3438 | #define RCVRBIASCALC 0xc8 |
| 3420 | 3439 | ||
| 3421 | #define DFBKPTR 0xc9 | 3440 | #define DFPTRS 0xc8 |
| 3422 | 3441 | ||
| 3423 | #define SKEWCALC 0xc9 | 3442 | #define SKEWCALC 0xc9 |
| 3424 | 3443 | ||
| 3444 | #define DFBKPTR 0xc9 | ||
| 3445 | |||
| 3425 | #define DFDBCTL 0xcb | 3446 | #define DFDBCTL 0xcb |
| 3426 | #define DFF_CIO_WR_RDY 0x20 | 3447 | #define DFF_CIO_WR_RDY 0x20 |
| 3427 | #define DFF_CIO_RD_RDY 0x10 | 3448 | #define DFF_CIO_RD_RDY 0x10 |
| @@ -3475,11 +3496,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3475 | 3496 | ||
| 3476 | #define DINDEX 0xe4 | 3497 | #define DINDEX 0xe4 |
| 3477 | 3498 | ||
| 3499 | #define BRKADDR0 0xe6 | ||
| 3500 | |||
| 3478 | #define BRKADDR1 0xe6 | 3501 | #define BRKADDR1 0xe6 |
| 3479 | #define BRKDIS 0x80 | 3502 | #define BRKDIS 0x80 |
| 3480 | 3503 | ||
| 3481 | #define BRKADDR0 0xe6 | ||
| 3482 | |||
| 3483 | #define ALLONES 0xe8 | 3504 | #define ALLONES 0xe8 |
| 3484 | 3505 | ||
| 3485 | #define ALLZEROS 0xea | 3506 | #define ALLZEROS 0xea |
| @@ -3494,14 +3515,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3494 | 3515 | ||
| 3495 | #define STACK 0xf2 | 3516 | #define STACK 0xf2 |
| 3496 | 3517 | ||
| 3497 | #define CURADDR 0xf4 | ||
| 3498 | |||
| 3499 | #define INTVEC1_ADDR 0xf4 | 3518 | #define INTVEC1_ADDR 0xf4 |
| 3500 | 3519 | ||
| 3501 | #define INTVEC2_ADDR 0xf6 | 3520 | #define CURADDR 0xf4 |
| 3502 | 3521 | ||
| 3503 | #define LASTADDR 0xf6 | 3522 | #define LASTADDR 0xf6 |
| 3504 | 3523 | ||
| 3524 | #define INTVEC2_ADDR 0xf6 | ||
| 3525 | |||
| 3505 | #define LONGJMP_ADDR 0xf8 | 3526 | #define LONGJMP_ADDR 0xf8 |
| 3506 | 3527 | ||
| 3507 | #define ACCUM_SAVE 0xfa | 3528 | #define ACCUM_SAVE 0xfa |
| @@ -3524,25 +3545,31 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3524 | 3545 | ||
| 3525 | #define COMPLETE_DMA_SCB_HEAD 0x12c | 3546 | #define COMPLETE_DMA_SCB_HEAD 0x12c |
| 3526 | 3547 | ||
| 3527 | #define QFREEZE_COUNT 0x12e | 3548 | #define COMPLETE_DMA_SCB_TAIL 0x12e |
| 3549 | |||
| 3550 | #define COMPLETE_ON_QFREEZE_HEAD 0x130 | ||
| 3551 | |||
| 3552 | #define QFREEZE_COUNT 0x132 | ||
| 3528 | 3553 | ||
| 3529 | #define SAVED_MODE 0x130 | 3554 | #define KERNEL_QFREEZE_COUNT 0x134 |
| 3530 | 3555 | ||
| 3531 | #define MSG_OUT 0x131 | 3556 | #define SAVED_MODE 0x136 |
| 3532 | 3557 | ||
| 3533 | #define DMAPARAMS 0x132 | 3558 | #define MSG_OUT 0x137 |
| 3559 | |||
| 3560 | #define DMAPARAMS 0x138 | ||
| 3534 | #define PRELOADEN 0x80 | 3561 | #define PRELOADEN 0x80 |
| 3535 | #define WIDEODD 0x40 | 3562 | #define WIDEODD 0x40 |
| 3536 | #define SCSIEN 0x20 | 3563 | #define SCSIEN 0x20 |
| 3537 | #define SDMAEN 0x10 | 3564 | #define SDMAEN 0x10 |
| 3538 | #define SDMAENACK 0x10 | 3565 | #define SDMAENACK 0x10 |
| 3539 | #define HDMAENACK 0x08 | ||
| 3540 | #define HDMAEN 0x08 | 3566 | #define HDMAEN 0x08 |
| 3567 | #define HDMAENACK 0x08 | ||
| 3541 | #define DIRECTION 0x04 | 3568 | #define DIRECTION 0x04 |
| 3542 | #define FIFOFLUSH 0x02 | 3569 | #define FIFOFLUSH 0x02 |
| 3543 | #define FIFORESET 0x01 | 3570 | #define FIFORESET 0x01 |
| 3544 | 3571 | ||
| 3545 | #define SEQ_FLAGS 0x133 | 3572 | #define SEQ_FLAGS 0x139 |
| 3546 | #define NOT_IDENTIFIED 0x80 | 3573 | #define NOT_IDENTIFIED 0x80 |
| 3547 | #define NO_CDB_SENT 0x40 | 3574 | #define NO_CDB_SENT 0x40 |
| 3548 | #define TARGET_CMD_IS_TAGGED 0x40 | 3575 | #define TARGET_CMD_IS_TAGGED 0x40 |
| @@ -3553,11 +3580,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3553 | #define SPHASE_PENDING 0x02 | 3580 | #define SPHASE_PENDING 0x02 |
| 3554 | #define NO_DISCONNECT 0x01 | 3581 | #define NO_DISCONNECT 0x01 |
| 3555 | 3582 | ||
| 3556 | #define SAVED_SCSIID 0x134 | 3583 | #define SAVED_SCSIID 0x13a |
| 3557 | 3584 | ||
| 3558 | #define SAVED_LUN 0x135 | 3585 | #define SAVED_LUN 0x13b |
| 3559 | 3586 | ||
| 3560 | #define LASTPHASE 0x136 | 3587 | #define LASTPHASE 0x13c |
| 3561 | #define PHASE_MASK 0xe0 | 3588 | #define PHASE_MASK 0xe0 |
| 3562 | #define CDI 0x80 | 3589 | #define CDI 0x80 |
| 3563 | #define IOI 0x40 | 3590 | #define IOI 0x40 |
| @@ -3572,18 +3599,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3572 | #define P_DATAOUT_DT 0x20 | 3599 | #define P_DATAOUT_DT 0x20 |
| 3573 | #define P_DATAOUT 0x00 | 3600 | #define P_DATAOUT 0x00 |
| 3574 | 3601 | ||
| 3575 | #define QOUTFIFO_ENTRY_VALID_TAG 0x137 | 3602 | #define QOUTFIFO_ENTRY_VALID_TAG 0x13d |
| 3576 | 3603 | ||
| 3577 | #define SHARED_DATA_ADDR 0x138 | 3604 | #define KERNEL_TQINPOS 0x13e |
| 3578 | 3605 | ||
| 3579 | #define QOUTFIFO_NEXT_ADDR 0x13c | 3606 | #define TQINPOS 0x13f |
| 3580 | 3607 | ||
| 3581 | #define KERNEL_TQINPOS 0x140 | 3608 | #define SHARED_DATA_ADDR 0x140 |
| 3582 | 3609 | ||
| 3583 | #define TQINPOS 0x141 | 3610 | #define QOUTFIFO_NEXT_ADDR 0x144 |
| 3584 | 3611 | ||
| 3585 | #define ARG_1 0x142 | 3612 | #define ARG_1 0x148 |
| 3586 | #define RETURN_1 0x142 | 3613 | #define RETURN_1 0x148 |
| 3587 | #define SEND_MSG 0x80 | 3614 | #define SEND_MSG 0x80 |
| 3588 | #define SEND_SENSE 0x40 | 3615 | #define SEND_SENSE 0x40 |
| 3589 | #define SEND_REJ 0x20 | 3616 | #define SEND_REJ 0x20 |
| @@ -3593,12 +3620,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3593 | #define CONT_MSG_LOOP_READ 0x03 | 3620 | #define CONT_MSG_LOOP_READ 0x03 |
| 3594 | #define CONT_MSG_LOOP_TARG 0x02 | 3621 | #define CONT_MSG_LOOP_TARG 0x02 |
| 3595 | 3622 | ||
| 3596 | #define ARG_2 0x143 | 3623 | #define ARG_2 0x149 |
| 3597 | #define RETURN_2 0x143 | 3624 | #define RETURN_2 0x149 |
| 3598 | 3625 | ||
| 3599 | #define LAST_MSG 0x144 | 3626 | #define LAST_MSG 0x14a |
| 3600 | 3627 | ||
| 3601 | #define SCSISEQ_TEMPLATE 0x145 | 3628 | #define SCSISEQ_TEMPLATE 0x14b |
| 3602 | #define MANUALCTL 0x40 | 3629 | #define MANUALCTL 0x40 |
| 3603 | #define ENSELI 0x20 | 3630 | #define ENSELI 0x20 |
| 3604 | #define ENRSELI 0x10 | 3631 | #define ENRSELI 0x10 |
| @@ -3606,27 +3633,27 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3606 | #define ENAUTOATNP 0x02 | 3633 | #define ENAUTOATNP 0x02 |
| 3607 | #define ALTSTIM 0x01 | 3634 | #define ALTSTIM 0x01 |
| 3608 | 3635 | ||
| 3609 | #define INITIATOR_TAG 0x146 | 3636 | #define INITIATOR_TAG 0x14c |
| 3610 | 3637 | ||
| 3611 | #define SEQ_FLAGS2 0x147 | 3638 | #define SEQ_FLAGS2 0x14d |
| 3612 | #define SELECTOUT_QFROZEN 0x04 | 3639 | #define SELECTOUT_QFROZEN 0x04 |
| 3613 | #define TARGET_MSG_PENDING 0x02 | 3640 | #define TARGET_MSG_PENDING 0x02 |
| 3614 | 3641 | ||
| 3615 | #define ALLOCFIFO_SCBPTR 0x148 | 3642 | #define ALLOCFIFO_SCBPTR 0x14e |
| 3616 | 3643 | ||
| 3617 | #define INT_COALESCING_TIMER 0x14a | 3644 | #define INT_COALESCING_TIMER 0x150 |
| 3618 | 3645 | ||
| 3619 | #define INT_COALESCING_MAXCMDS 0x14c | 3646 | #define INT_COALESCING_MAXCMDS 0x152 |
| 3620 | 3647 | ||
| 3621 | #define INT_COALESCING_MINCMDS 0x14d | 3648 | #define INT_COALESCING_MINCMDS 0x153 |
| 3622 | 3649 | ||
| 3623 | #define CMDS_PENDING 0x14e | 3650 | #define CMDS_PENDING 0x154 |
| 3624 | 3651 | ||
| 3625 | #define INT_COALESCING_CMDCOUNT 0x150 | 3652 | #define INT_COALESCING_CMDCOUNT 0x156 |
| 3626 | 3653 | ||
| 3627 | #define LOCAL_HS_MAILBOX 0x151 | 3654 | #define LOCAL_HS_MAILBOX 0x157 |
| 3628 | 3655 | ||
| 3629 | #define CMDSIZE_TABLE 0x152 | 3656 | #define CMDSIZE_TABLE 0x158 |
| 3630 | 3657 | ||
| 3631 | #define SCB_BASE 0x180 | 3658 | #define SCB_BASE 0x180 |
| 3632 | 3659 | ||
| @@ -3701,6 +3728,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3701 | #define SCB_DISCONNECTED_LISTS 0x1b8 | 3728 | #define SCB_DISCONNECTED_LISTS 0x1b8 |
| 3702 | 3729 | ||
| 3703 | 3730 | ||
| 3731 | #define AHD_TIMER_MAX_US 0x18ffe7 | ||
| 3732 | #define AHD_TIMER_MAX_TICKS 0xffff | ||
| 3733 | #define AHD_SENSE_BUFSIZE 0x100 | ||
| 3734 | #define BUS_8_BIT 0x00 | ||
| 3735 | #define TARGET_CMD_CMPLT 0xfe | ||
| 3736 | #define SEEOP_WRAL_ADDR 0x40 | ||
| 3737 | #define AHD_AMPLITUDE_DEF 0x07 | ||
| 3738 | #define AHD_PRECOMP_CUTBACK_37 0x07 | ||
| 3739 | #define AHD_PRECOMP_SHIFT 0x00 | ||
| 3740 | #define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 | ||
| 3704 | #define AHD_TIMER_US_PER_TICK 0x19 | 3741 | #define AHD_TIMER_US_PER_TICK 0x19 |
| 3705 | #define SCB_TRANSFER_SIZE_FULL_LUN 0x38 | 3742 | #define SCB_TRANSFER_SIZE_FULL_LUN 0x38 |
| 3706 | #define STATUS_QUEUE_FULL 0x28 | 3743 | #define STATUS_QUEUE_FULL 0x28 |
| @@ -3724,28 +3761,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3724 | #define B_CURRFIFO_0 0x02 | 3761 | #define B_CURRFIFO_0 0x02 |
| 3725 | #define LUNLEN_SINGLE_LEVEL_LUN 0x0f | 3762 | #define LUNLEN_SINGLE_LEVEL_LUN 0x0f |
| 3726 | #define NVRAM_SCB_OFFSET 0x2c | 3763 | #define NVRAM_SCB_OFFSET 0x2c |
| 3727 | #define AHD_TIMER_MAX_US 0x18ffe7 | ||
| 3728 | #define AHD_TIMER_MAX_TICKS 0xffff | ||
| 3729 | #define STATUS_PKT_SENSE 0xff | 3764 | #define STATUS_PKT_SENSE 0xff |
| 3730 | #define CMD_GROUP_CODE_SHIFT 0x05 | 3765 | #define CMD_GROUP_CODE_SHIFT 0x05 |
| 3731 | #define AHD_SENSE_BUFSIZE 0x100 | ||
| 3732 | #define MAX_OFFSET_PACED_BUG 0x7f | 3766 | #define MAX_OFFSET_PACED_BUG 0x7f |
| 3733 | #define BUS_8_BIT 0x00 | ||
| 3734 | #define STIMESEL_BUG_ADJ 0x08 | 3767 | #define STIMESEL_BUG_ADJ 0x08 |
| 3735 | #define STIMESEL_MIN 0x18 | 3768 | #define STIMESEL_MIN 0x18 |
| 3736 | #define STIMESEL_SHIFT 0x03 | 3769 | #define STIMESEL_SHIFT 0x03 |
| 3737 | #define CCSGRAM_MAXSEGS 0x10 | 3770 | #define CCSGRAM_MAXSEGS 0x10 |
| 3738 | #define INVALID_ADDR 0x80 | 3771 | #define INVALID_ADDR 0x80 |
| 3739 | #define TARGET_CMD_CMPLT 0xfe | ||
| 3740 | #define SEEOP_WRAL_ADDR 0x40 | ||
| 3741 | #define SEEOP_ERAL_ADDR 0x80 | 3772 | #define SEEOP_ERAL_ADDR 0x80 |
| 3742 | #define AHD_AMPLITUDE_DEF 0x07 | ||
| 3743 | #define AHD_SLEWRATE_DEF_REVB 0x08 | 3773 | #define AHD_SLEWRATE_DEF_REVB 0x08 |
| 3744 | #define AHD_PRECOMP_CUTBACK_37 0x07 | ||
| 3745 | #define AHD_PRECOMP_CUTBACK_17 0x04 | 3774 | #define AHD_PRECOMP_CUTBACK_17 0x04 |
| 3746 | #define AHD_PRECOMP_SHIFT 0x00 | ||
| 3747 | #define AHD_PRECOMP_MASK 0x07 | 3775 | #define AHD_PRECOMP_MASK 0x07 |
| 3748 | #define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 | ||
| 3749 | #define SRC_MODE_SHIFT 0x00 | 3776 | #define SRC_MODE_SHIFT 0x00 |
| 3750 | #define PKT_OVERRUN_BUFSIZE 0x200 | 3777 | #define PKT_OVERRUN_BUFSIZE 0x200 |
| 3751 | #define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30 | 3778 | #define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30 |
| @@ -3761,6 +3788,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3761 | 3788 | ||
| 3762 | 3789 | ||
| 3763 | /* Downloaded Constant Definitions */ | 3790 | /* Downloaded Constant Definitions */ |
| 3791 | #define CACHELINE_MASK 0x07 | ||
| 3764 | #define SCB_TRANSFER_SIZE 0x06 | 3792 | #define SCB_TRANSFER_SIZE 0x06 |
| 3765 | #define PKT_OVERRUN_BUFOFFSET 0x05 | 3793 | #define PKT_OVERRUN_BUFOFFSET 0x05 |
| 3766 | #define SG_SIZEOF 0x04 | 3794 | #define SG_SIZEOF 0x04 |
| @@ -3768,9 +3796,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; | |||
| 3768 | #define SG_PREFETCH_ALIGN_MASK 0x02 | 3796 | #define SG_PREFETCH_ALIGN_MASK 0x02 |
| 3769 | #define SG_PREFETCH_CNT_LIMIT 0x01 | 3797 | #define SG_PREFETCH_CNT_LIMIT 0x01 |
| 3770 | #define SG_PREFETCH_CNT 0x00 | 3798 | #define SG_PREFETCH_CNT 0x00 |
| 3771 | #define DOWNLOAD_CONST_COUNT 0x07 | 3799 | #define DOWNLOAD_CONST_COUNT 0x08 |
| 3772 | 3800 | ||
| 3773 | 3801 | ||
| 3774 | /* Exported Labels */ | 3802 | /* Exported Labels */ |
| 3775 | #define LABEL_seq_isr 0x269 | 3803 | #define LABEL_seq_isr 0x285 |
| 3776 | #define LABEL_timer_isr 0x265 | 3804 | #define LABEL_timer_isr 0x281 |
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped index 3098a757e3d7..a4137c985376 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | * DO NOT EDIT - This file is automatically generated | 2 | * DO NOT EDIT - This file is automatically generated |
| 3 | * from the following source files: | 3 | * from the following source files: |
| 4 | * | 4 | * |
| 5 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ | 5 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ |
| 6 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ | 6 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include "aic79xx_osm.h" | 9 | #include "aic79xx_osm.h" |
| @@ -172,21 +172,6 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 172 | 0x0b, regvalue, cur_col, wrap)); | 172 | 0x0b, regvalue, cur_col, wrap)); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { | ||
| 176 | { "CLRSEQ_SPLTINT", 0x01, 0x01 }, | ||
| 177 | { "CLRSEQ_PCIINT", 0x02, 0x02 }, | ||
| 178 | { "CLRSEQ_SCSIINT", 0x04, 0x04 }, | ||
| 179 | { "CLRSEQ_SEQINT", 0x08, 0x08 }, | ||
| 180 | { "CLRSEQ_SWTMRTO", 0x10, 0x10 } | ||
| 181 | }; | ||
| 182 | |||
| 183 | int | ||
| 184 | ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 185 | { | ||
| 186 | return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", | ||
| 187 | 0x0c, regvalue, cur_col, wrap)); | ||
| 188 | } | ||
| 189 | |||
| 190 | static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = { | 175 | static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = { |
| 191 | { "SEQ_SPLTINT", 0x01, 0x01 }, | 176 | { "SEQ_SPLTINT", 0x01, 0x01 }, |
| 192 | { "SEQ_PCIINT", 0x02, 0x02 }, | 177 | { "SEQ_PCIINT", 0x02, 0x02 }, |
| @@ -202,6 +187,21 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 202 | 0x0c, regvalue, cur_col, wrap)); | 187 | 0x0c, regvalue, cur_col, wrap)); |
| 203 | } | 188 | } |
| 204 | 189 | ||
| 190 | static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { | ||
| 191 | { "CLRSEQ_SPLTINT", 0x01, 0x01 }, | ||
| 192 | { "CLRSEQ_PCIINT", 0x02, 0x02 }, | ||
| 193 | { "CLRSEQ_SCSIINT", 0x04, 0x04 }, | ||
| 194 | { "CLRSEQ_SEQINT", 0x08, 0x08 }, | ||
| 195 | { "CLRSEQ_SWTMRTO", 0x10, 0x10 } | ||
| 196 | }; | ||
| 197 | |||
| 198 | int | ||
| 199 | ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 200 | { | ||
| 201 | return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", | ||
| 202 | 0x0c, regvalue, cur_col, wrap)); | ||
| 203 | } | ||
| 204 | |||
| 205 | int | 205 | int |
| 206 | ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap) | 206 | ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 207 | { | 207 | { |
| @@ -670,16 +670,16 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 670 | } | 670 | } |
| 671 | 671 | ||
| 672 | int | 672 | int |
| 673 | ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) | 673 | ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 674 | { | 674 | { |
| 675 | return (ahd_print_register(NULL, 0, "BUSINITID", | 675 | return (ahd_print_register(NULL, 0, "DLCOUNT", |
| 676 | 0x3c, regvalue, cur_col, wrap)); | 676 | 0x3c, regvalue, cur_col, wrap)); |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | int | 679 | int |
| 680 | ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) | 680 | ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 681 | { | 681 | { |
| 682 | return (ahd_print_register(NULL, 0, "DLCOUNT", | 682 | return (ahd_print_register(NULL, 0, "BUSINITID", |
| 683 | 0x3c, regvalue, cur_col, wrap)); | 683 | 0x3c, regvalue, cur_col, wrap)); |
| 684 | } | 684 | } |
| 685 | 685 | ||
| @@ -859,21 +859,6 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 859 | 0x49, regvalue, cur_col, wrap)); | 859 | 0x49, regvalue, cur_col, wrap)); |
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { | ||
| 863 | { "SELWIDE", 0x02, 0x02 }, | ||
| 864 | { "ENAB20", 0x04, 0x04 }, | ||
| 865 | { "ENAB40", 0x08, 0x08 }, | ||
| 866 | { "DIAGLEDON", 0x40, 0x40 }, | ||
| 867 | { "DIAGLEDEN", 0x80, 0x80 } | ||
| 868 | }; | ||
| 869 | |||
| 870 | int | ||
| 871 | ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 872 | { | ||
| 873 | return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", | ||
| 874 | 0x4a, regvalue, cur_col, wrap)); | ||
| 875 | } | ||
| 876 | |||
| 877 | static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = { | 862 | static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = { |
| 878 | { "AUTO_MSGOUT_DE", 0x02, 0x02 }, | 863 | { "AUTO_MSGOUT_DE", 0x02, 0x02 }, |
| 879 | { "ENDGFORMCHK", 0x04, 0x04 }, | 864 | { "ENDGFORMCHK", 0x04, 0x04 }, |
| @@ -891,22 +876,19 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 891 | 0x4a, regvalue, cur_col, wrap)); | 876 | 0x4a, regvalue, cur_col, wrap)); |
| 892 | } | 877 | } |
| 893 | 878 | ||
| 894 | static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { | 879 | static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { |
| 895 | { "ARBDO", 0x01, 0x01 }, | 880 | { "SELWIDE", 0x02, 0x02 }, |
| 896 | { "SPIORDY", 0x02, 0x02 }, | 881 | { "ENAB20", 0x04, 0x04 }, |
| 897 | { "OVERRUN", 0x04, 0x04 }, | 882 | { "ENAB40", 0x08, 0x08 }, |
| 898 | { "IOERR", 0x08, 0x08 }, | 883 | { "DIAGLEDON", 0x40, 0x40 }, |
| 899 | { "SELINGO", 0x10, 0x10 }, | 884 | { "DIAGLEDEN", 0x80, 0x80 } |
| 900 | { "SELDI", 0x20, 0x20 }, | ||
| 901 | { "SELDO", 0x40, 0x40 }, | ||
| 902 | { "TARGET", 0x80, 0x80 } | ||
| 903 | }; | 885 | }; |
| 904 | 886 | ||
| 905 | int | 887 | int |
| 906 | ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) | 888 | ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 907 | { | 889 | { |
| 908 | return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", | 890 | return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", |
| 909 | 0x4b, regvalue, cur_col, wrap)); | 891 | 0x4a, regvalue, cur_col, wrap)); |
| 910 | } | 892 | } |
| 911 | 893 | ||
| 912 | static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = { | 894 | static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = { |
| @@ -926,6 +908,24 @@ ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 926 | 0x4b, regvalue, cur_col, wrap)); | 908 | 0x4b, regvalue, cur_col, wrap)); |
| 927 | } | 909 | } |
| 928 | 910 | ||
| 911 | static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { | ||
| 912 | { "ARBDO", 0x01, 0x01 }, | ||
| 913 | { "SPIORDY", 0x02, 0x02 }, | ||
| 914 | { "OVERRUN", 0x04, 0x04 }, | ||
| 915 | { "IOERR", 0x08, 0x08 }, | ||
| 916 | { "SELINGO", 0x10, 0x10 }, | ||
| 917 | { "SELDI", 0x20, 0x20 }, | ||
| 918 | { "SELDO", 0x40, 0x40 }, | ||
| 919 | { "TARGET", 0x80, 0x80 } | ||
| 920 | }; | ||
| 921 | |||
| 922 | int | ||
| 923 | ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 924 | { | ||
| 925 | return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", | ||
| 926 | 0x4b, regvalue, cur_col, wrap)); | ||
| 927 | } | ||
| 928 | |||
| 929 | static ahd_reg_parse_entry_t SIMODE0_parse_table[] = { | 929 | static ahd_reg_parse_entry_t SIMODE0_parse_table[] = { |
| 930 | { "ENARBDO", 0x01, 0x01 }, | 930 | { "ENARBDO", 0x01, 0x01 }, |
| 931 | { "ENSPIORDY", 0x02, 0x02 }, | 931 | { "ENSPIORDY", 0x02, 0x02 }, |
| @@ -998,30 +998,30 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 998 | 0x4d, regvalue, cur_col, wrap)); | 998 | 0x4d, regvalue, cur_col, wrap)); |
| 999 | } | 999 | } |
| 1000 | 1000 | ||
| 1001 | static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { | 1001 | static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { |
| 1002 | { "CLRDMADONE", 0x01, 0x01 }, | 1002 | { "ENDMADONE", 0x01, 0x01 }, |
| 1003 | { "CLRSDONE", 0x02, 0x02 }, | 1003 | { "ENSDONE", 0x02, 0x02 }, |
| 1004 | { "CLRWIDE_RES", 0x04, 0x04 }, | 1004 | { "ENWIDE_RES", 0x04, 0x04 } |
| 1005 | { "CLRNONPACKREQ", 0x20, 0x20 } | ||
| 1006 | }; | 1005 | }; |
| 1007 | 1006 | ||
| 1008 | int | 1007 | int |
| 1009 | ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1008 | ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1010 | { | 1009 | { |
| 1011 | return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", | 1010 | return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", |
| 1012 | 0x4d, regvalue, cur_col, wrap)); | 1011 | 0x4d, regvalue, cur_col, wrap)); |
| 1013 | } | 1012 | } |
| 1014 | 1013 | ||
| 1015 | static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { | 1014 | static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { |
| 1016 | { "ENDMADONE", 0x01, 0x01 }, | 1015 | { "CLRDMADONE", 0x01, 0x01 }, |
| 1017 | { "ENSDONE", 0x02, 0x02 }, | 1016 | { "CLRSDONE", 0x02, 0x02 }, |
| 1018 | { "ENWIDE_RES", 0x04, 0x04 } | 1017 | { "CLRWIDE_RES", 0x04, 0x04 }, |
| 1018 | { "CLRNONPACKREQ", 0x20, 0x20 } | ||
| 1019 | }; | 1019 | }; |
| 1020 | 1020 | ||
| 1021 | int | 1021 | int |
| 1022 | ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1022 | ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1023 | { | 1023 | { |
| 1024 | return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", | 1024 | return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", |
| 1025 | 0x4d, regvalue, cur_col, wrap)); | 1025 | 0x4d, regvalue, cur_col, wrap)); |
| 1026 | } | 1026 | } |
| 1027 | 1027 | ||
| @@ -1220,21 +1220,6 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1220 | 0x53, regvalue, cur_col, wrap)); | 1220 | 0x53, regvalue, cur_col, wrap)); |
| 1221 | } | 1221 | } |
| 1222 | 1222 | ||
| 1223 | static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { | ||
| 1224 | { "ENLQOTCRC", 0x01, 0x01 }, | ||
| 1225 | { "ENLQOATNPKT", 0x02, 0x02 }, | ||
| 1226 | { "ENLQOATNLQ", 0x04, 0x04 }, | ||
| 1227 | { "ENLQOSTOPT2", 0x08, 0x08 }, | ||
| 1228 | { "ENLQOTARGSCBPERR", 0x10, 0x10 } | ||
| 1229 | }; | ||
| 1230 | |||
| 1231 | int | ||
| 1232 | ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1233 | { | ||
| 1234 | return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", | ||
| 1235 | 0x54, regvalue, cur_col, wrap)); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = { | 1223 | static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = { |
| 1239 | { "LQOTCRC", 0x01, 0x01 }, | 1224 | { "LQOTCRC", 0x01, 0x01 }, |
| 1240 | { "LQOATNPKT", 0x02, 0x02 }, | 1225 | { "LQOATNPKT", 0x02, 0x02 }, |
| @@ -1265,6 +1250,36 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1265 | 0x54, regvalue, cur_col, wrap)); | 1250 | 0x54, regvalue, cur_col, wrap)); |
| 1266 | } | 1251 | } |
| 1267 | 1252 | ||
| 1253 | static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { | ||
| 1254 | { "ENLQOTCRC", 0x01, 0x01 }, | ||
| 1255 | { "ENLQOATNPKT", 0x02, 0x02 }, | ||
| 1256 | { "ENLQOATNLQ", 0x04, 0x04 }, | ||
| 1257 | { "ENLQOSTOPT2", 0x08, 0x08 }, | ||
| 1258 | { "ENLQOTARGSCBPERR", 0x10, 0x10 } | ||
| 1259 | }; | ||
| 1260 | |||
| 1261 | int | ||
| 1262 | ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1263 | { | ||
| 1264 | return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", | ||
| 1265 | 0x54, regvalue, cur_col, wrap)); | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { | ||
| 1269 | { "ENLQOPHACHGINPKT", 0x01, 0x01 }, | ||
| 1270 | { "ENLQOBUSFREE", 0x02, 0x02 }, | ||
| 1271 | { "ENLQOBADQAS", 0x04, 0x04 }, | ||
| 1272 | { "ENLQOSTOPI2", 0x08, 0x08 }, | ||
| 1273 | { "ENLQOINITSCBPERR", 0x10, 0x10 } | ||
| 1274 | }; | ||
| 1275 | |||
| 1276 | int | ||
| 1277 | ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1278 | { | ||
| 1279 | return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", | ||
| 1280 | 0x55, regvalue, cur_col, wrap)); | ||
| 1281 | } | ||
| 1282 | |||
| 1268 | static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = { | 1283 | static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = { |
| 1269 | { "LQOPHACHGINPKT", 0x01, 0x01 }, | 1284 | { "LQOPHACHGINPKT", 0x01, 0x01 }, |
| 1270 | { "LQOBUSFREE", 0x02, 0x02 }, | 1285 | { "LQOBUSFREE", 0x02, 0x02 }, |
| @@ -1295,21 +1310,6 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1295 | 0x55, regvalue, cur_col, wrap)); | 1310 | 0x55, regvalue, cur_col, wrap)); |
| 1296 | } | 1311 | } |
| 1297 | 1312 | ||
| 1298 | static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { | ||
| 1299 | { "ENLQOPHACHGINPKT", 0x01, 0x01 }, | ||
| 1300 | { "ENLQOBUSFREE", 0x02, 0x02 }, | ||
| 1301 | { "ENLQOBADQAS", 0x04, 0x04 }, | ||
| 1302 | { "ENLQOSTOPI2", 0x08, 0x08 }, | ||
| 1303 | { "ENLQOINITSCBPERR", 0x10, 0x10 } | ||
| 1304 | }; | ||
| 1305 | |||
| 1306 | int | ||
| 1307 | ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1308 | { | ||
| 1309 | return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", | ||
| 1310 | 0x55, regvalue, cur_col, wrap)); | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = { | 1313 | static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = { |
| 1314 | { "LQOSTOP0", 0x01, 0x01 }, | 1314 | { "LQOSTOP0", 0x01, 0x01 }, |
| 1315 | { "LQOPHACHGOUTPKT", 0x02, 0x02 }, | 1315 | { "LQOPHACHGOUTPKT", 0x02, 0x02 }, |
| @@ -1594,6 +1594,13 @@ ahd_annexcol_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1594 | 0x65, regvalue, cur_col, wrap)); | 1594 | 0x65, regvalue, cur_col, wrap)); |
| 1595 | } | 1595 | } |
| 1596 | 1596 | ||
| 1597 | int | ||
| 1598 | ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1599 | { | ||
| 1600 | return (ahd_print_register(NULL, 0, "ANNEXDAT", | ||
| 1601 | 0x66, regvalue, cur_col, wrap)); | ||
| 1602 | } | ||
| 1603 | |||
| 1597 | static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = { | 1604 | static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = { |
| 1598 | { "LSTSGCLRDIS", 0x01, 0x01 }, | 1605 | { "LSTSGCLRDIS", 0x01, 0x01 }, |
| 1599 | { "SHVALIDSTDIS", 0x02, 0x02 }, | 1606 | { "SHVALIDSTDIS", 0x02, 0x02 }, |
| @@ -1612,13 +1619,6 @@ ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1612 | } | 1619 | } |
| 1613 | 1620 | ||
| 1614 | int | 1621 | int |
| 1615 | ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1616 | { | ||
| 1617 | return (ahd_print_register(NULL, 0, "ANNEXDAT", | ||
| 1618 | 0x66, regvalue, cur_col, wrap)); | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | int | ||
| 1622 | ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1622 | ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1623 | { | 1623 | { |
| 1624 | return (ahd_print_register(NULL, 0, "IOWNID", | 1624 | return (ahd_print_register(NULL, 0, "IOWNID", |
| @@ -1728,16 +1728,16 @@ ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1728 | } | 1728 | } |
| 1729 | 1729 | ||
| 1730 | int | 1730 | int |
| 1731 | ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1731 | ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1732 | { | 1732 | { |
| 1733 | return (ahd_print_register(NULL, 0, "PLL400CNT0", | 1733 | return (ahd_print_register(NULL, 0, "UNFAIRNESS", |
| 1734 | 0x6e, regvalue, cur_col, wrap)); | 1734 | 0x6e, regvalue, cur_col, wrap)); |
| 1735 | } | 1735 | } |
| 1736 | 1736 | ||
| 1737 | int | 1737 | int |
| 1738 | ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1738 | ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1739 | { | 1739 | { |
| 1740 | return (ahd_print_register(NULL, 0, "UNFAIRNESS", | 1740 | return (ahd_print_register(NULL, 0, "PLL400CNT0", |
| 1741 | 0x6e, regvalue, cur_col, wrap)); | 1741 | 0x6e, regvalue, cur_col, wrap)); |
| 1742 | } | 1742 | } |
| 1743 | 1743 | ||
| @@ -1788,30 +1788,30 @@ ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1788 | } | 1788 | } |
| 1789 | 1789 | ||
| 1790 | int | 1790 | int |
| 1791 | ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1791 | ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1792 | { | 1792 | { |
| 1793 | return (ahd_print_register(NULL, 0, "SGHADDR", | 1793 | return (ahd_print_register(NULL, 0, "SCBHADDR", |
| 1794 | 0x7c, regvalue, cur_col, wrap)); | 1794 | 0x7c, regvalue, cur_col, wrap)); |
| 1795 | } | 1795 | } |
| 1796 | 1796 | ||
| 1797 | int | 1797 | int |
| 1798 | ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1798 | ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1799 | { | 1799 | { |
| 1800 | return (ahd_print_register(NULL, 0, "SCBHADDR", | 1800 | return (ahd_print_register(NULL, 0, "SGHADDR", |
| 1801 | 0x7c, regvalue, cur_col, wrap)); | 1801 | 0x7c, regvalue, cur_col, wrap)); |
| 1802 | } | 1802 | } |
| 1803 | 1803 | ||
| 1804 | int | 1804 | int |
| 1805 | ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1805 | ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1806 | { | 1806 | { |
| 1807 | return (ahd_print_register(NULL, 0, "SGHCNT", | 1807 | return (ahd_print_register(NULL, 0, "SCBHCNT", |
| 1808 | 0x84, regvalue, cur_col, wrap)); | 1808 | 0x84, regvalue, cur_col, wrap)); |
| 1809 | } | 1809 | } |
| 1810 | 1810 | ||
| 1811 | int | 1811 | int |
| 1812 | ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1812 | ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1813 | { | 1813 | { |
| 1814 | return (ahd_print_register(NULL, 0, "SCBHCNT", | 1814 | return (ahd_print_register(NULL, 0, "SGHCNT", |
| 1815 | 0x84, regvalue, cur_col, wrap)); | 1815 | 0x84, regvalue, cur_col, wrap)); |
| 1816 | } | 1816 | } |
| 1817 | 1817 | ||
| @@ -1950,25 +1950,25 @@ ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1950 | 0x91, regvalue, cur_col, wrap)); | 1950 | 0x91, regvalue, cur_col, wrap)); |
| 1951 | } | 1951 | } |
| 1952 | 1952 | ||
| 1953 | static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { | 1953 | static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { |
| 1954 | { "CBNUM", 0xff, 0xff } | 1954 | { "CBNUM", 0xff, 0xff } |
| 1955 | }; | 1955 | }; |
| 1956 | 1956 | ||
| 1957 | int | 1957 | int |
| 1958 | ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1958 | ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1959 | { | 1959 | { |
| 1960 | return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", | 1960 | return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", |
| 1961 | 0x91, regvalue, cur_col, wrap)); | 1961 | 0x91, regvalue, cur_col, wrap)); |
| 1962 | } | 1962 | } |
| 1963 | 1963 | ||
| 1964 | static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { | 1964 | static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { |
| 1965 | { "CBNUM", 0xff, 0xff } | 1965 | { "CBNUM", 0xff, 0xff } |
| 1966 | }; | 1966 | }; |
| 1967 | 1967 | ||
| 1968 | int | 1968 | int |
| 1969 | ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 1969 | ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 1970 | { | 1970 | { |
| 1971 | return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", | 1971 | return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", |
| 1972 | 0x91, regvalue, cur_col, wrap)); | 1972 | 0x91, regvalue, cur_col, wrap)); |
| 1973 | } | 1973 | } |
| 1974 | 1974 | ||
| @@ -1983,17 +1983,6 @@ ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 1983 | 0x92, regvalue, cur_col, wrap)); | 1983 | 0x92, regvalue, cur_col, wrap)); |
| 1984 | } | 1984 | } |
| 1985 | 1985 | ||
| 1986 | static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { | ||
| 1987 | { "MINDEX", 0xff, 0xff } | ||
| 1988 | }; | ||
| 1989 | |||
| 1990 | int | ||
| 1991 | ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 1992 | { | ||
| 1993 | return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", | ||
| 1994 | 0x92, regvalue, cur_col, wrap)); | ||
| 1995 | } | ||
| 1996 | |||
| 1997 | static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = { | 1986 | static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = { |
| 1998 | { "MINDEX", 0xff, 0xff } | 1987 | { "MINDEX", 0xff, 0xff } |
| 1999 | }; | 1988 | }; |
| @@ -2012,6 +2001,17 @@ ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2012 | 0x92, regvalue, cur_col, wrap)); | 2001 | 0x92, regvalue, cur_col, wrap)); |
| 2013 | } | 2002 | } |
| 2014 | 2003 | ||
| 2004 | static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { | ||
| 2005 | { "MINDEX", 0xff, 0xff } | ||
| 2006 | }; | ||
| 2007 | |||
| 2008 | int | ||
| 2009 | ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 2010 | { | ||
| 2011 | return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", | ||
| 2012 | 0x92, regvalue, cur_col, wrap)); | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = { | 2015 | static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = { |
| 2016 | { "MCLASS", 0x0f, 0x0f } | 2016 | { "MCLASS", 0x0f, 0x0f } |
| 2017 | }; | 2017 | }; |
| @@ -2023,6 +2023,17 @@ ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2023 | 0x93, regvalue, cur_col, wrap)); | 2023 | 0x93, regvalue, cur_col, wrap)); |
| 2024 | } | 2024 | } |
| 2025 | 2025 | ||
| 2026 | static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { | ||
| 2027 | { "MCLASS", 0x0f, 0x0f } | ||
| 2028 | }; | ||
| 2029 | |||
| 2030 | int | ||
| 2031 | ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 2032 | { | ||
| 2033 | return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", | ||
| 2034 | 0x93, regvalue, cur_col, wrap)); | ||
| 2035 | } | ||
| 2036 | |||
| 2026 | static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = { | 2037 | static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = { |
| 2027 | { "MCLASS", 0x0f, 0x0f } | 2038 | { "MCLASS", 0x0f, 0x0f } |
| 2028 | }; | 2039 | }; |
| @@ -2051,17 +2062,6 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2051 | 0x93, regvalue, cur_col, wrap)); | 2062 | 0x93, regvalue, cur_col, wrap)); |
| 2052 | } | 2063 | } |
| 2053 | 2064 | ||
| 2054 | static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { | ||
| 2055 | { "MCLASS", 0x0f, 0x0f } | ||
| 2056 | }; | ||
| 2057 | |||
| 2058 | int | ||
| 2059 | ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 2060 | { | ||
| 2061 | return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", | ||
| 2062 | 0x93, regvalue, cur_col, wrap)); | ||
| 2063 | } | ||
| 2064 | |||
| 2065 | int | 2065 | int |
| 2066 | ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2066 | ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2067 | { | 2067 | { |
| @@ -2070,16 +2070,16 @@ ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2070 | } | 2070 | } |
| 2071 | 2071 | ||
| 2072 | int | 2072 | int |
| 2073 | ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2073 | ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2074 | { | 2074 | { |
| 2075 | return (ahd_print_register(NULL, 0, "CMCSEQBCNT", | 2075 | return (ahd_print_register(NULL, 0, "DCHSEQBCNT", |
| 2076 | 0x94, regvalue, cur_col, wrap)); | 2076 | 0x94, regvalue, cur_col, wrap)); |
| 2077 | } | 2077 | } |
| 2078 | 2078 | ||
| 2079 | int | 2079 | int |
| 2080 | ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2080 | ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2081 | { | 2081 | { |
| 2082 | return (ahd_print_register(NULL, 0, "DCHSEQBCNT", | 2082 | return (ahd_print_register(NULL, 0, "CMCSEQBCNT", |
| 2083 | 0x94, regvalue, cur_col, wrap)); | 2083 | 0x94, regvalue, cur_col, wrap)); |
| 2084 | } | 2084 | } |
| 2085 | 2085 | ||
| @@ -2101,7 +2101,7 @@ ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2101 | 0x96, regvalue, cur_col, wrap)); | 2101 | 0x96, regvalue, cur_col, wrap)); |
| 2102 | } | 2102 | } |
| 2103 | 2103 | ||
| 2104 | static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { | 2104 | static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { |
| 2105 | { "RXSPLTRSP", 0x01, 0x01 }, | 2105 | { "RXSPLTRSP", 0x01, 0x01 }, |
| 2106 | { "RXSCEMSG", 0x02, 0x02 }, | 2106 | { "RXSCEMSG", 0x02, 0x02 }, |
| 2107 | { "RXOVRUN", 0x04, 0x04 }, | 2107 | { "RXOVRUN", 0x04, 0x04 }, |
| @@ -2113,13 +2113,13 @@ static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { | |||
| 2113 | }; | 2113 | }; |
| 2114 | 2114 | ||
| 2115 | int | 2115 | int |
| 2116 | ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2116 | ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2117 | { | 2117 | { |
| 2118 | return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", | 2118 | return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", |
| 2119 | 0x96, regvalue, cur_col, wrap)); | 2119 | 0x96, regvalue, cur_col, wrap)); |
| 2120 | } | 2120 | } |
| 2121 | 2121 | ||
| 2122 | static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { | 2122 | static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { |
| 2123 | { "RXSPLTRSP", 0x01, 0x01 }, | 2123 | { "RXSPLTRSP", 0x01, 0x01 }, |
| 2124 | { "RXSCEMSG", 0x02, 0x02 }, | 2124 | { "RXSCEMSG", 0x02, 0x02 }, |
| 2125 | { "RXOVRUN", 0x04, 0x04 }, | 2125 | { "RXOVRUN", 0x04, 0x04 }, |
| @@ -2131,42 +2131,42 @@ static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { | |||
| 2131 | }; | 2131 | }; |
| 2132 | 2132 | ||
| 2133 | int | 2133 | int |
| 2134 | ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2134 | ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2135 | { | 2135 | { |
| 2136 | return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", | 2136 | return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", |
| 2137 | 0x96, regvalue, cur_col, wrap)); | 2137 | 0x96, regvalue, cur_col, wrap)); |
| 2138 | } | 2138 | } |
| 2139 | 2139 | ||
| 2140 | static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { | 2140 | static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { |
| 2141 | { "RXDATABUCKET", 0x01, 0x01 } | 2141 | { "RXDATABUCKET", 0x01, 0x01 } |
| 2142 | }; | 2142 | }; |
| 2143 | 2143 | ||
| 2144 | int | 2144 | int |
| 2145 | ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2145 | ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2146 | { | 2146 | { |
| 2147 | return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", | 2147 | return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", |
| 2148 | 0x97, regvalue, cur_col, wrap)); | 2148 | 0x97, regvalue, cur_col, wrap)); |
| 2149 | } | 2149 | } |
| 2150 | 2150 | ||
| 2151 | static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { | 2151 | static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { |
| 2152 | { "RXDATABUCKET", 0x01, 0x01 } | 2152 | { "RXDATABUCKET", 0x01, 0x01 } |
| 2153 | }; | 2153 | }; |
| 2154 | 2154 | ||
| 2155 | int | 2155 | int |
| 2156 | ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2156 | ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2157 | { | 2157 | { |
| 2158 | return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", | 2158 | return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", |
| 2159 | 0x97, regvalue, cur_col, wrap)); | 2159 | 0x97, regvalue, cur_col, wrap)); |
| 2160 | } | 2160 | } |
| 2161 | 2161 | ||
| 2162 | static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { | 2162 | static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { |
| 2163 | { "RXDATABUCKET", 0x01, 0x01 } | 2163 | { "RXDATABUCKET", 0x01, 0x01 } |
| 2164 | }; | 2164 | }; |
| 2165 | 2165 | ||
| 2166 | int | 2166 | int |
| 2167 | ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2167 | ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2168 | { | 2168 | { |
| 2169 | return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", | 2169 | return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", |
| 2170 | 0x97, regvalue, cur_col, wrap)); | 2170 | 0x97, regvalue, cur_col, wrap)); |
| 2171 | } | 2171 | } |
| 2172 | 2172 | ||
| @@ -2320,26 +2320,26 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2320 | 0x9e, regvalue, cur_col, wrap)); | 2320 | 0x9e, regvalue, cur_col, wrap)); |
| 2321 | } | 2321 | } |
| 2322 | 2322 | ||
| 2323 | static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { | 2323 | static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { |
| 2324 | { "TEST_NUM", 0x0f, 0x0f }, | 2324 | { "RXDATABUCKET", 0x01, 0x01 } |
| 2325 | { "TEST_GROUP", 0xf0, 0xf0 } | ||
| 2326 | }; | 2325 | }; |
| 2327 | 2326 | ||
| 2328 | int | 2327 | int |
| 2329 | ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2328 | ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2330 | { | 2329 | { |
| 2331 | return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", | 2330 | return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", |
| 2332 | 0x9f, regvalue, cur_col, wrap)); | 2331 | 0x9f, regvalue, cur_col, wrap)); |
| 2333 | } | 2332 | } |
| 2334 | 2333 | ||
| 2335 | static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { | 2334 | static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { |
| 2336 | { "RXDATABUCKET", 0x01, 0x01 } | 2335 | { "TEST_NUM", 0x0f, 0x0f }, |
| 2336 | { "TEST_GROUP", 0xf0, 0xf0 } | ||
| 2337 | }; | 2337 | }; |
| 2338 | 2338 | ||
| 2339 | int | 2339 | int |
| 2340 | ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2340 | ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2341 | { | 2341 | { |
| 2342 | return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", | 2342 | return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", |
| 2343 | 0x9f, regvalue, cur_col, wrap)); | 2343 | 0x9f, regvalue, cur_col, wrap)); |
| 2344 | } | 2344 | } |
| 2345 | 2345 | ||
| @@ -2537,16 +2537,16 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2537 | } | 2537 | } |
| 2538 | 2538 | ||
| 2539 | int | 2539 | int |
| 2540 | ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2540 | ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2541 | { | 2541 | { |
| 2542 | return (ahd_print_register(NULL, 0, "CCSCBADDR", | 2542 | return (ahd_print_register(NULL, 0, "CCSCBADR_BK", |
| 2543 | 0xac, regvalue, cur_col, wrap)); | 2543 | 0xac, regvalue, cur_col, wrap)); |
| 2544 | } | 2544 | } |
| 2545 | 2545 | ||
| 2546 | int | 2546 | int |
| 2547 | ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2547 | ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2548 | { | 2548 | { |
| 2549 | return (ahd_print_register(NULL, 0, "CCSCBADR_BK", | 2549 | return (ahd_print_register(NULL, 0, "CCSCBADDR", |
| 2550 | 0xac, regvalue, cur_col, wrap)); | 2550 | 0xac, regvalue, cur_col, wrap)); |
| 2551 | } | 2551 | } |
| 2552 | 2552 | ||
| @@ -2566,22 +2566,6 @@ ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2566 | 0xad, regvalue, cur_col, wrap)); | 2566 | 0xad, regvalue, cur_col, wrap)); |
| 2567 | } | 2567 | } |
| 2568 | 2568 | ||
| 2569 | static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { | ||
| 2570 | { "CCSGRESET", 0x01, 0x01 }, | ||
| 2571 | { "SG_FETCH_REQ", 0x02, 0x02 }, | ||
| 2572 | { "CCSGENACK", 0x08, 0x08 }, | ||
| 2573 | { "SG_CACHE_AVAIL", 0x10, 0x10 }, | ||
| 2574 | { "CCSGDONE", 0x80, 0x80 }, | ||
| 2575 | { "CCSGEN", 0x0c, 0x0c } | ||
| 2576 | }; | ||
| 2577 | |||
| 2578 | int | ||
| 2579 | ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 2580 | { | ||
| 2581 | return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", | ||
| 2582 | 0xad, regvalue, cur_col, wrap)); | ||
| 2583 | } | ||
| 2584 | |||
| 2585 | static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = { | 2569 | static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = { |
| 2586 | { "CCSCBRESET", 0x01, 0x01 }, | 2570 | { "CCSCBRESET", 0x01, 0x01 }, |
| 2587 | { "CCSCBDIR", 0x04, 0x04 }, | 2571 | { "CCSCBDIR", 0x04, 0x04 }, |
| @@ -2598,6 +2582,22 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2598 | 0xad, regvalue, cur_col, wrap)); | 2582 | 0xad, regvalue, cur_col, wrap)); |
| 2599 | } | 2583 | } |
| 2600 | 2584 | ||
| 2585 | static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { | ||
| 2586 | { "CCSGRESET", 0x01, 0x01 }, | ||
| 2587 | { "SG_FETCH_REQ", 0x02, 0x02 }, | ||
| 2588 | { "CCSGENACK", 0x08, 0x08 }, | ||
| 2589 | { "SG_CACHE_AVAIL", 0x10, 0x10 }, | ||
| 2590 | { "CCSGDONE", 0x80, 0x80 }, | ||
| 2591 | { "CCSGEN", 0x0c, 0x0c } | ||
| 2592 | }; | ||
| 2593 | |||
| 2594 | int | ||
| 2595 | ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 2596 | { | ||
| 2597 | return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", | ||
| 2598 | 0xad, regvalue, cur_col, wrap)); | ||
| 2599 | } | ||
| 2600 | |||
| 2601 | int | 2601 | int |
| 2602 | ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2602 | ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2603 | { | 2603 | { |
| @@ -2841,30 +2841,30 @@ ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 2841 | } | 2841 | } |
| 2842 | 2842 | ||
| 2843 | int | 2843 | int |
| 2844 | ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2844 | ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2845 | { | 2845 | { |
| 2846 | return (ahd_print_register(NULL, 0, "DFPTRS", | 2846 | return (ahd_print_register(NULL, 0, "RCVRBIASCALC", |
| 2847 | 0xc8, regvalue, cur_col, wrap)); | 2847 | 0xc8, regvalue, cur_col, wrap)); |
| 2848 | } | 2848 | } |
| 2849 | 2849 | ||
| 2850 | int | 2850 | int |
| 2851 | ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2851 | ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2852 | { | 2852 | { |
| 2853 | return (ahd_print_register(NULL, 0, "RCVRBIASCALC", | 2853 | return (ahd_print_register(NULL, 0, "DFPTRS", |
| 2854 | 0xc8, regvalue, cur_col, wrap)); | 2854 | 0xc8, regvalue, cur_col, wrap)); |
| 2855 | } | 2855 | } |
| 2856 | 2856 | ||
| 2857 | int | 2857 | int |
| 2858 | ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2858 | ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2859 | { | 2859 | { |
| 2860 | return (ahd_print_register(NULL, 0, "DFBKPTR", | 2860 | return (ahd_print_register(NULL, 0, "SKEWCALC", |
| 2861 | 0xc9, regvalue, cur_col, wrap)); | 2861 | 0xc9, regvalue, cur_col, wrap)); |
| 2862 | } | 2862 | } |
| 2863 | 2863 | ||
| 2864 | int | 2864 | int |
| 2865 | ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) | 2865 | ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 2866 | { | 2866 | { |
| 2867 | return (ahd_print_register(NULL, 0, "SKEWCALC", | 2867 | return (ahd_print_register(NULL, 0, "DFBKPTR", |
| 2868 | 0xc9, regvalue, cur_col, wrap)); | 2868 | 0xc9, regvalue, cur_col, wrap)); |
| 2869 | } | 2869 | } |
| 2870 | 2870 | ||
| @@ -3001,6 +3001,13 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 3001 | 0xe4, regvalue, cur_col, wrap)); | 3001 | 0xe4, regvalue, cur_col, wrap)); |
| 3002 | } | 3002 | } |
| 3003 | 3003 | ||
| 3004 | int | ||
| 3005 | ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 3006 | { | ||
| 3007 | return (ahd_print_register(NULL, 0, "BRKADDR0", | ||
| 3008 | 0xe6, regvalue, cur_col, wrap)); | ||
| 3009 | } | ||
| 3010 | |||
| 3004 | static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = { | 3011 | static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = { |
| 3005 | { "BRKDIS", 0x80, 0x80 } | 3012 | { "BRKDIS", 0x80, 0x80 } |
| 3006 | }; | 3013 | }; |
| @@ -3013,13 +3020,6 @@ ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 3013 | } | 3020 | } |
| 3014 | 3021 | ||
| 3015 | int | 3022 | int |
| 3016 | ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 3017 | { | ||
| 3018 | return (ahd_print_register(NULL, 0, "BRKADDR0", | ||
| 3019 | 0xe6, regvalue, cur_col, wrap)); | ||
| 3020 | } | ||
| 3021 | |||
| 3022 | int | ||
| 3023 | ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3023 | ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3024 | { | 3024 | { |
| 3025 | return (ahd_print_register(NULL, 0, "ALLONES", | 3025 | return (ahd_print_register(NULL, 0, "ALLONES", |
| @@ -3069,30 +3069,30 @@ ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 3069 | } | 3069 | } |
| 3070 | 3070 | ||
| 3071 | int | 3071 | int |
| 3072 | ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3072 | ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3073 | { | 3073 | { |
| 3074 | return (ahd_print_register(NULL, 0, "CURADDR", | 3074 | return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", |
| 3075 | 0xf4, regvalue, cur_col, wrap)); | 3075 | 0xf4, regvalue, cur_col, wrap)); |
| 3076 | } | 3076 | } |
| 3077 | 3077 | ||
| 3078 | int | 3078 | int |
| 3079 | ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3079 | ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3080 | { | 3080 | { |
| 3081 | return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", | 3081 | return (ahd_print_register(NULL, 0, "CURADDR", |
| 3082 | 0xf4, regvalue, cur_col, wrap)); | 3082 | 0xf4, regvalue, cur_col, wrap)); |
| 3083 | } | 3083 | } |
| 3084 | 3084 | ||
| 3085 | int | 3085 | int |
| 3086 | ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3086 | ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3087 | { | 3087 | { |
| 3088 | return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", | 3088 | return (ahd_print_register(NULL, 0, "LASTADDR", |
| 3089 | 0xf6, regvalue, cur_col, wrap)); | 3089 | 0xf6, regvalue, cur_col, wrap)); |
| 3090 | } | 3090 | } |
| 3091 | 3091 | ||
| 3092 | int | 3092 | int |
| 3093 | ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3093 | ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3094 | { | 3094 | { |
| 3095 | return (ahd_print_register(NULL, 0, "LASTADDR", | 3095 | return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", |
| 3096 | 0xf6, regvalue, cur_col, wrap)); | 3096 | 0xf6, regvalue, cur_col, wrap)); |
| 3097 | } | 3097 | } |
| 3098 | 3098 | ||
| @@ -3174,24 +3174,45 @@ ahd_complete_dma_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap) | |||
| 3174 | } | 3174 | } |
| 3175 | 3175 | ||
| 3176 | int | 3176 | int |
| 3177 | ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 3178 | { | ||
| 3179 | return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", | ||
| 3180 | 0x12e, regvalue, cur_col, wrap)); | ||
| 3181 | } | ||
| 3182 | |||
| 3183 | int | ||
| 3184 | ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 3185 | { | ||
| 3186 | return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", | ||
| 3187 | 0x130, regvalue, cur_col, wrap)); | ||
| 3188 | } | ||
| 3189 | |||
| 3190 | int | ||
| 3177 | ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3191 | ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3178 | { | 3192 | { |
| 3179 | return (ahd_print_register(NULL, 0, "QFREEZE_COUNT", | 3193 | return (ahd_print_register(NULL, 0, "QFREEZE_COUNT", |
| 3180 | 0x12e, regvalue, cur_col, wrap)); | 3194 | 0x132, regvalue, cur_col, wrap)); |
| 3195 | } | ||
| 3196 | |||
| 3197 | int | ||
| 3198 | ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) | ||
| 3199 | { | ||
| 3200 | return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", | ||
| 3201 | 0x134, regvalue, cur_col, wrap)); | ||
| 3181 | } | 3202 | } |
| 3182 | 3203 | ||
| 3183 | int | 3204 | int |
| 3184 | ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3205 | ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3185 | { | 3206 | { |
| 3186 | return (ahd_print_register(NULL, 0, "SAVED_MODE", | 3207 | return (ahd_print_register(NULL, 0, "SAVED_MODE", |
| 3187 | 0x130, regvalue, cur_col, wrap)); | 3208 | 0x136, regvalue, cur_col, wrap)); |
| 3188 | } | 3209 | } |
| 3189 | 3210 | ||
| 3190 | int | 3211 | int |
| 3191 | ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3212 | ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3192 | { | 3213 | { |
| 3193 | return (ahd_print_register(NULL, 0, "MSG_OUT", | 3214 | return (ahd_print_register(NULL, 0, "MSG_OUT", |
| 3194 | 0x131, regvalue, cur_col, wrap)); | 3215 | 0x137, regvalue, cur_col, wrap)); |
| 3195 | } | 3216 | } |
| 3196 | 3217 | ||
| 3197 | static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = { | 3218 | static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = { |
| @@ -3211,7 +3232,7 @@ int | |||
| 3211 | ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3232 | ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3212 | { | 3233 | { |
| 3213 | return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS", | 3234 | return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS", |
| 3214 | 0x132, regvalue, cur_col, wrap)); | 3235 | 0x138, regvalue, cur_col, wrap)); |
| 3215 | } | 3236 | } |
| 3216 | 3237 | ||
| 3217 | static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = { | 3238 | static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = { |
| @@ -3230,21 +3251,21 @@ int | |||
| 3230 | ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3251 | ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3231 | { | 3252 | { |
| 3232 | return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS", | 3253 | return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS", |
| 3233 | 0x133, regvalue, cur_col, wrap)); | 3254 | 0x139, regvalue, cur_col, wrap)); |
| 3234 | } | 3255 | } |
| 3235 | 3256 | ||
| 3236 | int | 3257 | int |
| 3237 | ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3258 | ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3238 | { | 3259 | { |
| 3239 | return (ahd_print_register(NULL, 0, "SAVED_SCSIID", | 3260 | return (ahd_print_register(NULL, 0, "SAVED_SCSIID", |
| 3240 | 0x134, regvalue, cur_col, wrap)); | 3261 | 0x13a, regvalue, cur_col, wrap)); |
| 3241 | } | 3262 | } |
| 3242 | 3263 | ||
| 3243 | int | 3264 | int |
| 3244 | ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3265 | ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3245 | { | 3266 | { |
| 3246 | return (ahd_print_register(NULL, 0, "SAVED_LUN", | 3267 | return (ahd_print_register(NULL, 0, "SAVED_LUN", |
| 3247 | 0x135, regvalue, cur_col, wrap)); | 3268 | 0x13b, regvalue, cur_col, wrap)); |
| 3248 | } | 3269 | } |
| 3249 | 3270 | ||
| 3250 | static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = { | 3271 | static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = { |
| @@ -3267,42 +3288,42 @@ int | |||
| 3267 | ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3288 | ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3268 | { | 3289 | { |
| 3269 | return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE", | 3290 | return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE", |
| 3270 | 0x136, regvalue, cur_col, wrap)); | 3291 | 0x13c, regvalue, cur_col, wrap)); |
| 3271 | } | 3292 | } |
| 3272 | 3293 | ||
| 3273 | int | 3294 | int |
| 3274 | ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3295 | ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3275 | { | 3296 | { |
| 3276 | return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", | 3297 | return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", |
| 3277 | 0x137, regvalue, cur_col, wrap)); | 3298 | 0x13d, regvalue, cur_col, wrap)); |
| 3278 | } | 3299 | } |
| 3279 | 3300 | ||
| 3280 | int | 3301 | int |
| 3281 | ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3302 | ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3282 | { | 3303 | { |
| 3283 | return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", | 3304 | return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", |
| 3284 | 0x138, regvalue, cur_col, wrap)); | 3305 | 0x13e, regvalue, cur_col, wrap)); |
| 3285 | } | 3306 | } |
| 3286 | 3307 | ||
| 3287 | int | 3308 | int |
| 3288 | ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3309 | ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3289 | { | 3310 | { |
| 3290 | return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", | 3311 | return (ahd_print_register(NULL, 0, "TQINPOS", |
| 3291 | 0x13c, regvalue, cur_col, wrap)); | 3312 | 0x13f, regvalue, cur_col, wrap)); |
| 3292 | } | 3313 | } |
| 3293 | 3314 | ||
| 3294 | int | 3315 | int |
| 3295 | ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3316 | ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3296 | { | 3317 | { |
| 3297 | return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", | 3318 | return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", |
| 3298 | 0x140, regvalue, cur_col, wrap)); | 3319 | 0x140, regvalue, cur_col, wrap)); |
| 3299 | } | 3320 | } |
| 3300 | 3321 | ||
| 3301 | int | 3322 | int |
| 3302 | ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3323 | ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3303 | { | 3324 | { |
| 3304 | return (ahd_print_register(NULL, 0, "TQINPOS", | 3325 | return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", |
| 3305 | 0x141, regvalue, cur_col, wrap)); | 3326 | 0x144, regvalue, cur_col, wrap)); |
| 3306 | } | 3327 | } |
| 3307 | 3328 | ||
| 3308 | static ahd_reg_parse_entry_t ARG_1_parse_table[] = { | 3329 | static ahd_reg_parse_entry_t ARG_1_parse_table[] = { |
| @@ -3320,21 +3341,21 @@ int | |||
| 3320 | ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3341 | ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3321 | { | 3342 | { |
| 3322 | return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1", | 3343 | return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1", |
| 3323 | 0x142, regvalue, cur_col, wrap)); | 3344 | 0x148, regvalue, cur_col, wrap)); |
| 3324 | } | 3345 | } |
| 3325 | 3346 | ||
| 3326 | int | 3347 | int |
| 3327 | ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3348 | ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3328 | { | 3349 | { |
| 3329 | return (ahd_print_register(NULL, 0, "ARG_2", | 3350 | return (ahd_print_register(NULL, 0, "ARG_2", |
| 3330 | 0x143, regvalue, cur_col, wrap)); | 3351 | 0x149, regvalue, cur_col, wrap)); |
| 3331 | } | 3352 | } |
| 3332 | 3353 | ||
| 3333 | int | 3354 | int |
| 3334 | ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3355 | ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3335 | { | 3356 | { |
| 3336 | return (ahd_print_register(NULL, 0, "LAST_MSG", | 3357 | return (ahd_print_register(NULL, 0, "LAST_MSG", |
| 3337 | 0x144, regvalue, cur_col, wrap)); | 3358 | 0x14a, regvalue, cur_col, wrap)); |
| 3338 | } | 3359 | } |
| 3339 | 3360 | ||
| 3340 | static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = { | 3361 | static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = { |
| @@ -3350,14 +3371,14 @@ int | |||
| 3350 | ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3371 | ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3351 | { | 3372 | { |
| 3352 | return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE", | 3373 | return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE", |
| 3353 | 0x145, regvalue, cur_col, wrap)); | 3374 | 0x14b, regvalue, cur_col, wrap)); |
| 3354 | } | 3375 | } |
| 3355 | 3376 | ||
| 3356 | int | 3377 | int |
| 3357 | ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3378 | ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3358 | { | 3379 | { |
| 3359 | return (ahd_print_register(NULL, 0, "INITIATOR_TAG", | 3380 | return (ahd_print_register(NULL, 0, "INITIATOR_TAG", |
| 3360 | 0x146, regvalue, cur_col, wrap)); | 3381 | 0x14c, regvalue, cur_col, wrap)); |
| 3361 | } | 3382 | } |
| 3362 | 3383 | ||
| 3363 | static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { | 3384 | static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { |
| @@ -3369,63 +3390,63 @@ int | |||
| 3369 | ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3390 | ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3370 | { | 3391 | { |
| 3371 | return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", | 3392 | return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", |
| 3372 | 0x147, regvalue, cur_col, wrap)); | 3393 | 0x14d, regvalue, cur_col, wrap)); |
| 3373 | } | 3394 | } |
| 3374 | 3395 | ||
| 3375 | int | 3396 | int |
| 3376 | ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3397 | ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3377 | { | 3398 | { |
| 3378 | return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", | 3399 | return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", |
| 3379 | 0x148, regvalue, cur_col, wrap)); | 3400 | 0x14e, regvalue, cur_col, wrap)); |
| 3380 | } | 3401 | } |
| 3381 | 3402 | ||
| 3382 | int | 3403 | int |
| 3383 | ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3404 | ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3384 | { | 3405 | { |
| 3385 | return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", | 3406 | return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", |
| 3386 | 0x14a, regvalue, cur_col, wrap)); | 3407 | 0x150, regvalue, cur_col, wrap)); |
| 3387 | } | 3408 | } |
| 3388 | 3409 | ||
| 3389 | int | 3410 | int |
| 3390 | ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3411 | ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3391 | { | 3412 | { |
| 3392 | return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", | 3413 | return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", |
| 3393 | 0x14c, regvalue, cur_col, wrap)); | 3414 | 0x152, regvalue, cur_col, wrap)); |
| 3394 | } | 3415 | } |
| 3395 | 3416 | ||
| 3396 | int | 3417 | int |
| 3397 | ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3418 | ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3398 | { | 3419 | { |
| 3399 | return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", | 3420 | return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", |
| 3400 | 0x14d, regvalue, cur_col, wrap)); | 3421 | 0x153, regvalue, cur_col, wrap)); |
| 3401 | } | 3422 | } |
| 3402 | 3423 | ||
| 3403 | int | 3424 | int |
| 3404 | ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3425 | ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3405 | { | 3426 | { |
| 3406 | return (ahd_print_register(NULL, 0, "CMDS_PENDING", | 3427 | return (ahd_print_register(NULL, 0, "CMDS_PENDING", |
| 3407 | 0x14e, regvalue, cur_col, wrap)); | 3428 | 0x154, regvalue, cur_col, wrap)); |
| 3408 | } | 3429 | } |
| 3409 | 3430 | ||
| 3410 | int | 3431 | int |
| 3411 | ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3432 | ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3412 | { | 3433 | { |
| 3413 | return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", | 3434 | return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", |
| 3414 | 0x150, regvalue, cur_col, wrap)); | 3435 | 0x156, regvalue, cur_col, wrap)); |
| 3415 | } | 3436 | } |
| 3416 | 3437 | ||
| 3417 | int | 3438 | int |
| 3418 | ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3439 | ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3419 | { | 3440 | { |
| 3420 | return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", | 3441 | return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", |
| 3421 | 0x151, regvalue, cur_col, wrap)); | 3442 | 0x157, regvalue, cur_col, wrap)); |
| 3422 | } | 3443 | } |
| 3423 | 3444 | ||
| 3424 | int | 3445 | int |
| 3425 | ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) | 3446 | ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) |
| 3426 | { | 3447 | { |
| 3427 | return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE", | 3448 | return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE", |
| 3428 | 0x152, regvalue, cur_col, wrap)); | 3449 | 0x158, regvalue, cur_col, wrap)); |
| 3429 | } | 3450 | } |
| 3430 | 3451 | ||
| 3431 | int | 3452 | int |
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped index 77c471f934e0..b1e5365be230 100644 --- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped | |||
| @@ -2,215 +2,228 @@ | |||
| 2 | * DO NOT EDIT - This file is automatically generated | 2 | * DO NOT EDIT - This file is automatically generated |
| 3 | * from the following source files: | 3 | * from the following source files: |
| 4 | * | 4 | * |
| 5 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ | 5 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $ |
| 6 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ | 6 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $ |
| 7 | */ | 7 | */ |
| 8 | static uint8_t seqprog[] = { | 8 | static uint8_t seqprog[] = { |
| 9 | 0xff, 0x02, 0x06, 0x78, | 9 | 0xff, 0x02, 0x06, 0x78, |
| 10 | 0x00, 0xea, 0x50, 0x59, | 10 | 0x00, 0xea, 0x64, 0x59, |
| 11 | 0x01, 0xea, 0x04, 0x30, | 11 | 0x01, 0xea, 0x04, 0x30, |
| 12 | 0xff, 0x04, 0x0c, 0x78, | 12 | 0xff, 0x04, 0x0c, 0x78, |
| 13 | 0x19, 0xea, 0x50, 0x59, | 13 | 0x19, 0xea, 0x64, 0x59, |
| 14 | 0x19, 0xea, 0x04, 0x00, | 14 | 0x19, 0xea, 0x04, 0x00, |
| 15 | 0x33, 0xea, 0x44, 0x59, | 15 | 0x33, 0xea, 0x5e, 0x59, |
| 16 | 0x33, 0xea, 0x00, 0x00, | 16 | 0x33, 0xea, 0x00, 0x00, |
| 17 | 0x60, 0x3a, 0x1a, 0x68, | 17 | 0x60, 0x3a, 0x3a, 0x68, |
| 18 | 0x04, 0x47, 0x1b, 0x68, | 18 | 0x04, 0x4d, 0x35, 0x78, |
| 19 | 0xff, 0x21, 0x1b, 0x70, | 19 | 0x01, 0x34, 0xc1, 0x31, |
| 20 | 0x40, 0x4b, 0x92, 0x69, | 20 | 0x00, 0x32, 0x21, 0x60, |
| 21 | 0x00, 0xe2, 0x54, 0x59, | 21 | 0x01, 0x35, 0xc1, 0x31, |
| 22 | 0x40, 0x4b, 0x92, 0x69, | 22 | 0x00, 0x33, 0x21, 0x60, |
| 23 | 0x20, 0x4b, 0x82, 0x69, | 23 | 0xfb, 0x4d, 0x9b, 0x0a, |
| 24 | 0xfc, 0x42, 0x24, 0x78, | 24 | 0x00, 0xe2, 0x34, 0x40, |
| 25 | 0x10, 0x40, 0x24, 0x78, | 25 | 0x50, 0x4b, 0x3a, 0x68, |
| 26 | 0x00, 0xe2, 0xc4, 0x5d, | 26 | 0xff, 0x31, 0x3b, 0x70, |
| 27 | 0x20, 0x4d, 0x28, 0x78, | 27 | 0x02, 0x30, 0x51, 0x31, |
| 28 | 0x00, 0xe2, 0xc4, 0x5d, | 28 | 0xff, 0x8d, 0x2d, 0x70, |
| 29 | 0x02, 0x8c, 0x51, 0x31, | ||
| 30 | 0xff, 0x8d, 0x29, 0x60, | ||
| 31 | 0x02, 0x28, 0x19, 0x33, | ||
| 32 | 0x02, 0x30, 0x51, 0x32, | ||
| 33 | 0xff, 0xea, 0x62, 0x02, | ||
| 34 | 0x00, 0xe2, 0x3a, 0x40, | ||
| 35 | 0xff, 0x21, 0x3b, 0x70, | ||
| 36 | 0x40, 0x4b, 0xaa, 0x69, | ||
| 37 | 0x00, 0xe2, 0x68, 0x59, | ||
| 38 | 0x40, 0x4b, 0xaa, 0x69, | ||
| 39 | 0x20, 0x4b, 0x96, 0x69, | ||
| 40 | 0xfc, 0x42, 0x44, 0x78, | ||
| 41 | 0x10, 0x40, 0x44, 0x78, | ||
| 42 | 0x00, 0xe2, 0xfc, 0x5d, | ||
| 43 | 0x20, 0x4d, 0x48, 0x78, | ||
| 44 | 0x00, 0xe2, 0xfc, 0x5d, | ||
| 29 | 0x30, 0x3f, 0xc0, 0x09, | 45 | 0x30, 0x3f, 0xc0, 0x09, |
| 30 | 0x30, 0xe0, 0x30, 0x60, | 46 | 0x30, 0xe0, 0x50, 0x60, |
| 31 | 0x7f, 0x4a, 0x94, 0x08, | 47 | 0x7f, 0x4a, 0x94, 0x08, |
| 32 | 0x00, 0xe2, 0x32, 0x40, | 48 | 0x00, 0xe2, 0x52, 0x40, |
| 33 | 0xc0, 0x4a, 0x94, 0x00, | 49 | 0xc0, 0x4a, 0x94, 0x00, |
| 34 | 0x00, 0xe2, 0x3e, 0x58, | 50 | 0x00, 0xe2, 0x5e, 0x58, |
| 35 | 0x00, 0xe2, 0x56, 0x58, | 51 | 0x00, 0xe2, 0x76, 0x58, |
| 36 | 0x00, 0xe2, 0x66, 0x58, | 52 | 0x00, 0xe2, 0x86, 0x58, |
| 37 | 0x00, 0xe2, 0x06, 0x40, | 53 | 0x00, 0xe2, 0x06, 0x40, |
| 38 | 0x33, 0xea, 0x44, 0x59, | 54 | 0x33, 0xea, 0x5e, 0x59, |
| 39 | 0x33, 0xea, 0x00, 0x00, | 55 | 0x33, 0xea, 0x00, 0x00, |
| 40 | 0x01, 0x52, 0x64, 0x78, | 56 | 0x01, 0x52, 0x84, 0x78, |
| 41 | 0x02, 0x58, 0x50, 0x31, | 57 | 0x02, 0x58, 0x50, 0x31, |
| 42 | 0xff, 0xea, 0x10, 0x0b, | 58 | 0xff, 0xea, 0x10, 0x0b, |
| 43 | 0xff, 0x97, 0x4f, 0x78, | 59 | 0xff, 0x97, 0x6f, 0x78, |
| 44 | 0x50, 0x4b, 0x4a, 0x68, | 60 | 0x50, 0x4b, 0x6a, 0x68, |
| 45 | 0xbf, 0x3a, 0x74, 0x08, | 61 | 0xbf, 0x3a, 0x74, 0x08, |
| 46 | 0x14, 0xea, 0x50, 0x59, | 62 | 0x14, 0xea, 0x64, 0x59, |
| 47 | 0x14, 0xea, 0x04, 0x00, | 63 | 0x14, 0xea, 0x04, 0x00, |
| 48 | 0x08, 0x92, 0x25, 0x03, | 64 | 0x08, 0x92, 0x25, 0x03, |
| 49 | 0xff, 0x90, 0x3f, 0x68, | 65 | 0xff, 0x90, 0x5f, 0x68, |
| 50 | 0x00, 0xe2, 0x56, 0x5b, | 66 | 0x00, 0xe2, 0x76, 0x5b, |
| 51 | 0x00, 0xe2, 0x3e, 0x40, | 67 | 0x00, 0xe2, 0x5e, 0x40, |
| 52 | 0x00, 0xea, 0x44, 0x59, | 68 | 0x00, 0xea, 0x5e, 0x59, |
| 53 | 0x01, 0xea, 0x00, 0x30, | 69 | 0x01, 0xea, 0x00, 0x30, |
| 54 | 0x80, 0xf9, 0x5e, 0x68, | 70 | 0x80, 0xf9, 0x7e, 0x68, |
| 55 | 0x00, 0xe2, 0x42, 0x59, | 71 | 0x00, 0xe2, 0x5c, 0x59, |
| 56 | 0x11, 0xea, 0x44, 0x59, | 72 | 0x11, 0xea, 0x5e, 0x59, |
| 57 | 0x11, 0xea, 0x00, 0x00, | 73 | 0x11, 0xea, 0x00, 0x00, |
| 58 | 0x80, 0xf9, 0x42, 0x79, | 74 | 0x80, 0xf9, 0x5c, 0x79, |
| 59 | 0xff, 0xea, 0xd4, 0x0d, | 75 | 0xff, 0xea, 0xd4, 0x0d, |
| 60 | 0x22, 0xea, 0x44, 0x59, | 76 | 0x22, 0xea, 0x5e, 0x59, |
| 61 | 0x22, 0xea, 0x00, 0x00, | 77 | 0x22, 0xea, 0x00, 0x00, |
| 62 | 0x10, 0x16, 0x70, 0x78, | 78 | 0x10, 0x16, 0x90, 0x78, |
| 63 | 0x01, 0x0b, 0xa2, 0x32, | ||
| 64 | 0x10, 0x16, 0x2c, 0x00, | 79 | 0x10, 0x16, 0x2c, 0x00, |
| 65 | 0x18, 0xad, 0x00, 0x79, | 80 | 0x01, 0x0b, 0xae, 0x32, |
| 66 | 0x04, 0xad, 0xca, 0x68, | 81 | 0x18, 0xad, 0x12, 0x79, |
| 67 | 0x80, 0xad, 0x64, 0x78, | 82 | 0x04, 0xad, 0xdc, 0x68, |
| 68 | 0x10, 0xad, 0x98, 0x78, | 83 | 0x80, 0xad, 0x84, 0x78, |
| 69 | 0xff, 0x88, 0x83, 0x68, | 84 | 0x10, 0xad, 0xaa, 0x78, |
| 70 | 0xe7, 0xad, 0x5a, 0x09, | 85 | 0xe7, 0xad, 0x5a, 0x09, |
| 71 | 0x02, 0x8c, 0x59, 0x32, | 86 | 0x02, 0x8c, 0x59, 0x32, |
| 87 | 0xff, 0x8d, 0xa1, 0x60, | ||
| 88 | 0xff, 0xea, 0x5e, 0x02, | ||
| 89 | 0xff, 0x88, 0xa7, 0x78, | ||
| 90 | 0x02, 0x30, 0x19, 0x33, | ||
| 91 | 0x02, 0xa8, 0x60, 0x36, | ||
| 72 | 0x02, 0x28, 0x19, 0x33, | 92 | 0x02, 0x28, 0x19, 0x33, |
| 73 | 0x02, 0xa8, 0x50, 0x36, | 93 | 0x02, 0xa8, 0x50, 0x36, |
| 74 | 0x33, 0xea, 0x44, 0x59, | ||
| 75 | 0x33, 0xea, 0x00, 0x00, | ||
| 76 | 0x40, 0x3a, 0x64, 0x68, | ||
| 77 | 0x50, 0x4b, 0x64, 0x68, | ||
| 78 | 0x22, 0xea, 0x44, 0x59, | ||
| 79 | 0x22, 0xea, 0x00, 0x00, | ||
| 80 | 0xe7, 0xad, 0x5a, 0x09, | ||
| 81 | 0x02, 0x8c, 0x59, 0x32, | ||
| 82 | 0x1a, 0xea, 0x50, 0x59, | ||
| 83 | 0x1a, 0xea, 0x04, 0x00, | ||
| 84 | 0xff, 0xea, 0xd4, 0x0d, | ||
| 85 | 0xe7, 0xad, 0x5a, 0x09, | 94 | 0xe7, 0xad, 0x5a, 0x09, |
| 86 | 0x00, 0xe2, 0xa6, 0x58, | 95 | 0x00, 0xe2, 0xb8, 0x58, |
| 87 | 0xff, 0xea, 0x56, 0x02, | 96 | 0xff, 0xea, 0x56, 0x02, |
| 88 | 0x04, 0x7c, 0x78, 0x32, | 97 | 0x04, 0x7c, 0x88, 0x32, |
| 89 | 0x20, 0x16, 0x64, 0x78, | 98 | 0x20, 0x16, 0x84, 0x78, |
| 90 | 0x04, 0x38, 0x79, 0x32, | 99 | 0x04, 0x40, 0x89, 0x32, |
| 91 | 0x80, 0x37, 0x6f, 0x16, | 100 | 0x80, 0x3d, 0x7b, 0x16, |
| 92 | 0xff, 0x2d, 0xb5, 0x60, | 101 | 0xff, 0x2d, 0xc7, 0x60, |
| 93 | 0xff, 0x29, 0xb5, 0x60, | 102 | 0xff, 0x29, 0xc7, 0x60, |
| 94 | 0x40, 0x51, 0xc5, 0x78, | 103 | 0x40, 0x57, 0xd7, 0x78, |
| 95 | 0xff, 0x4f, 0xb5, 0x68, | 104 | 0xff, 0x55, 0xc7, 0x68, |
| 96 | 0xff, 0x4d, 0xc1, 0x19, | 105 | 0xff, 0x53, 0xc1, 0x19, |
| 97 | 0x00, 0x4e, 0xd5, 0x19, | 106 | 0x00, 0x54, 0xd5, 0x19, |
| 98 | 0x00, 0xe2, 0xc4, 0x50, | 107 | 0x00, 0xe2, 0xd6, 0x50, |
| 99 | 0x01, 0x4c, 0xc1, 0x31, | 108 | 0x01, 0x52, 0xc1, 0x31, |
| 100 | 0x00, 0x50, 0xd5, 0x19, | 109 | 0x00, 0x56, 0xd5, 0x19, |
| 101 | 0x00, 0xe2, 0xc4, 0x48, | 110 | 0x00, 0xe2, 0xd6, 0x48, |
| 102 | 0x80, 0x18, 0x64, 0x78, | 111 | 0x80, 0x18, 0x84, 0x78, |
| 103 | 0x02, 0x4a, 0x1d, 0x30, | 112 | 0x02, 0x50, 0x1d, 0x30, |
| 104 | 0x10, 0xea, 0x18, 0x00, | 113 | 0x10, 0xea, 0x18, 0x00, |
| 105 | 0x60, 0x18, 0x30, 0x00, | 114 | 0x60, 0x18, 0x30, 0x00, |
| 106 | 0x7f, 0x18, 0x30, 0x0c, | 115 | 0x7f, 0x18, 0x30, 0x0c, |
| 107 | 0x02, 0xea, 0x02, 0x00, | 116 | 0x02, 0xea, 0x02, 0x00, |
| 108 | 0xff, 0xea, 0xa0, 0x0a, | 117 | 0xff, 0xea, 0xac, 0x0a, |
| 109 | 0x80, 0x18, 0x30, 0x04, | 118 | 0x80, 0x18, 0x30, 0x04, |
| 110 | 0x40, 0xad, 0x64, 0x78, | 119 | 0x40, 0xad, 0x84, 0x78, |
| 111 | 0xe7, 0xad, 0x5a, 0x09, | 120 | 0xe7, 0xad, 0x5a, 0x09, |
| 112 | 0x02, 0xa8, 0x40, 0x31, | 121 | 0x02, 0xa8, 0x40, 0x31, |
| 113 | 0xff, 0xea, 0xc0, 0x09, | 122 | 0xff, 0xea, 0xc0, 0x09, |
| 114 | 0x01, 0x4e, 0x9d, 0x1a, | 123 | 0x01, 0x54, 0xa9, 0x1a, |
| 115 | 0x00, 0x4f, 0x9f, 0x22, | 124 | 0x00, 0x55, 0xab, 0x22, |
| 116 | 0x01, 0x94, 0x6d, 0x33, | 125 | 0x01, 0x94, 0x6d, 0x33, |
| 117 | 0x01, 0xea, 0x20, 0x33, | 126 | 0xff, 0xea, 0x20, 0x0b, |
| 118 | 0x04, 0xac, 0x49, 0x32, | 127 | 0x04, 0xac, 0x49, 0x32, |
| 119 | 0xff, 0xea, 0x5a, 0x03, | 128 | 0xff, 0xea, 0x5a, 0x03, |
| 120 | 0xff, 0xea, 0x5e, 0x03, | 129 | 0xff, 0xea, 0x5e, 0x03, |
| 121 | 0x01, 0x10, 0xd4, 0x31, | 130 | 0x01, 0x10, 0xd4, 0x31, |
| 122 | 0x10, 0x92, 0xf5, 0x68, | 131 | 0x10, 0x92, 0x07, 0x69, |
| 123 | 0x3d, 0x93, 0xc5, 0x29, | 132 | 0x3d, 0x93, 0xc5, 0x29, |
| 124 | 0xfe, 0xe2, 0xc4, 0x09, | 133 | 0xfe, 0xe2, 0xc4, 0x09, |
| 125 | 0x01, 0xea, 0xc6, 0x01, | 134 | 0x01, 0xea, 0xc6, 0x01, |
| 126 | 0x02, 0xe2, 0xc8, 0x31, | 135 | 0x02, 0xe2, 0xc8, 0x31, |
| 127 | 0x02, 0xec, 0x50, 0x31, | 136 | 0x02, 0xec, 0x50, 0x31, |
| 128 | 0x02, 0xa0, 0xda, 0x31, | 137 | 0x02, 0xa0, 0xda, 0x31, |
| 129 | 0xff, 0xa9, 0xf4, 0x70, | 138 | 0xff, 0xa9, 0x06, 0x71, |
| 130 | 0x02, 0xa0, 0x58, 0x37, | 139 | 0x02, 0xa0, 0x58, 0x37, |
| 131 | 0xff, 0x21, 0xfd, 0x70, | 140 | 0xff, 0x21, 0x0f, 0x71, |
| 132 | 0x02, 0x22, 0x51, 0x31, | 141 | 0x02, 0x22, 0x51, 0x31, |
| 133 | 0x02, 0xa0, 0x5c, 0x33, | 142 | 0x02, 0xa0, 0x5c, 0x33, |
| 134 | 0x02, 0xa0, 0x44, 0x36, | 143 | 0x02, 0xa0, 0x44, 0x36, |
| 135 | 0x02, 0xa0, 0x40, 0x32, | 144 | 0x02, 0xa0, 0x40, 0x32, |
| 136 | 0x02, 0xa0, 0x44, 0x36, | 145 | 0x02, 0xa0, 0x44, 0x36, |
| 137 | 0x04, 0x47, 0x05, 0x69, | 146 | 0x04, 0x4d, 0x17, 0x69, |
| 138 | 0x40, 0x16, 0x30, 0x69, | 147 | 0x40, 0x16, 0x48, 0x69, |
| 139 | 0xff, 0x2d, 0x35, 0x61, | 148 | 0xff, 0x2d, 0x4d, 0x61, |
| 140 | 0xff, 0x29, 0x65, 0x70, | 149 | 0xff, 0x29, 0x85, 0x70, |
| 141 | 0x01, 0x37, 0xc1, 0x31, | ||
| 142 | 0x02, 0x28, 0x55, 0x32, | 150 | 0x02, 0x28, 0x55, 0x32, |
| 143 | 0x01, 0xea, 0x5a, 0x01, | 151 | 0x01, 0xea, 0x5a, 0x01, |
| 144 | 0x04, 0x3c, 0xf9, 0x30, | 152 | 0x04, 0x44, 0xf9, 0x30, |
| 153 | 0x01, 0x44, 0xc1, 0x31, | ||
| 145 | 0x02, 0x28, 0x51, 0x31, | 154 | 0x02, 0x28, 0x51, 0x31, |
| 146 | 0x01, 0xa8, 0x60, 0x31, | 155 | 0x02, 0xa8, 0x60, 0x31, |
| 147 | 0x00, 0xa9, 0x60, 0x01, | 156 | 0x01, 0xa4, 0x61, 0x31, |
| 157 | 0x01, 0x3d, 0x61, 0x31, | ||
| 148 | 0x01, 0x14, 0xd4, 0x31, | 158 | 0x01, 0x14, 0xd4, 0x31, |
| 149 | 0x01, 0x50, 0xa1, 0x1a, | 159 | 0x01, 0x56, 0xad, 0x1a, |
| 150 | 0xff, 0x4e, 0x9d, 0x1a, | 160 | 0xff, 0x54, 0xa9, 0x1a, |
| 151 | 0xff, 0x4f, 0x9f, 0x22, | 161 | 0xff, 0x55, 0xab, 0x22, |
| 152 | 0xff, 0x8d, 0x29, 0x71, | 162 | 0xff, 0x8d, 0x41, 0x71, |
| 153 | 0x80, 0xac, 0x28, 0x71, | 163 | 0x80, 0xac, 0x40, 0x71, |
| 154 | 0x20, 0x16, 0x28, 0x69, | 164 | 0x20, 0x16, 0x40, 0x69, |
| 165 | 0x00, 0xac, 0xc4, 0x19, | ||
| 166 | 0x07, 0xe2, 0x40, 0xf9, | ||
| 155 | 0x02, 0x8c, 0x51, 0x31, | 167 | 0x02, 0x8c, 0x51, 0x31, |
| 156 | 0x00, 0xe2, 0x12, 0x41, | 168 | 0x00, 0xe2, 0x24, 0x41, |
| 157 | 0x01, 0xac, 0x08, 0x31, | 169 | 0x01, 0xac, 0x08, 0x31, |
| 158 | 0x09, 0xea, 0x5a, 0x01, | 170 | 0x09, 0xea, 0x5a, 0x01, |
| 159 | 0x02, 0x8c, 0x51, 0x32, | 171 | 0x02, 0x8c, 0x51, 0x32, |
| 160 | 0xff, 0xea, 0x1a, 0x07, | 172 | 0xff, 0xea, 0x1a, 0x07, |
| 161 | 0x04, 0x24, 0xf9, 0x30, | 173 | 0x04, 0x24, 0xf9, 0x30, |
| 162 | 0x1d, 0xea, 0x3a, 0x41, | 174 | 0x1d, 0xea, 0x52, 0x41, |
| 163 | 0x02, 0x2c, 0x51, 0x31, | 175 | 0x02, 0x2c, 0x51, 0x31, |
| 164 | 0x04, 0xa8, 0xf9, 0x30, | 176 | 0x04, 0xa8, 0xf9, 0x30, |
| 165 | 0x19, 0xea, 0x3a, 0x41, | 177 | 0x19, 0xea, 0x52, 0x41, |
| 166 | 0x06, 0xea, 0x08, 0x81, | 178 | 0x06, 0xea, 0x08, 0x81, |
| 167 | 0x01, 0xe2, 0x5a, 0x35, | 179 | 0x01, 0xe2, 0x5a, 0x35, |
| 168 | 0x02, 0xf2, 0xf0, 0x35, | 180 | 0x02, 0xf2, 0xf0, 0x31, |
| 181 | 0xff, 0xea, 0xd4, 0x0d, | ||
| 169 | 0x02, 0xf2, 0xf0, 0x31, | 182 | 0x02, 0xf2, 0xf0, 0x31, |
| 170 | 0x02, 0xf8, 0xe4, 0x35, | 183 | 0x02, 0xf8, 0xe4, 0x35, |
| 171 | 0x80, 0xea, 0xb2, 0x01, | 184 | 0x80, 0xea, 0xb2, 0x01, |
| 172 | 0x01, 0xe2, 0x00, 0x30, | 185 | 0x01, 0xe2, 0x00, 0x30, |
| 173 | 0xff, 0xea, 0xb2, 0x0d, | 186 | 0xff, 0xea, 0xb2, 0x0d, |
| 174 | 0x80, 0xea, 0xb2, 0x01, | ||
| 175 | 0x11, 0x00, 0x00, 0x10, | ||
| 176 | 0xff, 0xea, 0xb2, 0x0d, | ||
| 177 | 0x01, 0xe2, 0x04, 0x30, | 187 | 0x01, 0xe2, 0x04, 0x30, |
| 178 | 0x01, 0xea, 0x04, 0x34, | 188 | 0x01, 0xea, 0x04, 0x34, |
| 179 | 0x02, 0x20, 0xbd, 0x30, | 189 | 0x02, 0x20, 0xbd, 0x30, |
| 180 | 0x02, 0x20, 0xb9, 0x30, | 190 | 0x02, 0x20, 0xb9, 0x30, |
| 181 | 0x02, 0x20, 0x51, 0x31, | 191 | 0x02, 0x20, 0x51, 0x31, |
| 182 | 0x4c, 0x93, 0xd7, 0x28, | 192 | 0x4c, 0x93, 0xd7, 0x28, |
| 183 | 0x10, 0x92, 0x63, 0x79, | 193 | 0x10, 0x92, 0x77, 0x79, |
| 184 | 0x01, 0x6b, 0xc0, 0x30, | 194 | 0x01, 0x6b, 0xc0, 0x30, |
| 185 | 0x02, 0x64, 0xc8, 0x00, | 195 | 0x02, 0x64, 0xc8, 0x00, |
| 186 | 0x40, 0x3a, 0x74, 0x04, | 196 | 0x40, 0x3a, 0x74, 0x04, |
| 187 | 0x00, 0xe2, 0x56, 0x58, | 197 | 0x00, 0xe2, 0x76, 0x58, |
| 188 | 0x33, 0xea, 0x44, 0x59, | 198 | 0x33, 0xea, 0x5e, 0x59, |
| 189 | 0x33, 0xea, 0x00, 0x00, | 199 | 0x33, 0xea, 0x00, 0x00, |
| 190 | 0x30, 0x3f, 0xc0, 0x09, | 200 | 0x30, 0x3f, 0xc0, 0x09, |
| 191 | 0x30, 0xe0, 0x64, 0x61, | 201 | 0x30, 0xe0, 0x78, 0x61, |
| 192 | 0x20, 0x3f, 0x7a, 0x69, | 202 | 0x20, 0x3f, 0x8e, 0x69, |
| 193 | 0x10, 0x3f, 0x64, 0x79, | 203 | 0x10, 0x3f, 0x78, 0x79, |
| 194 | 0x02, 0xea, 0x7e, 0x00, | 204 | 0x02, 0xea, 0x7e, 0x00, |
| 195 | 0x00, 0xea, 0x44, 0x59, | 205 | 0x00, 0xea, 0x5e, 0x59, |
| 196 | 0x01, 0xea, 0x00, 0x30, | 206 | 0x01, 0xea, 0x00, 0x30, |
| 197 | 0x02, 0x48, 0x51, 0x35, | 207 | 0x02, 0x4e, 0x51, 0x35, |
| 198 | 0x01, 0xea, 0x7e, 0x00, | 208 | 0x01, 0xea, 0x7e, 0x00, |
| 199 | 0x11, 0xea, 0x44, 0x59, | 209 | 0x11, 0xea, 0x5e, 0x59, |
| 200 | 0x11, 0xea, 0x00, 0x00, | 210 | 0x11, 0xea, 0x00, 0x00, |
| 201 | 0x02, 0x48, 0x51, 0x35, | 211 | 0x02, 0x4e, 0x51, 0x35, |
| 212 | 0xc0, 0x4a, 0x94, 0x00, | ||
| 213 | 0x04, 0x41, 0x9c, 0x79, | ||
| 202 | 0x08, 0xea, 0x98, 0x00, | 214 | 0x08, 0xea, 0x98, 0x00, |
| 203 | 0x08, 0x57, 0xae, 0x00, | 215 | 0x08, 0x57, 0xae, 0x00, |
| 204 | 0x08, 0x3c, 0x78, 0x00, | 216 | 0x08, 0x3c, 0x78, 0x00, |
| 205 | 0xf0, 0x49, 0x68, 0x0a, | 217 | 0xf0, 0x49, 0x74, 0x0a, |
| 206 | 0x0f, 0x67, 0xc0, 0x09, | 218 | 0x0f, 0x67, 0xc0, 0x09, |
| 207 | 0x00, 0x34, 0x69, 0x02, | 219 | 0x00, 0x3a, 0x75, 0x02, |
| 208 | 0x20, 0xea, 0x96, 0x00, | 220 | 0x20, 0xea, 0x96, 0x00, |
| 209 | 0x00, 0xe2, 0xf8, 0x41, | 221 | 0x00, 0xe2, 0x14, 0x42, |
| 210 | 0x40, 0x3a, 0xae, 0x69, | 222 | 0xc0, 0x4a, 0x94, 0x00, |
| 223 | 0x40, 0x3a, 0xc8, 0x69, | ||
| 211 | 0x02, 0x55, 0x06, 0x68, | 224 | 0x02, 0x55, 0x06, 0x68, |
| 212 | 0x02, 0x56, 0xae, 0x69, | 225 | 0x02, 0x56, 0xc8, 0x69, |
| 213 | 0xff, 0x5b, 0xae, 0x61, | 226 | 0xff, 0x5b, 0xc8, 0x61, |
| 214 | 0x02, 0x20, 0x51, 0x31, | 227 | 0x02, 0x20, 0x51, 0x31, |
| 215 | 0x80, 0xea, 0xb2, 0x01, | 228 | 0x80, 0xea, 0xb2, 0x01, |
| 216 | 0x44, 0xea, 0x00, 0x00, | 229 | 0x44, 0xea, 0x00, 0x00, |
| @@ -218,237 +231,246 @@ static uint8_t seqprog[] = { | |||
| 218 | 0x33, 0xea, 0x00, 0x00, | 231 | 0x33, 0xea, 0x00, 0x00, |
| 219 | 0xff, 0xea, 0xb2, 0x09, | 232 | 0xff, 0xea, 0xb2, 0x09, |
| 220 | 0xff, 0xe0, 0xc0, 0x19, | 233 | 0xff, 0xe0, 0xc0, 0x19, |
| 221 | 0xff, 0xe0, 0xb0, 0x79, | 234 | 0xff, 0xe0, 0xca, 0x79, |
| 222 | 0x02, 0xac, 0x51, 0x31, | 235 | 0x02, 0xac, 0x51, 0x31, |
| 223 | 0x00, 0xe2, 0xa6, 0x41, | 236 | 0x00, 0xe2, 0xc0, 0x41, |
| 224 | 0x02, 0x5e, 0x50, 0x31, | 237 | 0x02, 0x5e, 0x50, 0x31, |
| 225 | 0x02, 0xa8, 0xb8, 0x30, | 238 | 0x02, 0xa8, 0xb8, 0x30, |
| 226 | 0x02, 0x5c, 0x50, 0x31, | 239 | 0x02, 0x5c, 0x50, 0x31, |
| 227 | 0xff, 0xad, 0xc1, 0x71, | 240 | 0xff, 0xad, 0xdb, 0x71, |
| 228 | 0x02, 0xac, 0x41, 0x31, | 241 | 0x02, 0xac, 0x41, 0x31, |
| 229 | 0x02, 0x22, 0x51, 0x31, | 242 | 0x02, 0x22, 0x51, 0x31, |
| 230 | 0x02, 0xa0, 0x5c, 0x33, | 243 | 0x02, 0xa0, 0x5c, 0x33, |
| 231 | 0x02, 0xa0, 0x44, 0x32, | 244 | 0x02, 0xa0, 0x44, 0x32, |
| 232 | 0x00, 0xe2, 0xca, 0x41, | 245 | 0x00, 0xe2, 0xe4, 0x41, |
| 233 | 0x10, 0x92, 0xcb, 0x69, | 246 | 0x10, 0x92, 0xe5, 0x69, |
| 234 | 0x3d, 0x93, 0xc9, 0x29, | 247 | 0x3d, 0x93, 0xc9, 0x29, |
| 235 | 0x01, 0xe4, 0xc8, 0x01, | 248 | 0x01, 0xe4, 0xc8, 0x01, |
| 236 | 0x01, 0xea, 0xca, 0x01, | 249 | 0x01, 0xea, 0xca, 0x01, |
| 237 | 0xff, 0xea, 0xda, 0x01, | 250 | 0xff, 0xea, 0xda, 0x01, |
| 238 | 0x02, 0x20, 0x51, 0x31, | 251 | 0x02, 0x20, 0x51, 0x31, |
| 239 | 0x02, 0xae, 0x41, 0x32, | 252 | 0x02, 0xae, 0x41, 0x32, |
| 240 | 0xff, 0x21, 0xd3, 0x61, | 253 | 0xff, 0x21, 0xed, 0x61, |
| 241 | 0xff, 0xea, 0x46, 0x02, | 254 | 0xff, 0xea, 0x46, 0x02, |
| 242 | 0x02, 0x5c, 0x50, 0x31, | 255 | 0x02, 0x5c, 0x50, 0x31, |
| 243 | 0x40, 0xea, 0x96, 0x00, | 256 | 0x40, 0xea, 0x96, 0x00, |
| 244 | 0x02, 0x56, 0xcc, 0x6d, | 257 | 0x02, 0x56, 0x04, 0x6e, |
| 245 | 0x01, 0x55, 0xcc, 0x6d, | 258 | 0x01, 0x55, 0x04, 0x6e, |
| 246 | 0x10, 0x92, 0xdf, 0x79, | 259 | 0x10, 0x92, 0xf9, 0x79, |
| 247 | 0x10, 0x40, 0xe8, 0x69, | 260 | 0x10, 0x40, 0x02, 0x6a, |
| 248 | 0x01, 0x56, 0xe8, 0x79, | 261 | 0x01, 0x56, 0x02, 0x7a, |
| 249 | 0xff, 0x97, 0x07, 0x78, | 262 | 0xff, 0x97, 0x07, 0x78, |
| 250 | 0x13, 0xea, 0x50, 0x59, | 263 | 0x13, 0xea, 0x64, 0x59, |
| 251 | 0x13, 0xea, 0x04, 0x00, | 264 | 0x13, 0xea, 0x04, 0x00, |
| 252 | 0x00, 0xe2, 0x06, 0x40, | 265 | 0x00, 0xe2, 0x06, 0x40, |
| 253 | 0xbf, 0x3a, 0x74, 0x08, | 266 | 0xbf, 0x3a, 0x74, 0x08, |
| 267 | 0x04, 0x41, 0x08, 0x7a, | ||
| 254 | 0x08, 0xea, 0x98, 0x00, | 268 | 0x08, 0xea, 0x98, 0x00, |
| 255 | 0x08, 0x57, 0xae, 0x00, | 269 | 0x08, 0x57, 0xae, 0x00, |
| 256 | 0x01, 0x93, 0x69, 0x32, | 270 | 0x01, 0x93, 0x75, 0x32, |
| 257 | 0x01, 0x94, 0x6b, 0x32, | 271 | 0x01, 0x94, 0x77, 0x32, |
| 258 | 0x40, 0xea, 0x66, 0x02, | 272 | 0x40, 0xea, 0x72, 0x02, |
| 259 | 0x08, 0x3c, 0x78, 0x00, | 273 | 0x08, 0x3c, 0x78, 0x00, |
| 260 | 0x80, 0xea, 0x62, 0x02, | 274 | 0x80, 0xea, 0x6e, 0x02, |
| 261 | 0x00, 0xe2, 0xb8, 0x5b, | 275 | 0x00, 0xe2, 0xe2, 0x5b, |
| 262 | 0x01, 0x36, 0xc1, 0x31, | 276 | 0x01, 0x3c, 0xc1, 0x31, |
| 263 | 0x9f, 0xe0, 0x4c, 0x7c, | 277 | 0x9f, 0xe0, 0x84, 0x7c, |
| 264 | 0x80, 0xe0, 0x0c, 0x72, | 278 | 0x80, 0xe0, 0x28, 0x72, |
| 265 | 0xa0, 0xe0, 0x44, 0x72, | 279 | 0xa0, 0xe0, 0x64, 0x72, |
| 266 | 0xc0, 0xe0, 0x3a, 0x72, | 280 | 0xc0, 0xe0, 0x5a, 0x72, |
| 267 | 0xe0, 0xe0, 0x74, 0x72, | 281 | 0xe0, 0xe0, 0x94, 0x72, |
| 268 | 0x01, 0xea, 0x50, 0x59, | 282 | 0x01, 0xea, 0x64, 0x59, |
| 269 | 0x01, 0xea, 0x04, 0x00, | 283 | 0x01, 0xea, 0x04, 0x00, |
| 270 | 0x00, 0xe2, 0xf8, 0x41, | 284 | 0x00, 0xe2, 0x14, 0x42, |
| 271 | 0x80, 0x33, 0x13, 0x7a, | 285 | 0x80, 0x39, 0x2f, 0x7a, |
| 272 | 0x03, 0xea, 0x50, 0x59, | 286 | 0x03, 0xea, 0x64, 0x59, |
| 273 | 0x03, 0xea, 0x04, 0x00, | 287 | 0x03, 0xea, 0x04, 0x00, |
| 274 | 0xee, 0x00, 0x1a, 0x6a, | 288 | 0xee, 0x00, 0x36, 0x6a, |
| 275 | 0x05, 0xea, 0xb4, 0x00, | 289 | 0x05, 0xea, 0xb4, 0x00, |
| 276 | 0x33, 0xea, 0x44, 0x59, | 290 | 0x33, 0xea, 0x5e, 0x59, |
| 277 | 0x33, 0xea, 0x00, 0x00, | 291 | 0x33, 0xea, 0x00, 0x00, |
| 278 | 0x02, 0xa8, 0x90, 0x32, | 292 | 0x02, 0xa8, 0x9c, 0x32, |
| 279 | 0x00, 0xe2, 0x6a, 0x59, | 293 | 0x00, 0xe2, 0x7e, 0x59, |
| 280 | 0xef, 0x96, 0xd5, 0x19, | 294 | 0xef, 0x96, 0xd5, 0x19, |
| 281 | 0x00, 0xe2, 0x2a, 0x52, | 295 | 0x00, 0xe2, 0x46, 0x52, |
| 282 | 0x09, 0x80, 0xe1, 0x30, | 296 | 0x09, 0x80, 0xe1, 0x30, |
| 283 | 0x02, 0xea, 0x36, 0x00, | 297 | 0x02, 0xea, 0x36, 0x00, |
| 284 | 0xa8, 0xea, 0x32, 0x00, | 298 | 0xa8, 0xea, 0x32, 0x00, |
| 285 | 0x00, 0xe2, 0x30, 0x42, | 299 | 0x00, 0xe2, 0x4c, 0x42, |
| 286 | 0x01, 0x96, 0xd1, 0x30, | 300 | 0x01, 0x96, 0xd1, 0x30, |
| 287 | 0x10, 0x80, 0x89, 0x31, | 301 | 0x10, 0x80, 0x89, 0x31, |
| 288 | 0x20, 0xea, 0x32, 0x00, | 302 | 0x20, 0xea, 0x32, 0x00, |
| 289 | 0xbf, 0x33, 0x67, 0x0a, | 303 | 0xbf, 0x39, 0x73, 0x0a, |
| 290 | 0x20, 0x19, 0x32, 0x6a, | 304 | 0x10, 0x4c, 0x56, 0x6a, |
| 291 | 0x02, 0x4d, 0xf8, 0x69, | 305 | 0x20, 0x19, 0x4e, 0x6a, |
| 292 | 0x40, 0x33, 0x67, 0x02, | 306 | 0x20, 0x19, 0x52, 0x6a, |
| 293 | 0x00, 0xe2, 0xf8, 0x41, | 307 | 0x02, 0x4d, 0x14, 0x6a, |
| 294 | 0x80, 0x33, 0xb5, 0x6a, | 308 | 0x40, 0x39, 0x73, 0x02, |
| 309 | 0x00, 0xe2, 0x14, 0x42, | ||
| 310 | 0x80, 0x39, 0xd5, 0x6a, | ||
| 295 | 0x01, 0x44, 0x10, 0x33, | 311 | 0x01, 0x44, 0x10, 0x33, |
| 296 | 0x08, 0x92, 0x25, 0x03, | 312 | 0x08, 0x92, 0x25, 0x03, |
| 297 | 0x00, 0xe2, 0xf8, 0x41, | 313 | 0x00, 0xe2, 0x14, 0x42, |
| 298 | 0x10, 0xea, 0x80, 0x00, | 314 | 0x10, 0xea, 0x80, 0x00, |
| 299 | 0x01, 0x31, 0xc5, 0x31, | 315 | 0x01, 0x37, 0xc5, 0x31, |
| 300 | 0x80, 0xe2, 0x60, 0x62, | 316 | 0x80, 0xe2, 0x80, 0x62, |
| 301 | 0x10, 0x92, 0x85, 0x6a, | 317 | 0x10, 0x92, 0xa5, 0x6a, |
| 302 | 0xc0, 0x94, 0xc5, 0x01, | 318 | 0xc0, 0x94, 0xc5, 0x01, |
| 303 | 0x40, 0x92, 0x51, 0x6a, | 319 | 0x40, 0x92, 0x71, 0x6a, |
| 304 | 0xbf, 0xe2, 0xc4, 0x09, | 320 | 0xbf, 0xe2, 0xc4, 0x09, |
| 305 | 0x20, 0x92, 0x65, 0x7a, | 321 | 0x20, 0x92, 0x85, 0x7a, |
| 306 | 0x01, 0xe2, 0x88, 0x30, | 322 | 0x01, 0xe2, 0x88, 0x30, |
| 307 | 0x00, 0xe2, 0xb8, 0x5b, | 323 | 0x00, 0xe2, 0xe2, 0x5b, |
| 308 | 0xa0, 0x36, 0x6d, 0x62, | 324 | 0xa0, 0x3c, 0x8d, 0x62, |
| 309 | 0x23, 0x92, 0x89, 0x08, | 325 | 0x23, 0x92, 0x89, 0x08, |
| 310 | 0x00, 0xe2, 0xb8, 0x5b, | 326 | 0x00, 0xe2, 0xe2, 0x5b, |
| 311 | 0xa0, 0x36, 0x6d, 0x62, | 327 | 0xa0, 0x3c, 0x8d, 0x62, |
| 312 | 0x00, 0xa8, 0x64, 0x42, | 328 | 0x00, 0xa8, 0x84, 0x42, |
| 313 | 0xff, 0xe2, 0x64, 0x62, | 329 | 0xff, 0xe2, 0x84, 0x62, |
| 314 | 0x00, 0xe2, 0x84, 0x42, | 330 | 0x00, 0xe2, 0xa4, 0x42, |
| 315 | 0x40, 0xea, 0x98, 0x00, | 331 | 0x40, 0xea, 0x98, 0x00, |
| 316 | 0x01, 0xe2, 0x88, 0x30, | 332 | 0x01, 0xe2, 0x88, 0x30, |
| 317 | 0x00, 0xe2, 0xb8, 0x5b, | 333 | 0x00, 0xe2, 0xe2, 0x5b, |
| 318 | 0xa0, 0x36, 0x43, 0x72, | 334 | 0xa0, 0x3c, 0x63, 0x72, |
| 319 | 0x40, 0xea, 0x98, 0x00, | 335 | 0x40, 0xea, 0x98, 0x00, |
| 320 | 0x01, 0x31, 0x89, 0x32, | 336 | 0x01, 0x37, 0x95, 0x32, |
| 321 | 0x08, 0xea, 0x62, 0x02, | 337 | 0x08, 0xea, 0x6e, 0x02, |
| 322 | 0x00, 0xe2, 0xf8, 0x41, | 338 | 0x00, 0xe2, 0x14, 0x42, |
| 323 | 0xe0, 0xea, 0xd4, 0x5b, | 339 | 0xe0, 0xea, 0xfe, 0x5b, |
| 324 | 0x80, 0xe0, 0xc0, 0x6a, | 340 | 0x80, 0xe0, 0xe0, 0x6a, |
| 325 | 0x04, 0xe0, 0x66, 0x73, | 341 | 0x04, 0xe0, 0x92, 0x73, |
| 326 | 0x02, 0xe0, 0x96, 0x73, | 342 | 0x02, 0xe0, 0xc4, 0x73, |
| 327 | 0x00, 0xea, 0x1e, 0x73, | 343 | 0x00, 0xea, 0x3e, 0x73, |
| 328 | 0x03, 0xe0, 0xa6, 0x73, | 344 | 0x03, 0xe0, 0xd4, 0x73, |
| 329 | 0x23, 0xe0, 0x96, 0x72, | 345 | 0x23, 0xe0, 0xb6, 0x72, |
| 330 | 0x08, 0xe0, 0xbc, 0x72, | 346 | 0x08, 0xe0, 0xdc, 0x72, |
| 331 | 0x00, 0xe2, 0xb8, 0x5b, | 347 | 0x00, 0xe2, 0xe2, 0x5b, |
| 332 | 0x07, 0xea, 0x50, 0x59, | 348 | 0x07, 0xea, 0x64, 0x59, |
| 333 | 0x07, 0xea, 0x04, 0x00, | 349 | 0x07, 0xea, 0x04, 0x00, |
| 334 | 0x08, 0x42, 0xf9, 0x71, | 350 | 0x08, 0x48, 0x15, 0x72, |
| 335 | 0x04, 0x42, 0x93, 0x62, | 351 | 0x04, 0x48, 0xb3, 0x62, |
| 336 | 0x01, 0x43, 0x89, 0x30, | 352 | 0x01, 0x49, 0x89, 0x30, |
| 337 | 0x00, 0xe2, 0x84, 0x42, | 353 | 0x00, 0xe2, 0xa4, 0x42, |
| 338 | 0x01, 0x44, 0xd4, 0x31, | 354 | 0x01, 0x44, 0xd4, 0x31, |
| 339 | 0x00, 0xe2, 0x84, 0x42, | 355 | 0x00, 0xe2, 0xa4, 0x42, |
| 340 | 0x01, 0x00, 0x60, 0x32, | 356 | 0x01, 0x00, 0x6c, 0x32, |
| 341 | 0x33, 0xea, 0x44, 0x59, | 357 | 0x33, 0xea, 0x5e, 0x59, |
| 342 | 0x33, 0xea, 0x00, 0x00, | 358 | 0x33, 0xea, 0x00, 0x00, |
| 343 | 0x4c, 0x34, 0xc1, 0x28, | 359 | 0x4c, 0x3a, 0xc1, 0x28, |
| 344 | 0x01, 0x64, 0xc0, 0x31, | 360 | 0x01, 0x64, 0xc0, 0x31, |
| 345 | 0x00, 0x30, 0x45, 0x59, | 361 | 0x00, 0x36, 0x5f, 0x59, |
| 346 | 0x01, 0x30, 0x01, 0x30, | 362 | 0x01, 0x36, 0x01, 0x30, |
| 347 | 0x01, 0xe0, 0xba, 0x7a, | 363 | 0x01, 0xe0, 0xda, 0x7a, |
| 348 | 0xa0, 0xea, 0xca, 0x5b, | 364 | 0xa0, 0xea, 0xf4, 0x5b, |
| 349 | 0x01, 0xa0, 0xba, 0x62, | 365 | 0x01, 0xa0, 0xda, 0x62, |
| 350 | 0x01, 0x84, 0xaf, 0x7a, | 366 | 0x01, 0x84, 0xcf, 0x7a, |
| 351 | 0x01, 0x95, 0xbd, 0x6a, | 367 | 0x01, 0x95, 0xdd, 0x6a, |
| 352 | 0x05, 0xea, 0x50, 0x59, | 368 | 0x05, 0xea, 0x64, 0x59, |
| 353 | 0x05, 0xea, 0x04, 0x00, | 369 | 0x05, 0xea, 0x04, 0x00, |
| 354 | 0x00, 0xe2, 0xbc, 0x42, | 370 | 0x00, 0xe2, 0xdc, 0x42, |
| 355 | 0x03, 0xea, 0x50, 0x59, | 371 | 0x03, 0xea, 0x64, 0x59, |
| 356 | 0x03, 0xea, 0x04, 0x00, | 372 | 0x03, 0xea, 0x04, 0x00, |
| 357 | 0x00, 0xe2, 0xbc, 0x42, | 373 | 0x00, 0xe2, 0xdc, 0x42, |
| 358 | 0x07, 0xea, 0xdc, 0x5b, | 374 | 0x07, 0xea, 0x06, 0x5c, |
| 359 | 0x01, 0x44, 0xd4, 0x31, | 375 | 0x01, 0x44, 0xd4, 0x31, |
| 360 | 0x00, 0xe2, 0xf8, 0x41, | 376 | 0x00, 0xe2, 0x14, 0x42, |
| 361 | 0x3f, 0xe0, 0x6a, 0x0a, | 377 | 0x3f, 0xe0, 0x76, 0x0a, |
| 362 | 0xc0, 0x34, 0xc1, 0x09, | 378 | 0xc0, 0x3a, 0xc1, 0x09, |
| 363 | 0x00, 0x35, 0x51, 0x01, | 379 | 0x00, 0x3b, 0x51, 0x01, |
| 364 | 0xff, 0xea, 0x52, 0x09, | 380 | 0xff, 0xea, 0x52, 0x09, |
| 365 | 0x30, 0x34, 0xc5, 0x09, | 381 | 0x30, 0x3a, 0xc5, 0x09, |
| 366 | 0x3d, 0xe2, 0xc4, 0x29, | 382 | 0x3d, 0xe2, 0xc4, 0x29, |
| 367 | 0xb8, 0xe2, 0xc4, 0x19, | 383 | 0xb8, 0xe2, 0xc4, 0x19, |
| 368 | 0x01, 0xea, 0xc6, 0x01, | 384 | 0x01, 0xea, 0xc6, 0x01, |
| 369 | 0x02, 0xe2, 0xc8, 0x31, | 385 | 0x02, 0xe2, 0xc8, 0x31, |
| 370 | 0x02, 0xec, 0x40, 0x31, | 386 | 0x02, 0xec, 0x40, 0x31, |
| 371 | 0xff, 0xa1, 0xdc, 0x72, | 387 | 0xff, 0xa1, 0xfc, 0x72, |
| 372 | 0x02, 0xe8, 0xda, 0x31, | 388 | 0x02, 0xe8, 0xda, 0x31, |
| 373 | 0x02, 0xa0, 0x50, 0x31, | 389 | 0x02, 0xa0, 0x50, 0x31, |
| 374 | 0x00, 0xe2, 0xfe, 0x42, | 390 | 0x00, 0xe2, 0x1e, 0x43, |
| 375 | 0x80, 0x33, 0x67, 0x02, | 391 | 0x80, 0x39, 0x73, 0x02, |
| 376 | 0x01, 0x44, 0xd4, 0x31, | 392 | 0x01, 0x44, 0xd4, 0x31, |
| 377 | 0x00, 0xe2, 0xb8, 0x5b, | 393 | 0x00, 0xe2, 0xe2, 0x5b, |
| 378 | 0x01, 0x33, 0x67, 0x02, | 394 | 0x01, 0x39, 0x73, 0x02, |
| 379 | 0xe0, 0x36, 0x19, 0x63, | 395 | 0xe0, 0x3c, 0x39, 0x63, |
| 380 | 0x02, 0x33, 0x67, 0x02, | 396 | 0x02, 0x39, 0x73, 0x02, |
| 381 | 0x20, 0x46, 0x12, 0x63, | 397 | 0x20, 0x46, 0x32, 0x63, |
| 382 | 0xff, 0xea, 0x52, 0x09, | 398 | 0xff, 0xea, 0x52, 0x09, |
| 383 | 0xa8, 0xea, 0xca, 0x5b, | 399 | 0xa8, 0xea, 0xf4, 0x5b, |
| 384 | 0x04, 0x92, 0xf9, 0x7a, | 400 | 0x04, 0x92, 0x19, 0x7b, |
| 385 | 0x01, 0x34, 0xc1, 0x31, | 401 | 0x01, 0x3a, 0xc1, 0x31, |
| 386 | 0x00, 0x93, 0xf9, 0x62, | 402 | 0x00, 0x93, 0x19, 0x63, |
| 387 | 0x01, 0x35, 0xc1, 0x31, | 403 | 0x01, 0x3b, 0xc1, 0x31, |
| 388 | 0x00, 0x94, 0x03, 0x73, | 404 | 0x00, 0x94, 0x23, 0x73, |
| 389 | 0x01, 0xa9, 0x52, 0x11, | 405 | 0x01, 0xa9, 0x52, 0x11, |
| 390 | 0xff, 0xa9, 0xee, 0x6a, | 406 | 0xff, 0xa9, 0x0e, 0x6b, |
| 391 | 0x00, 0xe2, 0x12, 0x43, | 407 | 0x00, 0xe2, 0x32, 0x43, |
| 392 | 0x10, 0x33, 0x67, 0x02, | 408 | 0x10, 0x39, 0x73, 0x02, |
| 393 | 0x04, 0x92, 0x13, 0x7b, | 409 | 0x04, 0x92, 0x33, 0x7b, |
| 394 | 0xfb, 0x92, 0x25, 0x0b, | 410 | 0xfb, 0x92, 0x25, 0x0b, |
| 395 | 0xff, 0xea, 0x66, 0x0a, | 411 | 0xff, 0xea, 0x72, 0x0a, |
| 396 | 0x01, 0xa4, 0x0d, 0x6b, | 412 | 0x01, 0xa4, 0x2d, 0x6b, |
| 397 | 0x02, 0xa8, 0x90, 0x32, | 413 | 0x02, 0xa8, 0x9c, 0x32, |
| 398 | 0x00, 0xe2, 0x6a, 0x59, | 414 | 0x00, 0xe2, 0x7e, 0x59, |
| 399 | 0x10, 0x92, 0xbd, 0x7a, | 415 | 0x10, 0x92, 0xdd, 0x7a, |
| 400 | 0xff, 0xea, 0xdc, 0x5b, | 416 | 0xff, 0xea, 0x06, 0x5c, |
| 401 | 0x00, 0xe2, 0xbc, 0x42, | 417 | 0x00, 0xe2, 0xdc, 0x42, |
| 402 | 0x04, 0xea, 0x50, 0x59, | 418 | 0x04, 0xea, 0x64, 0x59, |
| 403 | 0x04, 0xea, 0x04, 0x00, | 419 | 0x04, 0xea, 0x04, 0x00, |
| 404 | 0x00, 0xe2, 0xbc, 0x42, | 420 | 0x00, 0xe2, 0xdc, 0x42, |
| 405 | 0x04, 0xea, 0x50, 0x59, | 421 | 0x04, 0xea, 0x64, 0x59, |
| 406 | 0x04, 0xea, 0x04, 0x00, | 422 | 0x04, 0xea, 0x04, 0x00, |
| 407 | 0x00, 0xe2, 0xf8, 0x41, | 423 | 0x00, 0xe2, 0x14, 0x42, |
| 408 | 0x08, 0x92, 0xb5, 0x7a, | 424 | 0x08, 0x92, 0xd5, 0x7a, |
| 409 | 0xc0, 0x33, 0x29, 0x7b, | 425 | 0xc0, 0x39, 0x49, 0x7b, |
| 410 | 0x80, 0x33, 0xb5, 0x6a, | 426 | 0x80, 0x39, 0xd5, 0x6a, |
| 411 | 0xff, 0x88, 0x29, 0x6b, | 427 | 0xff, 0x88, 0x49, 0x6b, |
| 412 | 0x40, 0x33, 0xb5, 0x6a, | 428 | 0x40, 0x39, 0xd5, 0x6a, |
| 413 | 0x10, 0x92, 0x2f, 0x7b, | 429 | 0x10, 0x92, 0x4f, 0x7b, |
| 414 | 0x0a, 0xea, 0x50, 0x59, | 430 | 0x0a, 0xea, 0x64, 0x59, |
| 415 | 0x0a, 0xea, 0x04, 0x00, | 431 | 0x0a, 0xea, 0x04, 0x00, |
| 416 | 0x00, 0xe2, 0x4e, 0x5b, | 432 | 0x00, 0xe2, 0x6e, 0x5b, |
| 417 | 0x00, 0xe2, 0x82, 0x43, | 433 | 0x00, 0xe2, 0xae, 0x43, |
| 418 | 0x50, 0x4b, 0x36, 0x6b, | 434 | 0x50, 0x4b, 0x56, 0x6b, |
| 419 | 0xbf, 0x3a, 0x74, 0x08, | 435 | 0xbf, 0x3a, 0x74, 0x08, |
| 420 | 0x01, 0xe0, 0xf4, 0x31, | 436 | 0x01, 0xe0, 0xf4, 0x31, |
| 421 | 0xff, 0xea, 0xc0, 0x09, | 437 | 0xff, 0xea, 0xc0, 0x09, |
| 422 | 0x01, 0x2e, 0x5d, 0x1a, | 438 | 0x01, 0x32, 0x65, 0x1a, |
| 423 | 0x00, 0x2f, 0x5f, 0x22, | 439 | 0x00, 0x33, 0x67, 0x22, |
| 424 | 0x04, 0x47, 0x8f, 0x02, | 440 | 0x04, 0x4d, 0x9b, 0x02, |
| 425 | 0x01, 0xfa, 0xc0, 0x35, | 441 | 0x01, 0xfa, 0xc0, 0x35, |
| 426 | 0x02, 0xa8, 0x84, 0x32, | 442 | 0x02, 0xa8, 0x90, 0x32, |
| 427 | 0x02, 0xea, 0xb4, 0x00, | 443 | 0x02, 0xea, 0xb4, 0x00, |
| 428 | 0x33, 0xea, 0x44, 0x59, | 444 | 0x33, 0xea, 0x5e, 0x59, |
| 429 | 0x33, 0xea, 0x00, 0x00, | 445 | 0x33, 0xea, 0x00, 0x00, |
| 430 | 0x02, 0x42, 0x51, 0x31, | 446 | 0x02, 0x48, 0x51, 0x31, |
| 431 | 0xff, 0x90, 0x65, 0x68, | 447 | 0xff, 0x90, 0x85, 0x68, |
| 432 | 0xff, 0x88, 0x5b, 0x6b, | 448 | 0xff, 0x88, 0x7b, 0x6b, |
| 433 | 0x01, 0xa4, 0x57, 0x6b, | 449 | 0x01, 0xa4, 0x77, 0x6b, |
| 434 | 0x02, 0xa4, 0x5f, 0x6b, | 450 | 0x02, 0xa4, 0x7f, 0x6b, |
| 435 | 0x01, 0x84, 0x5f, 0x7b, | 451 | 0x01, 0x84, 0x7f, 0x7b, |
| 436 | 0x02, 0x28, 0x19, 0x33, | 452 | 0x02, 0x28, 0x19, 0x33, |
| 437 | 0x02, 0xa8, 0x50, 0x36, | 453 | 0x02, 0xa8, 0x50, 0x36, |
| 438 | 0xff, 0x88, 0x5f, 0x73, | 454 | 0xff, 0x88, 0x7f, 0x73, |
| 439 | 0x00, 0xe2, 0x32, 0x5b, | 455 | 0x00, 0xe2, 0x52, 0x5b, |
| 440 | 0x02, 0xa8, 0x20, 0x33, | 456 | 0x02, 0xa8, 0x20, 0x33, |
| 441 | 0x02, 0x2c, 0x19, 0x33, | 457 | 0x04, 0xa4, 0x49, 0x03, |
| 458 | 0xff, 0xea, 0x1a, 0x03, | ||
| 459 | 0xff, 0x2d, 0x8b, 0x63, | ||
| 442 | 0x02, 0xa8, 0x58, 0x32, | 460 | 0x02, 0xa8, 0x58, 0x32, |
| 443 | 0x04, 0xa4, 0x49, 0x07, | 461 | 0x02, 0xa8, 0x5c, 0x36, |
| 444 | 0xc0, 0x33, 0xb5, 0x6a, | 462 | 0x02, 0xa8, 0x40, 0x31, |
| 463 | 0x02, 0x2e, 0x51, 0x31, | ||
| 464 | 0x02, 0xa0, 0x18, 0x33, | ||
| 465 | 0x02, 0xa0, 0x5c, 0x36, | ||
| 466 | 0xc0, 0x39, 0xd5, 0x6a, | ||
| 445 | 0x04, 0x92, 0x25, 0x03, | 467 | 0x04, 0x92, 0x25, 0x03, |
| 446 | 0x20, 0x92, 0x83, 0x6b, | 468 | 0x20, 0x92, 0xaf, 0x6b, |
| 447 | 0x02, 0xa8, 0x40, 0x31, | 469 | 0x02, 0xa8, 0x40, 0x31, |
| 448 | 0xc0, 0x34, 0xc1, 0x09, | 470 | 0xc0, 0x3a, 0xc1, 0x09, |
| 449 | 0x00, 0x35, 0x51, 0x01, | 471 | 0x00, 0x3b, 0x51, 0x01, |
| 450 | 0xff, 0xea, 0x52, 0x09, | 472 | 0xff, 0xea, 0x52, 0x09, |
| 451 | 0x30, 0x34, 0xc5, 0x09, | 473 | 0x30, 0x3a, 0xc5, 0x09, |
| 452 | 0x3d, 0xe2, 0xc4, 0x29, | 474 | 0x3d, 0xe2, 0xc4, 0x29, |
| 453 | 0xb8, 0xe2, 0xc4, 0x19, | 475 | 0xb8, 0xe2, 0xc4, 0x19, |
| 454 | 0x01, 0xea, 0xc6, 0x01, | 476 | 0x01, 0xea, 0xc6, 0x01, |
| @@ -458,69 +480,75 @@ static uint8_t seqprog[] = { | |||
| 458 | 0xf7, 0x57, 0xae, 0x08, | 480 | 0xf7, 0x57, 0xae, 0x08, |
| 459 | 0x08, 0xea, 0x98, 0x00, | 481 | 0x08, 0xea, 0x98, 0x00, |
| 460 | 0x01, 0x44, 0xd4, 0x31, | 482 | 0x01, 0x44, 0xd4, 0x31, |
| 461 | 0xee, 0x00, 0x8c, 0x6b, | 483 | 0xee, 0x00, 0xb8, 0x6b, |
| 462 | 0x02, 0xea, 0xb4, 0x00, | 484 | 0x02, 0xea, 0xb4, 0x00, |
| 463 | 0x00, 0xe2, 0xb4, 0x5b, | 485 | 0xc0, 0xea, 0x72, 0x02, |
| 464 | 0x09, 0x4c, 0x8e, 0x7b, | 486 | 0x09, 0x4c, 0xba, 0x7b, |
| 487 | 0x01, 0xea, 0x78, 0x02, | ||
| 465 | 0x08, 0x4c, 0x06, 0x68, | 488 | 0x08, 0x4c, 0x06, 0x68, |
| 466 | 0x0b, 0xea, 0x50, 0x59, | 489 | 0x0b, 0xea, 0x64, 0x59, |
| 467 | 0x0b, 0xea, 0x04, 0x00, | 490 | 0x0b, 0xea, 0x04, 0x00, |
| 468 | 0x01, 0x44, 0xd4, 0x31, | 491 | 0x01, 0x44, 0xd4, 0x31, |
| 469 | 0x20, 0x33, 0xf9, 0x79, | 492 | 0x20, 0x39, 0x15, 0x7a, |
| 470 | 0x00, 0xe2, 0x9e, 0x5b, | 493 | 0x00, 0xe2, 0xcc, 0x5b, |
| 471 | 0x00, 0xe2, 0xf8, 0x41, | 494 | 0x00, 0xe2, 0x14, 0x42, |
| 472 | 0x01, 0x84, 0xa3, 0x7b, | 495 | 0x01, 0x84, 0xd1, 0x7b, |
| 473 | 0x01, 0xa4, 0x49, 0x07, | 496 | 0x01, 0xa4, 0x49, 0x07, |
| 474 | 0x08, 0x60, 0x30, 0x33, | 497 | 0x08, 0x60, 0x30, 0x33, |
| 475 | 0x08, 0x80, 0x41, 0x37, | 498 | 0x08, 0x80, 0x41, 0x37, |
| 476 | 0xdf, 0x33, 0x67, 0x0a, | 499 | 0xdf, 0x39, 0x73, 0x0a, |
| 477 | 0xee, 0x00, 0xb0, 0x6b, | 500 | 0xee, 0x00, 0xde, 0x6b, |
| 478 | 0x05, 0xea, 0xb4, 0x00, | 501 | 0x05, 0xea, 0xb4, 0x00, |
| 479 | 0x33, 0xea, 0x44, 0x59, | 502 | 0x33, 0xea, 0x5e, 0x59, |
| 480 | 0x33, 0xea, 0x00, 0x00, | 503 | 0x33, 0xea, 0x00, 0x00, |
| 481 | 0x00, 0xe2, 0x6a, 0x59, | 504 | 0x00, 0xe2, 0x7e, 0x59, |
| 482 | 0x00, 0xe2, 0xbc, 0x42, | 505 | 0x00, 0xe2, 0xdc, 0x42, |
| 483 | 0x01, 0xea, 0x6c, 0x02, | 506 | 0xff, 0x42, 0xee, 0x6b, |
| 484 | 0xc0, 0xea, 0x66, 0x06, | 507 | 0x01, 0x41, 0xe2, 0x6b, |
| 485 | 0xff, 0x42, 0xc4, 0x6b, | 508 | 0x02, 0x41, 0xe2, 0x7b, |
| 486 | 0x01, 0x41, 0xb8, 0x6b, | 509 | 0xff, 0x42, 0xee, 0x6b, |
| 487 | 0x02, 0x41, 0xb8, 0x7b, | 510 | 0x01, 0x41, 0xe2, 0x6b, |
| 488 | 0xff, 0x42, 0xc4, 0x6b, | 511 | 0x02, 0x41, 0xe2, 0x7b, |
| 489 | 0x01, 0x41, 0xb8, 0x6b, | 512 | 0xff, 0x42, 0xee, 0x7b, |
| 490 | 0x02, 0x41, 0xb8, 0x7b, | 513 | 0x04, 0x4c, 0xe2, 0x6b, |
| 491 | 0xff, 0x42, 0xc4, 0x7b, | 514 | 0xe0, 0x41, 0x78, 0x0e, |
| 492 | 0x04, 0x4c, 0xb8, 0x6b, | ||
| 493 | 0xe0, 0x41, 0x6c, 0x0e, | ||
| 494 | 0x01, 0x44, 0xd4, 0x31, | 515 | 0x01, 0x44, 0xd4, 0x31, |
| 495 | 0xff, 0x42, 0xcc, 0x7b, | 516 | 0xff, 0x42, 0xf6, 0x7b, |
| 496 | 0x04, 0x4c, 0xcc, 0x6b, | 517 | 0x04, 0x4c, 0xf6, 0x6b, |
| 497 | 0xe0, 0x41, 0x6c, 0x0a, | 518 | 0xe0, 0x41, 0x78, 0x0a, |
| 498 | 0xe0, 0x36, 0xf9, 0x61, | 519 | 0xe0, 0x3c, 0x15, 0x62, |
| 499 | 0xff, 0xea, 0xca, 0x09, | 520 | 0xff, 0xea, 0xca, 0x09, |
| 500 | 0x01, 0xe2, 0xc8, 0x31, | 521 | 0x01, 0xe2, 0xc8, 0x31, |
| 501 | 0x01, 0x46, 0xda, 0x35, | 522 | 0x01, 0x46, 0xda, 0x35, |
| 502 | 0x01, 0x44, 0xd4, 0x35, | 523 | 0x01, 0x44, 0xd4, 0x35, |
| 503 | 0x10, 0xea, 0x80, 0x00, | 524 | 0x10, 0xea, 0x80, 0x00, |
| 504 | 0x01, 0xe2, 0x62, 0x36, | 525 | 0x01, 0xe2, 0x6e, 0x36, |
| 505 | 0x04, 0xa6, 0xe4, 0x7b, | 526 | 0x04, 0xa6, 0x0e, 0x7c, |
| 506 | 0xff, 0xea, 0x5a, 0x09, | 527 | 0xff, 0xea, 0x5a, 0x09, |
| 507 | 0xff, 0xea, 0x4c, 0x0d, | 528 | 0xff, 0xea, 0x4c, 0x0d, |
| 508 | 0x01, 0xa6, 0x02, 0x6c, | 529 | 0x01, 0xa6, 0x3a, 0x6c, |
| 509 | 0x10, 0xad, 0x64, 0x78, | 530 | 0x10, 0xad, 0x84, 0x78, |
| 510 | 0x80, 0xad, 0xfa, 0x6b, | 531 | 0x80, 0xad, 0x32, 0x6c, |
| 511 | 0x08, 0xad, 0x64, 0x68, | 532 | 0x08, 0xad, 0x84, 0x68, |
| 533 | 0x20, 0x19, 0x26, 0x7c, | ||
| 534 | 0x80, 0xea, 0xb2, 0x01, | ||
| 535 | 0x11, 0x00, 0x00, 0x10, | ||
| 536 | 0x02, 0xa6, 0x22, 0x7c, | ||
| 537 | 0xff, 0xea, 0xb2, 0x0d, | ||
| 538 | 0x11, 0x00, 0x00, 0x10, | ||
| 539 | 0xff, 0xea, 0xb2, 0x09, | ||
| 512 | 0x04, 0x84, 0xf9, 0x30, | 540 | 0x04, 0x84, 0xf9, 0x30, |
| 513 | 0x00, 0xea, 0x08, 0x81, | 541 | 0x00, 0xea, 0x08, 0x81, |
| 514 | 0xff, 0xea, 0xd4, 0x09, | 542 | 0xff, 0xea, 0xd4, 0x09, |
| 515 | 0x02, 0x84, 0xf9, 0x88, | 543 | 0x02, 0x84, 0xf9, 0x88, |
| 516 | 0x0d, 0xea, 0x5a, 0x01, | 544 | 0x0d, 0xea, 0x5a, 0x01, |
| 517 | 0x04, 0xa6, 0x4c, 0x05, | 545 | 0x04, 0xa6, 0x4c, 0x05, |
| 518 | 0x04, 0xa6, 0x64, 0x78, | 546 | 0x04, 0xa6, 0x84, 0x78, |
| 519 | 0xff, 0xea, 0x5a, 0x09, | 547 | 0xff, 0xea, 0x5a, 0x09, |
| 520 | 0x03, 0x84, 0x59, 0x89, | 548 | 0x03, 0x84, 0x59, 0x89, |
| 521 | 0x03, 0xea, 0x4c, 0x01, | 549 | 0x03, 0xea, 0x4c, 0x01, |
| 522 | 0x80, 0x1a, 0x64, 0x78, | 550 | 0x80, 0x1a, 0x84, 0x78, |
| 523 | 0x08, 0x19, 0x64, 0x78, | 551 | 0x08, 0x19, 0x84, 0x78, |
| 524 | 0x08, 0xb0, 0xe0, 0x30, | 552 | 0x08, 0xb0, 0xe0, 0x30, |
| 525 | 0x04, 0xb0, 0xe0, 0x30, | 553 | 0x04, 0xb0, 0xe0, 0x30, |
| 526 | 0x03, 0xb0, 0xf0, 0x30, | 554 | 0x03, 0xb0, 0xf0, 0x30, |
| @@ -533,259 +561,259 @@ static uint8_t seqprog[] = { | |||
| 533 | 0x00, 0x86, 0x0d, 0x23, | 561 | 0x00, 0x86, 0x0d, 0x23, |
| 534 | 0x00, 0x87, 0x0f, 0x23, | 562 | 0x00, 0x87, 0x0f, 0x23, |
| 535 | 0x01, 0x84, 0xc5, 0x31, | 563 | 0x01, 0x84, 0xc5, 0x31, |
| 536 | 0x80, 0x83, 0x25, 0x7c, | 564 | 0x80, 0x83, 0x5d, 0x7c, |
| 537 | 0x02, 0xe2, 0xc4, 0x01, | 565 | 0x02, 0xe2, 0xc4, 0x01, |
| 538 | 0xff, 0xea, 0x4c, 0x09, | 566 | 0xff, 0xea, 0x4c, 0x09, |
| 539 | 0x01, 0xe2, 0x36, 0x30, | 567 | 0x01, 0xe2, 0x36, 0x30, |
| 540 | 0xc8, 0x19, 0x32, 0x00, | 568 | 0xc8, 0x19, 0x32, 0x00, |
| 541 | 0x88, 0x19, 0x32, 0x00, | 569 | 0x88, 0x19, 0x32, 0x00, |
| 542 | 0x01, 0xac, 0xd4, 0x99, | 570 | 0x01, 0xac, 0xd4, 0x99, |
| 543 | 0x00, 0xe2, 0x64, 0x50, | 571 | 0x00, 0xe2, 0x84, 0x50, |
| 544 | 0xfe, 0xa6, 0x4c, 0x0d, | 572 | 0xfe, 0xa6, 0x4c, 0x0d, |
| 545 | 0x0b, 0x98, 0xe1, 0x30, | 573 | 0x0b, 0x98, 0xe1, 0x30, |
| 546 | 0xfd, 0xa4, 0x49, 0x09, | 574 | 0xfd, 0xa4, 0x49, 0x09, |
| 547 | 0x80, 0xa3, 0x39, 0x7c, | 575 | 0x80, 0xa3, 0x71, 0x7c, |
| 548 | 0x02, 0xa4, 0x48, 0x01, | 576 | 0x02, 0xa4, 0x48, 0x01, |
| 549 | 0x01, 0xa4, 0x36, 0x30, | 577 | 0x01, 0xa4, 0x36, 0x30, |
| 550 | 0xa8, 0xea, 0x32, 0x00, | 578 | 0xa8, 0xea, 0x32, 0x00, |
| 551 | 0xfd, 0xa4, 0x49, 0x0b, | 579 | 0xfd, 0xa4, 0x49, 0x0b, |
| 552 | 0x05, 0xa3, 0x07, 0x33, | 580 | 0x05, 0xa3, 0x07, 0x33, |
| 553 | 0x80, 0x83, 0x45, 0x6c, | 581 | 0x80, 0x83, 0x7d, 0x6c, |
| 554 | 0x02, 0xea, 0x4c, 0x05, | 582 | 0x02, 0xea, 0x4c, 0x05, |
| 555 | 0xff, 0xea, 0x4c, 0x0d, | 583 | 0xff, 0xea, 0x4c, 0x0d, |
| 556 | 0x00, 0xe2, 0x3e, 0x59, | 584 | 0x00, 0xe2, 0x56, 0x59, |
| 557 | 0x02, 0xa6, 0xe6, 0x6b, | 585 | 0x02, 0xa6, 0x10, 0x6c, |
| 558 | 0x80, 0xf9, 0xf2, 0x05, | 586 | 0x80, 0xf9, 0xf2, 0x05, |
| 559 | 0xc0, 0x33, 0x53, 0x7c, | 587 | 0xc0, 0x39, 0x8b, 0x7c, |
| 560 | 0x03, 0xea, 0x50, 0x59, | 588 | 0x03, 0xea, 0x64, 0x59, |
| 561 | 0x03, 0xea, 0x04, 0x00, | 589 | 0x03, 0xea, 0x04, 0x00, |
| 562 | 0x20, 0x33, 0x77, 0x7c, | 590 | 0x20, 0x39, 0xaf, 0x7c, |
| 563 | 0x01, 0x84, 0x5d, 0x6c, | 591 | 0x01, 0x84, 0x95, 0x6c, |
| 564 | 0x06, 0xea, 0x50, 0x59, | 592 | 0x06, 0xea, 0x64, 0x59, |
| 565 | 0x06, 0xea, 0x04, 0x00, | 593 | 0x06, 0xea, 0x04, 0x00, |
| 566 | 0x00, 0xe2, 0x7a, 0x44, | 594 | 0x00, 0xe2, 0xb2, 0x44, |
| 567 | 0x01, 0x00, 0x60, 0x32, | 595 | 0x01, 0x00, 0x6c, 0x32, |
| 568 | 0xee, 0x00, 0x66, 0x6c, | 596 | 0xee, 0x00, 0x9e, 0x6c, |
| 569 | 0x05, 0xea, 0xb4, 0x00, | 597 | 0x05, 0xea, 0xb4, 0x00, |
| 570 | 0x33, 0xea, 0x44, 0x59, | 598 | 0x33, 0xea, 0x5e, 0x59, |
| 571 | 0x33, 0xea, 0x00, 0x00, | 599 | 0x33, 0xea, 0x00, 0x00, |
| 572 | 0x80, 0x3d, 0x7a, 0x00, | 600 | 0x80, 0x3d, 0x7a, 0x00, |
| 573 | 0xfc, 0x42, 0x68, 0x7c, | 601 | 0xfc, 0x42, 0xa0, 0x7c, |
| 574 | 0x7f, 0x3d, 0x7a, 0x08, | 602 | 0x7f, 0x3d, 0x7a, 0x08, |
| 575 | 0x00, 0x30, 0x45, 0x59, | 603 | 0x00, 0x36, 0x5f, 0x59, |
| 576 | 0x01, 0x30, 0x01, 0x30, | 604 | 0x01, 0x36, 0x01, 0x30, |
| 577 | 0x09, 0xea, 0x50, 0x59, | 605 | 0x09, 0xea, 0x64, 0x59, |
| 578 | 0x09, 0xea, 0x04, 0x00, | 606 | 0x09, 0xea, 0x04, 0x00, |
| 579 | 0x00, 0xe2, 0xf8, 0x41, | 607 | 0x00, 0xe2, 0x14, 0x42, |
| 580 | 0x01, 0xa4, 0x5d, 0x6c, | 608 | 0x01, 0xa4, 0x95, 0x6c, |
| 581 | 0x00, 0xe2, 0x30, 0x5c, | 609 | 0x00, 0xe2, 0x68, 0x5c, |
| 582 | 0x20, 0x33, 0x67, 0x02, | 610 | 0x20, 0x39, 0x73, 0x02, |
| 583 | 0x01, 0x00, 0x60, 0x32, | 611 | 0x01, 0x00, 0x6c, 0x32, |
| 584 | 0x02, 0xa6, 0x82, 0x7c, | 612 | 0x02, 0xa6, 0xba, 0x7c, |
| 585 | 0x00, 0xe2, 0x46, 0x5c, | 613 | 0x00, 0xe2, 0x7e, 0x5c, |
| 586 | 0x00, 0xe2, 0x56, 0x58, | 614 | 0x00, 0xe2, 0x76, 0x58, |
| 587 | 0x00, 0xe2, 0x66, 0x58, | 615 | 0x00, 0xe2, 0x86, 0x58, |
| 588 | 0x00, 0xe2, 0x3a, 0x58, | 616 | 0x00, 0xe2, 0x5a, 0x58, |
| 589 | 0x00, 0x30, 0x45, 0x59, | 617 | 0x00, 0x36, 0x5f, 0x59, |
| 590 | 0x01, 0x30, 0x01, 0x30, | 618 | 0x01, 0x36, 0x01, 0x30, |
| 591 | 0x20, 0x19, 0x82, 0x6c, | 619 | 0x20, 0x19, 0xba, 0x6c, |
| 592 | 0x00, 0xe2, 0xb2, 0x5c, | 620 | 0x00, 0xe2, 0xea, 0x5c, |
| 593 | 0x04, 0x19, 0x9c, 0x6c, | 621 | 0x04, 0x19, 0xd4, 0x6c, |
| 594 | 0x02, 0x19, 0x32, 0x00, | 622 | 0x02, 0x19, 0x32, 0x00, |
| 595 | 0x01, 0x84, 0x9d, 0x7c, | 623 | 0x01, 0x84, 0xd5, 0x7c, |
| 596 | 0x01, 0x1b, 0x96, 0x7c, | 624 | 0x01, 0x1b, 0xce, 0x7c, |
| 597 | 0x01, 0x1a, 0x9c, 0x6c, | 625 | 0x01, 0x1a, 0xd4, 0x6c, |
| 598 | 0x00, 0xe2, 0x4c, 0x44, | 626 | 0x00, 0xe2, 0x84, 0x44, |
| 599 | 0x80, 0x4b, 0xa2, 0x6c, | 627 | 0x80, 0x4b, 0xda, 0x6c, |
| 600 | 0x01, 0x4c, 0x9e, 0x7c, | 628 | 0x01, 0x4c, 0xd6, 0x7c, |
| 601 | 0x03, 0x42, 0x4c, 0x6c, | 629 | 0x03, 0x42, 0x84, 0x6c, |
| 602 | 0x00, 0xe2, 0xe0, 0x5b, | 630 | 0x00, 0xe2, 0x0a, 0x5c, |
| 603 | 0x80, 0xf9, 0xf2, 0x01, | 631 | 0x80, 0xf9, 0xf2, 0x01, |
| 604 | 0x04, 0x33, 0xf9, 0x79, | 632 | 0x04, 0x39, 0x15, 0x7a, |
| 605 | 0x00, 0xe2, 0xf8, 0x41, | 633 | 0x00, 0xe2, 0x14, 0x42, |
| 606 | 0x08, 0x5d, 0xba, 0x6c, | 634 | 0x08, 0x5d, 0xf2, 0x6c, |
| 607 | 0x00, 0xe2, 0x56, 0x58, | 635 | 0x00, 0xe2, 0x76, 0x58, |
| 608 | 0x00, 0x30, 0x45, 0x59, | 636 | 0x00, 0x36, 0x5f, 0x59, |
| 609 | 0x01, 0x30, 0x01, 0x30, | 637 | 0x01, 0x36, 0x01, 0x30, |
| 610 | 0x02, 0x1b, 0xaa, 0x7c, | 638 | 0x02, 0x1b, 0xe2, 0x7c, |
| 611 | 0x08, 0x5d, 0xb8, 0x7c, | 639 | 0x08, 0x5d, 0xf0, 0x7c, |
| 612 | 0x03, 0x68, 0x00, 0x37, | 640 | 0x03, 0x68, 0x00, 0x37, |
| 613 | 0x01, 0x84, 0x09, 0x07, | 641 | 0x01, 0x84, 0x09, 0x07, |
| 614 | 0x80, 0x1b, 0xc4, 0x7c, | 642 | 0x80, 0x1b, 0xfc, 0x7c, |
| 615 | 0x80, 0x84, 0xc5, 0x6c, | 643 | 0x80, 0x84, 0xfd, 0x6c, |
| 616 | 0xff, 0x85, 0x0b, 0x1b, | 644 | 0xff, 0x85, 0x0b, 0x1b, |
| 617 | 0xff, 0x86, 0x0d, 0x23, | 645 | 0xff, 0x86, 0x0d, 0x23, |
| 618 | 0xff, 0x87, 0x0f, 0x23, | 646 | 0xff, 0x87, 0x0f, 0x23, |
| 619 | 0xf8, 0x1b, 0x08, 0x0b, | 647 | 0xf8, 0x1b, 0x08, 0x0b, |
| 620 | 0xff, 0xea, 0x06, 0x0b, | 648 | 0xff, 0xea, 0x06, 0x0b, |
| 621 | 0x03, 0x68, 0x00, 0x37, | 649 | 0x03, 0x68, 0x00, 0x37, |
| 622 | 0x00, 0xe2, 0xc4, 0x58, | 650 | 0x00, 0xe2, 0xd6, 0x58, |
| 623 | 0x10, 0xea, 0x18, 0x00, | 651 | 0x10, 0xea, 0x18, 0x00, |
| 624 | 0xf9, 0xd9, 0xb2, 0x0d, | 652 | 0xf9, 0xd9, 0xb2, 0x0d, |
| 625 | 0x01, 0xd9, 0xb2, 0x05, | 653 | 0x01, 0xd9, 0xb2, 0x05, |
| 626 | 0x01, 0x52, 0x48, 0x31, | 654 | 0x01, 0x52, 0x48, 0x31, |
| 627 | 0x20, 0xa4, 0xee, 0x7c, | 655 | 0x20, 0xa4, 0x26, 0x7d, |
| 628 | 0x20, 0x5b, 0xee, 0x7c, | 656 | 0x20, 0x5b, 0x26, 0x7d, |
| 629 | 0x80, 0xf9, 0xfc, 0x7c, | 657 | 0x80, 0xf9, 0x34, 0x7d, |
| 630 | 0x02, 0xea, 0xb4, 0x00, | 658 | 0x02, 0xea, 0xb4, 0x00, |
| 631 | 0x11, 0x00, 0x00, 0x10, | 659 | 0x11, 0x00, 0x00, 0x10, |
| 632 | 0x04, 0x19, 0x08, 0x7d, | 660 | 0x04, 0x19, 0x40, 0x7d, |
| 633 | 0xdf, 0x19, 0x32, 0x08, | 661 | 0xdf, 0x19, 0x32, 0x08, |
| 634 | 0x60, 0x5b, 0xe6, 0x6c, | 662 | 0x60, 0x5b, 0x40, 0x6d, |
| 635 | 0x01, 0x4c, 0xe2, 0x7c, | 663 | 0x01, 0x4c, 0x1a, 0x7d, |
| 636 | 0x20, 0x19, 0x32, 0x00, | 664 | 0x20, 0x19, 0x32, 0x00, |
| 637 | 0x01, 0xd9, 0xb2, 0x05, | 665 | 0x01, 0xd9, 0xb2, 0x05, |
| 638 | 0x02, 0xea, 0xb4, 0x00, | 666 | 0x02, 0xea, 0xb4, 0x00, |
| 639 | 0x01, 0xd9, 0xb2, 0x05, | 667 | 0x01, 0xd9, 0xb2, 0x05, |
| 640 | 0x10, 0x5b, 0x00, 0x6d, | 668 | 0x10, 0x5b, 0x38, 0x6d, |
| 641 | 0x08, 0x5b, 0x0a, 0x6d, | 669 | 0x08, 0x5b, 0x42, 0x6d, |
| 642 | 0x20, 0x5b, 0xfa, 0x6c, | 670 | 0x20, 0x5b, 0x32, 0x6d, |
| 643 | 0x02, 0x5b, 0x2a, 0x6d, | 671 | 0x02, 0x5b, 0x62, 0x6d, |
| 644 | 0x0e, 0xea, 0x50, 0x59, | 672 | 0x0e, 0xea, 0x64, 0x59, |
| 645 | 0x0e, 0xea, 0x04, 0x00, | 673 | 0x0e, 0xea, 0x04, 0x00, |
| 646 | 0x80, 0xf9, 0xea, 0x6c, | 674 | 0x80, 0xf9, 0x22, 0x6d, |
| 647 | 0xdf, 0x5c, 0xb8, 0x08, | 675 | 0xdf, 0x5c, 0xb8, 0x08, |
| 648 | 0x01, 0xd9, 0xb2, 0x05, | 676 | 0x01, 0xd9, 0xb2, 0x05, |
| 649 | 0x01, 0xa4, 0xe5, 0x6d, | 677 | 0x01, 0xa4, 0x1d, 0x6e, |
| 650 | 0x00, 0xe2, 0x30, 0x5c, | 678 | 0x00, 0xe2, 0x68, 0x5c, |
| 651 | 0x00, 0xe2, 0x34, 0x5d, | 679 | 0x00, 0xe2, 0x6c, 0x5d, |
| 652 | 0x01, 0x90, 0x21, 0x1b, | 680 | 0x01, 0x90, 0x21, 0x1b, |
| 653 | 0x01, 0xd9, 0xb2, 0x05, | 681 | 0x01, 0xd9, 0xb2, 0x05, |
| 654 | 0x00, 0xe2, 0x32, 0x5b, | 682 | 0x00, 0xe2, 0x52, 0x5b, |
| 655 | 0xf3, 0x96, 0xd5, 0x19, | 683 | 0xf3, 0x96, 0xd5, 0x19, |
| 656 | 0x00, 0xe2, 0x18, 0x55, | 684 | 0x00, 0xe2, 0x50, 0x55, |
| 657 | 0x80, 0x96, 0x19, 0x6d, | 685 | 0x80, 0x96, 0x51, 0x6d, |
| 658 | 0x0f, 0xea, 0x50, 0x59, | 686 | 0x0f, 0xea, 0x64, 0x59, |
| 659 | 0x0f, 0xea, 0x04, 0x00, | 687 | 0x0f, 0xea, 0x04, 0x00, |
| 660 | 0x00, 0xe2, 0x20, 0x45, | 688 | 0x00, 0xe2, 0x58, 0x45, |
| 661 | 0x04, 0x8c, 0xe1, 0x30, | 689 | 0x04, 0x8c, 0xe1, 0x30, |
| 662 | 0x01, 0xea, 0xf2, 0x00, | 690 | 0x01, 0xea, 0xf2, 0x00, |
| 663 | 0x02, 0xea, 0x36, 0x00, | 691 | 0x02, 0xea, 0x36, 0x00, |
| 664 | 0xa8, 0xea, 0x32, 0x00, | 692 | 0xa8, 0xea, 0x32, 0x00, |
| 665 | 0xff, 0x97, 0x27, 0x7d, | 693 | 0xff, 0x97, 0x5f, 0x7d, |
| 666 | 0x14, 0xea, 0x50, 0x59, | 694 | 0x14, 0xea, 0x64, 0x59, |
| 667 | 0x14, 0xea, 0x04, 0x00, | 695 | 0x14, 0xea, 0x04, 0x00, |
| 668 | 0x00, 0xe2, 0x96, 0x5d, | 696 | 0x00, 0xe2, 0xce, 0x5d, |
| 669 | 0x01, 0xd9, 0xb2, 0x05, | 697 | 0x01, 0xd9, 0xb2, 0x05, |
| 670 | 0x09, 0x80, 0xe1, 0x30, | 698 | 0x09, 0x80, 0xe1, 0x30, |
| 671 | 0x02, 0xea, 0x36, 0x00, | 699 | 0x02, 0xea, 0x36, 0x00, |
| 672 | 0xa8, 0xea, 0x32, 0x00, | 700 | 0xa8, 0xea, 0x32, 0x00, |
| 673 | 0x00, 0xe2, 0x8e, 0x5d, | 701 | 0x00, 0xe2, 0xc6, 0x5d, |
| 674 | 0x01, 0xd9, 0xb2, 0x05, | 702 | 0x01, 0xd9, 0xb2, 0x05, |
| 675 | 0x02, 0xa6, 0x44, 0x7d, | 703 | 0x02, 0xa6, 0x7c, 0x7d, |
| 676 | 0x00, 0xe2, 0x3e, 0x59, | 704 | 0x00, 0xe2, 0x56, 0x59, |
| 677 | 0x20, 0x5b, 0x52, 0x6d, | 705 | 0x20, 0x5b, 0x8a, 0x6d, |
| 678 | 0xfc, 0x42, 0x3e, 0x7d, | 706 | 0xfc, 0x42, 0x76, 0x7d, |
| 679 | 0x10, 0x40, 0x40, 0x6d, | 707 | 0x10, 0x40, 0x78, 0x6d, |
| 680 | 0x20, 0x4d, 0x42, 0x7d, | 708 | 0x20, 0x4d, 0x7a, 0x7d, |
| 681 | 0x08, 0x5d, 0x52, 0x6d, | 709 | 0x08, 0x5d, 0x8a, 0x6d, |
| 682 | 0x02, 0xa6, 0xe6, 0x6b, | 710 | 0x02, 0xa6, 0x10, 0x6c, |
| 683 | 0x00, 0xe2, 0x3e, 0x59, | 711 | 0x00, 0xe2, 0x56, 0x59, |
| 684 | 0x20, 0x5b, 0x52, 0x6d, | 712 | 0x20, 0x5b, 0x8a, 0x6d, |
| 685 | 0x01, 0x1b, 0x72, 0x6d, | 713 | 0x01, 0x1b, 0xaa, 0x6d, |
| 686 | 0xfc, 0x42, 0x4e, 0x7d, | 714 | 0xfc, 0x42, 0x86, 0x7d, |
| 687 | 0x10, 0x40, 0x50, 0x6d, | 715 | 0x10, 0x40, 0x88, 0x6d, |
| 688 | 0x20, 0x4d, 0x64, 0x78, | 716 | 0x20, 0x4d, 0x84, 0x78, |
| 689 | 0x08, 0x5d, 0x64, 0x78, | 717 | 0x08, 0x5d, 0x84, 0x78, |
| 690 | 0x02, 0x19, 0x32, 0x00, | 718 | 0x02, 0x19, 0x32, 0x00, |
| 691 | 0x01, 0x5b, 0x40, 0x31, | 719 | 0x01, 0x5b, 0x40, 0x31, |
| 692 | 0x00, 0xe2, 0xb2, 0x5c, | 720 | 0x00, 0xe2, 0xea, 0x5c, |
| 693 | 0x00, 0xe2, 0x9e, 0x5b, | 721 | 0x00, 0xe2, 0xcc, 0x5b, |
| 694 | 0x20, 0xea, 0xb6, 0x00, | 722 | 0x20, 0xea, 0xb6, 0x00, |
| 695 | 0x00, 0xe2, 0xe0, 0x5b, | 723 | 0x00, 0xe2, 0x0a, 0x5c, |
| 696 | 0x20, 0x5c, 0xb8, 0x00, | 724 | 0x20, 0x5c, 0xb8, 0x00, |
| 697 | 0x04, 0x19, 0x68, 0x6d, | 725 | 0x04, 0x19, 0xa0, 0x6d, |
| 698 | 0x01, 0x1a, 0x68, 0x6d, | 726 | 0x01, 0x1a, 0xa0, 0x6d, |
| 699 | 0x00, 0xe2, 0x3e, 0x59, | 727 | 0x00, 0xe2, 0x56, 0x59, |
| 700 | 0x01, 0x1a, 0x64, 0x78, | 728 | 0x01, 0x1a, 0x84, 0x78, |
| 701 | 0x80, 0xf9, 0xf2, 0x01, | 729 | 0x80, 0xf9, 0xf2, 0x01, |
| 702 | 0x20, 0xa0, 0xcc, 0x7d, | 730 | 0x20, 0xa0, 0x04, 0x7e, |
| 703 | 0xff, 0x90, 0x21, 0x1b, | 731 | 0xff, 0x90, 0x21, 0x1b, |
| 704 | 0x08, 0x92, 0x43, 0x6b, | 732 | 0x08, 0x92, 0x63, 0x6b, |
| 705 | 0x02, 0xea, 0xb4, 0x04, | 733 | 0x02, 0xea, 0xb4, 0x04, |
| 706 | 0x01, 0xa4, 0x49, 0x03, | 734 | 0x01, 0xa4, 0x49, 0x03, |
| 707 | 0x40, 0x5b, 0x82, 0x6d, | 735 | 0x40, 0x5b, 0xba, 0x6d, |
| 708 | 0x00, 0xe2, 0x3e, 0x59, | 736 | 0x00, 0xe2, 0x56, 0x59, |
| 709 | 0x40, 0x5b, 0x82, 0x6d, | 737 | 0x40, 0x5b, 0xba, 0x6d, |
| 710 | 0x04, 0x5d, 0xe6, 0x7d, | 738 | 0x04, 0x5d, 0x1e, 0x7e, |
| 711 | 0x01, 0x1a, 0xe6, 0x7d, | 739 | 0x01, 0x1a, 0x1e, 0x7e, |
| 712 | 0x20, 0x4d, 0x64, 0x78, | 740 | 0x20, 0x4d, 0x84, 0x78, |
| 713 | 0x40, 0x5b, 0xcc, 0x7d, | 741 | 0x40, 0x5b, 0x04, 0x7e, |
| 714 | 0x04, 0x5d, 0xe6, 0x7d, | 742 | 0x04, 0x5d, 0x1e, 0x7e, |
| 715 | 0x01, 0x1a, 0xe6, 0x7d, | 743 | 0x01, 0x1a, 0x1e, 0x7e, |
| 716 | 0x80, 0xf9, 0xf2, 0x01, | 744 | 0x80, 0xf9, 0xf2, 0x01, |
| 717 | 0xff, 0x90, 0x21, 0x1b, | 745 | 0xff, 0x90, 0x21, 0x1b, |
| 718 | 0x08, 0x92, 0x43, 0x6b, | 746 | 0x08, 0x92, 0x63, 0x6b, |
| 719 | 0x02, 0xea, 0xb4, 0x04, | 747 | 0x02, 0xea, 0xb4, 0x04, |
| 720 | 0x00, 0xe2, 0x3e, 0x59, | 748 | 0x00, 0xe2, 0x56, 0x59, |
| 721 | 0x01, 0x1b, 0x64, 0x78, | 749 | 0x01, 0x1b, 0x84, 0x78, |
| 722 | 0x80, 0xf9, 0xf2, 0x01, | 750 | 0x80, 0xf9, 0xf2, 0x01, |
| 723 | 0x02, 0xea, 0xb4, 0x04, | 751 | 0x02, 0xea, 0xb4, 0x04, |
| 724 | 0x00, 0xe2, 0x3e, 0x59, | 752 | 0x00, 0xe2, 0x56, 0x59, |
| 725 | 0x01, 0x1b, 0xaa, 0x6d, | 753 | 0x01, 0x1b, 0xe2, 0x6d, |
| 726 | 0x40, 0x5b, 0xb8, 0x7d, | 754 | 0x40, 0x5b, 0xf0, 0x7d, |
| 727 | 0x01, 0x1b, 0xaa, 0x6d, | 755 | 0x01, 0x1b, 0xe2, 0x6d, |
| 728 | 0x02, 0x19, 0x32, 0x00, | 756 | 0x02, 0x19, 0x32, 0x00, |
| 729 | 0x01, 0x1a, 0x64, 0x78, | 757 | 0x01, 0x1a, 0x84, 0x78, |
| 730 | 0x80, 0xf9, 0xf2, 0x01, | 758 | 0x80, 0xf9, 0xf2, 0x01, |
| 731 | 0xff, 0xea, 0x10, 0x03, | 759 | 0xff, 0xea, 0x10, 0x03, |
| 732 | 0x08, 0x92, 0x25, 0x03, | 760 | 0x08, 0x92, 0x25, 0x03, |
| 733 | 0x00, 0xe2, 0x42, 0x43, | 761 | 0x00, 0xe2, 0x62, 0x43, |
| 734 | 0x01, 0x1a, 0xb4, 0x7d, | 762 | 0x01, 0x1a, 0xec, 0x7d, |
| 735 | 0x40, 0x5b, 0xb0, 0x7d, | 763 | 0x40, 0x5b, 0xe8, 0x7d, |
| 736 | 0x01, 0x1a, 0x9e, 0x6d, | 764 | 0x01, 0x1a, 0xd6, 0x6d, |
| 737 | 0xfc, 0x42, 0x64, 0x78, | 765 | 0xfc, 0x42, 0x84, 0x78, |
| 738 | 0x01, 0x1a, 0xb8, 0x6d, | 766 | 0x01, 0x1a, 0xf0, 0x6d, |
| 739 | 0x10, 0xea, 0x50, 0x59, | 767 | 0x10, 0xea, 0x64, 0x59, |
| 740 | 0x10, 0xea, 0x04, 0x00, | 768 | 0x10, 0xea, 0x04, 0x00, |
| 741 | 0xfc, 0x42, 0x64, 0x78, | 769 | 0xfc, 0x42, 0x84, 0x78, |
| 742 | 0x10, 0x40, 0xbe, 0x6d, | 770 | 0x10, 0x40, 0xf6, 0x6d, |
| 743 | 0x20, 0x4d, 0x64, 0x78, | 771 | 0x20, 0x4d, 0x84, 0x78, |
| 744 | 0x40, 0x5b, 0x9e, 0x6d, | 772 | 0x40, 0x5b, 0xd6, 0x6d, |
| 745 | 0x01, 0x1a, 0x64, 0x78, | 773 | 0x01, 0x1a, 0x84, 0x78, |
| 746 | 0x01, 0x90, 0x21, 0x1b, | 774 | 0x01, 0x90, 0x21, 0x1b, |
| 747 | 0x30, 0x3f, 0xc0, 0x09, | 775 | 0x30, 0x3f, 0xc0, 0x09, |
| 748 | 0x30, 0xe0, 0x64, 0x60, | 776 | 0x30, 0xe0, 0x84, 0x60, |
| 749 | 0x40, 0x4b, 0x64, 0x68, | 777 | 0x40, 0x4b, 0x84, 0x68, |
| 750 | 0xff, 0xea, 0x52, 0x01, | 778 | 0xff, 0xea, 0x52, 0x01, |
| 751 | 0xee, 0x00, 0xd2, 0x6d, | 779 | 0xee, 0x00, 0x0c, 0x6e, |
| 752 | 0x80, 0xf9, 0xf2, 0x01, | 780 | 0x80, 0xf9, 0xf2, 0x01, |
| 753 | 0xff, 0x90, 0x21, 0x1b, | 781 | 0xff, 0x90, 0x21, 0x1b, |
| 754 | 0x02, 0xea, 0xb4, 0x00, | 782 | 0x02, 0xea, 0xb4, 0x00, |
| 755 | 0x20, 0xea, 0x9a, 0x00, | 783 | 0x20, 0xea, 0x9a, 0x00, |
| 756 | 0xf3, 0x42, 0xde, 0x6d, | 784 | 0xf3, 0x42, 0x16, 0x6e, |
| 757 | 0x12, 0xea, 0x50, 0x59, | 785 | 0x12, 0xea, 0x64, 0x59, |
| 758 | 0x12, 0xea, 0x04, 0x00, | 786 | 0x12, 0xea, 0x04, 0x00, |
| 759 | 0x00, 0xe2, 0xf8, 0x41, | 787 | 0x00, 0xe2, 0x14, 0x42, |
| 760 | 0x0d, 0xea, 0x50, 0x59, | 788 | 0x0d, 0xea, 0x64, 0x59, |
| 761 | 0x0d, 0xea, 0x04, 0x00, | 789 | 0x0d, 0xea, 0x04, 0x00, |
| 762 | 0x00, 0xe2, 0xf8, 0x41, | 790 | 0x00, 0xe2, 0x14, 0x42, |
| 763 | 0x01, 0x90, 0x21, 0x1b, | 791 | 0x01, 0x90, 0x21, 0x1b, |
| 764 | 0x11, 0xea, 0x50, 0x59, | 792 | 0x11, 0xea, 0x64, 0x59, |
| 765 | 0x11, 0xea, 0x04, 0x00, | 793 | 0x11, 0xea, 0x04, 0x00, |
| 766 | 0x00, 0xe2, 0x32, 0x5b, | 794 | 0x00, 0xe2, 0x52, 0x5b, |
| 767 | 0x08, 0x5a, 0xb4, 0x00, | 795 | 0x08, 0x5a, 0xb4, 0x00, |
| 768 | 0x00, 0xe2, 0x0c, 0x5e, | 796 | 0x00, 0xe2, 0x44, 0x5e, |
| 769 | 0xa8, 0xea, 0x32, 0x00, | 797 | 0xa8, 0xea, 0x32, 0x00, |
| 770 | 0x00, 0xe2, 0x3e, 0x59, | 798 | 0x00, 0xe2, 0x56, 0x59, |
| 771 | 0x80, 0x1a, 0xfa, 0x7d, | 799 | 0x80, 0x1a, 0x32, 0x7e, |
| 772 | 0x00, 0xe2, 0x0c, 0x5e, | 800 | 0x00, 0xe2, 0x44, 0x5e, |
| 773 | 0x80, 0x19, 0x32, 0x00, | 801 | 0x80, 0x19, 0x32, 0x00, |
| 774 | 0x40, 0x5b, 0x00, 0x6e, | 802 | 0x40, 0x5b, 0x38, 0x6e, |
| 775 | 0x08, 0x5a, 0x00, 0x7e, | 803 | 0x08, 0x5a, 0x38, 0x7e, |
| 776 | 0x20, 0x4d, 0x64, 0x78, | 804 | 0x20, 0x4d, 0x84, 0x78, |
| 777 | 0x02, 0x84, 0x09, 0x03, | 805 | 0x02, 0x84, 0x09, 0x03, |
| 778 | 0x40, 0x5b, 0xcc, 0x7d, | 806 | 0x40, 0x5b, 0x04, 0x7e, |
| 779 | 0xff, 0x90, 0x21, 0x1b, | 807 | 0xff, 0x90, 0x21, 0x1b, |
| 780 | 0x80, 0xf9, 0xf2, 0x01, | 808 | 0x80, 0xf9, 0xf2, 0x01, |
| 781 | 0x08, 0x92, 0x43, 0x6b, | 809 | 0x08, 0x92, 0x63, 0x6b, |
| 782 | 0x02, 0xea, 0xb4, 0x04, | 810 | 0x02, 0xea, 0xb4, 0x04, |
| 783 | 0x01, 0x38, 0xe1, 0x30, | 811 | 0x01, 0x40, 0xe1, 0x30, |
| 784 | 0x05, 0x39, 0xe3, 0x98, | 812 | 0x05, 0x41, 0xe3, 0x98, |
| 785 | 0x01, 0xe0, 0xf4, 0x31, | 813 | 0x01, 0xe0, 0xf4, 0x31, |
| 786 | 0xff, 0xea, 0xc0, 0x09, | 814 | 0xff, 0xea, 0xc0, 0x09, |
| 787 | 0x00, 0x3a, 0xe5, 0x20, | 815 | 0x00, 0x42, 0xe5, 0x20, |
| 788 | 0x00, 0x3b, 0xe7, 0x20, | 816 | 0x00, 0x43, 0xe7, 0x20, |
| 789 | 0x01, 0xfa, 0xc0, 0x31, | 817 | 0x01, 0xfa, 0xc0, 0x31, |
| 790 | 0x04, 0xea, 0xe8, 0x30, | 818 | 0x04, 0xea, 0xe8, 0x30, |
| 791 | 0xff, 0xea, 0xf0, 0x08, | 819 | 0xff, 0xea, 0xf0, 0x08, |
| @@ -794,12 +822,20 @@ static uint8_t seqprog[] = { | |||
| 794 | }; | 822 | }; |
| 795 | 823 | ||
| 796 | typedef int ahd_patch_func_t (struct ahd_softc *ahd); | 824 | typedef int ahd_patch_func_t (struct ahd_softc *ahd); |
| 825 | static ahd_patch_func_t ahd_patch23_func; | ||
| 826 | |||
| 827 | static int | ||
| 828 | ahd_patch23_func(struct ahd_softc *ahd) | ||
| 829 | { | ||
| 830 | return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); | ||
| 831 | } | ||
| 832 | |||
| 797 | static ahd_patch_func_t ahd_patch22_func; | 833 | static ahd_patch_func_t ahd_patch22_func; |
| 798 | 834 | ||
| 799 | static int | 835 | static int |
| 800 | ahd_patch22_func(struct ahd_softc *ahd) | 836 | ahd_patch22_func(struct ahd_softc *ahd) |
| 801 | { | 837 | { |
| 802 | return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); | 838 | return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); |
| 803 | } | 839 | } |
| 804 | 840 | ||
| 805 | static ahd_patch_func_t ahd_patch21_func; | 841 | static ahd_patch_func_t ahd_patch21_func; |
| @@ -807,7 +843,7 @@ static ahd_patch_func_t ahd_patch21_func; | |||
| 807 | static int | 843 | static int |
| 808 | ahd_patch21_func(struct ahd_softc *ahd) | 844 | ahd_patch21_func(struct ahd_softc *ahd) |
| 809 | { | 845 | { |
| 810 | return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); | 846 | return ((ahd->flags & AHD_INITIATORROLE) != 0); |
| 811 | } | 847 | } |
| 812 | 848 | ||
| 813 | static ahd_patch_func_t ahd_patch20_func; | 849 | static ahd_patch_func_t ahd_patch20_func; |
| @@ -815,7 +851,7 @@ static ahd_patch_func_t ahd_patch20_func; | |||
| 815 | static int | 851 | static int |
| 816 | ahd_patch20_func(struct ahd_softc *ahd) | 852 | ahd_patch20_func(struct ahd_softc *ahd) |
| 817 | { | 853 | { |
| 818 | return ((ahd->features & AHD_RTI) == 0); | 854 | return ((ahd->flags & AHD_TARGETROLE) != 0); |
| 819 | } | 855 | } |
| 820 | 856 | ||
| 821 | static ahd_patch_func_t ahd_patch19_func; | 857 | static ahd_patch_func_t ahd_patch19_func; |
| @@ -823,7 +859,7 @@ static ahd_patch_func_t ahd_patch19_func; | |||
| 823 | static int | 859 | static int |
| 824 | ahd_patch19_func(struct ahd_softc *ahd) | 860 | ahd_patch19_func(struct ahd_softc *ahd) |
| 825 | { | 861 | { |
| 826 | return ((ahd->flags & AHD_INITIATORROLE) != 0); | 862 | return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); |
| 827 | } | 863 | } |
| 828 | 864 | ||
| 829 | static ahd_patch_func_t ahd_patch18_func; | 865 | static ahd_patch_func_t ahd_patch18_func; |
| @@ -831,7 +867,7 @@ static ahd_patch_func_t ahd_patch18_func; | |||
| 831 | static int | 867 | static int |
| 832 | ahd_patch18_func(struct ahd_softc *ahd) | 868 | ahd_patch18_func(struct ahd_softc *ahd) |
| 833 | { | 869 | { |
| 834 | return ((ahd->flags & AHD_TARGETROLE) != 0); | 870 | return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); |
| 835 | } | 871 | } |
| 836 | 872 | ||
| 837 | static ahd_patch_func_t ahd_patch17_func; | 873 | static ahd_patch_func_t ahd_patch17_func; |
| @@ -839,7 +875,7 @@ static ahd_patch_func_t ahd_patch17_func; | |||
| 839 | static int | 875 | static int |
| 840 | ahd_patch17_func(struct ahd_softc *ahd) | 876 | ahd_patch17_func(struct ahd_softc *ahd) |
| 841 | { | 877 | { |
| 842 | return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); | 878 | return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); |
| 843 | } | 879 | } |
| 844 | 880 | ||
| 845 | static ahd_patch_func_t ahd_patch16_func; | 881 | static ahd_patch_func_t ahd_patch16_func; |
| @@ -847,7 +883,7 @@ static ahd_patch_func_t ahd_patch16_func; | |||
| 847 | static int | 883 | static int |
| 848 | ahd_patch16_func(struct ahd_softc *ahd) | 884 | ahd_patch16_func(struct ahd_softc *ahd) |
| 849 | { | 885 | { |
| 850 | return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); | 886 | return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); |
| 851 | } | 887 | } |
| 852 | 888 | ||
| 853 | static ahd_patch_func_t ahd_patch15_func; | 889 | static ahd_patch_func_t ahd_patch15_func; |
| @@ -855,7 +891,7 @@ static ahd_patch_func_t ahd_patch15_func; | |||
| 855 | static int | 891 | static int |
| 856 | ahd_patch15_func(struct ahd_softc *ahd) | 892 | ahd_patch15_func(struct ahd_softc *ahd) |
| 857 | { | 893 | { |
| 858 | return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); | 894 | return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); |
| 859 | } | 895 | } |
| 860 | 896 | ||
| 861 | static ahd_patch_func_t ahd_patch14_func; | 897 | static ahd_patch_func_t ahd_patch14_func; |
| @@ -863,7 +899,7 @@ static ahd_patch_func_t ahd_patch14_func; | |||
| 863 | static int | 899 | static int |
| 864 | ahd_patch14_func(struct ahd_softc *ahd) | 900 | ahd_patch14_func(struct ahd_softc *ahd) |
| 865 | { | 901 | { |
| 866 | return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); | 902 | return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); |
| 867 | } | 903 | } |
| 868 | 904 | ||
| 869 | static ahd_patch_func_t ahd_patch13_func; | 905 | static ahd_patch_func_t ahd_patch13_func; |
| @@ -871,7 +907,7 @@ static ahd_patch_func_t ahd_patch13_func; | |||
| 871 | static int | 907 | static int |
| 872 | ahd_patch13_func(struct ahd_softc *ahd) | 908 | ahd_patch13_func(struct ahd_softc *ahd) |
| 873 | { | 909 | { |
| 874 | return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); | 910 | return ((ahd->features & AHD_RTI) == 0); |
| 875 | } | 911 | } |
| 876 | 912 | ||
| 877 | static ahd_patch_func_t ahd_patch12_func; | 913 | static ahd_patch_func_t ahd_patch12_func; |
| @@ -879,7 +915,7 @@ static ahd_patch_func_t ahd_patch12_func; | |||
| 879 | static int | 915 | static int |
| 880 | ahd_patch12_func(struct ahd_softc *ahd) | 916 | ahd_patch12_func(struct ahd_softc *ahd) |
| 881 | { | 917 | { |
| 882 | return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); | 918 | return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); |
| 883 | } | 919 | } |
| 884 | 920 | ||
| 885 | static ahd_patch_func_t ahd_patch11_func; | 921 | static ahd_patch_func_t ahd_patch11_func; |
| @@ -887,7 +923,7 @@ static ahd_patch_func_t ahd_patch11_func; | |||
| 887 | static int | 923 | static int |
| 888 | ahd_patch11_func(struct ahd_softc *ahd) | 924 | ahd_patch11_func(struct ahd_softc *ahd) |
| 889 | { | 925 | { |
| 890 | return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); | 926 | return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); |
| 891 | } | 927 | } |
| 892 | 928 | ||
| 893 | static ahd_patch_func_t ahd_patch10_func; | 929 | static ahd_patch_func_t ahd_patch10_func; |
| @@ -895,7 +931,7 @@ static ahd_patch_func_t ahd_patch10_func; | |||
| 895 | static int | 931 | static int |
| 896 | ahd_patch10_func(struct ahd_softc *ahd) | 932 | ahd_patch10_func(struct ahd_softc *ahd) |
| 897 | { | 933 | { |
| 898 | return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); | 934 | return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); |
| 899 | } | 935 | } |
| 900 | 936 | ||
| 901 | static ahd_patch_func_t ahd_patch9_func; | 937 | static ahd_patch_func_t ahd_patch9_func; |
| @@ -903,7 +939,7 @@ static ahd_patch_func_t ahd_patch9_func; | |||
| 903 | static int | 939 | static int |
| 904 | ahd_patch9_func(struct ahd_softc *ahd) | 940 | ahd_patch9_func(struct ahd_softc *ahd) |
| 905 | { | 941 | { |
| 906 | return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); | 942 | return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0); |
| 907 | } | 943 | } |
| 908 | 944 | ||
| 909 | static ahd_patch_func_t ahd_patch8_func; | 945 | static ahd_patch_func_t ahd_patch8_func; |
| @@ -992,147 +1028,149 @@ static struct patch { | |||
| 992 | { ahd_patch0_func, 5, 1, 1 }, | 1028 | { ahd_patch0_func, 5, 1, 1 }, |
| 993 | { ahd_patch2_func, 6, 1, 2 }, | 1029 | { ahd_patch2_func, 6, 1, 2 }, |
| 994 | { ahd_patch0_func, 7, 1, 1 }, | 1030 | { ahd_patch0_func, 7, 1, 1 }, |
| 995 | { ahd_patch3_func, 20, 5, 1 }, | 1031 | { ahd_patch3_func, 36, 5, 1 }, |
| 996 | { ahd_patch2_func, 29, 1, 2 }, | 1032 | { ahd_patch2_func, 45, 1, 2 }, |
| 997 | { ahd_patch0_func, 30, 1, 1 }, | 1033 | { ahd_patch0_func, 46, 1, 1 }, |
| 998 | { ahd_patch1_func, 37, 1, 2 }, | 1034 | { ahd_patch1_func, 53, 1, 2 }, |
| 999 | { ahd_patch0_func, 38, 1, 1 }, | 1035 | { ahd_patch0_func, 54, 1, 1 }, |
| 1000 | { ahd_patch2_func, 43, 1, 2 }, | 1036 | { ahd_patch2_func, 59, 1, 2 }, |
| 1001 | { ahd_patch0_func, 44, 1, 1 }, | 1037 | { ahd_patch0_func, 60, 1, 1 }, |
| 1002 | { ahd_patch2_func, 47, 1, 2 }, | 1038 | { ahd_patch2_func, 63, 1, 2 }, |
| 1003 | { ahd_patch0_func, 48, 1, 1 }, | 1039 | { ahd_patch0_func, 64, 1, 1 }, |
| 1004 | { ahd_patch2_func, 51, 1, 2 }, | 1040 | { ahd_patch2_func, 67, 1, 2 }, |
| 1005 | { ahd_patch0_func, 52, 1, 1 }, | 1041 | { ahd_patch0_func, 68, 1, 1 }, |
| 1006 | { ahd_patch2_func, 65, 1, 2 }, | 1042 | { ahd_patch4_func, 116, 1, 1 }, |
| 1007 | { ahd_patch0_func, 66, 1, 1 }, | 1043 | { ahd_patch2_func, 175, 3, 1 }, |
| 1008 | { ahd_patch2_func, 69, 1, 2 }, | 1044 | { ahd_patch1_func, 178, 2, 1 }, |
| 1009 | { ahd_patch0_func, 70, 1, 1 }, | 1045 | { ahd_patch5_func, 180, 1, 1 }, |
| 1010 | { ahd_patch1_func, 73, 1, 2 }, | 1046 | { ahd_patch2_func, 189, 1, 2 }, |
| 1011 | { ahd_patch0_func, 74, 1, 1 }, | 1047 | { ahd_patch0_func, 190, 1, 1 }, |
| 1012 | { ahd_patch4_func, 107, 1, 1 }, | 1048 | { ahd_patch6_func, 191, 2, 2 }, |
| 1013 | { ahd_patch2_func, 162, 6, 1 }, | 1049 | { ahd_patch0_func, 193, 6, 3 }, |
| 1014 | { ahd_patch1_func, 168, 2, 1 }, | 1050 | { ahd_patch2_func, 196, 1, 2 }, |
| 1015 | { ahd_patch5_func, 170, 1, 1 }, | 1051 | { ahd_patch0_func, 197, 1, 1 }, |
| 1016 | { ahd_patch2_func, 179, 1, 2 }, | 1052 | { ahd_patch2_func, 200, 1, 2 }, |
| 1017 | { ahd_patch0_func, 180, 1, 1 }, | 1053 | { ahd_patch0_func, 201, 1, 1 }, |
| 1018 | { ahd_patch6_func, 181, 2, 2 }, | 1054 | { ahd_patch3_func, 203, 1, 1 }, |
| 1019 | { ahd_patch0_func, 183, 6, 3 }, | 1055 | { ahd_patch7_func, 204, 3, 1 }, |
| 1020 | { ahd_patch2_func, 186, 1, 2 }, | 1056 | { ahd_patch3_func, 213, 1, 1 }, |
| 1021 | { ahd_patch0_func, 187, 1, 1 }, | 1057 | { ahd_patch5_func, 214, 16, 2 }, |
| 1022 | { ahd_patch2_func, 190, 1, 2 }, | 1058 | { ahd_patch0_func, 230, 1, 1 }, |
| 1023 | { ahd_patch0_func, 191, 1, 1 }, | 1059 | { ahd_patch8_func, 250, 2, 1 }, |
| 1024 | { ahd_patch7_func, 193, 2, 1 }, | 1060 | { ahd_patch1_func, 254, 1, 2 }, |
| 1025 | { ahd_patch5_func, 201, 16, 2 }, | 1061 | { ahd_patch0_func, 255, 1, 1 }, |
| 1026 | { ahd_patch0_func, 217, 1, 1 }, | 1062 | { ahd_patch7_func, 258, 3, 1 }, |
| 1027 | { ahd_patch8_func, 237, 2, 1 }, | 1063 | { ahd_patch1_func, 273, 1, 2 }, |
| 1028 | { ahd_patch1_func, 241, 1, 2 }, | 1064 | { ahd_patch0_func, 274, 1, 1 }, |
| 1029 | { ahd_patch0_func, 242, 1, 1 }, | 1065 | { ahd_patch1_func, 277, 1, 2 }, |
| 1030 | { ahd_patch7_func, 245, 2, 1 }, | 1066 | { ahd_patch0_func, 278, 1, 1 }, |
| 1031 | { ahd_patch1_func, 259, 1, 2 }, | 1067 | { ahd_patch2_func, 281, 1, 2 }, |
| 1032 | { ahd_patch0_func, 260, 1, 1 }, | 1068 | { ahd_patch0_func, 282, 1, 1 }, |
| 1033 | { ahd_patch1_func, 263, 1, 2 }, | 1069 | { ahd_patch9_func, 295, 2, 2 }, |
| 1034 | { ahd_patch0_func, 264, 1, 1 }, | 1070 | { ahd_patch0_func, 297, 1, 1 }, |
| 1035 | { ahd_patch2_func, 267, 1, 2 }, | 1071 | { ahd_patch1_func, 339, 1, 2 }, |
| 1036 | { ahd_patch0_func, 268, 1, 1 }, | 1072 | { ahd_patch0_func, 340, 1, 1 }, |
| 1037 | { ahd_patch1_func, 323, 1, 2 }, | 1073 | { ahd_patch2_func, 348, 1, 2 }, |
| 1038 | { ahd_patch0_func, 324, 1, 1 }, | 1074 | { ahd_patch0_func, 349, 1, 1 }, |
| 1039 | { ahd_patch2_func, 332, 1, 2 }, | 1075 | { ahd_patch2_func, 352, 1, 2 }, |
| 1040 | { ahd_patch0_func, 333, 1, 1 }, | 1076 | { ahd_patch0_func, 353, 1, 1 }, |
| 1041 | { ahd_patch2_func, 336, 1, 2 }, | 1077 | { ahd_patch1_func, 359, 1, 2 }, |
| 1042 | { ahd_patch0_func, 337, 1, 1 }, | 1078 | { ahd_patch0_func, 360, 1, 1 }, |
| 1043 | { ahd_patch1_func, 343, 1, 2 }, | 1079 | { ahd_patch1_func, 362, 1, 2 }, |
| 1044 | { ahd_patch0_func, 344, 1, 1 }, | 1080 | { ahd_patch0_func, 363, 1, 1 }, |
| 1045 | { ahd_patch1_func, 346, 1, 2 }, | 1081 | { ahd_patch10_func, 382, 1, 1 }, |
| 1046 | { ahd_patch0_func, 347, 1, 1 }, | 1082 | { ahd_patch10_func, 385, 1, 1 }, |
| 1047 | { ahd_patch9_func, 366, 1, 1 }, | 1083 | { ahd_patch10_func, 387, 1, 1 }, |
| 1048 | { ahd_patch9_func, 369, 1, 1 }, | 1084 | { ahd_patch10_func, 399, 1, 1 }, |
| 1049 | { ahd_patch9_func, 371, 1, 1 }, | 1085 | { ahd_patch1_func, 409, 1, 2 }, |
| 1050 | { ahd_patch9_func, 383, 1, 1 }, | 1086 | { ahd_patch0_func, 410, 1, 1 }, |
| 1051 | { ahd_patch1_func, 393, 1, 2 }, | 1087 | { ahd_patch1_func, 412, 1, 2 }, |
| 1052 | { ahd_patch0_func, 394, 1, 1 }, | 1088 | { ahd_patch0_func, 413, 1, 1 }, |
| 1053 | { ahd_patch1_func, 396, 1, 2 }, | 1089 | { ahd_patch1_func, 421, 1, 2 }, |
| 1054 | { ahd_patch0_func, 397, 1, 1 }, | 1090 | { ahd_patch0_func, 422, 1, 1 }, |
| 1055 | { ahd_patch1_func, 405, 1, 2 }, | 1091 | { ahd_patch2_func, 435, 1, 2 }, |
| 1056 | { ahd_patch0_func, 406, 1, 1 }, | 1092 | { ahd_patch0_func, 436, 1, 1 }, |
| 1057 | { ahd_patch2_func, 419, 1, 2 }, | 1093 | { ahd_patch11_func, 472, 1, 1 }, |
| 1058 | { ahd_patch0_func, 420, 1, 1 }, | 1094 | { ahd_patch1_func, 480, 1, 2 }, |
| 1059 | { ahd_patch10_func, 450, 1, 1 }, | 1095 | { ahd_patch0_func, 481, 1, 1 }, |
| 1060 | { ahd_patch1_func, 457, 1, 2 }, | 1096 | { ahd_patch2_func, 493, 1, 2 }, |
| 1061 | { ahd_patch0_func, 458, 1, 1 }, | 1097 | { ahd_patch0_func, 494, 1, 1 }, |
| 1062 | { ahd_patch2_func, 470, 1, 2 }, | 1098 | { ahd_patch12_func, 497, 6, 2 }, |
| 1063 | { ahd_patch0_func, 471, 1, 1 }, | 1099 | { ahd_patch0_func, 503, 1, 1 }, |
| 1064 | { ahd_patch11_func, 476, 6, 2 }, | 1100 | { ahd_patch13_func, 524, 7, 1 }, |
| 1065 | { ahd_patch0_func, 482, 1, 1 }, | 1101 | { ahd_patch14_func, 533, 1, 1 }, |
| 1066 | { ahd_patch12_func, 505, 1, 1 }, | 1102 | { ahd_patch15_func, 542, 1, 1 }, |
| 1067 | { ahd_patch13_func, 514, 1, 1 }, | 1103 | { ahd_patch16_func, 543, 1, 2 }, |
| 1068 | { ahd_patch14_func, 515, 1, 2 }, | 1104 | { ahd_patch0_func, 544, 1, 1 }, |
| 1069 | { ahd_patch0_func, 516, 1, 1 }, | 1105 | { ahd_patch17_func, 547, 1, 1 }, |
| 1070 | { ahd_patch15_func, 519, 1, 1 }, | 1106 | { ahd_patch16_func, 548, 1, 1 }, |
| 1071 | { ahd_patch14_func, 520, 1, 1 }, | 1107 | { ahd_patch18_func, 559, 1, 2 }, |
| 1072 | { ahd_patch16_func, 531, 1, 2 }, | 1108 | { ahd_patch0_func, 560, 1, 1 }, |
| 1073 | { ahd_patch0_func, 532, 1, 1 }, | 1109 | { ahd_patch1_func, 579, 1, 2 }, |
| 1074 | { ahd_patch1_func, 551, 1, 2 }, | 1110 | { ahd_patch0_func, 580, 1, 1 }, |
| 1075 | { ahd_patch0_func, 552, 1, 1 }, | 1111 | { ahd_patch1_func, 583, 1, 2 }, |
| 1076 | { ahd_patch1_func, 555, 1, 2 }, | 1112 | { ahd_patch0_func, 584, 1, 1 }, |
| 1077 | { ahd_patch0_func, 556, 1, 1 }, | 1113 | { ahd_patch2_func, 589, 1, 2 }, |
| 1078 | { ahd_patch2_func, 561, 1, 2 }, | 1114 | { ahd_patch0_func, 590, 1, 1 }, |
| 1079 | { ahd_patch0_func, 562, 1, 1 }, | 1115 | { ahd_patch2_func, 594, 1, 2 }, |
| 1080 | { ahd_patch2_func, 566, 1, 2 }, | 1116 | { ahd_patch0_func, 595, 1, 1 }, |
| 1081 | { ahd_patch0_func, 567, 1, 1 }, | 1117 | { ahd_patch1_func, 596, 1, 2 }, |
| 1082 | { ahd_patch1_func, 568, 1, 2 }, | 1118 | { ahd_patch0_func, 597, 1, 1 }, |
| 1083 | { ahd_patch0_func, 569, 1, 1 }, | 1119 | { ahd_patch2_func, 608, 1, 2 }, |
| 1084 | { ahd_patch2_func, 580, 1, 2 }, | 1120 | { ahd_patch0_func, 609, 1, 1 }, |
| 1085 | { ahd_patch0_func, 581, 1, 1 }, | 1121 | { ahd_patch19_func, 613, 1, 1 }, |
| 1086 | { ahd_patch17_func, 585, 1, 1 }, | 1122 | { ahd_patch20_func, 618, 1, 1 }, |
| 1087 | { ahd_patch18_func, 590, 1, 1 }, | 1123 | { ahd_patch21_func, 619, 2, 1 }, |
| 1088 | { ahd_patch19_func, 591, 2, 1 }, | 1124 | { ahd_patch20_func, 623, 1, 2 }, |
| 1089 | { ahd_patch18_func, 595, 1, 2 }, | 1125 | { ahd_patch0_func, 624, 1, 1 }, |
| 1090 | { ahd_patch0_func, 596, 1, 1 }, | 1126 | { ahd_patch2_func, 627, 1, 2 }, |
| 1091 | { ahd_patch2_func, 599, 1, 2 }, | 1127 | { ahd_patch0_func, 628, 1, 1 }, |
| 1092 | { ahd_patch0_func, 600, 1, 1 }, | 1128 | { ahd_patch2_func, 643, 1, 2 }, |
| 1093 | { ahd_patch2_func, 615, 1, 2 }, | 1129 | { ahd_patch0_func, 644, 1, 1 }, |
| 1094 | { ahd_patch0_func, 616, 1, 1 }, | 1130 | { ahd_patch13_func, 645, 14, 1 }, |
| 1095 | { ahd_patch20_func, 617, 14, 1 }, | 1131 | { ahd_patch1_func, 663, 1, 2 }, |
| 1096 | { ahd_patch1_func, 635, 1, 2 }, | 1132 | { ahd_patch0_func, 664, 1, 1 }, |
| 1097 | { ahd_patch0_func, 636, 1, 1 }, | 1133 | { ahd_patch13_func, 665, 1, 1 }, |
| 1098 | { ahd_patch20_func, 637, 1, 1 }, | 1134 | { ahd_patch1_func, 677, 1, 2 }, |
| 1099 | { ahd_patch1_func, 649, 1, 2 }, | 1135 | { ahd_patch0_func, 678, 1, 1 }, |
| 1100 | { ahd_patch0_func, 650, 1, 1 }, | 1136 | { ahd_patch1_func, 685, 1, 2 }, |
| 1101 | { ahd_patch1_func, 657, 1, 2 }, | 1137 | { ahd_patch0_func, 686, 1, 1 }, |
| 1102 | { ahd_patch0_func, 658, 1, 1 }, | 1138 | { ahd_patch19_func, 709, 1, 1 }, |
| 1103 | { ahd_patch17_func, 681, 1, 1 }, | 1139 | { ahd_patch19_func, 747, 1, 1 }, |
| 1104 | { ahd_patch17_func, 719, 1, 1 }, | 1140 | { ahd_patch1_func, 758, 1, 2 }, |
| 1105 | { ahd_patch1_func, 730, 1, 2 }, | 1141 | { ahd_patch0_func, 759, 1, 1 }, |
| 1106 | { ahd_patch0_func, 731, 1, 1 }, | 1142 | { ahd_patch1_func, 776, 1, 2 }, |
| 1107 | { ahd_patch1_func, 748, 1, 2 }, | 1143 | { ahd_patch0_func, 777, 1, 1 }, |
| 1108 | { ahd_patch0_func, 749, 1, 1 }, | 1144 | { ahd_patch1_func, 779, 1, 2 }, |
| 1109 | { ahd_patch1_func, 751, 1, 2 }, | 1145 | { ahd_patch0_func, 780, 1, 1 }, |
| 1110 | { ahd_patch0_func, 752, 1, 1 }, | 1146 | { ahd_patch1_func, 783, 1, 2 }, |
| 1111 | { ahd_patch1_func, 755, 1, 2 }, | 1147 | { ahd_patch0_func, 784, 1, 1 }, |
| 1112 | { ahd_patch0_func, 756, 1, 1 }, | 1148 | { ahd_patch22_func, 786, 1, 2 }, |
| 1113 | { ahd_patch21_func, 758, 1, 2 }, | 1149 | { ahd_patch0_func, 787, 2, 1 }, |
| 1114 | { ahd_patch0_func, 759, 2, 1 }, | 1150 | { ahd_patch23_func, 790, 4, 2 }, |
| 1115 | { ahd_patch22_func, 762, 4, 2 }, | 1151 | { ahd_patch0_func, 794, 1, 1 }, |
| 1116 | { ahd_patch0_func, 766, 1, 1 }, | 1152 | { ahd_patch23_func, 802, 11, 1 } |
| 1117 | { ahd_patch22_func, 774, 11, 1 } | ||
| 1118 | }; | 1153 | }; |
| 1119 | 1154 | ||
| 1120 | static struct cs { | 1155 | static struct cs { |
| 1121 | uint16_t begin; | 1156 | uint16_t begin; |
| 1122 | uint16_t end; | 1157 | uint16_t end; |
| 1123 | } critical_sections[] = { | 1158 | } critical_sections[] = { |
| 1124 | { 11, 12 }, | 1159 | { 17, 28 }, |
| 1125 | { 13, 14 }, | 1160 | { 29, 30 }, |
| 1126 | { 29, 42 }, | 1161 | { 47, 58 }, |
| 1127 | { 56, 59 }, | 1162 | { 61, 63 }, |
| 1128 | { 101, 128 }, | 1163 | { 65, 66 }, |
| 1129 | { 129, 157 }, | 1164 | { 72, 92 }, |
| 1130 | { 159, 162 }, | 1165 | { 110, 137 }, |
| 1131 | { 170, 178 }, | 1166 | { 138, 175 }, |
| 1132 | { 201, 250 }, | 1167 | { 180, 188 }, |
| 1133 | { 681, 697 }, | 1168 | { 213, 264 }, |
| 1134 | { 697, 711 }, | 1169 | { 425, 433 }, |
| 1135 | { 721, 725 } | 1170 | { 443, 445 }, |
| 1171 | { 448, 457 }, | ||
| 1172 | { 709, 739 }, | ||
| 1173 | { 749, 753 } | ||
| 1136 | }; | 1174 | }; |
| 1137 | 1175 | ||
| 1138 | static const int num_critical_sections = sizeof(critical_sections) | 1176 | static const int num_critical_sections = sizeof(critical_sections) |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index fd389e9f9460..051970efba68 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
| @@ -375,7 +375,7 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, | |||
| 375 | struct scsi_cmnd *cmd); | 375 | struct scsi_cmnd *cmd); |
| 376 | static void ahc_linux_sem_timeout(u_long arg); | 376 | static void ahc_linux_sem_timeout(u_long arg); |
| 377 | static void ahc_linux_freeze_simq(struct ahc_softc *ahc); | 377 | static void ahc_linux_freeze_simq(struct ahc_softc *ahc); |
| 378 | static void ahc_linux_release_simq(u_long arg); | 378 | static void ahc_linux_release_simq(struct ahc_softc *ahc); |
| 379 | static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); | 379 | static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); |
| 380 | static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); | 380 | static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); |
| 381 | static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, | 381 | static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, |
| @@ -1073,7 +1073,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa | |||
| 1073 | return (ENOMEM); | 1073 | return (ENOMEM); |
| 1074 | 1074 | ||
| 1075 | *((struct ahc_softc **)host->hostdata) = ahc; | 1075 | *((struct ahc_softc **)host->hostdata) = ahc; |
| 1076 | ahc_lock(ahc, &s); | ||
| 1077 | ahc->platform_data->host = host; | 1076 | ahc->platform_data->host = host; |
| 1078 | host->can_queue = AHC_MAX_QUEUE; | 1077 | host->can_queue = AHC_MAX_QUEUE; |
| 1079 | host->cmd_per_lun = 2; | 1078 | host->cmd_per_lun = 2; |
| @@ -1084,7 +1083,9 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa | |||
| 1084 | host->max_lun = AHC_NUM_LUNS; | 1083 | host->max_lun = AHC_NUM_LUNS; |
| 1085 | host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; | 1084 | host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; |
| 1086 | host->sg_tablesize = AHC_NSEG; | 1085 | host->sg_tablesize = AHC_NSEG; |
| 1086 | ahc_lock(ahc, &s); | ||
| 1087 | ahc_set_unit(ahc, ahc_linux_unit++); | 1087 | ahc_set_unit(ahc, ahc_linux_unit++); |
| 1088 | ahc_unlock(ahc, &s); | ||
| 1088 | sprintf(buf, "scsi%d", host->host_no); | 1089 | sprintf(buf, "scsi%d", host->host_no); |
| 1089 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | 1090 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); |
| 1090 | if (new_name != NULL) { | 1091 | if (new_name != NULL) { |
| @@ -1094,7 +1095,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa | |||
| 1094 | host->unique_id = ahc->unit; | 1095 | host->unique_id = ahc->unit; |
| 1095 | ahc_linux_initialize_scsi_bus(ahc); | 1096 | ahc_linux_initialize_scsi_bus(ahc); |
| 1096 | ahc_intr_enable(ahc, TRUE); | 1097 | ahc_intr_enable(ahc, TRUE); |
| 1097 | ahc_unlock(ahc, &s); | ||
| 1098 | 1098 | ||
| 1099 | host->transportt = ahc_linux_transport_template; | 1099 | host->transportt = ahc_linux_transport_template; |
| 1100 | 1100 | ||
| @@ -1120,10 +1120,13 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc) | |||
| 1120 | { | 1120 | { |
| 1121 | int i; | 1121 | int i; |
| 1122 | int numtarg; | 1122 | int numtarg; |
| 1123 | unsigned long s; | ||
| 1123 | 1124 | ||
| 1124 | i = 0; | 1125 | i = 0; |
| 1125 | numtarg = 0; | 1126 | numtarg = 0; |
| 1126 | 1127 | ||
| 1128 | ahc_lock(ahc, &s); | ||
| 1129 | |||
| 1127 | if (aic7xxx_no_reset != 0) | 1130 | if (aic7xxx_no_reset != 0) |
| 1128 | ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B); | 1131 | ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B); |
| 1129 | 1132 | ||
| @@ -1170,16 +1173,12 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc) | |||
| 1170 | ahc_update_neg_request(ahc, &devinfo, tstate, | 1173 | ahc_update_neg_request(ahc, &devinfo, tstate, |
| 1171 | tinfo, AHC_NEG_ALWAYS); | 1174 | tinfo, AHC_NEG_ALWAYS); |
| 1172 | } | 1175 | } |
| 1176 | ahc_unlock(ahc, &s); | ||
| 1173 | /* Give the bus some time to recover */ | 1177 | /* Give the bus some time to recover */ |
| 1174 | if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { | 1178 | if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { |
| 1175 | ahc_linux_freeze_simq(ahc); | 1179 | ahc_linux_freeze_simq(ahc); |
| 1176 | init_timer(&ahc->platform_data->reset_timer); | 1180 | msleep(AIC7XXX_RESET_DELAY); |
| 1177 | ahc->platform_data->reset_timer.data = (u_long)ahc; | 1181 | ahc_linux_release_simq(ahc); |
| 1178 | ahc->platform_data->reset_timer.expires = | ||
| 1179 | jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; | ||
| 1180 | ahc->platform_data->reset_timer.function = | ||
| 1181 | ahc_linux_release_simq; | ||
| 1182 | add_timer(&ahc->platform_data->reset_timer); | ||
| 1183 | } | 1182 | } |
| 1184 | } | 1183 | } |
| 1185 | 1184 | ||
| @@ -2059,6 +2058,9 @@ ahc_linux_sem_timeout(u_long arg) | |||
| 2059 | static void | 2058 | static void |
| 2060 | ahc_linux_freeze_simq(struct ahc_softc *ahc) | 2059 | ahc_linux_freeze_simq(struct ahc_softc *ahc) |
| 2061 | { | 2060 | { |
| 2061 | unsigned long s; | ||
| 2062 | |||
| 2063 | ahc_lock(ahc, &s); | ||
| 2062 | ahc->platform_data->qfrozen++; | 2064 | ahc->platform_data->qfrozen++; |
| 2063 | if (ahc->platform_data->qfrozen == 1) { | 2065 | if (ahc->platform_data->qfrozen == 1) { |
| 2064 | scsi_block_requests(ahc->platform_data->host); | 2066 | scsi_block_requests(ahc->platform_data->host); |
| @@ -2068,17 +2070,15 @@ ahc_linux_freeze_simq(struct ahc_softc *ahc) | |||
| 2068 | CAM_LUN_WILDCARD, SCB_LIST_NULL, | 2070 | CAM_LUN_WILDCARD, SCB_LIST_NULL, |
| 2069 | ROLE_INITIATOR, CAM_REQUEUE_REQ); | 2071 | ROLE_INITIATOR, CAM_REQUEUE_REQ); |
| 2070 | } | 2072 | } |
| 2073 | ahc_unlock(ahc, &s); | ||
| 2071 | } | 2074 | } |
| 2072 | 2075 | ||
| 2073 | static void | 2076 | static void |
| 2074 | ahc_linux_release_simq(u_long arg) | 2077 | ahc_linux_release_simq(struct ahc_softc *ahc) |
| 2075 | { | 2078 | { |
| 2076 | struct ahc_softc *ahc; | ||
| 2077 | u_long s; | 2079 | u_long s; |
| 2078 | int unblock_reqs; | 2080 | int unblock_reqs; |
| 2079 | 2081 | ||
| 2080 | ahc = (struct ahc_softc *)arg; | ||
| 2081 | |||
| 2082 | unblock_reqs = 0; | 2082 | unblock_reqs = 0; |
| 2083 | ahc_lock(ahc, &s); | 2083 | ahc_lock(ahc, &s); |
| 2084 | if (ahc->platform_data->qfrozen > 0) | 2084 | if (ahc->platform_data->qfrozen > 0) |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index f2a95447142c..e0edacae895f 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h | |||
| @@ -223,9 +223,6 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t); | |||
| 223 | */ | 223 | */ |
| 224 | #define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) | 224 | #define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) |
| 225 | 225 | ||
| 226 | /************************** Timer DataStructures ******************************/ | ||
| 227 | typedef struct timer_list ahc_timer_t; | ||
| 228 | |||
| 229 | /********************************** Includes **********************************/ | 226 | /********************************** Includes **********************************/ |
| 230 | #ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT | 227 | #ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT |
| 231 | #define AIC_DEBUG_REGISTERS 1 | 228 | #define AIC_DEBUG_REGISTERS 1 |
| @@ -235,30 +232,9 @@ typedef struct timer_list ahc_timer_t; | |||
| 235 | #include "aic7xxx.h" | 232 | #include "aic7xxx.h" |
| 236 | 233 | ||
| 237 | /***************************** Timer Facilities *******************************/ | 234 | /***************************** Timer Facilities *******************************/ |
| 238 | #define ahc_timer_init init_timer | ||
| 239 | #define ahc_timer_stop del_timer_sync | ||
| 240 | typedef void ahc_linux_callback_t (u_long); | ||
| 241 | static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec, | ||
| 242 | ahc_callback_t *func, void *arg); | ||
| 243 | static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec); | ||
| 244 | |||
| 245 | static __inline void | ||
| 246 | ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg) | ||
| 247 | { | ||
| 248 | struct ahc_softc *ahc; | ||
| 249 | |||
| 250 | ahc = (struct ahc_softc *)arg; | ||
| 251 | del_timer(timer); | ||
| 252 | timer->data = (u_long)arg; | ||
| 253 | timer->expires = jiffies + (usec * HZ)/1000000; | ||
| 254 | timer->function = (ahc_linux_callback_t*)func; | ||
| 255 | add_timer(timer); | ||
| 256 | } | ||
| 257 | |||
| 258 | static __inline void | 235 | static __inline void |
| 259 | ahc_scb_timer_reset(struct scb *scb, u_int usec) | 236 | ahc_scb_timer_reset(struct scb *scb, u_int usec) |
| 260 | { | 237 | { |
| 261 | mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); | ||
| 262 | } | 238 | } |
| 263 | 239 | ||
| 264 | /***************************** SMP support ************************************/ | 240 | /***************************** SMP support ************************************/ |
| @@ -393,7 +369,6 @@ struct ahc_platform_data { | |||
| 393 | 369 | ||
| 394 | spinlock_t spin_lock; | 370 | spinlock_t spin_lock; |
| 395 | u_int qfrozen; | 371 | u_int qfrozen; |
| 396 | struct timer_list reset_timer; | ||
| 397 | struct semaphore eh_sem; | 372 | struct semaphore eh_sem; |
| 398 | struct Scsi_Host *host; /* pointer to scsi host */ | 373 | struct Scsi_Host *host; /* pointer to scsi host */ |
| 399 | #define AHC_LINUX_NOIRQ ((uint32_t)~0) | 374 | #define AHC_LINUX_NOIRQ ((uint32_t)~0) |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index b3b2e2237eb3..5f586140e057 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c | |||
| @@ -39,9 +39,7 @@ | |||
| 39 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 39 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 40 | * POSSIBILITY OF SUCH DAMAGES. | 40 | * POSSIBILITY OF SUCH DAMAGES. |
| 41 | * | 41 | * |
| 42 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $ | 42 | * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $ |
| 43 | * | ||
| 44 | * $FreeBSD$ | ||
| 45 | */ | 43 | */ |
| 46 | 44 | ||
| 47 | #ifdef __linux__ | 45 | #ifdef __linux__ |
| @@ -393,6 +391,12 @@ struct ahc_pci_identity ahc_pci_ident_table [] = | |||
| 393 | "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", | 391 | "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", |
| 394 | ahc_aic7892_setup | 392 | ahc_aic7892_setup |
| 395 | }, | 393 | }, |
| 394 | { | ||
| 395 | ID_AHA_2915_30LP, | ||
| 396 | ID_ALL_MASK, | ||
| 397 | "Adaptec 2915/30LP Ultra160 SCSI adapter", | ||
| 398 | ahc_aic7892_setup | ||
| 399 | }, | ||
| 396 | /* aic7895 based controllers */ | 400 | /* aic7895 based controllers */ |
| 397 | { | 401 | { |
| 398 | ID_AHA_2940U_DUAL, | 402 | ID_AHA_2940U_DUAL, |
| @@ -1193,9 +1197,19 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) | |||
| 1193 | * use for this test. | 1197 | * use for this test. |
| 1194 | */ | 1198 | */ |
| 1195 | hcntrl = ahc_inb(ahc, HCNTRL); | 1199 | hcntrl = ahc_inb(ahc, HCNTRL); |
| 1200 | |||
| 1196 | if (hcntrl == 0xFF) | 1201 | if (hcntrl == 0xFF) |
| 1197 | goto fail; | 1202 | goto fail; |
| 1198 | 1203 | ||
| 1204 | if ((hcntrl & CHIPRST) != 0) { | ||
| 1205 | /* | ||
| 1206 | * The chip has not been initialized since | ||
| 1207 | * PCI/EISA/VLB bus reset. Don't trust | ||
| 1208 | * "left over BIOS data". | ||
| 1209 | */ | ||
| 1210 | ahc->flags |= AHC_NO_BIOS_INIT; | ||
| 1211 | } | ||
| 1212 | |||
| 1199 | /* | 1213 | /* |
| 1200 | * Next create a situation where write combining | 1214 | * Next create a situation where write combining |
| 1201 | * or read prefetching could be initiated by the | 1215 | * or read prefetching could be initiated by the |
| @@ -1307,6 +1321,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) | |||
| 1307 | sd.sd_chip = C56_66; | 1321 | sd.sd_chip = C56_66; |
| 1308 | } | 1322 | } |
| 1309 | ahc_release_seeprom(&sd); | 1323 | ahc_release_seeprom(&sd); |
| 1324 | |||
| 1325 | /* Remember the SEEPROM type for later */ | ||
| 1326 | if (sd.sd_chip == C56_66) | ||
| 1327 | ahc->flags |= AHC_LARGE_SEEPROM; | ||
| 1310 | } | 1328 | } |
| 1311 | 1329 | ||
| 1312 | if (!have_seeprom) { | 1330 | if (!have_seeprom) { |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.h b/drivers/scsi/aic7xxx/aic7xxx_pci.h index be27fcb20346..263f85da405e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.h +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.h | |||
| @@ -105,6 +105,7 @@ | |||
| 105 | #define ID_AHA_29160C 0x0080900562209005ull | 105 | #define ID_AHA_29160C 0x0080900562209005ull |
| 106 | #define ID_AHA_29160B 0x00809005E2209005ull | 106 | #define ID_AHA_29160B 0x00809005E2209005ull |
| 107 | #define ID_AHA_19160B 0x0081900562A19005ull | 107 | #define ID_AHA_19160B 0x0081900562A19005ull |
| 108 | #define ID_AHA_2915_30LP 0x0082900502109005ull | ||
| 108 | 109 | ||
| 109 | #define ID_AIC7896 0x005F9005FFFF9005ull | 110 | #define ID_AIC7896 0x005F9005FFFF9005ull |
| 110 | #define ID_AIC7896_ARO 0x00539005FFFF9005ull | 111 | #define ID_AIC7896_ARO 0x00539005FFFF9005ull |
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 33d56c344944..770f1647e4d6 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c | |||
| @@ -1290,7 +1290,7 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer); | |||
| 1290 | * | 1290 | * |
| 1291 | ***************************************************************************/ | 1291 | ***************************************************************************/ |
| 1292 | 1292 | ||
| 1293 | static inline unsigned char | 1293 | static unsigned char |
| 1294 | aic_inb(struct aic7xxx_host *p, long port) | 1294 | aic_inb(struct aic7xxx_host *p, long port) |
| 1295 | { | 1295 | { |
| 1296 | #ifdef MMAPIO | 1296 | #ifdef MMAPIO |
| @@ -1309,7 +1309,7 @@ aic_inb(struct aic7xxx_host *p, long port) | |||
| 1309 | #endif | 1309 | #endif |
| 1310 | } | 1310 | } |
| 1311 | 1311 | ||
| 1312 | static inline void | 1312 | static void |
| 1313 | aic_outb(struct aic7xxx_host *p, unsigned char val, long port) | 1313 | aic_outb(struct aic7xxx_host *p, unsigned char val, long port) |
| 1314 | { | 1314 | { |
| 1315 | #ifdef MMAPIO | 1315 | #ifdef MMAPIO |
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 4299fabca554..c3f27285db1b 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/completion.h> | 22 | #include <linux/completion.h> |
| 23 | #include <linux/compat.h> | 23 | #include <linux/compat.h> |
| 24 | #include <linux/chio.h> /* here are all the ioctls */ | 24 | #include <linux/chio.h> /* here are all the ioctls */ |
| 25 | #include <linux/mutex.h> | ||
| 25 | 26 | ||
| 26 | #include <scsi/scsi.h> | 27 | #include <scsi/scsi.h> |
| 27 | #include <scsi/scsi_cmnd.h> | 28 | #include <scsi/scsi_cmnd.h> |
| @@ -111,7 +112,7 @@ typedef struct { | |||
| 111 | u_int counts[CH_TYPES]; | 112 | u_int counts[CH_TYPES]; |
| 112 | u_int unit_attention; | 113 | u_int unit_attention; |
| 113 | u_int voltags; | 114 | u_int voltags; |
| 114 | struct semaphore lock; | 115 | struct mutex lock; |
| 115 | } scsi_changer; | 116 | } scsi_changer; |
| 116 | 117 | ||
| 117 | static LIST_HEAD(ch_devlist); | 118 | static LIST_HEAD(ch_devlist); |
| @@ -565,7 +566,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) | |||
| 565 | u_char data[16]; | 566 | u_char data[16]; |
| 566 | unsigned int i; | 567 | unsigned int i; |
| 567 | 568 | ||
| 568 | down(&ch->lock); | 569 | mutex_lock(&ch->lock); |
| 569 | for (i = 0; i < ch->counts[type]; i++) { | 570 | for (i = 0; i < ch->counts[type]; i++) { |
| 570 | if (0 != ch_read_element_status | 571 | if (0 != ch_read_element_status |
| 571 | (ch, ch->firsts[type]+i,data)) { | 572 | (ch, ch->firsts[type]+i,data)) { |
| @@ -582,7 +583,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) | |||
| 582 | if (0 != retval) | 583 | if (0 != retval) |
| 583 | break; | 584 | break; |
| 584 | } | 585 | } |
| 585 | up(&ch->lock); | 586 | mutex_unlock(&ch->lock); |
| 586 | return retval; | 587 | return retval; |
| 587 | } | 588 | } |
| 588 | 589 | ||
| @@ -687,11 +688,11 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 687 | dprintk("CHIOPOSITION: invalid parameter\n"); | 688 | dprintk("CHIOPOSITION: invalid parameter\n"); |
| 688 | return -EBADSLT; | 689 | return -EBADSLT; |
| 689 | } | 690 | } |
| 690 | down(&ch->lock); | 691 | mutex_lock(&ch->lock); |
| 691 | retval = ch_position(ch,0, | 692 | retval = ch_position(ch,0, |
| 692 | ch->firsts[pos.cp_type] + pos.cp_unit, | 693 | ch->firsts[pos.cp_type] + pos.cp_unit, |
| 693 | pos.cp_flags & CP_INVERT); | 694 | pos.cp_flags & CP_INVERT); |
| 694 | up(&ch->lock); | 695 | mutex_unlock(&ch->lock); |
| 695 | return retval; | 696 | return retval; |
| 696 | } | 697 | } |
| 697 | 698 | ||
| @@ -708,12 +709,12 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 708 | return -EBADSLT; | 709 | return -EBADSLT; |
| 709 | } | 710 | } |
| 710 | 711 | ||
| 711 | down(&ch->lock); | 712 | mutex_lock(&ch->lock); |
| 712 | retval = ch_move(ch,0, | 713 | retval = ch_move(ch,0, |
| 713 | ch->firsts[mv.cm_fromtype] + mv.cm_fromunit, | 714 | ch->firsts[mv.cm_fromtype] + mv.cm_fromunit, |
| 714 | ch->firsts[mv.cm_totype] + mv.cm_tounit, | 715 | ch->firsts[mv.cm_totype] + mv.cm_tounit, |
| 715 | mv.cm_flags & CM_INVERT); | 716 | mv.cm_flags & CM_INVERT); |
| 716 | up(&ch->lock); | 717 | mutex_unlock(&ch->lock); |
| 717 | return retval; | 718 | return retval; |
| 718 | } | 719 | } |
| 719 | 720 | ||
| @@ -731,14 +732,14 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 731 | return -EBADSLT; | 732 | return -EBADSLT; |
| 732 | } | 733 | } |
| 733 | 734 | ||
| 734 | down(&ch->lock); | 735 | mutex_lock(&ch->lock); |
| 735 | retval = ch_exchange | 736 | retval = ch_exchange |
| 736 | (ch,0, | 737 | (ch,0, |
| 737 | ch->firsts[mv.ce_srctype] + mv.ce_srcunit, | 738 | ch->firsts[mv.ce_srctype] + mv.ce_srcunit, |
| 738 | ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit, | 739 | ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit, |
| 739 | ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit, | 740 | ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit, |
| 740 | mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2); | 741 | mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2); |
| 741 | up(&ch->lock); | 742 | mutex_unlock(&ch->lock); |
| 742 | return retval; | 743 | return retval; |
| 743 | } | 744 | } |
| 744 | 745 | ||
| @@ -772,7 +773,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 772 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); | 773 | buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); |
| 773 | if (!buffer) | 774 | if (!buffer) |
| 774 | return -ENOMEM; | 775 | return -ENOMEM; |
| 775 | down(&ch->lock); | 776 | mutex_lock(&ch->lock); |
| 776 | 777 | ||
| 777 | voltag_retry: | 778 | voltag_retry: |
| 778 | memset(cmd,0,sizeof(cmd)); | 779 | memset(cmd,0,sizeof(cmd)); |
| @@ -823,7 +824,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 823 | goto voltag_retry; | 824 | goto voltag_retry; |
| 824 | } | 825 | } |
| 825 | kfree(buffer); | 826 | kfree(buffer); |
| 826 | up(&ch->lock); | 827 | mutex_unlock(&ch->lock); |
| 827 | 828 | ||
| 828 | if (copy_to_user(argp, &cge, sizeof (cge))) | 829 | if (copy_to_user(argp, &cge, sizeof (cge))) |
| 829 | return -EFAULT; | 830 | return -EFAULT; |
| @@ -832,9 +833,9 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 832 | 833 | ||
| 833 | case CHIOINITELEM: | 834 | case CHIOINITELEM: |
| 834 | { | 835 | { |
| 835 | down(&ch->lock); | 836 | mutex_lock(&ch->lock); |
| 836 | retval = ch_init_elem(ch); | 837 | retval = ch_init_elem(ch); |
| 837 | up(&ch->lock); | 838 | mutex_unlock(&ch->lock); |
| 838 | return retval; | 839 | return retval; |
| 839 | } | 840 | } |
| 840 | 841 | ||
| @@ -851,12 +852,12 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
| 851 | return -EBADSLT; | 852 | return -EBADSLT; |
| 852 | } | 853 | } |
| 853 | elem = ch->firsts[csv.csv_type] + csv.csv_unit; | 854 | elem = ch->firsts[csv.csv_type] + csv.csv_unit; |
| 854 | down(&ch->lock); | 855 | mutex_lock(&ch->lock); |
| 855 | retval = ch_set_voltag(ch, elem, | 856 | retval = ch_set_voltag(ch, elem, |
| 856 | csv.csv_flags & CSV_AVOLTAG, | 857 | csv.csv_flags & CSV_AVOLTAG, |
| 857 | csv.csv_flags & CSV_CLEARTAG, | 858 | csv.csv_flags & CSV_CLEARTAG, |
| 858 | csv.csv_voltag); | 859 | csv.csv_voltag); |
| 859 | up(&ch->lock); | 860 | mutex_unlock(&ch->lock); |
| 860 | return retval; | 861 | return retval; |
| 861 | } | 862 | } |
| 862 | 863 | ||
| @@ -929,7 +930,7 @@ static int ch_probe(struct device *dev) | |||
| 929 | memset(ch,0,sizeof(*ch)); | 930 | memset(ch,0,sizeof(*ch)); |
| 930 | ch->minor = ch_devcount; | 931 | ch->minor = ch_devcount; |
| 931 | sprintf(ch->name,"ch%d",ch->minor); | 932 | sprintf(ch->name,"ch%d",ch->minor); |
| 932 | init_MUTEX(&ch->lock); | 933 | mutex_init(&ch->lock); |
| 933 | ch->device = sd; | 934 | ch->device = sd; |
| 934 | ch_readconfig(ch); | 935 | ch_readconfig(ch); |
| 935 | if (init) | 936 | if (init) |
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 6252b9ddc01e..6e6b293dcb28 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
| @@ -61,6 +61,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); | |||
| 61 | #include <linux/timer.h> | 61 | #include <linux/timer.h> |
| 62 | #include <linux/string.h> | 62 | #include <linux/string.h> |
| 63 | #include <linux/ioport.h> | 63 | #include <linux/ioport.h> |
| 64 | #include <linux/mutex.h> | ||
| 64 | 65 | ||
| 65 | #include <asm/processor.h> /* for boot_cpu_data */ | 66 | #include <asm/processor.h> /* for boot_cpu_data */ |
| 66 | #include <asm/pgtable.h> | 67 | #include <asm/pgtable.h> |
| @@ -106,7 +107,7 @@ static dpt_sig_S DPTI_sig = { | |||
| 106 | *============================================================================ | 107 | *============================================================================ |
| 107 | */ | 108 | */ |
| 108 | 109 | ||
| 109 | static DECLARE_MUTEX(adpt_configuration_lock); | 110 | static DEFINE_MUTEX(adpt_configuration_lock); |
| 110 | 111 | ||
| 111 | static struct i2o_sys_tbl *sys_tbl = NULL; | 112 | static struct i2o_sys_tbl *sys_tbl = NULL; |
| 112 | static int sys_tbl_ind = 0; | 113 | static int sys_tbl_ind = 0; |
| @@ -537,13 +538,13 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of | |||
| 537 | */ | 538 | */ |
| 538 | 539 | ||
| 539 | // Find HBA (host bus adapter) we are looking for | 540 | // Find HBA (host bus adapter) we are looking for |
| 540 | down(&adpt_configuration_lock); | 541 | mutex_lock(&adpt_configuration_lock); |
| 541 | for (pHba = hba_chain; pHba; pHba = pHba->next) { | 542 | for (pHba = hba_chain; pHba; pHba = pHba->next) { |
| 542 | if (pHba->host == host) { | 543 | if (pHba->host == host) { |
| 543 | break; /* found adapter */ | 544 | break; /* found adapter */ |
| 544 | } | 545 | } |
| 545 | } | 546 | } |
| 546 | up(&adpt_configuration_lock); | 547 | mutex_unlock(&adpt_configuration_lock); |
| 547 | if (pHba == NULL) { | 548 | if (pHba == NULL) { |
| 548 | return 0; | 549 | return 0; |
| 549 | } | 550 | } |
| @@ -898,6 +899,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 898 | if(pci_enable_device(pDev)) { | 899 | if(pci_enable_device(pDev)) { |
| 899 | return -EINVAL; | 900 | return -EINVAL; |
| 900 | } | 901 | } |
| 902 | |||
| 903 | if (pci_request_regions(pDev, "dpt_i2o")) { | ||
| 904 | PERROR("dpti: adpt_config_hba: pci request region failed\n"); | ||
| 905 | return -EINVAL; | ||
| 906 | } | ||
| 907 | |||
| 901 | pci_set_master(pDev); | 908 | pci_set_master(pDev); |
| 902 | if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && | 909 | if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && |
| 903 | pci_set_dma_mask(pDev, 0xffffffffULL)) | 910 | pci_set_dma_mask(pDev, 0xffffffffULL)) |
| @@ -923,10 +930,6 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 923 | raptorFlag = TRUE; | 930 | raptorFlag = TRUE; |
| 924 | } | 931 | } |
| 925 | 932 | ||
| 926 | if (pci_request_regions(pDev, "dpt_i2o")) { | ||
| 927 | PERROR("dpti: adpt_config_hba: pci request region failed\n"); | ||
| 928 | return -EINVAL; | ||
| 929 | } | ||
| 930 | base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); | 933 | base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); |
| 931 | if (!base_addr_virt) { | 934 | if (!base_addr_virt) { |
| 932 | pci_release_regions(pDev); | 935 | pci_release_regions(pDev); |
| @@ -958,7 +961,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 958 | } | 961 | } |
| 959 | memset(pHba, 0, sizeof(adpt_hba)); | 962 | memset(pHba, 0, sizeof(adpt_hba)); |
| 960 | 963 | ||
| 961 | down(&adpt_configuration_lock); | 964 | mutex_lock(&adpt_configuration_lock); |
| 962 | 965 | ||
| 963 | if(hba_chain != NULL){ | 966 | if(hba_chain != NULL){ |
| 964 | for(p = hba_chain; p->next; p = p->next); | 967 | for(p = hba_chain; p->next; p = p->next); |
| @@ -971,7 +974,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 971 | sprintf(pHba->name, "dpti%d", hba_count); | 974 | sprintf(pHba->name, "dpti%d", hba_count); |
| 972 | hba_count++; | 975 | hba_count++; |
| 973 | 976 | ||
| 974 | up(&adpt_configuration_lock); | 977 | mutex_unlock(&adpt_configuration_lock); |
| 975 | 978 | ||
| 976 | pHba->pDev = pDev; | 979 | pHba->pDev = pDev; |
| 977 | pHba->base_addr_phys = base_addr0_phys; | 980 | pHba->base_addr_phys = base_addr0_phys; |
| @@ -1027,7 +1030,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) | |||
| 1027 | struct adpt_device* pNext; | 1030 | struct adpt_device* pNext; |
| 1028 | 1031 | ||
| 1029 | 1032 | ||
| 1030 | down(&adpt_configuration_lock); | 1033 | mutex_lock(&adpt_configuration_lock); |
| 1031 | // scsi_unregister calls our adpt_release which | 1034 | // scsi_unregister calls our adpt_release which |
| 1032 | // does a quiese | 1035 | // does a quiese |
| 1033 | if(pHba->host){ | 1036 | if(pHba->host){ |
| @@ -1046,7 +1049,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) | |||
| 1046 | } | 1049 | } |
| 1047 | 1050 | ||
| 1048 | hba_count--; | 1051 | hba_count--; |
| 1049 | up(&adpt_configuration_lock); | 1052 | mutex_unlock(&adpt_configuration_lock); |
| 1050 | 1053 | ||
| 1051 | iounmap(pHba->base_addr_virt); | 1054 | iounmap(pHba->base_addr_virt); |
| 1052 | pci_release_regions(pHba->pDev); | 1055 | pci_release_regions(pHba->pDev); |
| @@ -1549,7 +1552,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) | |||
| 1549 | 1552 | ||
| 1550 | static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) | 1553 | static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) |
| 1551 | { | 1554 | { |
| 1552 | down(&adpt_configuration_lock); | 1555 | mutex_lock(&adpt_configuration_lock); |
| 1553 | d->controller=pHba; | 1556 | d->controller=pHba; |
| 1554 | d->owner=NULL; | 1557 | d->owner=NULL; |
| 1555 | d->next=pHba->devices; | 1558 | d->next=pHba->devices; |
| @@ -1560,7 +1563,7 @@ static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) | |||
| 1560 | pHba->devices=d; | 1563 | pHba->devices=d; |
| 1561 | *d->dev_name = 0; | 1564 | *d->dev_name = 0; |
| 1562 | 1565 | ||
| 1563 | up(&adpt_configuration_lock); | 1566 | mutex_unlock(&adpt_configuration_lock); |
| 1564 | return 0; | 1567 | return 0; |
| 1565 | } | 1568 | } |
| 1566 | 1569 | ||
| @@ -1575,24 +1578,24 @@ static int adpt_open(struct inode *inode, struct file *file) | |||
| 1575 | if (minor >= hba_count) { | 1578 | if (minor >= hba_count) { |
| 1576 | return -ENXIO; | 1579 | return -ENXIO; |
| 1577 | } | 1580 | } |
| 1578 | down(&adpt_configuration_lock); | 1581 | mutex_lock(&adpt_configuration_lock); |
| 1579 | for (pHba = hba_chain; pHba; pHba = pHba->next) { | 1582 | for (pHba = hba_chain; pHba; pHba = pHba->next) { |
| 1580 | if (pHba->unit == minor) { | 1583 | if (pHba->unit == minor) { |
| 1581 | break; /* found adapter */ | 1584 | break; /* found adapter */ |
| 1582 | } | 1585 | } |
| 1583 | } | 1586 | } |
| 1584 | if (pHba == NULL) { | 1587 | if (pHba == NULL) { |
| 1585 | up(&adpt_configuration_lock); | 1588 | mutex_unlock(&adpt_configuration_lock); |
| 1586 | return -ENXIO; | 1589 | return -ENXIO; |
| 1587 | } | 1590 | } |
| 1588 | 1591 | ||
| 1589 | // if(pHba->in_use){ | 1592 | // if(pHba->in_use){ |
| 1590 | // up(&adpt_configuration_lock); | 1593 | // mutex_unlock(&adpt_configuration_lock); |
| 1591 | // return -EBUSY; | 1594 | // return -EBUSY; |
| 1592 | // } | 1595 | // } |
| 1593 | 1596 | ||
| 1594 | pHba->in_use = 1; | 1597 | pHba->in_use = 1; |
| 1595 | up(&adpt_configuration_lock); | 1598 | mutex_unlock(&adpt_configuration_lock); |
| 1596 | 1599 | ||
| 1597 | return 0; | 1600 | return 0; |
| 1598 | } | 1601 | } |
| @@ -1606,13 +1609,13 @@ static int adpt_close(struct inode *inode, struct file *file) | |||
| 1606 | if (minor >= hba_count) { | 1609 | if (minor >= hba_count) { |
| 1607 | return -ENXIO; | 1610 | return -ENXIO; |
| 1608 | } | 1611 | } |
| 1609 | down(&adpt_configuration_lock); | 1612 | mutex_lock(&adpt_configuration_lock); |
| 1610 | for (pHba = hba_chain; pHba; pHba = pHba->next) { | 1613 | for (pHba = hba_chain; pHba; pHba = pHba->next) { |
| 1611 | if (pHba->unit == minor) { | 1614 | if (pHba->unit == minor) { |
| 1612 | break; /* found adapter */ | 1615 | break; /* found adapter */ |
| 1613 | } | 1616 | } |
| 1614 | } | 1617 | } |
| 1615 | up(&adpt_configuration_lock); | 1618 | mutex_unlock(&adpt_configuration_lock); |
| 1616 | if (pHba == NULL) { | 1619 | if (pHba == NULL) { |
| 1617 | return -ENXIO; | 1620 | return -ENXIO; |
| 1618 | } | 1621 | } |
| @@ -1910,13 +1913,13 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, | |||
| 1910 | if (minor >= DPTI_MAX_HBA){ | 1913 | if (minor >= DPTI_MAX_HBA){ |
| 1911 | return -ENXIO; | 1914 | return -ENXIO; |
| 1912 | } | 1915 | } |
| 1913 | down(&adpt_configuration_lock); | 1916 | mutex_lock(&adpt_configuration_lock); |
| 1914 | for (pHba = hba_chain; pHba; pHba = pHba->next) { | 1917 | for (pHba = hba_chain; pHba; pHba = pHba->next) { |
| 1915 | if (pHba->unit == minor) { | 1918 | if (pHba->unit == minor) { |
| 1916 | break; /* found adapter */ | 1919 | break; /* found adapter */ |
| 1917 | } | 1920 | } |
| 1918 | } | 1921 | } |
| 1919 | up(&adpt_configuration_lock); | 1922 | mutex_unlock(&adpt_configuration_lock); |
| 1920 | if(pHba == NULL){ | 1923 | if(pHba == NULL){ |
| 1921 | return -ENXIO; | 1924 | return -ENXIO; |
| 1922 | } | 1925 | } |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 66783c860a19..588107923499 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
| @@ -156,16 +156,16 @@ EXPORT_SYMBOL(scsi_host_set_state); | |||
| 156 | void scsi_remove_host(struct Scsi_Host *shost) | 156 | void scsi_remove_host(struct Scsi_Host *shost) |
| 157 | { | 157 | { |
| 158 | unsigned long flags; | 158 | unsigned long flags; |
| 159 | down(&shost->scan_mutex); | 159 | mutex_lock(&shost->scan_mutex); |
| 160 | spin_lock_irqsave(shost->host_lock, flags); | 160 | spin_lock_irqsave(shost->host_lock, flags); |
| 161 | if (scsi_host_set_state(shost, SHOST_CANCEL)) | 161 | if (scsi_host_set_state(shost, SHOST_CANCEL)) |
| 162 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { | 162 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { |
| 163 | spin_unlock_irqrestore(shost->host_lock, flags); | 163 | spin_unlock_irqrestore(shost->host_lock, flags); |
| 164 | up(&shost->scan_mutex); | 164 | mutex_unlock(&shost->scan_mutex); |
| 165 | return; | 165 | return; |
| 166 | } | 166 | } |
| 167 | spin_unlock_irqrestore(shost->host_lock, flags); | 167 | spin_unlock_irqrestore(shost->host_lock, flags); |
| 168 | up(&shost->scan_mutex); | 168 | mutex_unlock(&shost->scan_mutex); |
| 169 | scsi_forget_host(shost); | 169 | scsi_forget_host(shost); |
| 170 | scsi_proc_host_rm(shost); | 170 | scsi_proc_host_rm(shost); |
| 171 | 171 | ||
| @@ -320,7 +320,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
| 320 | INIT_LIST_HEAD(&shost->starved_list); | 320 | INIT_LIST_HEAD(&shost->starved_list); |
| 321 | init_waitqueue_head(&shost->host_wait); | 321 | init_waitqueue_head(&shost->host_wait); |
| 322 | 322 | ||
| 323 | init_MUTEX(&shost->scan_mutex); | 323 | mutex_init(&shost->scan_mutex); |
| 324 | 324 | ||
| 325 | shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ | 325 | shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ |
| 326 | shost->dma_channel = 0xff; | 326 | shost->dma_channel = 0xff; |
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 3882d48a42bf..e5e1ca44e1ee 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c | |||
| @@ -1319,6 +1319,9 @@ ips_slave_configure(struct scsi_device * SDptr) | |||
| 1319 | min = ha->max_cmds - 1; | 1319 | min = ha->max_cmds - 1; |
| 1320 | scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min); | 1320 | scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min); |
| 1321 | } | 1321 | } |
| 1322 | |||
| 1323 | SDptr->skip_ms_page_8 = 1; | ||
| 1324 | SDptr->skip_ms_page_3f = 1; | ||
| 1322 | return 0; | 1325 | return 0; |
| 1323 | } | 1326 | } |
| 1324 | #endif | 1327 | #endif |
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 10bcf42cb65c..780bfcc67096 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
| 34 | #include <linux/kfifo.h> | 34 | #include <linux/kfifo.h> |
| 35 | #include <linux/scatterlist.h> | 35 | #include <linux/scatterlist.h> |
| 36 | #include <linux/mutex.h> | ||
| 36 | #include <net/tcp.h> | 37 | #include <net/tcp.h> |
| 37 | #include <scsi/scsi_cmnd.h> | 38 | #include <scsi/scsi_cmnd.h> |
| 38 | #include <scsi/scsi_device.h> | 39 | #include <scsi/scsi_device.h> |
| @@ -86,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) | |||
| 86 | { | 87 | { |
| 87 | sg_init_one(&ibuf->sg, (u8 *)vbuf, size); | 88 | sg_init_one(&ibuf->sg, (u8 *)vbuf, size); |
| 88 | ibuf->sent = 0; | 89 | ibuf->sent = 0; |
| 90 | ibuf->use_sendmsg = 0; | ||
| 89 | } | 91 | } |
| 90 | 92 | ||
| 91 | static inline void | 93 | static inline void |
| 92 | iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) | 94 | iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) |
| 93 | { | 95 | { |
| 94 | ibuf->sg.page = (void*)vbuf; | 96 | ibuf->sg.page = virt_to_page(vbuf); |
| 95 | ibuf->sg.offset = (unsigned int)-1; | 97 | ibuf->sg.offset = offset_in_page(vbuf); |
| 96 | ibuf->sg.length = size; | 98 | ibuf->sg.length = size; |
| 97 | ibuf->sent = 0; | 99 | ibuf->sent = 0; |
| 98 | } | 100 | ibuf->use_sendmsg = 1; |
| 99 | |||
| 100 | static inline void* | ||
| 101 | iscsi_buf_iov_base(struct iscsi_buf *ibuf) | ||
| 102 | { | ||
| 103 | return (char*)ibuf->sg.page + ibuf->sent; | ||
| 104 | } | 101 | } |
| 105 | 102 | ||
| 106 | static inline void | 103 | static inline void |
| 107 | iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) | 104 | iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) |
| 108 | { | 105 | { |
| 106 | ibuf->sg.page = sg->page; | ||
| 107 | ibuf->sg.offset = sg->offset; | ||
| 108 | ibuf->sg.length = sg->length; | ||
| 109 | /* | 109 | /* |
| 110 | * Fastpath: sg element fits into single page | 110 | * Fastpath: sg element fits into single page |
| 111 | */ | 111 | */ |
| 112 | if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) { | 112 | if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page)) |
| 113 | ibuf->sg.page = sg->page; | 113 | ibuf->use_sendmsg = 0; |
| 114 | ibuf->sg.offset = sg->offset; | 114 | else |
| 115 | ibuf->sg.length = sg->length; | 115 | ibuf->use_sendmsg = 1; |
| 116 | } else | ||
| 117 | iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length); | ||
| 118 | ibuf->sent = 0; | 116 | ibuf->sent = 0; |
| 119 | } | 117 | } |
| 120 | 118 | ||
| @@ -356,7 +354,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 356 | struct scsi_cmnd *sc = ctask->sc; | 354 | struct scsi_cmnd *sc = ctask->sc; |
| 357 | 355 | ||
| 358 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; | 356 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; |
| 359 | if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { | 357 | if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) { |
| 360 | int res_count = be32_to_cpu(rhdr->residual_count); | 358 | int res_count = be32_to_cpu(rhdr->residual_count); |
| 361 | 359 | ||
| 362 | if (res_count > 0 && | 360 | if (res_count > 0 && |
| @@ -366,9 +364,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 366 | } else | 364 | } else |
| 367 | sc->result = (DID_BAD_TARGET << 16) | | 365 | sc->result = (DID_BAD_TARGET << 16) | |
| 368 | rhdr->cmd_status; | 366 | rhdr->cmd_status; |
| 369 | } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) | 367 | } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) { |
| 370 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | ||
| 371 | else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) { | ||
| 372 | sc->resid = be32_to_cpu(rhdr->residual_count); | 368 | sc->resid = be32_to_cpu(rhdr->residual_count); |
| 373 | sc->result = (DID_OK << 16) | rhdr->cmd_status; | 369 | sc->result = (DID_OK << 16) | rhdr->cmd_status; |
| 374 | } else | 370 | } else |
| @@ -529,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 529 | __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); | 525 | __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); |
| 530 | __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); | 526 | __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); |
| 531 | 527 | ||
| 532 | schedule_work(&conn->xmitwork); | 528 | scsi_queue_work(session->host, &conn->xmitwork); |
| 533 | conn->r2t_pdus_cnt++; | 529 | conn->r2t_pdus_cnt++; |
| 534 | spin_unlock(&session->lock); | 530 | spin_unlock(&session->lock); |
| 535 | 531 | ||
| @@ -686,7 +682,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
| 686 | switch(conn->in.opcode) { | 682 | switch(conn->in.opcode) { |
| 687 | case ISCSI_OP_LOGIN_RSP: | 683 | case ISCSI_OP_LOGIN_RSP: |
| 688 | case ISCSI_OP_TEXT_RSP: | 684 | case ISCSI_OP_TEXT_RSP: |
| 689 | case ISCSI_OP_LOGOUT_RSP: | 685 | case ISCSI_OP_LOGOUT_RSP: |
| 690 | rc = iscsi_check_assign_cmdsn(session, | 686 | rc = iscsi_check_assign_cmdsn(session, |
| 691 | (struct iscsi_nopin*)hdr); | 687 | (struct iscsi_nopin*)hdr); |
| 692 | if (rc) | 688 | if (rc) |
| @@ -727,12 +723,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
| 727 | } | 723 | } |
| 728 | spin_unlock(&session->lock); | 724 | spin_unlock(&session->lock); |
| 729 | break; | 725 | break; |
| 730 | case ISCSI_OP_NOOP_IN: | 726 | case ISCSI_OP_NOOP_IN: |
| 731 | if (hdr->ttt != ISCSI_RESERVED_TAG) { | 727 | if (hdr->ttt != ISCSI_RESERVED_TAG) { |
| 732 | rc = ISCSI_ERR_PROTO; | 728 | rc = ISCSI_ERR_PROTO; |
| 733 | break; | 729 | break; |
| 734 | } | 730 | } |
| 735 | rc = iscsi_check_assign_cmdsn(session, | 731 | rc = iscsi_check_assign_cmdsn(session, |
| 736 | (struct iscsi_nopin*)hdr); | 732 | (struct iscsi_nopin*)hdr); |
| 737 | if (rc) | 733 | if (rc) |
| 738 | break; | 734 | break; |
| @@ -767,7 +763,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
| 767 | if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) | 763 | if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) |
| 768 | rc = iscsi_recv_pdu(iscsi_handle(conn), | 764 | rc = iscsi_recv_pdu(iscsi_handle(conn), |
| 769 | hdr, NULL, 0); | 765 | hdr, NULL, 0); |
| 770 | } else | 766 | } else |
| 771 | rc = ISCSI_ERR_PROTO; | 767 | rc = ISCSI_ERR_PROTO; |
| 772 | break; | 768 | break; |
| 773 | case ISCSI_OP_REJECT: | 769 | case ISCSI_OP_REJECT: |
| @@ -929,7 +925,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) | |||
| 929 | sc->request_bufflen, ctask->data_offset); | 925 | sc->request_bufflen, ctask->data_offset); |
| 930 | if (rc == -EAGAIN) | 926 | if (rc == -EAGAIN) |
| 931 | return rc; | 927 | return rc; |
| 932 | if (conn->datadgst_en) | 928 | if (conn->datadgst_en) |
| 933 | iscsi_recv_digest_update(conn, sc->request_buffer, i); | 929 | iscsi_recv_digest_update(conn, sc->request_buffer, i); |
| 934 | rc = 0; | 930 | rc = 0; |
| 935 | goto done; | 931 | goto done; |
| @@ -1024,7 +1020,7 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
| 1024 | conn->in.hdr = &conn->hdr; | 1020 | conn->in.hdr = &conn->hdr; |
| 1025 | conn->senselen = (conn->data[0] << 8) | conn->data[1]; | 1021 | conn->senselen = (conn->data[0] << 8) | conn->data[1]; |
| 1026 | rc = iscsi_cmd_rsp(conn, conn->in.ctask); | 1022 | rc = iscsi_cmd_rsp(conn, conn->in.ctask); |
| 1027 | if (!rc && conn->datadgst_en) | 1023 | if (!rc && conn->datadgst_en) |
| 1028 | iscsi_recv_digest_update(conn, conn->data, | 1024 | iscsi_recv_digest_update(conn, conn->data, |
| 1029 | conn->in.datalen); | 1025 | conn->in.datalen); |
| 1030 | } | 1026 | } |
| @@ -1051,7 +1047,7 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
| 1051 | rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, | 1047 | rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, |
| 1052 | conn->data, conn->in.datalen); | 1048 | conn->data, conn->in.datalen); |
| 1053 | 1049 | ||
| 1054 | if (!rc && conn->datadgst_en && | 1050 | if (!rc && conn->datadgst_en && |
| 1055 | conn->in.opcode != ISCSI_OP_LOGIN_RSP) | 1051 | conn->in.opcode != ISCSI_OP_LOGIN_RSP) |
| 1056 | iscsi_recv_digest_update(conn, conn->data, | 1052 | iscsi_recv_digest_update(conn, conn->data, |
| 1057 | conn->in.datalen); | 1053 | conn->in.datalen); |
| @@ -1271,7 +1267,7 @@ iscsi_write_space(struct sock *sk) | |||
| 1271 | conn->old_write_space(sk); | 1267 | conn->old_write_space(sk); |
| 1272 | debug_tcp("iscsi_write_space: cid %d\n", conn->id); | 1268 | debug_tcp("iscsi_write_space: cid %d\n", conn->id); |
| 1273 | clear_bit(SUSPEND_BIT, &conn->suspend_tx); | 1269 | clear_bit(SUSPEND_BIT, &conn->suspend_tx); |
| 1274 | schedule_work(&conn->xmitwork); | 1270 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
| 1275 | } | 1271 | } |
| 1276 | 1272 | ||
| 1277 | static void | 1273 | static void |
| @@ -1312,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) | |||
| 1312 | * @buf: buffer to write from | 1308 | * @buf: buffer to write from |
| 1313 | * @size: actual size to write | 1309 | * @size: actual size to write |
| 1314 | * @flags: socket's flags | 1310 | * @flags: socket's flags |
| 1315 | * | ||
| 1316 | * Notes: | ||
| 1317 | * depending on buffer will use tcp_sendpage() or tcp_sendmsg(). | ||
| 1318 | * buf->sg.offset == -1 tells us that buffer is non S/G and forces | ||
| 1319 | * to use tcp_sendmsg(). | ||
| 1320 | */ | 1311 | */ |
| 1321 | static inline int | 1312 | static inline int |
| 1322 | iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) | 1313 | iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) |
| 1323 | { | 1314 | { |
| 1324 | int res; | 1315 | struct socket *sk = conn->sock; |
| 1325 | 1316 | int offset = buf->sg.offset + buf->sent; | |
| 1326 | if ((int)buf->sg.offset >= 0) { | ||
| 1327 | int offset = buf->sg.offset + buf->sent; | ||
| 1328 | |||
| 1329 | /* tcp_sendpage */ | ||
| 1330 | res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags); | ||
| 1331 | } else { | ||
| 1332 | struct msghdr msg; | ||
| 1333 | |||
| 1334 | buf->iov.iov_base = iscsi_buf_iov_base(buf); | ||
| 1335 | buf->iov.iov_len = size; | ||
| 1336 | |||
| 1337 | memset(&msg, 0, sizeof(struct msghdr)); | ||
| 1338 | |||
| 1339 | /* tcp_sendmsg */ | ||
| 1340 | res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size); | ||
| 1341 | } | ||
| 1342 | 1317 | ||
| 1343 | return res; | 1318 | /* |
| 1319 | * if we got use_sg=0 or are sending something we kmallocd | ||
| 1320 | * then we did not have to do kmap (kmap returns page_address) | ||
| 1321 | * | ||
| 1322 | * if we got use_sg > 0, but had to drop down, we do not | ||
| 1323 | * set clustering so this should only happen for that | ||
| 1324 | * slab case. | ||
| 1325 | */ | ||
| 1326 | if (buf->use_sendmsg) | ||
| 1327 | return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); | ||
| 1328 | else | ||
| 1329 | return conn->sendpage(sk, buf->sg.page, offset, size, flags); | ||
| 1344 | } | 1330 | } |
| 1345 | 1331 | ||
| 1346 | /** | 1332 | /** |
| @@ -1355,7 +1341,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) | |||
| 1355 | static inline int | 1341 | static inline int |
| 1356 | iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) | 1342 | iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) |
| 1357 | { | 1343 | { |
| 1358 | struct socket *sk = conn->sock; | ||
| 1359 | int flags = 0; /* MSG_DONTWAIT; */ | 1344 | int flags = 0; /* MSG_DONTWAIT; */ |
| 1360 | int res, size; | 1345 | int res, size; |
| 1361 | 1346 | ||
| @@ -1364,7 +1349,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) | |||
| 1364 | if (buf->sent + size != buf->sg.length || datalen) | 1349 | if (buf->sent + size != buf->sg.length || datalen) |
| 1365 | flags |= MSG_MORE; | 1350 | flags |= MSG_MORE; |
| 1366 | 1351 | ||
| 1367 | res = iscsi_send(sk, buf, size, flags); | 1352 | res = iscsi_send(conn, buf, size, flags); |
| 1368 | debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); | 1353 | debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); |
| 1369 | if (res >= 0) { | 1354 | if (res >= 0) { |
| 1370 | conn->txdata_octets += res; | 1355 | conn->txdata_octets += res; |
| @@ -1395,7 +1380,6 @@ static inline int | |||
| 1395 | iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | 1380 | iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, |
| 1396 | int *count, int *sent) | 1381 | int *count, int *sent) |
| 1397 | { | 1382 | { |
| 1398 | struct socket *sk = conn->sock; | ||
| 1399 | int flags = 0; /* MSG_DONTWAIT; */ | 1383 | int flags = 0; /* MSG_DONTWAIT; */ |
| 1400 | int res, size; | 1384 | int res, size; |
| 1401 | 1385 | ||
| @@ -1406,7 +1390,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | |||
| 1406 | if (buf->sent + size != buf->sg.length || *count != size) | 1390 | if (buf->sent + size != buf->sg.length || *count != size) |
| 1407 | flags |= MSG_MORE; | 1391 | flags |= MSG_MORE; |
| 1408 | 1392 | ||
| 1409 | res = iscsi_send(sk, buf, size, flags); | 1393 | res = iscsi_send(conn, buf, size, flags); |
| 1410 | debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", | 1394 | debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", |
| 1411 | size, buf->sent, *count, *sent, res); | 1395 | size, buf->sent, *count, *sent, res); |
| 1412 | if (res >= 0) { | 1396 | if (res >= 0) { |
| @@ -1434,20 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 1434 | ctask->digest_count = 4; | 1418 | ctask->digest_count = 4; |
| 1435 | } | 1419 | } |
| 1436 | 1420 | ||
| 1437 | static inline void | 1421 | static int |
| 1438 | iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf) | ||
| 1439 | { | ||
| 1440 | struct scatterlist sg; | ||
| 1441 | |||
| 1442 | if (buf->sg.offset != -1) | ||
| 1443 | crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1); | ||
| 1444 | else { | ||
| 1445 | sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length); | ||
| 1446 | crypto_digest_update(conn->data_tx_tfm, &sg, 1); | ||
| 1447 | } | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | static inline int | ||
| 1451 | iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 1422 | iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, |
| 1452 | struct iscsi_buf *buf, uint32_t *digest, int final) | 1423 | struct iscsi_buf *buf, uint32_t *digest, int final) |
| 1453 | { | 1424 | { |
| @@ -1680,7 +1651,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
| 1680 | zero_data(ctask->hdr.dlength); | 1651 | zero_data(ctask->hdr.dlength); |
| 1681 | } | 1652 | } |
| 1682 | 1653 | ||
| 1683 | iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, | 1654 | iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, |
| 1684 | sizeof(struct iscsi_hdr)); | 1655 | sizeof(struct iscsi_hdr)); |
| 1685 | conn->scsicmd_pdus_cnt++; | 1656 | conn->scsicmd_pdus_cnt++; |
| 1686 | } | 1657 | } |
| @@ -1746,7 +1717,7 @@ static inline int | |||
| 1746 | handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1717 | handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
| 1747 | { | 1718 | { |
| 1748 | ctask->xmstate &= ~XMSTATE_R_HDR; | 1719 | ctask->xmstate &= ~XMSTATE_R_HDR; |
| 1749 | if (conn->hdrdgst_en) | 1720 | if (conn->hdrdgst_en) |
| 1750 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); | 1721 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); |
| 1751 | if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { | 1722 | if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { |
| 1752 | BUG_ON(ctask->xmstate != XMSTATE_IDLE); | 1723 | BUG_ON(ctask->xmstate != XMSTATE_IDLE); |
| @@ -1760,7 +1731,7 @@ static inline int | |||
| 1760 | handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1731 | handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
| 1761 | { | 1732 | { |
| 1762 | ctask->xmstate &= ~XMSTATE_W_HDR; | 1733 | ctask->xmstate &= ~XMSTATE_W_HDR; |
| 1763 | if (conn->hdrdgst_en) | 1734 | if (conn->hdrdgst_en) |
| 1764 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); | 1735 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); |
| 1765 | if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { | 1736 | if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { |
| 1766 | ctask->xmstate |= XMSTATE_W_HDR; | 1737 | ctask->xmstate |= XMSTATE_W_HDR; |
| @@ -1809,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 1809 | return -EAGAIN; | 1780 | return -EAGAIN; |
| 1810 | } | 1781 | } |
| 1811 | if (conn->datadgst_en) | 1782 | if (conn->datadgst_en) |
| 1812 | iscsi_buf_data_digest_update(conn, &ctask->sendbuf); | 1783 | crypto_digest_update(conn->data_tx_tfm, |
| 1784 | &ctask->sendbuf.sg, 1); | ||
| 1813 | 1785 | ||
| 1814 | if (!ctask->imm_count) | 1786 | if (!ctask->imm_count) |
| 1815 | break; | 1787 | break; |
| @@ -1894,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 1894 | * so pass it | 1866 | * so pass it |
| 1895 | */ | 1867 | */ |
| 1896 | if (conn->datadgst_en && ctask->sent - start > 0) | 1868 | if (conn->datadgst_en && ctask->sent - start > 0) |
| 1897 | iscsi_buf_data_digest_update(conn, &ctask->sendbuf); | 1869 | crypto_digest_update(conn->data_tx_tfm, |
| 1870 | &ctask->sendbuf.sg, 1); | ||
| 1898 | 1871 | ||
| 1899 | if (!ctask->data_count) | 1872 | if (!ctask->data_count) |
| 1900 | break; | 1873 | break; |
| @@ -1972,7 +1945,7 @@ solicit_again: | |||
| 1972 | 1945 | ||
| 1973 | BUG_ON(r2t->data_count < 0); | 1946 | BUG_ON(r2t->data_count < 0); |
| 1974 | if (conn->datadgst_en) | 1947 | if (conn->datadgst_en) |
| 1975 | iscsi_buf_data_digest_update(conn, &r2t->sendbuf); | 1948 | crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); |
| 1976 | 1949 | ||
| 1977 | if (r2t->data_count) { | 1950 | if (r2t->data_count) { |
| 1978 | BUG_ON(ctask->sc->use_sg == 0); | 1951 | BUG_ON(ctask->sc->use_sg == 0); |
| @@ -2054,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 2054 | } | 2027 | } |
| 2055 | 2028 | ||
| 2056 | if (conn->datadgst_en) { | 2029 | if (conn->datadgst_en) { |
| 2057 | iscsi_buf_data_digest_update(conn, &ctask->sendbuf); | 2030 | crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); |
| 2058 | /* imm data? */ | 2031 | /* imm data? */ |
| 2059 | if (!dtask) { | 2032 | if (!dtask) { |
| 2060 | if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, | 2033 | if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, |
| @@ -2148,7 +2121,7 @@ unsolicit_head_again: | |||
| 2148 | solicit_head_again: | 2121 | solicit_head_again: |
| 2149 | r2t = ctask->r2t; | 2122 | r2t = ctask->r2t; |
| 2150 | if (conn->hdrdgst_en) | 2123 | if (conn->hdrdgst_en) |
| 2151 | iscsi_hdr_digest(conn, &r2t->headbuf, | 2124 | iscsi_hdr_digest(conn, &r2t->headbuf, |
| 2152 | (u8*)r2t->dtask->hdrext); | 2125 | (u8*)r2t->dtask->hdrext); |
| 2153 | if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { | 2126 | if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { |
| 2154 | ctask->xmstate &= ~XMSTATE_SOL_DATA; | 2127 | ctask->xmstate &= ~XMSTATE_SOL_DATA; |
| @@ -2300,10 +2273,10 @@ iscsi_xmitworker(void *data) | |||
| 2300 | /* | 2273 | /* |
| 2301 | * serialize Xmit worker on a per-connection basis. | 2274 | * serialize Xmit worker on a per-connection basis. |
| 2302 | */ | 2275 | */ |
| 2303 | down(&conn->xmitsema); | 2276 | mutex_lock(&conn->xmitmutex); |
| 2304 | if (iscsi_data_xmit(conn)) | 2277 | if (iscsi_data_xmit(conn)) |
| 2305 | schedule_work(&conn->xmitwork); | 2278 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
| 2306 | up(&conn->xmitsema); | 2279 | mutex_unlock(&conn->xmitmutex); |
| 2307 | } | 2280 | } |
| 2308 | 2281 | ||
| 2309 | #define FAILURE_BAD_HOST 1 | 2282 | #define FAILURE_BAD_HOST 1 |
| @@ -2367,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 2367 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); | 2340 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); |
| 2368 | spin_unlock(&session->lock); | 2341 | spin_unlock(&session->lock); |
| 2369 | 2342 | ||
| 2370 | if (!in_interrupt() && !down_trylock(&conn->xmitsema)) { | 2343 | scsi_queue_work(host, &conn->xmitwork); |
| 2371 | spin_unlock_irq(host->host_lock); | ||
| 2372 | if (iscsi_data_xmit(conn)) | ||
| 2373 | schedule_work(&conn->xmitwork); | ||
| 2374 | up(&conn->xmitsema); | ||
| 2375 | spin_lock_irq(host->host_lock); | ||
| 2376 | } else | ||
| 2377 | schedule_work(&conn->xmitwork); | ||
| 2378 | |||
| 2379 | return 0; | 2344 | return 0; |
| 2380 | 2345 | ||
| 2381 | reject: | 2346 | reject: |
| @@ -2462,17 +2427,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items) | |||
| 2462 | kfree(items); | 2427 | kfree(items); |
| 2463 | } | 2428 | } |
| 2464 | 2429 | ||
| 2465 | static iscsi_connh_t | 2430 | static struct iscsi_cls_conn * |
| 2466 | iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) | 2431 | iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx) |
| 2467 | { | 2432 | { |
| 2468 | struct iscsi_session *session = iscsi_ptr(sessionh); | 2433 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); |
| 2469 | struct iscsi_conn *conn = NULL; | 2434 | struct iscsi_conn *conn; |
| 2435 | struct iscsi_cls_conn *cls_conn; | ||
| 2470 | 2436 | ||
| 2471 | conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL); | 2437 | cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata), |
| 2472 | if (conn == NULL) | 2438 | conn_idx); |
| 2473 | goto conn_alloc_fail; | 2439 | if (!cls_conn) |
| 2474 | memset(conn, 0, sizeof(struct iscsi_conn)); | 2440 | return NULL; |
| 2441 | conn = cls_conn->dd_data; | ||
| 2475 | 2442 | ||
| 2443 | memset(conn, 0, sizeof(struct iscsi_conn)); | ||
| 2476 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; | 2444 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; |
| 2477 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; | 2445 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
| 2478 | conn->id = conn_idx; | 2446 | conn->id = conn_idx; |
| @@ -2531,10 +2499,10 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) | |||
| 2531 | goto max_recv_dlenght_alloc_fail; | 2499 | goto max_recv_dlenght_alloc_fail; |
| 2532 | 2500 | ||
| 2533 | init_timer(&conn->tmabort_timer); | 2501 | init_timer(&conn->tmabort_timer); |
| 2534 | init_MUTEX(&conn->xmitsema); | 2502 | mutex_init(&conn->xmitmutex); |
| 2535 | init_waitqueue_head(&conn->ehwait); | 2503 | init_waitqueue_head(&conn->ehwait); |
| 2536 | 2504 | ||
| 2537 | return iscsi_handle(conn); | 2505 | return cls_conn; |
| 2538 | 2506 | ||
| 2539 | max_recv_dlenght_alloc_fail: | 2507 | max_recv_dlenght_alloc_fail: |
| 2540 | spin_lock_bh(&session->lock); | 2508 | spin_lock_bh(&session->lock); |
| @@ -2550,18 +2518,18 @@ immqueue_alloc_fail: | |||
| 2550 | writequeue_alloc_fail: | 2518 | writequeue_alloc_fail: |
| 2551 | kfifo_free(conn->xmitqueue); | 2519 | kfifo_free(conn->xmitqueue); |
| 2552 | xmitqueue_alloc_fail: | 2520 | xmitqueue_alloc_fail: |
| 2553 | kfree(conn); | 2521 | iscsi_destroy_conn(cls_conn); |
| 2554 | conn_alloc_fail: | 2522 | return NULL; |
| 2555 | return iscsi_handle(NULL); | ||
| 2556 | } | 2523 | } |
| 2557 | 2524 | ||
| 2558 | static void | 2525 | static void |
| 2559 | iscsi_conn_destroy(iscsi_connh_t connh) | 2526 | iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) |
| 2560 | { | 2527 | { |
| 2561 | struct iscsi_conn *conn = iscsi_ptr(connh); | 2528 | struct iscsi_conn *conn = cls_conn->dd_data; |
| 2562 | struct iscsi_session *session = conn->session; | 2529 | struct iscsi_session *session = conn->session; |
| 2530 | unsigned long flags; | ||
| 2563 | 2531 | ||
| 2564 | down(&conn->xmitsema); | 2532 | mutex_lock(&conn->xmitmutex); |
| 2565 | set_bit(SUSPEND_BIT, &conn->suspend_tx); | 2533 | set_bit(SUSPEND_BIT, &conn->suspend_tx); |
| 2566 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { | 2534 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { |
| 2567 | struct sock *sk = conn->sock->sk; | 2535 | struct sock *sk = conn->sock->sk; |
| @@ -2592,19 +2560,19 @@ iscsi_conn_destroy(iscsi_connh_t connh) | |||
| 2592 | } | 2560 | } |
| 2593 | spin_unlock_bh(&session->lock); | 2561 | spin_unlock_bh(&session->lock); |
| 2594 | 2562 | ||
| 2595 | up(&conn->xmitsema); | 2563 | mutex_unlock(&conn->xmitmutex); |
| 2596 | 2564 | ||
| 2597 | /* | 2565 | /* |
| 2598 | * Block until all in-progress commands for this connection | 2566 | * Block until all in-progress commands for this connection |
| 2599 | * time out or fail. | 2567 | * time out or fail. |
| 2600 | */ | 2568 | */ |
| 2601 | for (;;) { | 2569 | for (;;) { |
| 2602 | spin_lock_bh(&conn->lock); | 2570 | spin_lock_irqsave(session->host->host_lock, flags); |
| 2603 | if (!session->host->host_busy) { /* OK for ERL == 0 */ | 2571 | if (!session->host->host_busy) { /* OK for ERL == 0 */ |
| 2604 | spin_unlock_bh(&conn->lock); | 2572 | spin_unlock_irqrestore(session->host->host_lock, flags); |
| 2605 | break; | 2573 | break; |
| 2606 | } | 2574 | } |
| 2607 | spin_unlock_bh(&conn->lock); | 2575 | spin_unlock_irqrestore(session->host->host_lock, flags); |
| 2608 | msleep_interruptible(500); | 2576 | msleep_interruptible(500); |
| 2609 | printk("conn_destroy(): host_busy %d host_failed %d\n", | 2577 | printk("conn_destroy(): host_busy %d host_failed %d\n", |
| 2610 | session->host->host_busy, session->host->host_failed); | 2578 | session->host->host_busy, session->host->host_failed); |
| @@ -2652,7 +2620,8 @@ iscsi_conn_destroy(iscsi_connh_t connh) | |||
| 2652 | kfifo_free(conn->writequeue); | 2620 | kfifo_free(conn->writequeue); |
| 2653 | kfifo_free(conn->immqueue); | 2621 | kfifo_free(conn->immqueue); |
| 2654 | kfifo_free(conn->mgmtqueue); | 2622 | kfifo_free(conn->mgmtqueue); |
| 2655 | kfree(conn); | 2623 | |
| 2624 | iscsi_destroy_conn(cls_conn); | ||
| 2656 | } | 2625 | } |
| 2657 | 2626 | ||
| 2658 | static int | 2627 | static int |
| @@ -2713,6 +2682,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, | |||
| 2713 | */ | 2682 | */ |
| 2714 | iscsi_conn_set_callbacks(conn); | 2683 | iscsi_conn_set_callbacks(conn); |
| 2715 | 2684 | ||
| 2685 | conn->sendpage = conn->sock->ops->sendpage; | ||
| 2686 | |||
| 2716 | /* | 2687 | /* |
| 2717 | * set receive state machine into initial state | 2688 | * set receive state machine into initial state |
| 2718 | */ | 2689 | */ |
| @@ -2796,7 +2767,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) | |||
| 2796 | set_bit(SUSPEND_BIT, &conn->suspend_rx); | 2767 | set_bit(SUSPEND_BIT, &conn->suspend_rx); |
| 2797 | write_unlock_bh(&sk->sk_callback_lock); | 2768 | write_unlock_bh(&sk->sk_callback_lock); |
| 2798 | 2769 | ||
| 2799 | down(&conn->xmitsema); | 2770 | mutex_lock(&conn->xmitmutex); |
| 2800 | 2771 | ||
| 2801 | spin_lock_irqsave(session->host->host_lock, flags); | 2772 | spin_lock_irqsave(session->host->host_lock, flags); |
| 2802 | spin_lock(&session->lock); | 2773 | spin_lock(&session->lock); |
| @@ -2878,7 +2849,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) | |||
| 2878 | conn->datadgst_en = 0; | 2849 | conn->datadgst_en = 0; |
| 2879 | } | 2850 | } |
| 2880 | } | 2851 | } |
| 2881 | up(&conn->xmitsema); | 2852 | mutex_unlock(&conn->xmitmutex); |
| 2882 | } | 2853 | } |
| 2883 | 2854 | ||
| 2884 | static int | 2855 | static int |
| @@ -2963,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 2963 | else | 2934 | else |
| 2964 | __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); | 2935 | __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); |
| 2965 | 2936 | ||
| 2966 | schedule_work(&conn->xmitwork); | 2937 | scsi_queue_work(session->host, &conn->xmitwork); |
| 2967 | |||
| 2968 | return 0; | 2938 | return 0; |
| 2969 | } | 2939 | } |
| 2970 | 2940 | ||
| @@ -3029,12 +2999,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 3029 | * 1) connection-level failure; | 2999 | * 1) connection-level failure; |
| 3030 | * 2) recovery due protocol error; | 3000 | * 2) recovery due protocol error; |
| 3031 | */ | 3001 | */ |
| 3032 | down(&conn->xmitsema); | 3002 | mutex_lock(&conn->xmitmutex); |
| 3033 | spin_lock_bh(&session->lock); | 3003 | spin_lock_bh(&session->lock); |
| 3034 | if (session->state != ISCSI_STATE_LOGGED_IN) { | 3004 | if (session->state != ISCSI_STATE_LOGGED_IN) { |
| 3035 | if (session->state == ISCSI_STATE_TERMINATE) { | 3005 | if (session->state == ISCSI_STATE_TERMINATE) { |
| 3036 | spin_unlock_bh(&session->lock); | 3006 | spin_unlock_bh(&session->lock); |
| 3037 | up(&conn->xmitsema); | 3007 | mutex_unlock(&conn->xmitmutex); |
| 3038 | goto failed; | 3008 | goto failed; |
| 3039 | } | 3009 | } |
| 3040 | spin_unlock_bh(&session->lock); | 3010 | spin_unlock_bh(&session->lock); |
| @@ -3052,7 +3022,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 3052 | * 2) session was re-open during time out of ctask. | 3022 | * 2) session was re-open during time out of ctask. |
| 3053 | */ | 3023 | */ |
| 3054 | spin_unlock_bh(&session->lock); | 3024 | spin_unlock_bh(&session->lock); |
| 3055 | up(&conn->xmitsema); | 3025 | mutex_unlock(&conn->xmitmutex); |
| 3056 | goto success; | 3026 | goto success; |
| 3057 | } | 3027 | } |
| 3058 | conn->tmabort_state = TMABORT_INITIAL; | 3028 | conn->tmabort_state = TMABORT_INITIAL; |
| @@ -3107,7 +3077,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 3107 | conn->tmabort_state == TMABORT_SUCCESS) { | 3077 | conn->tmabort_state == TMABORT_SUCCESS) { |
| 3108 | conn->tmabort_state = TMABORT_INITIAL; | 3078 | conn->tmabort_state = TMABORT_INITIAL; |
| 3109 | spin_unlock_bh(&session->lock); | 3079 | spin_unlock_bh(&session->lock); |
| 3110 | up(&conn->xmitsema); | 3080 | mutex_unlock(&conn->xmitmutex); |
| 3111 | goto success; | 3081 | goto success; |
| 3112 | } | 3082 | } |
| 3113 | conn->tmabort_state = TMABORT_INITIAL; | 3083 | conn->tmabort_state = TMABORT_INITIAL; |
| @@ -3116,7 +3086,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 3116 | spin_unlock_bh(&session->lock); | 3086 | spin_unlock_bh(&session->lock); |
| 3117 | } | 3087 | } |
| 3118 | } | 3088 | } |
| 3119 | up(&conn->xmitsema); | 3089 | mutex_unlock(&conn->xmitmutex); |
| 3120 | 3090 | ||
| 3121 | 3091 | ||
| 3122 | /* | 3092 | /* |
| @@ -3182,7 +3152,7 @@ failed: | |||
| 3182 | exit: | 3152 | exit: |
| 3183 | del_timer_sync(&conn->tmabort_timer); | 3153 | del_timer_sync(&conn->tmabort_timer); |
| 3184 | 3154 | ||
| 3185 | down(&conn->xmitsema); | 3155 | mutex_lock(&conn->xmitmutex); |
| 3186 | if (conn->sock) { | 3156 | if (conn->sock) { |
| 3187 | struct sock *sk = conn->sock->sk; | 3157 | struct sock *sk = conn->sock->sk; |
| 3188 | 3158 | ||
| @@ -3190,7 +3160,7 @@ exit: | |||
| 3190 | iscsi_ctask_cleanup(conn, ctask); | 3160 | iscsi_ctask_cleanup(conn, ctask); |
| 3191 | write_unlock_bh(&sk->sk_callback_lock); | 3161 | write_unlock_bh(&sk->sk_callback_lock); |
| 3192 | } | 3162 | } |
| 3193 | up(&conn->xmitsema); | 3163 | mutex_unlock(&conn->xmitmutex); |
| 3194 | return rc; | 3164 | return rc; |
| 3195 | } | 3165 | } |
| 3196 | 3166 | ||
| @@ -3281,17 +3251,23 @@ static struct scsi_host_template iscsi_sht = { | |||
| 3281 | .this_id = -1, | 3251 | .this_id = -1, |
| 3282 | }; | 3252 | }; |
| 3283 | 3253 | ||
| 3284 | static iscsi_sessionh_t | 3254 | static struct iscsi_transport iscsi_tcp_transport; |
| 3285 | iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) | 3255 | |
| 3256 | static struct Scsi_Host * | ||
| 3257 | iscsi_session_create(struct scsi_transport_template *scsit, | ||
| 3258 | uint32_t initial_cmdsn) | ||
| 3286 | { | 3259 | { |
| 3287 | int cmd_i; | 3260 | struct Scsi_Host *shost; |
| 3288 | struct iscsi_session *session; | 3261 | struct iscsi_session *session; |
| 3262 | int cmd_i; | ||
| 3289 | 3263 | ||
| 3290 | session = iscsi_hostdata(host->hostdata); | 3264 | shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); |
| 3291 | memset(session, 0, sizeof(struct iscsi_session)); | 3265 | if (!shost) |
| 3266 | return NULL; | ||
| 3292 | 3267 | ||
| 3293 | session->host = host; | 3268 | session = iscsi_hostdata(shost->hostdata); |
| 3294 | session->id = host->host_no; | 3269 | memset(session, 0, sizeof(struct iscsi_session)); |
| 3270 | session->host = shost; | ||
| 3295 | session->state = ISCSI_STATE_LOGGED_IN; | 3271 | session->state = ISCSI_STATE_LOGGED_IN; |
| 3296 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; | 3272 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; |
| 3297 | session->cmds_max = ISCSI_XMIT_CMDS_MAX; | 3273 | session->cmds_max = ISCSI_XMIT_CMDS_MAX; |
| @@ -3335,7 +3311,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) | |||
| 3335 | if (iscsi_r2tpool_alloc(session)) | 3311 | if (iscsi_r2tpool_alloc(session)) |
| 3336 | goto r2tpool_alloc_fail; | 3312 | goto r2tpool_alloc_fail; |
| 3337 | 3313 | ||
| 3338 | return iscsi_handle(session); | 3314 | return shost; |
| 3339 | 3315 | ||
| 3340 | r2tpool_alloc_fail: | 3316 | r2tpool_alloc_fail: |
| 3341 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) | 3317 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) |
| @@ -3345,15 +3321,15 @@ immdata_alloc_fail: | |||
| 3345 | mgmtpool_alloc_fail: | 3321 | mgmtpool_alloc_fail: |
| 3346 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 3322 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); |
| 3347 | cmdpool_alloc_fail: | 3323 | cmdpool_alloc_fail: |
| 3348 | return iscsi_handle(NULL); | 3324 | return NULL; |
| 3349 | } | 3325 | } |
| 3350 | 3326 | ||
| 3351 | static void | 3327 | static void |
| 3352 | iscsi_session_destroy(iscsi_sessionh_t sessionh) | 3328 | iscsi_session_destroy(struct Scsi_Host *shost) |
| 3353 | { | 3329 | { |
| 3330 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | ||
| 3354 | int cmd_i; | 3331 | int cmd_i; |
| 3355 | struct iscsi_data_task *dtask, *n; | 3332 | struct iscsi_data_task *dtask, *n; |
| 3356 | struct iscsi_session *session = iscsi_ptr(sessionh); | ||
| 3357 | 3333 | ||
| 3358 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 3334 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
| 3359 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 3335 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
| @@ -3369,6 +3345,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh) | |||
| 3369 | iscsi_r2tpool_free(session); | 3345 | iscsi_r2tpool_free(session); |
| 3370 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); | 3346 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); |
| 3371 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 3347 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); |
| 3348 | |||
| 3349 | iscsi_transport_destroy_session(shost); | ||
| 3372 | } | 3350 | } |
| 3373 | 3351 | ||
| 3374 | static int | 3352 | static int |
| @@ -3467,6 +3445,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, | |||
| 3467 | if (conn->data_rx_tfm) | 3445 | if (conn->data_rx_tfm) |
| 3468 | crypto_free_tfm(conn->data_rx_tfm); | 3446 | crypto_free_tfm(conn->data_rx_tfm); |
| 3469 | } | 3447 | } |
| 3448 | conn->sendpage = conn->datadgst_en ? | ||
| 3449 | sock_no_sendpage : conn->sock->ops->sendpage; | ||
| 3470 | break; | 3450 | break; |
| 3471 | case ISCSI_PARAM_INITIAL_R2T_EN: | 3451 | case ISCSI_PARAM_INITIAL_R2T_EN: |
| 3472 | session->initial_r2t_en = value; | 3452 | session->initial_r2t_en = value; |
| @@ -3515,25 +3495,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, | |||
| 3515 | } | 3495 | } |
| 3516 | 3496 | ||
| 3517 | static int | 3497 | static int |
| 3518 | iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, | 3498 | iscsi_session_get_param(struct Scsi_Host *shost, |
| 3519 | uint32_t *value) | 3499 | enum iscsi_param param, uint32_t *value) |
| 3520 | { | 3500 | { |
| 3521 | struct iscsi_conn *conn = iscsi_ptr(connh); | 3501 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); |
| 3522 | struct iscsi_session *session = conn->session; | ||
| 3523 | 3502 | ||
| 3524 | switch(param) { | 3503 | switch(param) { |
| 3525 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | ||
| 3526 | *value = conn->max_recv_dlength; | ||
| 3527 | break; | ||
| 3528 | case ISCSI_PARAM_MAX_XMIT_DLENGTH: | ||
| 3529 | *value = conn->max_xmit_dlength; | ||
| 3530 | break; | ||
| 3531 | case ISCSI_PARAM_HDRDGST_EN: | ||
| 3532 | *value = conn->hdrdgst_en; | ||
| 3533 | break; | ||
| 3534 | case ISCSI_PARAM_DATADGST_EN: | ||
| 3535 | *value = conn->datadgst_en; | ||
| 3536 | break; | ||
| 3537 | case ISCSI_PARAM_INITIAL_R2T_EN: | 3504 | case ISCSI_PARAM_INITIAL_R2T_EN: |
| 3538 | *value = session->initial_r2t_en; | 3505 | *value = session->initial_r2t_en; |
| 3539 | break; | 3506 | break; |
| @@ -3571,6 +3538,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, | |||
| 3571 | return 0; | 3538 | return 0; |
| 3572 | } | 3539 | } |
| 3573 | 3540 | ||
| 3541 | static int | ||
| 3542 | iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) | ||
| 3543 | { | ||
| 3544 | struct iscsi_conn *conn = data; | ||
| 3545 | |||
| 3546 | switch(param) { | ||
| 3547 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | ||
| 3548 | *value = conn->max_recv_dlength; | ||
| 3549 | break; | ||
| 3550 | case ISCSI_PARAM_MAX_XMIT_DLENGTH: | ||
| 3551 | *value = conn->max_xmit_dlength; | ||
| 3552 | break; | ||
| 3553 | case ISCSI_PARAM_HDRDGST_EN: | ||
| 3554 | *value = conn->hdrdgst_en; | ||
| 3555 | break; | ||
| 3556 | case ISCSI_PARAM_DATADGST_EN: | ||
| 3557 | *value = conn->datadgst_en; | ||
| 3558 | break; | ||
| 3559 | default: | ||
| 3560 | return ISCSI_ERR_PARAM_NOT_FOUND; | ||
| 3561 | } | ||
| 3562 | |||
| 3563 | return 0; | ||
| 3564 | } | ||
| 3565 | |||
| 3574 | static void | 3566 | static void |
| 3575 | iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) | 3567 | iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) |
| 3576 | { | 3568 | { |
| @@ -3601,9 +3593,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data, | |||
| 3601 | struct iscsi_conn *conn = iscsi_ptr(connh); | 3593 | struct iscsi_conn *conn = iscsi_ptr(connh); |
| 3602 | int rc; | 3594 | int rc; |
| 3603 | 3595 | ||
| 3604 | down(&conn->xmitsema); | 3596 | mutex_lock(&conn->xmitmutex); |
| 3605 | rc = iscsi_conn_send_generic(conn, hdr, data, data_size); | 3597 | rc = iscsi_conn_send_generic(conn, hdr, data, data_size); |
| 3606 | up(&conn->xmitsema); | 3598 | mutex_unlock(&conn->xmitmutex); |
| 3607 | 3599 | ||
| 3608 | return rc; | 3600 | return rc; |
| 3609 | } | 3601 | } |
| @@ -3615,6 +3607,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
| 3615 | | CAP_DATADGST, | 3607 | | CAP_DATADGST, |
| 3616 | .host_template = &iscsi_sht, | 3608 | .host_template = &iscsi_sht, |
| 3617 | .hostdata_size = sizeof(struct iscsi_session), | 3609 | .hostdata_size = sizeof(struct iscsi_session), |
| 3610 | .conndata_size = sizeof(struct iscsi_conn), | ||
| 3618 | .max_conn = 1, | 3611 | .max_conn = 1, |
| 3619 | .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, | 3612 | .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, |
| 3620 | .create_session = iscsi_session_create, | 3613 | .create_session = iscsi_session_create, |
| @@ -3623,7 +3616,8 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
| 3623 | .bind_conn = iscsi_conn_bind, | 3616 | .bind_conn = iscsi_conn_bind, |
| 3624 | .destroy_conn = iscsi_conn_destroy, | 3617 | .destroy_conn = iscsi_conn_destroy, |
| 3625 | .set_param = iscsi_conn_set_param, | 3618 | .set_param = iscsi_conn_set_param, |
| 3626 | .get_param = iscsi_conn_get_param, | 3619 | .get_conn_param = iscsi_conn_get_param, |
| 3620 | .get_session_param = iscsi_session_get_param, | ||
| 3627 | .start_conn = iscsi_conn_start, | 3621 | .start_conn = iscsi_conn_start, |
| 3628 | .stop_conn = iscsi_conn_stop, | 3622 | .stop_conn = iscsi_conn_stop, |
| 3629 | .send_pdu = iscsi_conn_send_pdu, | 3623 | .send_pdu = iscsi_conn_send_pdu, |
| @@ -3633,8 +3627,6 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
| 3633 | static int __init | 3627 | static int __init |
| 3634 | iscsi_tcp_init(void) | 3628 | iscsi_tcp_init(void) |
| 3635 | { | 3629 | { |
| 3636 | int error; | ||
| 3637 | |||
| 3638 | if (iscsi_max_lun < 1) { | 3630 | if (iscsi_max_lun < 1) { |
| 3639 | printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); | 3631 | printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); |
| 3640 | return -EINVAL; | 3632 | return -EINVAL; |
| @@ -3647,11 +3639,10 @@ iscsi_tcp_init(void) | |||
| 3647 | if (!taskcache) | 3639 | if (!taskcache) |
| 3648 | return -ENOMEM; | 3640 | return -ENOMEM; |
| 3649 | 3641 | ||
| 3650 | error = iscsi_register_transport(&iscsi_tcp_transport); | 3642 | if (!iscsi_register_transport(&iscsi_tcp_transport)) |
| 3651 | if (error) | ||
| 3652 | kmem_cache_destroy(taskcache); | 3643 | kmem_cache_destroy(taskcache); |
| 3653 | 3644 | ||
| 3654 | return error; | 3645 | return 0; |
| 3655 | } | 3646 | } |
| 3656 | 3647 | ||
| 3657 | static void __exit | 3648 | static void __exit |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 855f2dfd18af..f95e61b76f70 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
| @@ -158,7 +158,7 @@ struct iscsi_conn { | |||
| 158 | struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ | 158 | struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ |
| 159 | struct kfifo *xmitqueue; /* data-path cmd queue */ | 159 | struct kfifo *xmitqueue; /* data-path cmd queue */ |
| 160 | struct work_struct xmitwork; /* per-conn. xmit workqueue */ | 160 | struct work_struct xmitwork; /* per-conn. xmit workqueue */ |
| 161 | struct semaphore xmitsema; /* serializes connection xmit, | 161 | struct mutex xmitmutex; /* serializes connection xmit, |
| 162 | * access to kfifos: * | 162 | * access to kfifos: * |
| 163 | * xmitqueue, writequeue, * | 163 | * xmitqueue, writequeue, * |
| 164 | * immqueue, mgmtqueue */ | 164 | * immqueue, mgmtqueue */ |
| @@ -191,6 +191,8 @@ struct iscsi_conn { | |||
| 191 | uint32_t sendpage_failures_cnt; | 191 | uint32_t sendpage_failures_cnt; |
| 192 | uint32_t discontiguous_hdr_cnt; | 192 | uint32_t discontiguous_hdr_cnt; |
| 193 | uint32_t eh_abort_cnt; | 193 | uint32_t eh_abort_cnt; |
| 194 | |||
| 195 | ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); | ||
| 194 | }; | 196 | }; |
| 195 | 197 | ||
| 196 | struct iscsi_session { | 198 | struct iscsi_session { |
| @@ -240,8 +242,8 @@ struct iscsi_session { | |||
| 240 | 242 | ||
| 241 | struct iscsi_buf { | 243 | struct iscsi_buf { |
| 242 | struct scatterlist sg; | 244 | struct scatterlist sg; |
| 243 | struct kvec iov; | ||
| 244 | unsigned int sent; | 245 | unsigned int sent; |
| 246 | char use_sendmsg; | ||
| 245 | }; | 247 | }; |
| 246 | 248 | ||
| 247 | struct iscsi_data_task { | 249 | struct iscsi_data_task { |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f55b9b3f7b37..99bae8369ab2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
| @@ -1747,7 +1747,7 @@ static const struct { | |||
| 1747 | { ATA_SHIFT_PIO, XFER_PIO_0 }, | 1747 | { ATA_SHIFT_PIO, XFER_PIO_0 }, |
| 1748 | }; | 1748 | }; |
| 1749 | 1749 | ||
| 1750 | static inline u8 base_from_shift(unsigned int shift) | 1750 | static u8 base_from_shift(unsigned int shift) |
| 1751 | { | 1751 | { |
| 1752 | int i; | 1752 | int i; |
| 1753 | 1753 | ||
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 9ee8218404c0..dafabeefc5b3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -150,7 +150,7 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba) | |||
| 150 | return psb; | 150 | return psb; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | struct lpfc_scsi_buf* | 153 | static struct lpfc_scsi_buf* |
| 154 | lpfc_get_scsi_buf(struct lpfc_hba * phba) | 154 | lpfc_get_scsi_buf(struct lpfc_hba * phba) |
| 155 | { | 155 | { |
| 156 | struct lpfc_scsi_buf * lpfc_cmd = NULL; | 156 | struct lpfc_scsi_buf * lpfc_cmd = NULL; |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 4a6feb1e5e3d..d101a8a6f4e8 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
| @@ -4479,7 +4479,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) | |||
| 4479 | * serialized. This is so because we want to reserve maximum number of | 4479 | * serialized. This is so because we want to reserve maximum number of |
| 4480 | * available command ids for the I/O commands. | 4480 | * available command ids for the I/O commands. |
| 4481 | */ | 4481 | */ |
| 4482 | down(&adapter->int_mtx); | 4482 | mutex_lock(&adapter->int_mtx); |
| 4483 | 4483 | ||
| 4484 | scb = &adapter->int_scb; | 4484 | scb = &adapter->int_scb; |
| 4485 | memset(scb, 0, sizeof(scb_t)); | 4485 | memset(scb, 0, sizeof(scb_t)); |
| @@ -4527,7 +4527,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) | |||
| 4527 | mc->cmd, mc->opcode, mc->subopcode, scmd->result); | 4527 | mc->cmd, mc->opcode, mc->subopcode, scmd->result); |
| 4528 | } | 4528 | } |
| 4529 | 4529 | ||
| 4530 | up(&adapter->int_mtx); | 4530 | mutex_unlock(&adapter->int_mtx); |
| 4531 | 4531 | ||
| 4532 | return rval; | 4532 | return rval; |
| 4533 | } | 4533 | } |
| @@ -4866,7 +4866,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4866 | adapter->has_64bit_addr = 0; | 4866 | adapter->has_64bit_addr = 0; |
| 4867 | } | 4867 | } |
| 4868 | 4868 | ||
| 4869 | init_MUTEX(&adapter->int_mtx); | 4869 | mutex_init(&adapter->int_mtx); |
| 4870 | init_completion(&adapter->int_waitq); | 4870 | init_completion(&adapter->int_waitq); |
| 4871 | 4871 | ||
| 4872 | adapter->this_id = DEFAULT_INITIATOR_ID; | 4872 | adapter->this_id = DEFAULT_INITIATOR_ID; |
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index 6f9078025748..4b3e0d6e5afa 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #define __MEGARAID_H__ | 2 | #define __MEGARAID_H__ |
| 3 | 3 | ||
| 4 | #include <linux/spinlock.h> | 4 | #include <linux/spinlock.h> |
| 5 | 5 | #include <linux/mutex.h> | |
| 6 | 6 | ||
| 7 | #define MEGARAID_VERSION \ | 7 | #define MEGARAID_VERSION \ |
| 8 | "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n" | 8 | "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n" |
| @@ -889,7 +889,7 @@ typedef struct { | |||
| 889 | 889 | ||
| 890 | scb_t int_scb; | 890 | scb_t int_scb; |
| 891 | Scsi_Cmnd int_scmd; | 891 | Scsi_Cmnd int_scmd; |
| 892 | struct semaphore int_mtx; /* To synchronize the internal | 892 | struct mutex int_mtx; /* To synchronize the internal |
| 893 | commands */ | 893 | commands */ |
| 894 | struct completion int_waitq; /* wait queue for internal | 894 | struct completion int_waitq; /* wait queue for internal |
| 895 | cmds */ | 895 | cmds */ |
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index d18a4bc2498c..bf9f7f7ba354 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c | |||
| @@ -1266,7 +1266,7 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter) | |||
| 1266 | * return the scb from the head of the free list. NULL if there are none | 1266 | * return the scb from the head of the free list. NULL if there are none |
| 1267 | * available | 1267 | * available |
| 1268 | **/ | 1268 | **/ |
| 1269 | static inline scb_t * | 1269 | static scb_t * |
| 1270 | megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) | 1270 | megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) |
| 1271 | { | 1271 | { |
| 1272 | struct list_head *head = &adapter->kscb_pool; | 1272 | struct list_head *head = &adapter->kscb_pool; |
| @@ -1329,7 +1329,7 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) | |||
| 1329 | * | 1329 | * |
| 1330 | * prepare the scatter-gather list | 1330 | * prepare the scatter-gather list |
| 1331 | */ | 1331 | */ |
| 1332 | static inline int | 1332 | static int |
| 1333 | megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) | 1333 | megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) |
| 1334 | { | 1334 | { |
| 1335 | struct scatterlist *sgl; | 1335 | struct scatterlist *sgl; |
| @@ -1402,7 +1402,7 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) | |||
| 1402 | * | 1402 | * |
| 1403 | * post the command to the controller if mailbox is availble. | 1403 | * post the command to the controller if mailbox is availble. |
| 1404 | */ | 1404 | */ |
| 1405 | static inline int | 1405 | static int |
| 1406 | mbox_post_cmd(adapter_t *adapter, scb_t *scb) | 1406 | mbox_post_cmd(adapter_t *adapter, scb_t *scb) |
| 1407 | { | 1407 | { |
| 1408 | mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); | 1408 | mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); |
| @@ -2070,7 +2070,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, | |||
| 2070 | * | 2070 | * |
| 2071 | * Returns: 1 if the interrupt is valid, 0 otherwise | 2071 | * Returns: 1 if the interrupt is valid, 0 otherwise |
| 2072 | */ | 2072 | */ |
| 2073 | static inline int | 2073 | static int |
| 2074 | megaraid_ack_sequence(adapter_t *adapter) | 2074 | megaraid_ack_sequence(adapter_t *adapter) |
| 2075 | { | 2075 | { |
| 2076 | mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); | 2076 | mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); |
| @@ -2208,7 +2208,7 @@ megaraid_isr(int irq, void *devp, struct pt_regs *regs) | |||
| 2208 | * | 2208 | * |
| 2209 | * DMA sync if required. | 2209 | * DMA sync if required. |
| 2210 | */ | 2210 | */ |
| 2211 | static inline void | 2211 | static void |
| 2212 | megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) | 2212 | megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) |
| 2213 | { | 2213 | { |
| 2214 | mbox_ccb_t *ccb; | 2214 | mbox_ccb_t *ccb; |
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 3c32e69afcd9..511ed52a5807 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
| 36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
| 37 | #include <linux/compat.h> | 37 | #include <linux/compat.h> |
| 38 | #include <linux/mutex.h> | ||
| 38 | 39 | ||
| 39 | #include <scsi/scsi.h> | 40 | #include <scsi/scsi.h> |
| 40 | #include <scsi/scsi_cmnd.h> | 41 | #include <scsi/scsi_cmnd.h> |
| @@ -72,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, megasas_pci_table); | |||
| 72 | static int megasas_mgmt_majorno; | 73 | static int megasas_mgmt_majorno; |
| 73 | static struct megasas_mgmt_info megasas_mgmt_info; | 74 | static struct megasas_mgmt_info megasas_mgmt_info; |
| 74 | static struct fasync_struct *megasas_async_queue; | 75 | static struct fasync_struct *megasas_async_queue; |
| 75 | static DECLARE_MUTEX(megasas_async_queue_mutex); | 76 | static DEFINE_MUTEX(megasas_async_queue_mutex); |
| 76 | 77 | ||
| 77 | /** | 78 | /** |
| 78 | * megasas_get_cmd - Get a command from the free pool | 79 | * megasas_get_cmd - Get a command from the free pool |
| @@ -80,7 +81,7 @@ static DECLARE_MUTEX(megasas_async_queue_mutex); | |||
| 80 | * | 81 | * |
| 81 | * Returns a free command from the pool | 82 | * Returns a free command from the pool |
| 82 | */ | 83 | */ |
| 83 | static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance | 84 | static struct megasas_cmd *megasas_get_cmd(struct megasas_instance |
| 84 | *instance) | 85 | *instance) |
| 85 | { | 86 | { |
| 86 | unsigned long flags; | 87 | unsigned long flags; |
| @@ -262,7 +263,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, | |||
| 262 | * If successful, this function returns the number of SG elements. Otherwise, | 263 | * If successful, this function returns the number of SG elements. Otherwise, |
| 263 | * it returnes -1. | 264 | * it returnes -1. |
| 264 | */ | 265 | */ |
| 265 | static inline int | 266 | static int |
| 266 | megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, | 267 | megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, |
| 267 | union megasas_sgl *mfi_sgl) | 268 | union megasas_sgl *mfi_sgl) |
| 268 | { | 269 | { |
| @@ -310,7 +311,7 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
| 310 | * If successful, this function returns the number of SG elements. Otherwise, | 311 | * If successful, this function returns the number of SG elements. Otherwise, |
| 311 | * it returnes -1. | 312 | * it returnes -1. |
| 312 | */ | 313 | */ |
| 313 | static inline int | 314 | static int |
| 314 | megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | 315 | megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, |
| 315 | union megasas_sgl *mfi_sgl) | 316 | union megasas_sgl *mfi_sgl) |
| 316 | { | 317 | { |
| @@ -359,7 +360,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
| 359 | * This function prepares CDB commands. These are typcially pass-through | 360 | * This function prepares CDB commands. These are typcially pass-through |
| 360 | * commands to the devices. | 361 | * commands to the devices. |
| 361 | */ | 362 | */ |
| 362 | static inline int | 363 | static int |
| 363 | megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | 364 | megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, |
| 364 | struct megasas_cmd *cmd) | 365 | struct megasas_cmd *cmd) |
| 365 | { | 366 | { |
| @@ -440,7 +441,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
| 440 | * | 441 | * |
| 441 | * Frames (and accompanying SGLs) for regular SCSI IOs use this function. | 442 | * Frames (and accompanying SGLs) for regular SCSI IOs use this function. |
| 442 | */ | 443 | */ |
| 443 | static inline int | 444 | static int |
| 444 | megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | 445 | megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, |
| 445 | struct megasas_cmd *cmd) | 446 | struct megasas_cmd *cmd) |
| 446 | { | 447 | { |
| @@ -562,7 +563,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
| 562 | * @scp: SCSI command | 563 | * @scp: SCSI command |
| 563 | * @frame_count: [OUT] Number of frames used to prepare this command | 564 | * @frame_count: [OUT] Number of frames used to prepare this command |
| 564 | */ | 565 | */ |
| 565 | static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance | 566 | static struct megasas_cmd *megasas_build_cmd(struct megasas_instance |
| 566 | *instance, | 567 | *instance, |
| 567 | struct scsi_cmnd *scp, | 568 | struct scsi_cmnd *scp, |
| 568 | int *frame_count) | 569 | int *frame_count) |
| @@ -913,7 +914,7 @@ megasas_complete_abort(struct megasas_instance *instance, | |||
| 913 | * @instance: Adapter soft state | 914 | * @instance: Adapter soft state |
| 914 | * @cmd: Completed command | 915 | * @cmd: Completed command |
| 915 | */ | 916 | */ |
| 916 | static inline void | 917 | static void |
| 917 | megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) | 918 | megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) |
| 918 | { | 919 | { |
| 919 | dma_addr_t buf_h; | 920 | dma_addr_t buf_h; |
| @@ -957,7 +958,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
| 957 | * an alternate status (as in the case of aborted | 958 | * an alternate status (as in the case of aborted |
| 958 | * commands) | 959 | * commands) |
| 959 | */ | 960 | */ |
| 960 | static inline void | 961 | static void |
| 961 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | 962 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, |
| 962 | u8 alt_status) | 963 | u8 alt_status) |
| 963 | { | 964 | { |
| @@ -1104,7 +1105,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
| 1104 | * SCSI mid-layer instead of the status | 1105 | * SCSI mid-layer instead of the status |
| 1105 | * returned by the FW | 1106 | * returned by the FW |
| 1106 | */ | 1107 | */ |
| 1107 | static inline int | 1108 | static int |
| 1108 | megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) | 1109 | megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) |
| 1109 | { | 1110 | { |
| 1110 | u32 status; | 1111 | u32 status; |
| @@ -2362,11 +2363,11 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) | |||
| 2362 | { | 2363 | { |
| 2363 | int rc; | 2364 | int rc; |
| 2364 | 2365 | ||
| 2365 | down(&megasas_async_queue_mutex); | 2366 | mutex_lock(&megasas_async_queue_mutex); |
| 2366 | 2367 | ||
| 2367 | rc = fasync_helper(fd, filep, mode, &megasas_async_queue); | 2368 | rc = fasync_helper(fd, filep, mode, &megasas_async_queue); |
| 2368 | 2369 | ||
| 2369 | up(&megasas_async_queue_mutex); | 2370 | mutex_unlock(&megasas_async_queue_mutex); |
| 2370 | 2371 | ||
| 2371 | if (rc >= 0) { | 2372 | if (rc >= 0) { |
| 2372 | /* For sanity check when we get ioctl */ | 2373 | /* For sanity check when we get ioctl */ |
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 5205c4e7d6ff..5758b2566d7f 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | config SCSI_QLA2XXX | 1 | config SCSI_QLA_FC |
| 2 | tristate "QLogic QLA2XXX Fibre Channel Support" | 2 | tristate "QLogic QLA2XXX Fibre Channel Support" |
| 3 | depends on PCI && SCSI | 3 | depends on PCI && SCSI |
| 4 | select SCSI_FC_ATTRS | 4 | select SCSI_FC_ATTRS |
| @@ -22,49 +22,57 @@ config SCSI_QLA2XXX | |||
| 22 | Upon request, the driver caches the firmware image until | 22 | Upon request, the driver caches the firmware image until |
| 23 | the driver is unloaded. | 23 | the driver is unloaded. |
| 24 | 24 | ||
| 25 | Firmware images can be retrieved from: | ||
| 26 | |||
| 27 | ftp://ftp.qlogic.com/outgoing/linux/firmware/ | ||
| 28 | |||
| 25 | NOTE: The original method of building firmware-loader | 29 | NOTE: The original method of building firmware-loader |
| 26 | modules has been deprecated as the firmware-images will | 30 | modules has been deprecated as the firmware-images will |
| 27 | be removed from the kernel sources. | 31 | be removed from the kernel sources. |
| 28 | 32 | ||
| 29 | config SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 33 | config SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 30 | bool " Use firmware-loader modules (DEPRECATED)" | 34 | bool " Use firmware-loader modules (DEPRECATED)" |
| 31 | depends on SCSI_QLA2XXX | 35 | depends on SCSI_QLA_FC |
| 36 | help | ||
| 37 | This option offers you the deprecated firmware-loader | ||
| 38 | modules that have been obsoleted by the usage of the | ||
| 39 | Firmware Loader interface in the qla2xxx driver. | ||
| 32 | 40 | ||
| 33 | config SCSI_QLA21XX | 41 | config SCSI_QLA21XX |
| 34 | tristate " Build QLogic ISP2100 firmware-module" | 42 | tristate " Build QLogic ISP2100 firmware-module" |
| 35 | depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 43 | depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 36 | ---help--- | 44 | ---help--- |
| 37 | This driver supports the QLogic 21xx (ISP2100) host adapter family. | 45 | This driver supports the QLogic 21xx (ISP2100) host adapter family. |
| 38 | 46 | ||
| 39 | config SCSI_QLA22XX | 47 | config SCSI_QLA22XX |
| 40 | tristate " Build QLogic ISP2200 firmware-module" | 48 | tristate " Build QLogic ISP2200 firmware-module" |
| 41 | depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 49 | depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 42 | ---help--- | 50 | ---help--- |
| 43 | This driver supports the QLogic 22xx (ISP2200) host adapter family. | 51 | This driver supports the QLogic 22xx (ISP2200) host adapter family. |
| 44 | 52 | ||
| 45 | config SCSI_QLA2300 | 53 | config SCSI_QLA2300 |
| 46 | tristate " Build QLogic ISP2300 firmware-module" | 54 | tristate " Build QLogic ISP2300 firmware-module" |
| 47 | depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 55 | depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 48 | ---help--- | 56 | ---help--- |
| 49 | This driver supports the QLogic 2300 (ISP2300 and ISP2312) host | 57 | This driver supports the QLogic 2300 (ISP2300 and ISP2312) host |
| 50 | adapter family. | 58 | adapter family. |
| 51 | 59 | ||
| 52 | config SCSI_QLA2322 | 60 | config SCSI_QLA2322 |
| 53 | tristate " Build QLogic ISP2322 firmware-module" | 61 | tristate " Build QLogic ISP2322 firmware-module" |
| 54 | depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 62 | depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 55 | ---help--- | 63 | ---help--- |
| 56 | This driver supports the QLogic 2322 (ISP2322) host adapter family. | 64 | This driver supports the QLogic 2322 (ISP2322) host adapter family. |
| 57 | 65 | ||
| 58 | config SCSI_QLA6312 | 66 | config SCSI_QLA6312 |
| 59 | tristate " Build QLogic ISP63xx firmware-module" | 67 | tristate " Build QLogic ISP63xx firmware-module" |
| 60 | depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 68 | depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 61 | ---help--- | 69 | ---help--- |
| 62 | This driver supports the QLogic 63xx (ISP6312 and ISP6322) host | 70 | This driver supports the QLogic 63xx (ISP6312 and ISP6322) host |
| 63 | adapter family. | 71 | adapter family. |
| 64 | 72 | ||
| 65 | config SCSI_QLA24XX | 73 | config SCSI_QLA24XX |
| 66 | tristate " Build QLogic ISP24xx firmware-module" | 74 | tristate " Build QLogic ISP24xx firmware-module" |
| 67 | depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE | 75 | depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE |
| 68 | ---help--- | 76 | ---help--- |
| 69 | This driver supports the QLogic 24xx (ISP2422 and ISP2432) host | 77 | This driver supports the QLogic 24xx (ISP2422 and ISP2432) host |
| 70 | adapter family. | 78 | adapter family. |
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 40c0de125889..d028bc50ccf7 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile | |||
| @@ -3,7 +3,7 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME | |||
| 3 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ | 3 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ |
| 4 | qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o | 4 | qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o | 6 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o |
| 7 | 7 | ||
| 8 | qla2100-y := ql2100.o ql2100_fw.o | 8 | qla2100-y := ql2100.o ql2100_fw.o |
| 9 | qla2200-y := ql2200.o ql2200_fw.o | 9 | qla2200-y := ql2200.o ql2200_fw.o |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2efca52dff50..b17ee62dd1a9 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
| @@ -541,7 +541,7 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
| 541 | void | 541 | void |
| 542 | qla2x00_init_host_attr(scsi_qla_host_t *ha) | 542 | qla2x00_init_host_attr(scsi_qla_host_t *ha) |
| 543 | { | 543 | { |
| 544 | fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name); | 544 | fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); |
| 545 | fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name); | 545 | fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); |
| 546 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; | 546 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; |
| 547 | } | 547 | } |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 5c5d2315cfab..2d9b12ffe09c 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
| @@ -1003,10 +1003,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 1003 | fw = (struct qla24xx_fw_dump *) ha->fw_dump24; | 1003 | fw = (struct qla24xx_fw_dump *) ha->fw_dump24; |
| 1004 | 1004 | ||
| 1005 | rval = QLA_SUCCESS; | 1005 | rval = QLA_SUCCESS; |
| 1006 | fw->hccr = RD_REG_DWORD(®->hccr); | 1006 | fw->host_status = RD_REG_DWORD(®->host_status); |
| 1007 | 1007 | ||
| 1008 | /* Pause RISC. */ | 1008 | /* Pause RISC. */ |
| 1009 | if ((fw->hccr & HCCRX_RISC_PAUSE) == 0) { | 1009 | if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { |
| 1010 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | | 1010 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | |
| 1011 | HCCRX_CLR_HOST_INT); | 1011 | HCCRX_CLR_HOST_INT); |
| 1012 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ | 1012 | RD_REG_DWORD(®->hccr); /* PCI Posting. */ |
| @@ -1021,16 +1021,54 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 1021 | } | 1021 | } |
| 1022 | } | 1022 | } |
| 1023 | 1023 | ||
| 1024 | /* Disable interrupts. */ | ||
| 1025 | WRT_REG_DWORD(®->ictrl, 0); | ||
| 1026 | RD_REG_DWORD(®->ictrl); | ||
| 1027 | |||
| 1028 | if (rval == QLA_SUCCESS) { | 1024 | if (rval == QLA_SUCCESS) { |
| 1029 | /* Host interface registers. */ | 1025 | /* Host interface registers. */ |
| 1030 | dmp_reg = (uint32_t __iomem *)(reg + 0); | 1026 | dmp_reg = (uint32_t __iomem *)(reg + 0); |
| 1031 | for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) | 1027 | for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) |
| 1032 | fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++); | 1028 | fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++); |
| 1033 | 1029 | ||
| 1030 | /* Disable interrupts. */ | ||
| 1031 | WRT_REG_DWORD(®->ictrl, 0); | ||
| 1032 | RD_REG_DWORD(®->ictrl); | ||
| 1033 | |||
| 1034 | /* Shadow registers. */ | ||
| 1035 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); | ||
| 1036 | RD_REG_DWORD(®->iobase_addr); | ||
| 1037 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1038 | WRT_REG_DWORD(dmp_reg, 0xB0000000); | ||
| 1039 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1040 | fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg); | ||
| 1041 | |||
| 1042 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1043 | WRT_REG_DWORD(dmp_reg, 0xB0100000); | ||
| 1044 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1045 | fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg); | ||
| 1046 | |||
| 1047 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1048 | WRT_REG_DWORD(dmp_reg, 0xB0200000); | ||
| 1049 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1050 | fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg); | ||
| 1051 | |||
| 1052 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1053 | WRT_REG_DWORD(dmp_reg, 0xB0300000); | ||
| 1054 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1055 | fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg); | ||
| 1056 | |||
| 1057 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1058 | WRT_REG_DWORD(dmp_reg, 0xB0400000); | ||
| 1059 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1060 | fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg); | ||
| 1061 | |||
| 1062 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1063 | WRT_REG_DWORD(dmp_reg, 0xB0500000); | ||
| 1064 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1065 | fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg); | ||
| 1066 | |||
| 1067 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1068 | WRT_REG_DWORD(dmp_reg, 0xB0600000); | ||
| 1069 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1070 | fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg); | ||
| 1071 | |||
| 1034 | /* Mailbox registers. */ | 1072 | /* Mailbox registers. */ |
| 1035 | mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); | 1073 | mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); |
| 1036 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) | 1074 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) |
| @@ -1308,43 +1346,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
| 1308 | for (cnt = 0; cnt < 16; cnt++) | 1346 | for (cnt = 0; cnt < 16; cnt++) |
| 1309 | *iter_reg++ = RD_REG_DWORD(dmp_reg++); | 1347 | *iter_reg++ = RD_REG_DWORD(dmp_reg++); |
| 1310 | 1348 | ||
| 1311 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); | ||
| 1312 | RD_REG_DWORD(®->iobase_addr); | ||
| 1313 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1314 | WRT_REG_DWORD(dmp_reg, 0xB0000000); | ||
| 1315 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1316 | fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg); | ||
| 1317 | |||
| 1318 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1319 | WRT_REG_DWORD(dmp_reg, 0xB0100000); | ||
| 1320 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1321 | fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg); | ||
| 1322 | |||
| 1323 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1324 | WRT_REG_DWORD(dmp_reg, 0xB0200000); | ||
| 1325 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1326 | fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg); | ||
| 1327 | |||
| 1328 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1329 | WRT_REG_DWORD(dmp_reg, 0xB0300000); | ||
| 1330 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1331 | fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg); | ||
| 1332 | |||
| 1333 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1334 | WRT_REG_DWORD(dmp_reg, 0xB0400000); | ||
| 1335 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1336 | fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg); | ||
| 1337 | |||
| 1338 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1339 | WRT_REG_DWORD(dmp_reg, 0xB0500000); | ||
| 1340 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1341 | fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg); | ||
| 1342 | |||
| 1343 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | ||
| 1344 | WRT_REG_DWORD(dmp_reg, 0xB0600000); | ||
| 1345 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); | ||
| 1346 | fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg); | ||
| 1347 | |||
| 1348 | /* Local memory controller registers. */ | 1349 | /* Local memory controller registers. */ |
| 1349 | iter_reg = fw->lmc_reg; | 1350 | iter_reg = fw->lmc_reg; |
| 1350 | WRT_REG_DWORD(®->iobase_addr, 0x3000); | 1351 | WRT_REG_DWORD(®->iobase_addr, 0x3000); |
| @@ -1677,7 +1678,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) | |||
| 1677 | ha->fw_major_version, ha->fw_minor_version, | 1678 | ha->fw_major_version, ha->fw_minor_version, |
| 1678 | ha->fw_subminor_version, ha->fw_attributes); | 1679 | ha->fw_subminor_version, ha->fw_attributes); |
| 1679 | 1680 | ||
| 1680 | qla_uprintf(&uiter, "\nHCCR Register\n%04x\n", fw->hccr); | 1681 | qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status); |
| 1681 | 1682 | ||
| 1682 | qla_uprintf(&uiter, "\nHost Interface Registers"); | 1683 | qla_uprintf(&uiter, "\nHost Interface Registers"); |
| 1683 | for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) { | 1684 | for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) { |
| @@ -1687,6 +1688,14 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) | |||
| 1687 | qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]); | 1688 | qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]); |
| 1688 | } | 1689 | } |
| 1689 | 1690 | ||
| 1691 | qla_uprintf(&uiter, "\n\nShadow Registers"); | ||
| 1692 | for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) { | ||
| 1693 | if (cnt % 8 == 0) | ||
| 1694 | qla_uprintf(&uiter, "\n"); | ||
| 1695 | |||
| 1696 | qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]); | ||
| 1697 | } | ||
| 1698 | |||
| 1690 | qla_uprintf(&uiter, "\n\nMailbox Registers"); | 1699 | qla_uprintf(&uiter, "\n\nMailbox Registers"); |
| 1691 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) { | 1700 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) { |
| 1692 | if (cnt % 8 == 0) | 1701 | if (cnt % 8 == 0) |
| @@ -1855,14 +1864,6 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) | |||
| 1855 | qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]); | 1864 | qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]); |
| 1856 | } | 1865 | } |
| 1857 | 1866 | ||
| 1858 | qla_uprintf(&uiter, "\n\nShadow Registers"); | ||
| 1859 | for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) { | ||
| 1860 | if (cnt % 8 == 0) | ||
| 1861 | qla_uprintf(&uiter, "\n"); | ||
| 1862 | |||
| 1863 | qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]); | ||
| 1864 | } | ||
| 1865 | |||
| 1866 | qla_uprintf(&uiter, "\n\nLMC Registers"); | 1867 | qla_uprintf(&uiter, "\n\nLMC Registers"); |
| 1867 | for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) { | 1868 | for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) { |
| 1868 | if (cnt % 8 == 0) | 1869 | if (cnt % 8 == 0) |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 935a59a8c054..ab6afeaa2f2c 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
| @@ -227,8 +227,9 @@ struct qla2100_fw_dump { | |||
| 227 | #define FW_DUMP_SIZE_24XX 0x2B0000 | 227 | #define FW_DUMP_SIZE_24XX 0x2B0000 |
| 228 | 228 | ||
| 229 | struct qla24xx_fw_dump { | 229 | struct qla24xx_fw_dump { |
| 230 | uint32_t hccr; | 230 | uint32_t host_status; |
| 231 | uint32_t host_reg[32]; | 231 | uint32_t host_reg[32]; |
| 232 | uint32_t shadow_reg[7]; | ||
| 232 | uint16_t mailbox_reg[32]; | 233 | uint16_t mailbox_reg[32]; |
| 233 | uint32_t xseq_gp_reg[128]; | 234 | uint32_t xseq_gp_reg[128]; |
| 234 | uint32_t xseq_0_reg[16]; | 235 | uint32_t xseq_0_reg[16]; |
| @@ -250,7 +251,6 @@ struct qla24xx_fw_dump { | |||
| 250 | uint32_t rcvt0_data_dma_reg[32]; | 251 | uint32_t rcvt0_data_dma_reg[32]; |
| 251 | uint32_t rcvt1_data_dma_reg[32]; | 252 | uint32_t rcvt1_data_dma_reg[32]; |
| 252 | uint32_t risc_gp_reg[128]; | 253 | uint32_t risc_gp_reg[128]; |
| 253 | uint32_t shadow_reg[7]; | ||
| 254 | uint32_t lmc_reg[112]; | 254 | uint32_t lmc_reg[112]; |
| 255 | uint32_t fpm_hdw_reg[192]; | 255 | uint32_t fpm_hdw_reg[192]; |
| 256 | uint32_t fb_hdw_reg[176]; | 256 | uint32_t fb_hdw_reg[176]; |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index bec81adcf4fd..32be4c14cccb 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
| @@ -62,6 +62,7 @@ extern int qlport_down_retry; | |||
| 62 | extern int ql2xplogiabsentdevice; | 62 | extern int ql2xplogiabsentdevice; |
| 63 | extern int ql2xloginretrycount; | 63 | extern int ql2xloginretrycount; |
| 64 | extern int ql2xfdmienable; | 64 | extern int ql2xfdmienable; |
| 65 | extern int ql2xprocessrscn; | ||
| 65 | 66 | ||
| 66 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); | 67 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); |
| 67 | 68 | ||
| @@ -96,10 +97,7 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t); | |||
| 96 | * Global Function Prototypes in qla_mbx.c source file. | 97 | * Global Function Prototypes in qla_mbx.c source file. |
| 97 | */ | 98 | */ |
| 98 | extern int | 99 | extern int |
| 99 | qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t); | 100 | qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); |
| 100 | |||
| 101 | extern int | ||
| 102 | qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); | ||
| 103 | 101 | ||
| 104 | extern int | 102 | extern int |
| 105 | qla2x00_execute_fw(scsi_qla_host_t *, uint32_t); | 103 | qla2x00_execute_fw(scsi_qla_host_t *, uint32_t); |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index cd6f7c3cfe68..d620a8e8a614 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
| @@ -538,6 +538,7 @@ qla2x00_rff_id(scsi_qla_host_t *ha) | |||
| 538 | ct_req->req.rff_id.port_id[1] = ha->d_id.b.area; | 538 | ct_req->req.rff_id.port_id[1] = ha->d_id.b.area; |
| 539 | ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa; | 539 | ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa; |
| 540 | 540 | ||
| 541 | ct_req->req.rff_id.fc4_feature = BIT_1; | ||
| 541 | ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ | 542 | ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ |
| 542 | 543 | ||
| 543 | /* Execute MS IOCB */ | 544 | /* Execute MS IOCB */ |
| @@ -1529,9 +1530,9 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | |||
| 1529 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); | 1530 | eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); |
| 1530 | eiter->len = __constant_cpu_to_be16(4 + 4); | 1531 | eiter->len = __constant_cpu_to_be16(4 + 4); |
| 1531 | if (IS_QLA25XX(ha)) | 1532 | if (IS_QLA25XX(ha)) |
| 1532 | eiter->a.sup_speed = __constant_cpu_to_be32(4); | ||
| 1533 | else if (IS_QLA24XX(ha)) | ||
| 1534 | eiter->a.sup_speed = __constant_cpu_to_be32(8); | 1533 | eiter->a.sup_speed = __constant_cpu_to_be32(8); |
| 1534 | else if (IS_QLA24XX(ha)) | ||
| 1535 | eiter->a.sup_speed = __constant_cpu_to_be32(4); | ||
| 1535 | else if (IS_QLA23XX(ha)) | 1536 | else if (IS_QLA23XX(ha)) |
| 1536 | eiter->a.sup_speed = __constant_cpu_to_be32(2); | 1537 | eiter->a.sup_speed = __constant_cpu_to_be32(2); |
| 1537 | else | 1538 | else |
| @@ -1553,9 +1554,6 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) | |||
| 1553 | eiter->a.cur_speed = __constant_cpu_to_be32(2); | 1554 | eiter->a.cur_speed = __constant_cpu_to_be32(2); |
| 1554 | break; | 1555 | break; |
| 1555 | case 3: | 1556 | case 3: |
| 1556 | eiter->a.cur_speed = __constant_cpu_to_be32(8); | ||
| 1557 | break; | ||
| 1558 | case 4: | ||
| 1559 | eiter->a.cur_speed = __constant_cpu_to_be32(4); | 1557 | eiter->a.cur_speed = __constant_cpu_to_be32(4); |
| 1560 | break; | 1558 | break; |
| 1561 | } | 1559 | } |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7d973bd9022b..a91fea69ad63 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
| @@ -1014,11 +1014,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha) | |||
| 1014 | int rval; | 1014 | int rval; |
| 1015 | 1015 | ||
| 1016 | /* Update Serial Link options. */ | 1016 | /* Update Serial Link options. */ |
| 1017 | if ((ha->fw_seriallink_options24[0] & BIT_0) == 0) | 1017 | if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) |
| 1018 | return; | 1018 | return; |
| 1019 | 1019 | ||
| 1020 | rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1], | 1020 | rval = qla2x00_set_serdes_params(ha, |
| 1021 | ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]); | 1021 | le16_to_cpu(ha->fw_seriallink_options24[1]), |
| 1022 | le16_to_cpu(ha->fw_seriallink_options24[2]), | ||
| 1023 | le16_to_cpu(ha->fw_seriallink_options24[3])); | ||
| 1022 | if (rval != QLA_SUCCESS) { | 1024 | if (rval != QLA_SUCCESS) { |
| 1023 | qla_printk(KERN_WARNING, ha, | 1025 | qla_printk(KERN_WARNING, ha, |
| 1024 | "Unable to update Serial Link options (%x).\n", rval); | 1026 | "Unable to update Serial Link options (%x).\n", rval); |
| @@ -1939,6 +1941,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
| 1939 | "information -- get_port_database=%x, " | 1941 | "information -- get_port_database=%x, " |
| 1940 | "loop_id=0x%04x\n", | 1942 | "loop_id=0x%04x\n", |
| 1941 | ha->host_no, rval2, new_fcport->loop_id)); | 1943 | ha->host_no, rval2, new_fcport->loop_id)); |
| 1944 | DEBUG2(printk("scsi(%ld): Scheduling resync...\n", | ||
| 1945 | ha->host_no)); | ||
| 1946 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | ||
| 1942 | continue; | 1947 | continue; |
| 1943 | } | 1948 | } |
| 1944 | 1949 | ||
| @@ -2648,7 +2653,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha) | |||
| 2648 | 2653 | ||
| 2649 | switch (format) { | 2654 | switch (format) { |
| 2650 | case 0: | 2655 | case 0: |
| 2651 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && | 2656 | if (ql2xprocessrscn && |
| 2657 | !IS_QLA2100(ha) && !IS_QLA2200(ha) && | ||
| 2652 | !IS_QLA6312(ha) && !IS_QLA6322(ha) && | 2658 | !IS_QLA6312(ha) && !IS_QLA6322(ha) && |
| 2653 | !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && | 2659 | !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && |
| 2654 | ha->flags.init_done) { | 2660 | ha->flags.init_done) { |
| @@ -3402,6 +3408,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
| 3402 | ha->node_name = icb->node_name; | 3408 | ha->node_name = icb->node_name; |
| 3403 | ha->port_name = icb->port_name; | 3409 | ha->port_name = icb->port_name; |
| 3404 | 3410 | ||
| 3411 | icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); | ||
| 3412 | |||
| 3405 | ha->retry_count = le16_to_cpu(nv->login_retry_count); | 3413 | ha->retry_count = le16_to_cpu(nv->login_retry_count); |
| 3406 | 3414 | ||
| 3407 | /* Set minimum login_timeout to 4 seconds. */ | 3415 | /* Set minimum login_timeout to 4 seconds. */ |
| @@ -3667,8 +3675,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
| 3667 | for (i = 0; i < dlen; i++) | 3675 | for (i = 0; i < dlen; i++) |
| 3668 | dcode[i] = swab32(dcode[i]); | 3676 | dcode[i] = swab32(dcode[i]); |
| 3669 | 3677 | ||
| 3670 | rval = qla2x00_load_ram_ext(ha, ha->request_dma, | 3678 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, |
| 3671 | risc_addr, dlen); | 3679 | dlen); |
| 3672 | if (rval) { | 3680 | if (rval) { |
| 3673 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " | 3681 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " |
| 3674 | "segment %d of firmware\n", ha->host_no, | 3682 | "segment %d of firmware\n", ha->host_no, |
| @@ -3868,8 +3876,8 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
| 3868 | for (i = 0; i < dlen; i++) | 3876 | for (i = 0; i < dlen; i++) |
| 3869 | dcode[i] = swab32(fwcode[i]); | 3877 | dcode[i] = swab32(fwcode[i]); |
| 3870 | 3878 | ||
| 3871 | rval = qla2x00_load_ram_ext(ha, ha->request_dma, | 3879 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, |
| 3872 | risc_addr, dlen); | 3880 | dlen); |
| 3873 | if (rval) { | 3881 | if (rval) { |
| 3874 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " | 3882 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " |
| 3875 | "segment %d of firmware\n", ha->host_no, | 3883 | "segment %d of firmware\n", ha->host_no, |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5181d966fecb..f63af081d4ff 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
| @@ -519,7 +519,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
| 519 | * us, create a new entry in our rscn fcports list and handle | 519 | * us, create a new entry in our rscn fcports list and handle |
| 520 | * the event like an RSCN. | 520 | * the event like an RSCN. |
| 521 | */ | 521 | */ |
| 522 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && | 522 | if (ql2xprocessrscn && |
| 523 | !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && | ||
| 523 | !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && | 524 | !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && |
| 524 | ha->flags.init_done && mb[1] != 0xffff && | 525 | ha->flags.init_done && mb[1] != 0xffff && |
| 525 | ((ha->operating_mode == P2P && mb[1] != 0) || | 526 | ((ha->operating_mode == P2P && mb[1] != 0) || |
| @@ -963,15 +964,16 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
| 963 | break; | 964 | break; |
| 964 | 965 | ||
| 965 | case CS_DATA_UNDERRUN: | 966 | case CS_DATA_UNDERRUN: |
| 966 | DEBUG2(printk(KERN_INFO | ||
| 967 | "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n", | ||
| 968 | ha->host_no, cp->device->id, cp->device->lun, comp_status, | ||
| 969 | scsi_status)); | ||
| 970 | |||
| 971 | resid = resid_len; | 967 | resid = resid_len; |
| 972 | if (scsi_status & SS_RESIDUAL_UNDER) { | 968 | if (scsi_status & SS_RESIDUAL_UNDER) { |
| 973 | cp->resid = resid; | 969 | cp->resid = resid; |
| 974 | CMD_RESID_LEN(cp) = resid; | 970 | CMD_RESID_LEN(cp) = resid; |
| 971 | } else { | ||
| 972 | DEBUG2(printk(KERN_INFO | ||
| 973 | "scsi(%ld:%d:%d) UNDERRUN status detected " | ||
| 974 | "0x%x-0x%x.\n", ha->host_no, cp->device->id, | ||
| 975 | cp->device->lun, comp_status, scsi_status)); | ||
| 976 | |||
| 975 | } | 977 | } |
| 976 | 978 | ||
| 977 | /* | 979 | /* |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 9746cd1e664b..3099b379de9d 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
| @@ -196,7 +196,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
| 196 | /* Check for pending interrupts. */ | 196 | /* Check for pending interrupts. */ |
| 197 | qla2x00_poll(ha); | 197 | qla2x00_poll(ha); |
| 198 | 198 | ||
| 199 | udelay(10); /* v4.27 */ | 199 | if (command != MBC_LOAD_RISC_RAM_EXTENDED && |
| 200 | !ha->flags.mbox_int) | ||
| 201 | msleep(10); | ||
| 200 | } /* while */ | 202 | } /* while */ |
| 201 | } | 203 | } |
| 202 | 204 | ||
| @@ -325,113 +327,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
| 325 | return rval; | 327 | return rval; |
| 326 | } | 328 | } |
| 327 | 329 | ||
| 328 | /* | ||
| 329 | * qla2x00_load_ram | ||
| 330 | * Load adapter RAM using DMA. | ||
| 331 | * | ||
| 332 | * Input: | ||
| 333 | * ha = adapter block pointer. | ||
| 334 | * | ||
| 335 | * Returns: | ||
| 336 | * qla2x00 local function return status code. | ||
| 337 | * | ||
| 338 | * Context: | ||
| 339 | * Kernel context. | ||
| 340 | */ | ||
| 341 | int | 330 | int |
| 342 | qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr, | 331 | qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, |
| 343 | uint16_t risc_code_size) | 332 | uint32_t risc_code_size) |
| 344 | { | 333 | { |
| 345 | int rval; | 334 | int rval; |
| 346 | mbx_cmd_t mc; | 335 | mbx_cmd_t mc; |
| 347 | mbx_cmd_t *mcp = &mc; | 336 | mbx_cmd_t *mcp = &mc; |
| 348 | uint32_t req_len; | ||
| 349 | dma_addr_t nml_dma; | ||
| 350 | uint32_t nml_len; | ||
| 351 | uint32_t normalized; | ||
| 352 | |||
| 353 | DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n", | ||
| 354 | ha->host_no);) | ||
| 355 | 337 | ||
| 356 | req_len = risc_code_size; | 338 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); |
| 357 | nml_dma = 0; | ||
| 358 | nml_len = 0; | ||
| 359 | |||
| 360 | normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma, | ||
| 361 | &nml_len); | ||
| 362 | |||
| 363 | /* Load first segment */ | ||
| 364 | mcp->mb[0] = MBC_LOAD_RISC_RAM; | ||
| 365 | mcp->mb[1] = risc_addr; | ||
| 366 | mcp->mb[2] = MSW(req_dma); | ||
| 367 | mcp->mb[3] = LSW(req_dma); | ||
| 368 | mcp->mb[4] = (uint16_t)req_len; | ||
| 369 | mcp->mb[6] = MSW(MSD(req_dma)); | ||
| 370 | mcp->mb[7] = LSW(MSD(req_dma)); | ||
| 371 | mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
| 372 | mcp->in_mb = MBX_0; | ||
| 373 | mcp->tov = 30; | ||
| 374 | mcp->flags = 0; | ||
| 375 | rval = qla2x00_mailbox_command(ha, mcp); | ||
| 376 | |||
| 377 | /* Load second segment - if necessary */ | ||
| 378 | if (normalized && (rval == QLA_SUCCESS)) { | ||
| 379 | mcp->mb[0] = MBC_LOAD_RISC_RAM; | ||
| 380 | mcp->mb[1] = risc_addr + (uint16_t)req_len; | ||
| 381 | mcp->mb[2] = MSW(nml_dma); | ||
| 382 | mcp->mb[3] = LSW(nml_dma); | ||
| 383 | mcp->mb[4] = (uint16_t)nml_len; | ||
| 384 | mcp->mb[6] = MSW(MSD(nml_dma)); | ||
| 385 | mcp->mb[7] = LSW(MSD(nml_dma)); | ||
| 386 | mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
| 387 | mcp->in_mb = MBX_0; | ||
| 388 | mcp->tov = 30; | ||
| 389 | mcp->flags = 0; | ||
| 390 | rval = qla2x00_mailbox_command(ha, mcp); | ||
| 391 | } | ||
| 392 | 339 | ||
| 393 | if (rval == QLA_SUCCESS) { | 340 | if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
| 394 | /* Empty */ | 341 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; |
| 395 | DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);) | 342 | mcp->mb[8] = MSW(risc_addr); |
| 343 | mcp->out_mb = MBX_8|MBX_0; | ||
| 396 | } else { | 344 | } else { |
| 397 | /* Empty */ | 345 | mcp->mb[0] = MBC_LOAD_RISC_RAM; |
| 398 | DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x " | 346 | mcp->out_mb = MBX_0; |
| 399 | "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);) | ||
| 400 | } | 347 | } |
| 401 | return rval; | ||
| 402 | } | ||
| 403 | |||
| 404 | /* | ||
| 405 | * qla2x00_load_ram_ext | ||
| 406 | * Load adapter extended RAM using DMA. | ||
| 407 | * | ||
| 408 | * Input: | ||
| 409 | * ha = adapter block pointer. | ||
| 410 | * | ||
| 411 | * Returns: | ||
| 412 | * qla2x00 local function return status code. | ||
| 413 | * | ||
| 414 | * Context: | ||
| 415 | * Kernel context. | ||
| 416 | */ | ||
| 417 | int | ||
| 418 | qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma, | ||
| 419 | uint32_t risc_addr, uint32_t risc_code_size) | ||
| 420 | { | ||
| 421 | int rval; | ||
| 422 | mbx_cmd_t mc; | ||
| 423 | mbx_cmd_t *mcp = &mc; | ||
| 424 | |||
| 425 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
| 426 | |||
| 427 | mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; | ||
| 428 | mcp->mb[1] = LSW(risc_addr); | 348 | mcp->mb[1] = LSW(risc_addr); |
| 429 | mcp->mb[2] = MSW(req_dma); | 349 | mcp->mb[2] = MSW(req_dma); |
| 430 | mcp->mb[3] = LSW(req_dma); | 350 | mcp->mb[3] = LSW(req_dma); |
| 431 | mcp->mb[6] = MSW(MSD(req_dma)); | 351 | mcp->mb[6] = MSW(MSD(req_dma)); |
| 432 | mcp->mb[7] = LSW(MSD(req_dma)); | 352 | mcp->mb[7] = LSW(MSD(req_dma)); |
| 433 | mcp->mb[8] = MSW(risc_addr); | 353 | mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; |
| 434 | mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | ||
| 435 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | 354 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
| 436 | mcp->mb[4] = MSW(risc_code_size); | 355 | mcp->mb[4] = MSW(risc_code_size); |
| 437 | mcp->mb[5] = LSW(risc_code_size); | 356 | mcp->mb[5] = LSW(risc_code_size); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 24304300d7b5..4916847d84ec 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -71,6 +71,12 @@ MODULE_PARM_DESC(ql2xfdmienable, | |||
| 71 | "Enables FDMI registratons " | 71 | "Enables FDMI registratons " |
| 72 | "Default is 0 - no FDMI. 1 - perfom FDMI."); | 72 | "Default is 0 - no FDMI. 1 - perfom FDMI."); |
| 73 | 73 | ||
| 74 | int ql2xprocessrscn; | ||
| 75 | module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR); | ||
| 76 | MODULE_PARM_DESC(ql2xprocessrscn, | ||
| 77 | "Option to enable port RSCN handling via a series of less" | ||
| 78 | "fabric intrusive ADISCs and PLOGIs."); | ||
| 79 | |||
| 74 | /* | 80 | /* |
| 75 | * SCSI host template entry points | 81 | * SCSI host template entry points |
| 76 | */ | 82 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index d54d2a99c3d3..f4d755a643e4 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
| @@ -573,6 +573,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
| 573 | } | 573 | } |
| 574 | } while (0); | 574 | } while (0); |
| 575 | 575 | ||
| 576 | /* Enable flash write-protection. */ | ||
| 577 | qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); | ||
| 578 | |||
| 576 | /* Disable flash write. */ | 579 | /* Disable flash write. */ |
| 577 | WRT_REG_DWORD(®->ctrl_status, | 580 | WRT_REG_DWORD(®->ctrl_status, |
| 578 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 581 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index f7937f7f9c68..d537192a1edb 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | /* | 7 | /* |
| 8 | * Driver version | 8 | * Driver version |
| 9 | */ | 9 | */ |
| 10 | #define QLA2XXX_VERSION "8.01.03-k" | 10 | #define QLA2XXX_VERSION "8.01.04-k" |
| 11 | 11 | ||
| 12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
| 13 | #define QLA_DRIVER_MINOR_VER 1 | 13 | #define QLA_DRIVER_MINOR_VER 1 |
| 14 | #define QLA_DRIVER_PATCH_VER 3 | 14 | #define QLA_DRIVER_PATCH_VER 4 |
| 15 | #define QLA_DRIVER_BETA_VER 0 | 15 | #define QLA_DRIVER_BETA_VER 0 |
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 5ec5f44602ac..50c398aab557 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c | |||
| @@ -148,9 +148,11 @@ static struct { | |||
| 148 | { RAID_LEVEL_LINEAR, "linear" }, | 148 | { RAID_LEVEL_LINEAR, "linear" }, |
| 149 | { RAID_LEVEL_0, "raid0" }, | 149 | { RAID_LEVEL_0, "raid0" }, |
| 150 | { RAID_LEVEL_1, "raid1" }, | 150 | { RAID_LEVEL_1, "raid1" }, |
| 151 | { RAID_LEVEL_10, "raid10" }, | ||
| 151 | { RAID_LEVEL_3, "raid3" }, | 152 | { RAID_LEVEL_3, "raid3" }, |
| 152 | { RAID_LEVEL_4, "raid4" }, | 153 | { RAID_LEVEL_4, "raid4" }, |
| 153 | { RAID_LEVEL_5, "raid5" }, | 154 | { RAID_LEVEL_5, "raid5" }, |
| 155 | { RAID_LEVEL_50, "raid50" }, | ||
| 154 | { RAID_LEVEL_6, "raid6" }, | 156 | { RAID_LEVEL_6, "raid6" }, |
| 155 | }; | 157 | }; |
| 156 | 158 | ||
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ee5f4dfdab14..245ca99a641e 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | #include <linux/interrupt.h> | 55 | #include <linux/interrupt.h> |
| 56 | #include <linux/notifier.h> | 56 | #include <linux/notifier.h> |
| 57 | #include <linux/cpu.h> | 57 | #include <linux/cpu.h> |
| 58 | #include <linux/mutex.h> | ||
| 58 | 59 | ||
| 59 | #include <scsi/scsi.h> | 60 | #include <scsi/scsi.h> |
| 60 | #include <scsi/scsi_cmnd.h> | 61 | #include <scsi/scsi_cmnd.h> |
| @@ -209,7 +210,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { | |||
| 209 | .gfp_mask = __GFP_DMA, | 210 | .gfp_mask = __GFP_DMA, |
| 210 | }; | 211 | }; |
| 211 | 212 | ||
| 212 | static DECLARE_MUTEX(host_cmd_pool_mutex); | 213 | static DEFINE_MUTEX(host_cmd_pool_mutex); |
| 213 | 214 | ||
| 214 | static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, | 215 | static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, |
| 215 | gfp_t gfp_mask) | 216 | gfp_t gfp_mask) |
| @@ -330,7 +331,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) | |||
| 330 | * Select a command slab for this host and create it if not | 331 | * Select a command slab for this host and create it if not |
| 331 | * yet existant. | 332 | * yet existant. |
| 332 | */ | 333 | */ |
| 333 | down(&host_cmd_pool_mutex); | 334 | mutex_lock(&host_cmd_pool_mutex); |
| 334 | pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool); | 335 | pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool); |
| 335 | if (!pool->users) { | 336 | if (!pool->users) { |
| 336 | pool->slab = kmem_cache_create(pool->name, | 337 | pool->slab = kmem_cache_create(pool->name, |
| @@ -342,7 +343,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) | |||
| 342 | 343 | ||
| 343 | pool->users++; | 344 | pool->users++; |
| 344 | shost->cmd_pool = pool; | 345 | shost->cmd_pool = pool; |
| 345 | up(&host_cmd_pool_mutex); | 346 | mutex_unlock(&host_cmd_pool_mutex); |
| 346 | 347 | ||
| 347 | /* | 348 | /* |
| 348 | * Get one backup command for this host. | 349 | * Get one backup command for this host. |
| @@ -359,7 +360,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) | |||
| 359 | kmem_cache_destroy(pool->slab); | 360 | kmem_cache_destroy(pool->slab); |
| 360 | return -ENOMEM; | 361 | return -ENOMEM; |
| 361 | fail: | 362 | fail: |
| 362 | up(&host_cmd_pool_mutex); | 363 | mutex_unlock(&host_cmd_pool_mutex); |
| 363 | return -ENOMEM; | 364 | return -ENOMEM; |
| 364 | 365 | ||
| 365 | } | 366 | } |
| @@ -381,10 +382,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost) | |||
| 381 | kmem_cache_free(shost->cmd_pool->slab, cmd); | 382 | kmem_cache_free(shost->cmd_pool->slab, cmd); |
| 382 | } | 383 | } |
| 383 | 384 | ||
| 384 | down(&host_cmd_pool_mutex); | 385 | mutex_lock(&host_cmd_pool_mutex); |
| 385 | if (!--shost->cmd_pool->users) | 386 | if (!--shost->cmd_pool->users) |
| 386 | kmem_cache_destroy(shost->cmd_pool->slab); | 387 | kmem_cache_destroy(shost->cmd_pool->slab); |
| 387 | up(&host_cmd_pool_mutex); | 388 | mutex_unlock(&host_cmd_pool_mutex); |
| 388 | } | 389 | } |
| 389 | 390 | ||
| 390 | #ifdef CONFIG_SCSI_LOGGING | 391 | #ifdef CONFIG_SCSI_LOGGING |
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 3ded9daaf4a0..0e529f8171c4 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
| @@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus; | |||
| 221 | static struct device_driver sdebug_driverfs_driver = { | 221 | static struct device_driver sdebug_driverfs_driver = { |
| 222 | .name = sdebug_proc_name, | 222 | .name = sdebug_proc_name, |
| 223 | .bus = &pseudo_lld_bus, | 223 | .bus = &pseudo_lld_bus, |
| 224 | .probe = sdebug_driver_probe, | ||
| 225 | .remove = sdebug_driver_remove, | ||
| 226 | }; | 224 | }; |
| 227 | 225 | ||
| 228 | static const int check_condition_result = | 226 | static const int check_condition_result = |
| @@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct device *dev, | |||
| 1796 | static struct bus_type pseudo_lld_bus = { | 1794 | static struct bus_type pseudo_lld_bus = { |
| 1797 | .name = "pseudo", | 1795 | .name = "pseudo", |
| 1798 | .match = pseudo_lld_bus_match, | 1796 | .match = pseudo_lld_bus_match, |
| 1797 | .probe = sdebug_driver_probe, | ||
| 1798 | .remove = sdebug_driver_remove, | ||
| 1799 | }; | 1799 | }; |
| 1800 | 1800 | ||
| 1801 | static void sdebug_release_adapter(struct device * dev) | 1801 | static void sdebug_release_adapter(struct device * dev) |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 00c9bf383e23..3574ba935af8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -1212,7 +1212,7 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, | |||
| 1212 | return -EOPNOTSUPP; | 1212 | return -EOPNOTSUPP; |
| 1213 | } | 1213 | } |
| 1214 | 1214 | ||
| 1215 | static void scsi_generic_done(struct scsi_cmnd *cmd) | 1215 | static void scsi_blk_pc_done(struct scsi_cmnd *cmd) |
| 1216 | { | 1216 | { |
| 1217 | BUG_ON(!blk_pc_request(cmd->request)); | 1217 | BUG_ON(!blk_pc_request(cmd->request)); |
| 1218 | /* | 1218 | /* |
| @@ -1224,7 +1224,7 @@ static void scsi_generic_done(struct scsi_cmnd *cmd) | |||
| 1224 | scsi_io_completion(cmd, cmd->bufflen, 0); | 1224 | scsi_io_completion(cmd, cmd->bufflen, 0); |
| 1225 | } | 1225 | } |
| 1226 | 1226 | ||
| 1227 | void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) | 1227 | static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) |
| 1228 | { | 1228 | { |
| 1229 | struct request *req = cmd->request; | 1229 | struct request *req = cmd->request; |
| 1230 | 1230 | ||
| @@ -1241,8 +1241,8 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) | |||
| 1241 | cmd->transfersize = req->data_len; | 1241 | cmd->transfersize = req->data_len; |
| 1242 | cmd->allowed = req->retries; | 1242 | cmd->allowed = req->retries; |
| 1243 | cmd->timeout_per_command = req->timeout; | 1243 | cmd->timeout_per_command = req->timeout; |
| 1244 | cmd->done = scsi_blk_pc_done; | ||
| 1244 | } | 1245 | } |
| 1245 | EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd); | ||
| 1246 | 1246 | ||
| 1247 | static int scsi_prep_fn(struct request_queue *q, struct request *req) | 1247 | static int scsi_prep_fn(struct request_queue *q, struct request *req) |
| 1248 | { | 1248 | { |
| @@ -1339,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1339 | * happening now. | 1339 | * happening now. |
| 1340 | */ | 1340 | */ |
| 1341 | if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { | 1341 | if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { |
| 1342 | struct scsi_driver *drv; | ||
| 1343 | int ret; | 1342 | int ret; |
| 1344 | 1343 | ||
| 1345 | /* | 1344 | /* |
| @@ -1371,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1371 | /* | 1370 | /* |
| 1372 | * Initialize the actual SCSI command for this request. | 1371 | * Initialize the actual SCSI command for this request. |
| 1373 | */ | 1372 | */ |
| 1374 | if (req->rq_disk) { | 1373 | if (req->flags & REQ_BLOCK_PC) { |
| 1374 | scsi_setup_blk_pc_cmnd(cmd); | ||
| 1375 | } else if (req->rq_disk) { | ||
| 1376 | struct scsi_driver *drv; | ||
| 1377 | |||
| 1375 | drv = *(struct scsi_driver **)req->rq_disk->private_data; | 1378 | drv = *(struct scsi_driver **)req->rq_disk->private_data; |
| 1376 | if (unlikely(!drv->init_command(cmd))) { | 1379 | if (unlikely(!drv->init_command(cmd))) { |
| 1377 | scsi_release_buffers(cmd); | 1380 | scsi_release_buffers(cmd); |
| 1378 | scsi_put_command(cmd); | 1381 | scsi_put_command(cmd); |
| 1379 | goto kill; | 1382 | goto kill; |
| 1380 | } | 1383 | } |
| 1381 | } else { | ||
| 1382 | scsi_setup_blk_pc_cmnd(cmd); | ||
| 1383 | cmd->done = scsi_generic_done; | ||
| 1384 | } | 1384 | } |
| 1385 | } | 1385 | } |
| 1386 | 1386 | ||
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 14a6198cb8d2..27c48274e8cb 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
| @@ -26,12 +26,6 @@ struct Scsi_Host; | |||
| 26 | #define SCSI_SENSE_VALID(scmd) \ | 26 | #define SCSI_SENSE_VALID(scmd) \ |
| 27 | (((scmd)->sense_buffer[0] & 0x70) == 0x70) | 27 | (((scmd)->sense_buffer[0] & 0x70) == 0x70) |
| 28 | 28 | ||
| 29 | /* | ||
| 30 | * Special value for scanning to specify scanning or rescanning of all | ||
| 31 | * possible channels, (target) ids, or luns on a given shost. | ||
| 32 | */ | ||
| 33 | #define SCAN_WILD_CARD ~0 | ||
| 34 | |||
| 35 | /* hosts.c */ | 29 | /* hosts.c */ |
| 36 | extern int scsi_init_hosts(void); | 30 | extern int scsi_init_hosts(void); |
| 37 | extern void scsi_exit_hosts(void); | 31 | extern void scsi_exit_hosts(void); |
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index a50958b1b6ee..07be62bbaaea 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
| @@ -25,11 +25,13 @@ | |||
| 25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
| 26 | #include <linux/blkdev.h> | 26 | #include <linux/blkdev.h> |
| 27 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
| 28 | #include <linux/mutex.h> | ||
| 28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
| 29 | 30 | ||
| 30 | #include <scsi/scsi.h> | 31 | #include <scsi/scsi.h> |
| 31 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
| 32 | #include <scsi/scsi_host.h> | 33 | #include <scsi/scsi_host.h> |
| 34 | #include <scsi/scsi_transport.h> | ||
| 33 | 35 | ||
| 34 | #include "scsi_priv.h" | 36 | #include "scsi_priv.h" |
| 35 | #include "scsi_logging.h" | 37 | #include "scsi_logging.h" |
| @@ -41,7 +43,7 @@ | |||
| 41 | static struct proc_dir_entry *proc_scsi; | 43 | static struct proc_dir_entry *proc_scsi; |
| 42 | 44 | ||
| 43 | /* Protect sht->present and sht->proc_dir */ | 45 | /* Protect sht->present and sht->proc_dir */ |
| 44 | static DECLARE_MUTEX(global_host_template_sem); | 46 | static DEFINE_MUTEX(global_host_template_mutex); |
| 45 | 47 | ||
| 46 | static int proc_scsi_read(char *buffer, char **start, off_t offset, | 48 | static int proc_scsi_read(char *buffer, char **start, off_t offset, |
| 47 | int length, int *eof, void *data) | 49 | int length, int *eof, void *data) |
| @@ -83,7 +85,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) | |||
| 83 | if (!sht->proc_info) | 85 | if (!sht->proc_info) |
| 84 | return; | 86 | return; |
| 85 | 87 | ||
| 86 | down(&global_host_template_sem); | 88 | mutex_lock(&global_host_template_mutex); |
| 87 | if (!sht->present++) { | 89 | if (!sht->present++) { |
| 88 | sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); | 90 | sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); |
| 89 | if (!sht->proc_dir) | 91 | if (!sht->proc_dir) |
| @@ -92,7 +94,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) | |||
| 92 | else | 94 | else |
| 93 | sht->proc_dir->owner = sht->module; | 95 | sht->proc_dir->owner = sht->module; |
| 94 | } | 96 | } |
| 95 | up(&global_host_template_sem); | 97 | mutex_unlock(&global_host_template_mutex); |
| 96 | } | 98 | } |
| 97 | 99 | ||
| 98 | void scsi_proc_hostdir_rm(struct scsi_host_template *sht) | 100 | void scsi_proc_hostdir_rm(struct scsi_host_template *sht) |
| @@ -100,12 +102,12 @@ void scsi_proc_hostdir_rm(struct scsi_host_template *sht) | |||
| 100 | if (!sht->proc_info) | 102 | if (!sht->proc_info) |
| 101 | return; | 103 | return; |
| 102 | 104 | ||
| 103 | down(&global_host_template_sem); | 105 | mutex_lock(&global_host_template_mutex); |
| 104 | if (!--sht->present && sht->proc_dir) { | 106 | if (!--sht->present && sht->proc_dir) { |
| 105 | remove_proc_entry(sht->proc_name, proc_scsi); | 107 | remove_proc_entry(sht->proc_name, proc_scsi); |
| 106 | sht->proc_dir = NULL; | 108 | sht->proc_dir = NULL; |
| 107 | } | 109 | } |
| 108 | up(&global_host_template_sem); | 110 | mutex_unlock(&global_host_template_mutex); |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 111 | void scsi_proc_host_add(struct Scsi_Host *shost) | 113 | void scsi_proc_host_add(struct Scsi_Host *shost) |
| @@ -199,7 +201,10 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) | |||
| 199 | if (IS_ERR(shost)) | 201 | if (IS_ERR(shost)) |
| 200 | return PTR_ERR(shost); | 202 | return PTR_ERR(shost); |
| 201 | 203 | ||
| 202 | error = scsi_scan_host_selected(shost, channel, id, lun, 1); | 204 | if (shost->transportt->user_scan) |
| 205 | error = shost->transportt->user_scan(shost, channel, id, lun); | ||
| 206 | else | ||
| 207 | error = scsi_scan_host_selected(shost, channel, id, lun, 1); | ||
| 203 | scsi_host_put(shost); | 208 | scsi_host_put(shost); |
| 204 | return error; | 209 | return error; |
| 205 | } | 210 | } |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 05ebb9cef961..752fb5da3de4 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -334,19 +334,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
| 334 | struct scsi_target *starget; | 334 | struct scsi_target *starget; |
| 335 | struct scsi_target *found_target; | 335 | struct scsi_target *found_target; |
| 336 | 336 | ||
| 337 | /* | ||
| 338 | * Obtain the real parent from the transport. The transport | ||
| 339 | * is allowed to fail (no error) if there is nothing at that | ||
| 340 | * target id. | ||
| 341 | */ | ||
| 342 | if (shost->transportt->target_parent) { | ||
| 343 | spin_lock_irqsave(shost->host_lock, flags); | ||
| 344 | parent = shost->transportt->target_parent(shost, channel, id); | ||
| 345 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 346 | if (!parent) | ||
| 347 | return NULL; | ||
| 348 | } | ||
| 349 | |||
| 350 | starget = kmalloc(size, GFP_KERNEL); | 337 | starget = kmalloc(size, GFP_KERNEL); |
| 351 | if (!starget) { | 338 | if (!starget) { |
| 352 | printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); | 339 | printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); |
| @@ -1283,20 +1270,21 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
| 1283 | struct scsi_device *sdev; | 1270 | struct scsi_device *sdev; |
| 1284 | struct device *parent = &shost->shost_gendev; | 1271 | struct device *parent = &shost->shost_gendev; |
| 1285 | int res; | 1272 | int res; |
| 1286 | struct scsi_target *starget = scsi_alloc_target(parent, channel, id); | 1273 | struct scsi_target *starget; |
| 1287 | 1274 | ||
| 1275 | starget = scsi_alloc_target(parent, channel, id); | ||
| 1288 | if (!starget) | 1276 | if (!starget) |
| 1289 | return ERR_PTR(-ENOMEM); | 1277 | return ERR_PTR(-ENOMEM); |
| 1290 | 1278 | ||
| 1291 | get_device(&starget->dev); | 1279 | get_device(&starget->dev); |
| 1292 | down(&shost->scan_mutex); | 1280 | mutex_lock(&shost->scan_mutex); |
| 1293 | if (scsi_host_scan_allowed(shost)) { | 1281 | if (scsi_host_scan_allowed(shost)) { |
| 1294 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, | 1282 | res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, |
| 1295 | hostdata); | 1283 | hostdata); |
| 1296 | if (res != SCSI_SCAN_LUN_PRESENT) | 1284 | if (res != SCSI_SCAN_LUN_PRESENT) |
| 1297 | sdev = ERR_PTR(-ENODEV); | 1285 | sdev = ERR_PTR(-ENODEV); |
| 1298 | } | 1286 | } |
| 1299 | up(&shost->scan_mutex); | 1287 | mutex_unlock(&shost->scan_mutex); |
| 1300 | scsi_target_reap(starget); | 1288 | scsi_target_reap(starget); |
| 1301 | put_device(&starget->dev); | 1289 | put_device(&starget->dev); |
| 1302 | 1290 | ||
| @@ -1404,10 +1392,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
| 1404 | { | 1392 | { |
| 1405 | struct Scsi_Host *shost = dev_to_shost(parent); | 1393 | struct Scsi_Host *shost = dev_to_shost(parent); |
| 1406 | 1394 | ||
| 1407 | down(&shost->scan_mutex); | 1395 | mutex_lock(&shost->scan_mutex); |
| 1408 | if (scsi_host_scan_allowed(shost)) | 1396 | if (scsi_host_scan_allowed(shost)) |
| 1409 | __scsi_scan_target(parent, channel, id, lun, rescan); | 1397 | __scsi_scan_target(parent, channel, id, lun, rescan); |
| 1410 | up(&shost->scan_mutex); | 1398 | mutex_unlock(&shost->scan_mutex); |
| 1411 | } | 1399 | } |
| 1412 | EXPORT_SYMBOL(scsi_scan_target); | 1400 | EXPORT_SYMBOL(scsi_scan_target); |
| 1413 | 1401 | ||
| @@ -1454,7 +1442,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
| 1454 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) | 1442 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) |
| 1455 | return -EINVAL; | 1443 | return -EINVAL; |
| 1456 | 1444 | ||
| 1457 | down(&shost->scan_mutex); | 1445 | mutex_lock(&shost->scan_mutex); |
| 1458 | if (scsi_host_scan_allowed(shost)) { | 1446 | if (scsi_host_scan_allowed(shost)) { |
| 1459 | if (channel == SCAN_WILD_CARD) | 1447 | if (channel == SCAN_WILD_CARD) |
| 1460 | for (channel = 0; channel <= shost->max_channel; | 1448 | for (channel = 0; channel <= shost->max_channel; |
| @@ -1464,7 +1452,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
| 1464 | else | 1452 | else |
| 1465 | scsi_scan_channel(shost, channel, id, lun, rescan); | 1453 | scsi_scan_channel(shost, channel, id, lun, rescan); |
| 1466 | } | 1454 | } |
| 1467 | up(&shost->scan_mutex); | 1455 | mutex_unlock(&shost->scan_mutex); |
| 1468 | 1456 | ||
| 1469 | return 0; | 1457 | return 0; |
| 1470 | } | 1458 | } |
| @@ -1522,7 +1510,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
| 1522 | struct scsi_device *sdev = NULL; | 1510 | struct scsi_device *sdev = NULL; |
| 1523 | struct scsi_target *starget; | 1511 | struct scsi_target *starget; |
| 1524 | 1512 | ||
| 1525 | down(&shost->scan_mutex); | 1513 | mutex_lock(&shost->scan_mutex); |
| 1526 | if (!scsi_host_scan_allowed(shost)) | 1514 | if (!scsi_host_scan_allowed(shost)) |
| 1527 | goto out; | 1515 | goto out; |
| 1528 | starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); | 1516 | starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); |
| @@ -1536,7 +1524,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
| 1536 | } | 1524 | } |
| 1537 | put_device(&starget->dev); | 1525 | put_device(&starget->dev); |
| 1538 | out: | 1526 | out: |
| 1539 | up(&shost->scan_mutex); | 1527 | mutex_unlock(&shost->scan_mutex); |
| 1540 | return sdev; | 1528 | return sdev; |
| 1541 | } | 1529 | } |
| 1542 | EXPORT_SYMBOL(scsi_get_host_dev); | 1530 | EXPORT_SYMBOL(scsi_get_host_dev); |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ea7f3a433572..a77b32deaf8f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -106,7 +106,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str) | |||
| 106 | return -EINVAL; | 106 | return -EINVAL; |
| 107 | if (check_set(&lun, s3)) | 107 | if (check_set(&lun, s3)) |
| 108 | return -EINVAL; | 108 | return -EINVAL; |
| 109 | res = scsi_scan_host_selected(shost, channel, id, lun, 1); | 109 | if (shost->transportt->user_scan) |
| 110 | res = shost->transportt->user_scan(shost, channel, id, lun); | ||
| 111 | else | ||
| 112 | res = scsi_scan_host_selected(shost, channel, id, lun, 1); | ||
| 110 | return res; | 113 | return res; |
| 111 | } | 114 | } |
| 112 | 115 | ||
| @@ -745,9 +748,9 @@ void scsi_remove_device(struct scsi_device *sdev) | |||
| 745 | { | 748 | { |
| 746 | struct Scsi_Host *shost = sdev->host; | 749 | struct Scsi_Host *shost = sdev->host; |
| 747 | 750 | ||
| 748 | down(&shost->scan_mutex); | 751 | mutex_lock(&shost->scan_mutex); |
| 749 | __scsi_remove_device(sdev); | 752 | __scsi_remove_device(sdev); |
| 750 | up(&shost->scan_mutex); | 753 | mutex_unlock(&shost->scan_mutex); |
| 751 | } | 754 | } |
| 752 | EXPORT_SYMBOL(scsi_remove_device); | 755 | EXPORT_SYMBOL(scsi_remove_device); |
| 753 | 756 | ||
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 685b997306cf..f2c9acf11bd0 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
| @@ -295,6 +295,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, | |||
| 295 | */ | 295 | */ |
| 296 | fc_host_node_name(shost) = -1; | 296 | fc_host_node_name(shost) = -1; |
| 297 | fc_host_port_name(shost) = -1; | 297 | fc_host_port_name(shost) = -1; |
| 298 | fc_host_permanent_port_name(shost) = -1; | ||
| 298 | fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED; | 299 | fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED; |
| 299 | memset(fc_host_supported_fc4s(shost), 0, | 300 | memset(fc_host_supported_fc4s(shost), 0, |
| 300 | sizeof(fc_host_supported_fc4s(shost))); | 301 | sizeof(fc_host_supported_fc4s(shost))); |
| @@ -795,6 +796,8 @@ static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO, | |||
| 795 | 796 | ||
| 796 | fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); | 797 | fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); |
| 797 | fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); | 798 | fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); |
| 799 | fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, | ||
| 800 | unsigned long long); | ||
| 798 | fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); | 801 | fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); |
| 799 | fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); | 802 | fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); |
| 800 | fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); | 803 | fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); |
| @@ -1090,17 +1093,23 @@ static int fc_rport_match(struct attribute_container *cont, | |||
| 1090 | /* | 1093 | /* |
| 1091 | * Must be called with shost->host_lock held | 1094 | * Must be called with shost->host_lock held |
| 1092 | */ | 1095 | */ |
| 1093 | static struct device *fc_target_parent(struct Scsi_Host *shost, | 1096 | static int fc_user_scan(struct Scsi_Host *shost, uint channel, |
| 1094 | int channel, uint id) | 1097 | uint id, uint lun) |
| 1095 | { | 1098 | { |
| 1096 | struct fc_rport *rport; | 1099 | struct fc_rport *rport; |
| 1097 | 1100 | ||
| 1098 | list_for_each_entry(rport, &fc_host_rports(shost), peers) | 1101 | list_for_each_entry(rport, &fc_host_rports(shost), peers) { |
| 1099 | if ((rport->channel == channel) && | 1102 | if (rport->scsi_target_id == -1) |
| 1100 | (rport->scsi_target_id == id)) | 1103 | continue; |
| 1101 | return &rport->dev; | ||
| 1102 | 1104 | ||
| 1103 | return NULL; | 1105 | if ((channel == SCAN_WILD_CARD || channel == rport->channel) && |
| 1106 | (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) { | ||
| 1107 | scsi_scan_target(&rport->dev, rport->channel, | ||
| 1108 | rport->scsi_target_id, lun, 1); | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | return 0; | ||
| 1104 | } | 1113 | } |
| 1105 | 1114 | ||
| 1106 | struct scsi_transport_template * | 1115 | struct scsi_transport_template * |
| @@ -1139,7 +1148,7 @@ fc_attach_transport(struct fc_function_template *ft) | |||
| 1139 | /* Transport uses the shost workq for scsi scanning */ | 1148 | /* Transport uses the shost workq for scsi scanning */ |
| 1140 | i->t.create_work_queue = 1; | 1149 | i->t.create_work_queue = 1; |
| 1141 | 1150 | ||
| 1142 | i->t.target_parent = fc_target_parent; | 1151 | i->t.user_scan = fc_user_scan; |
| 1143 | 1152 | ||
| 1144 | /* | 1153 | /* |
| 1145 | * Setup SCSI Target Attributes. | 1154 | * Setup SCSI Target Attributes. |
| @@ -1160,6 +1169,7 @@ fc_attach_transport(struct fc_function_template *ft) | |||
| 1160 | count=0; | 1169 | count=0; |
| 1161 | SETUP_HOST_ATTRIBUTE_RD(node_name); | 1170 | SETUP_HOST_ATTRIBUTE_RD(node_name); |
| 1162 | SETUP_HOST_ATTRIBUTE_RD(port_name); | 1171 | SETUP_HOST_ATTRIBUTE_RD(port_name); |
| 1172 | SETUP_HOST_ATTRIBUTE_RD(permanent_port_name); | ||
| 1163 | SETUP_HOST_ATTRIBUTE_RD(supported_classes); | 1173 | SETUP_HOST_ATTRIBUTE_RD(supported_classes); |
| 1164 | SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); | 1174 | SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); |
| 1165 | SETUP_HOST_ATTRIBUTE_RD(symbolic_name); | 1175 | SETUP_HOST_ATTRIBUTE_RD(symbolic_name); |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e08462d50c97..59a1c9d9d3bd 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
| @@ -21,11 +21,9 @@ | |||
| 21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 22 | */ | 22 | */ |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/string.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/mempool.h> | 24 | #include <linux/mempool.h> |
| 25 | #include <linux/mutex.h> | ||
| 27 | #include <net/tcp.h> | 26 | #include <net/tcp.h> |
| 28 | |||
| 29 | #include <scsi/scsi.h> | 27 | #include <scsi/scsi.h> |
| 30 | #include <scsi/scsi_host.h> | 28 | #include <scsi/scsi_host.h> |
| 31 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
| @@ -45,11 +43,6 @@ struct iscsi_internal { | |||
| 45 | */ | 43 | */ |
| 46 | struct list_head sessions; | 44 | struct list_head sessions; |
| 47 | /* | 45 | /* |
| 48 | * lock to serialize access to the sessions list which must | ||
| 49 | * be taken after the rx_queue_sema | ||
| 50 | */ | ||
| 51 | spinlock_t session_lock; | ||
| 52 | /* | ||
| 53 | * based on transport capabilities, at register time we set these | 46 | * based on transport capabilities, at register time we set these |
| 54 | * bits to tell the transport class it wants attributes displayed | 47 | * bits to tell the transport class it wants attributes displayed |
| 55 | * in sysfs or that it can support different iSCSI Data-Path | 48 | * in sysfs or that it can support different iSCSI Data-Path |
| @@ -70,7 +63,7 @@ struct iscsi_internal { | |||
| 70 | /* | 63 | /* |
| 71 | * list of registered transports and lock that must | 64 | * list of registered transports and lock that must |
| 72 | * be held while accessing list. The iscsi_transport_lock must | 65 | * be held while accessing list. The iscsi_transport_lock must |
| 73 | * be acquired after the rx_queue_sema. | 66 | * be acquired after the rx_queue_mutex. |
| 74 | */ | 67 | */ |
| 75 | static LIST_HEAD(iscsi_transports); | 68 | static LIST_HEAD(iscsi_transports); |
| 76 | static DEFINE_SPINLOCK(iscsi_transport_lock); | 69 | static DEFINE_SPINLOCK(iscsi_transport_lock); |
| @@ -145,7 +138,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, | |||
| 145 | 138 | ||
| 146 | static struct sock *nls; | 139 | static struct sock *nls; |
| 147 | static int daemon_pid; | 140 | static int daemon_pid; |
| 148 | static DECLARE_MUTEX(rx_queue_sema); | 141 | static DEFINE_MUTEX(rx_queue_mutex); |
| 149 | 142 | ||
| 150 | struct mempool_zone { | 143 | struct mempool_zone { |
| 151 | mempool_t *pool; | 144 | mempool_t *pool; |
| @@ -156,7 +149,7 @@ struct mempool_zone { | |||
| 156 | spinlock_t freelock; | 149 | spinlock_t freelock; |
| 157 | }; | 150 | }; |
| 158 | 151 | ||
| 159 | static struct mempool_zone z_reply; | 152 | static struct mempool_zone *z_reply; |
| 160 | 153 | ||
| 161 | /* | 154 | /* |
| 162 | * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time | 155 | * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time |
| @@ -171,50 +164,271 @@ static struct mempool_zone z_reply; | |||
| 171 | #define Z_MAX_ERROR 16 | 164 | #define Z_MAX_ERROR 16 |
| 172 | #define Z_HIWAT_ERROR 12 | 165 | #define Z_HIWAT_ERROR 12 |
| 173 | 166 | ||
| 174 | struct iscsi_if_conn { | 167 | static LIST_HEAD(connlist); |
| 175 | struct list_head conn_list; /* item in connlist */ | 168 | static DEFINE_SPINLOCK(connlock); |
| 176 | struct list_head session_list; /* item in session->connections */ | ||
| 177 | iscsi_connh_t connh; | ||
| 178 | int active; /* must be accessed with the connlock */ | ||
| 179 | struct Scsi_Host *host; /* originated shost */ | ||
| 180 | struct device dev; /* sysfs transport/container device */ | ||
| 181 | struct iscsi_transport *transport; | ||
| 182 | struct mempool_zone z_error; | ||
| 183 | struct mempool_zone z_pdu; | ||
| 184 | struct list_head freequeue; | ||
| 185 | }; | ||
| 186 | 169 | ||
| 187 | #define iscsi_dev_to_if_conn(_dev) \ | 170 | /* |
| 188 | container_of(_dev, struct iscsi_if_conn, dev) | 171 | * The following functions can be used by LLDs that allocate |
| 172 | * their own scsi_hosts or by software iscsi LLDs | ||
| 173 | */ | ||
| 174 | static void iscsi_session_release(struct device *dev) | ||
| 175 | { | ||
| 176 | struct iscsi_cls_session *session = iscsi_dev_to_session(dev); | ||
| 177 | struct iscsi_transport *transport = session->transport; | ||
| 178 | struct Scsi_Host *shost; | ||
| 189 | 179 | ||
| 190 | #define iscsi_cdev_to_if_conn(_cdev) \ | 180 | shost = iscsi_session_to_shost(session); |
| 191 | iscsi_dev_to_if_conn(_cdev->dev) | 181 | scsi_host_put(shost); |
| 182 | kfree(session); | ||
| 183 | module_put(transport->owner); | ||
| 184 | } | ||
| 192 | 185 | ||
| 193 | static LIST_HEAD(connlist); | 186 | static int iscsi_is_session_dev(const struct device *dev) |
| 194 | static DEFINE_SPINLOCK(connlock); | 187 | { |
| 188 | return dev->release == iscsi_session_release; | ||
| 189 | } | ||
| 195 | 190 | ||
| 196 | struct iscsi_if_session { | 191 | /** |
| 197 | struct list_head list; /* item in session_list */ | 192 | * iscsi_create_session - create iscsi class session |
| 198 | struct list_head connections; | 193 | * @shost: scsi host |
| 199 | iscsi_sessionh_t sessionh; | 194 | * @transport: iscsi transport |
| 200 | struct iscsi_transport *transport; | 195 | * |
| 201 | struct device dev; /* sysfs transport/container device */ | 196 | * This can be called from a LLD or iscsi_transport |
| 202 | }; | 197 | **/ |
| 198 | struct iscsi_cls_session * | ||
| 199 | iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) | ||
| 200 | { | ||
| 201 | struct iscsi_cls_session *session; | ||
| 202 | int err; | ||
| 203 | |||
| 204 | if (!try_module_get(transport->owner)) | ||
| 205 | return NULL; | ||
| 206 | |||
| 207 | session = kzalloc(sizeof(*session), GFP_KERNEL); | ||
| 208 | if (!session) | ||
| 209 | goto module_put; | ||
| 210 | session->transport = transport; | ||
| 211 | |||
| 212 | /* this is released in the dev's release function */ | ||
| 213 | scsi_host_get(shost); | ||
| 214 | snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); | ||
| 215 | session->dev.parent = &shost->shost_gendev; | ||
| 216 | session->dev.release = iscsi_session_release; | ||
| 217 | err = device_register(&session->dev); | ||
| 218 | if (err) { | ||
| 219 | dev_printk(KERN_ERR, &session->dev, "iscsi: could not " | ||
| 220 | "register session's dev\n"); | ||
| 221 | goto free_session; | ||
| 222 | } | ||
| 223 | transport_register_device(&session->dev); | ||
| 224 | |||
| 225 | return session; | ||
| 226 | |||
| 227 | free_session: | ||
| 228 | kfree(session); | ||
| 229 | module_put: | ||
| 230 | module_put(transport->owner); | ||
| 231 | return NULL; | ||
| 232 | } | ||
| 233 | |||
| 234 | EXPORT_SYMBOL_GPL(iscsi_create_session); | ||
| 235 | |||
| 236 | /** | ||
| 237 | * iscsi_destroy_session - destroy iscsi session | ||
| 238 | * @session: iscsi_session | ||
| 239 | * | ||
| 240 | * Can be called by a LLD or iscsi_transport. There must not be | ||
| 241 | * any running connections. | ||
| 242 | **/ | ||
| 243 | int iscsi_destroy_session(struct iscsi_cls_session *session) | ||
| 244 | { | ||
| 245 | transport_unregister_device(&session->dev); | ||
| 246 | device_unregister(&session->dev); | ||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | EXPORT_SYMBOL_GPL(iscsi_destroy_session); | ||
| 251 | |||
| 252 | static void iscsi_conn_release(struct device *dev) | ||
| 253 | { | ||
| 254 | struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); | ||
| 255 | struct device *parent = conn->dev.parent; | ||
| 256 | |||
| 257 | kfree(conn); | ||
| 258 | put_device(parent); | ||
| 259 | } | ||
| 260 | |||
| 261 | static int iscsi_is_conn_dev(const struct device *dev) | ||
| 262 | { | ||
| 263 | return dev->release == iscsi_conn_release; | ||
| 264 | } | ||
| 265 | |||
| 266 | /** | ||
| 267 | * iscsi_create_conn - create iscsi class connection | ||
| 268 | * @session: iscsi cls session | ||
| 269 | * @cid: connection id | ||
| 270 | * | ||
| 271 | * This can be called from a LLD or iscsi_transport. The connection | ||
| 272 | * is child of the session so cid must be unique for all connections | ||
| 273 | * on the session. | ||
| 274 | **/ | ||
| 275 | struct iscsi_cls_conn * | ||
| 276 | iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) | ||
| 277 | { | ||
| 278 | struct iscsi_transport *transport = session->transport; | ||
| 279 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | ||
| 280 | struct iscsi_cls_conn *conn; | ||
| 281 | int err; | ||
| 282 | |||
| 283 | conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL); | ||
| 284 | if (!conn) | ||
| 285 | return NULL; | ||
| 286 | |||
| 287 | if (transport->conndata_size) | ||
| 288 | conn->dd_data = &conn[1]; | ||
| 289 | |||
| 290 | INIT_LIST_HEAD(&conn->conn_list); | ||
| 291 | conn->transport = transport; | ||
| 292 | |||
| 293 | /* this is released in the dev's release function */ | ||
| 294 | if (!get_device(&session->dev)) | ||
| 295 | goto free_conn; | ||
| 296 | snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", | ||
| 297 | shost->host_no, cid); | ||
| 298 | conn->dev.parent = &session->dev; | ||
| 299 | conn->dev.release = iscsi_conn_release; | ||
| 300 | err = device_register(&conn->dev); | ||
| 301 | if (err) { | ||
| 302 | dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register " | ||
| 303 | "connection's dev\n"); | ||
| 304 | goto release_parent_ref; | ||
| 305 | } | ||
| 306 | transport_register_device(&conn->dev); | ||
| 307 | return conn; | ||
| 308 | |||
| 309 | release_parent_ref: | ||
| 310 | put_device(&session->dev); | ||
| 311 | free_conn: | ||
| 312 | kfree(conn); | ||
| 313 | return NULL; | ||
| 314 | } | ||
| 315 | |||
| 316 | EXPORT_SYMBOL_GPL(iscsi_create_conn); | ||
| 317 | |||
| 318 | /** | ||
| 319 | * iscsi_destroy_conn - destroy iscsi class connection | ||
| 320 | * @session: iscsi cls session | ||
| 321 | * | ||
| 322 | * This can be called from a LLD or iscsi_transport. | ||
| 323 | **/ | ||
| 324 | int iscsi_destroy_conn(struct iscsi_cls_conn *conn) | ||
| 325 | { | ||
| 326 | transport_unregister_device(&conn->dev); | ||
| 327 | device_unregister(&conn->dev); | ||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | |||
| 331 | EXPORT_SYMBOL_GPL(iscsi_destroy_conn); | ||
| 332 | |||
| 333 | /* | ||
| 334 | * These functions are used only by software iscsi_transports | ||
| 335 | * which do not allocate and more their scsi_hosts since this | ||
| 336 | * is initiated from userspace. | ||
| 337 | */ | ||
| 338 | |||
| 339 | /* | ||
| 340 | * iSCSI Session's hostdata organization: | ||
| 341 | * | ||
| 342 | * *------------------* <== hostdata_session(host->hostdata) | ||
| 343 | * | ptr to class sess| | ||
| 344 | * |------------------| <== iscsi_hostdata(host->hostdata) | ||
| 345 | * | transport's data | | ||
| 346 | * *------------------* | ||
| 347 | */ | ||
| 348 | |||
| 349 | #define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ | ||
| 350 | _t->hostdata_size % sizeof(unsigned long)) | ||
| 351 | |||
| 352 | #define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) | ||
| 353 | |||
| 354 | /** | ||
| 355 | * iscsi_transport_create_session - create iscsi cls session and host | ||
| 356 | * scsit: scsi transport template | ||
| 357 | * transport: iscsi transport template | ||
| 358 | * | ||
| 359 | * This can be used by software iscsi_transports that allocate | ||
| 360 | * a session per scsi host. | ||
| 361 | **/ | ||
| 362 | struct Scsi_Host * | ||
| 363 | iscsi_transport_create_session(struct scsi_transport_template *scsit, | ||
| 364 | struct iscsi_transport *transport) | ||
| 365 | { | ||
| 366 | struct iscsi_cls_session *session; | ||
| 367 | struct Scsi_Host *shost; | ||
| 368 | |||
| 369 | shost = scsi_host_alloc(transport->host_template, | ||
| 370 | hostdata_privsize(transport)); | ||
| 371 | if (!shost) { | ||
| 372 | printk(KERN_ERR "iscsi: can not allocate SCSI host for " | ||
| 373 | "session\n"); | ||
| 374 | return NULL; | ||
| 375 | } | ||
| 376 | |||
| 377 | shost->max_id = 1; | ||
| 378 | shost->max_channel = 0; | ||
| 379 | shost->max_lun = transport->max_lun; | ||
| 380 | shost->max_cmd_len = transport->max_cmd_len; | ||
| 381 | shost->transportt = scsit; | ||
| 382 | shost->transportt->create_work_queue = 1; | ||
| 383 | |||
| 384 | if (scsi_add_host(shost, NULL)) | ||
| 385 | goto free_host; | ||
| 386 | |||
| 387 | session = iscsi_create_session(shost, transport); | ||
| 388 | if (!session) | ||
| 389 | goto remove_host; | ||
| 203 | 390 | ||
| 204 | #define iscsi_dev_to_if_session(_dev) \ | 391 | *(unsigned long*)shost->hostdata = (unsigned long)session; |
| 205 | container_of(_dev, struct iscsi_if_session, dev) | 392 | return shost; |
| 393 | |||
| 394 | remove_host: | ||
| 395 | scsi_remove_host(shost); | ||
| 396 | free_host: | ||
| 397 | scsi_host_put(shost); | ||
| 398 | return NULL; | ||
| 399 | } | ||
| 206 | 400 | ||
| 207 | #define iscsi_cdev_to_if_session(_cdev) \ | 401 | EXPORT_SYMBOL_GPL(iscsi_transport_create_session); |
| 208 | iscsi_dev_to_if_session(_cdev->dev) | ||
| 209 | 402 | ||
| 210 | #define iscsi_if_session_to_shost(_session) \ | 403 | /** |
| 211 | dev_to_shost(_session->dev.parent) | 404 | * iscsi_transport_destroy_session - destroy session and scsi host |
| 405 | * shost: scsi host | ||
| 406 | * | ||
| 407 | * This can be used by software iscsi_transports that allocate | ||
| 408 | * a session per scsi host. | ||
| 409 | **/ | ||
| 410 | int iscsi_transport_destroy_session(struct Scsi_Host *shost) | ||
| 411 | { | ||
| 412 | struct iscsi_cls_session *session; | ||
| 212 | 413 | ||
| 213 | static struct iscsi_if_conn* | 414 | scsi_remove_host(shost); |
| 415 | session = hostdata_session(shost->hostdata); | ||
| 416 | iscsi_destroy_session(session); | ||
| 417 | /* ref from host alloc */ | ||
| 418 | scsi_host_put(shost); | ||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session); | ||
| 423 | |||
| 424 | /* | ||
| 425 | * iscsi interface functions | ||
| 426 | */ | ||
| 427 | static struct iscsi_cls_conn* | ||
| 214 | iscsi_if_find_conn(uint64_t key) | 428 | iscsi_if_find_conn(uint64_t key) |
| 215 | { | 429 | { |
| 216 | unsigned long flags; | 430 | unsigned long flags; |
| 217 | struct iscsi_if_conn *conn; | 431 | struct iscsi_cls_conn *conn; |
| 218 | 432 | ||
| 219 | spin_lock_irqsave(&connlock, flags); | 433 | spin_lock_irqsave(&connlock, flags); |
| 220 | list_for_each_entry(conn, &connlist, conn_list) | 434 | list_for_each_entry(conn, &connlist, conn_list) |
| @@ -249,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb) | |||
| 249 | } | 463 | } |
| 250 | 464 | ||
| 251 | static void* | 465 | static void* |
| 252 | mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) | 466 | mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data) |
| 253 | { | 467 | { |
| 254 | struct mempool_zone *zone = pool_data; | 468 | struct mempool_zone *zone = pool_data; |
| 255 | 469 | ||
| @@ -281,14 +495,21 @@ mempool_zone_complete(struct mempool_zone *zone) | |||
| 281 | spin_unlock_irqrestore(&zone->freelock, flags); | 495 | spin_unlock_irqrestore(&zone->freelock, flags); |
| 282 | } | 496 | } |
| 283 | 497 | ||
| 284 | static int | 498 | static struct mempool_zone * |
| 285 | mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, | 499 | mempool_zone_init(unsigned max, unsigned size, unsigned hiwat) |
| 286 | unsigned hiwat) | ||
| 287 | { | 500 | { |
| 501 | struct mempool_zone *zp; | ||
| 502 | |||
| 503 | zp = kzalloc(sizeof(*zp), GFP_KERNEL); | ||
| 504 | if (!zp) | ||
| 505 | return NULL; | ||
| 506 | |||
| 288 | zp->pool = mempool_create(max, mempool_zone_alloc_skb, | 507 | zp->pool = mempool_create(max, mempool_zone_alloc_skb, |
| 289 | mempool_zone_free_skb, zp); | 508 | mempool_zone_free_skb, zp); |
| 290 | if (!zp->pool) | 509 | if (!zp->pool) { |
| 291 | return -ENOMEM; | 510 | kfree(zp); |
| 511 | return NULL; | ||
| 512 | } | ||
| 292 | 513 | ||
| 293 | zp->size = size; | 514 | zp->size = size; |
| 294 | zp->hiwat = hiwat; | 515 | zp->hiwat = hiwat; |
| @@ -297,9 +518,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, | |||
| 297 | spin_lock_init(&zp->freelock); | 518 | spin_lock_init(&zp->freelock); |
| 298 | atomic_set(&zp->allocated, 0); | 519 | atomic_set(&zp->allocated, 0); |
| 299 | 520 | ||
| 300 | return 0; | 521 | return zp; |
| 301 | } | 522 | } |
| 302 | 523 | ||
| 524 | static void mempool_zone_destroy(struct mempool_zone *zp) | ||
| 525 | { | ||
| 526 | mempool_destroy(zp->pool); | ||
| 527 | kfree(zp); | ||
| 528 | } | ||
| 303 | 529 | ||
| 304 | static struct sk_buff* | 530 | static struct sk_buff* |
| 305 | mempool_zone_get_skb(struct mempool_zone *zone) | 531 | mempool_zone_get_skb(struct mempool_zone *zone) |
| @@ -339,7 +565,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, | |||
| 339 | struct nlmsghdr *nlh; | 565 | struct nlmsghdr *nlh; |
| 340 | struct sk_buff *skb; | 566 | struct sk_buff *skb; |
| 341 | struct iscsi_uevent *ev; | 567 | struct iscsi_uevent *ev; |
| 342 | struct iscsi_if_conn *conn; | 568 | struct iscsi_cls_conn *conn; |
| 343 | char *pdu; | 569 | char *pdu; |
| 344 | int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + | 570 | int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + |
| 345 | data_size); | 571 | data_size); |
| @@ -347,13 +573,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, | |||
| 347 | conn = iscsi_if_find_conn(connh); | 573 | conn = iscsi_if_find_conn(connh); |
| 348 | BUG_ON(!conn); | 574 | BUG_ON(!conn); |
| 349 | 575 | ||
| 350 | mempool_zone_complete(&conn->z_pdu); | 576 | mempool_zone_complete(conn->z_pdu); |
| 351 | 577 | ||
| 352 | skb = mempool_zone_get_skb(&conn->z_pdu); | 578 | skb = mempool_zone_get_skb(conn->z_pdu); |
| 353 | if (!skb) { | 579 | if (!skb) { |
| 354 | iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); | 580 | iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); |
| 355 | printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n", | 581 | dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " |
| 356 | conn->host->host_no); | 582 | "control PDU: OOM\n"); |
| 357 | return -ENOMEM; | 583 | return -ENOMEM; |
| 358 | } | 584 | } |
| 359 | 585 | ||
| @@ -362,14 +588,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, | |||
| 362 | memset(ev, 0, sizeof(*ev)); | 588 | memset(ev, 0, sizeof(*ev)); |
| 363 | ev->transport_handle = iscsi_handle(conn->transport); | 589 | ev->transport_handle = iscsi_handle(conn->transport); |
| 364 | ev->type = ISCSI_KEVENT_RECV_PDU; | 590 | ev->type = ISCSI_KEVENT_RECV_PDU; |
| 365 | if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) | 591 | if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) |
| 366 | ev->iferror = -ENOMEM; | 592 | ev->iferror = -ENOMEM; |
| 367 | ev->r.recv_req.conn_handle = connh; | 593 | ev->r.recv_req.conn_handle = connh; |
| 368 | pdu = (char*)ev + sizeof(*ev); | 594 | pdu = (char*)ev + sizeof(*ev); |
| 369 | memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); | 595 | memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); |
| 370 | memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); | 596 | memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); |
| 371 | 597 | ||
| 372 | return iscsi_unicast_skb(&conn->z_pdu, skb); | 598 | return iscsi_unicast_skb(conn->z_pdu, skb); |
| 373 | } | 599 | } |
| 374 | EXPORT_SYMBOL_GPL(iscsi_recv_pdu); | 600 | EXPORT_SYMBOL_GPL(iscsi_recv_pdu); |
| 375 | 601 | ||
| @@ -378,18 +604,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) | |||
| 378 | struct nlmsghdr *nlh; | 604 | struct nlmsghdr *nlh; |
| 379 | struct sk_buff *skb; | 605 | struct sk_buff *skb; |
| 380 | struct iscsi_uevent *ev; | 606 | struct iscsi_uevent *ev; |
| 381 | struct iscsi_if_conn *conn; | 607 | struct iscsi_cls_conn *conn; |
| 382 | int len = NLMSG_SPACE(sizeof(*ev)); | 608 | int len = NLMSG_SPACE(sizeof(*ev)); |
| 383 | 609 | ||
| 384 | conn = iscsi_if_find_conn(connh); | 610 | conn = iscsi_if_find_conn(connh); |
| 385 | BUG_ON(!conn); | 611 | BUG_ON(!conn); |
| 386 | 612 | ||
| 387 | mempool_zone_complete(&conn->z_error); | 613 | mempool_zone_complete(conn->z_error); |
| 388 | 614 | ||
| 389 | skb = mempool_zone_get_skb(&conn->z_error); | 615 | skb = mempool_zone_get_skb(conn->z_error); |
| 390 | if (!skb) { | 616 | if (!skb) { |
| 391 | printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n", | 617 | dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " |
| 392 | conn->host->host_no, error); | 618 | "conn error (%d)\n", error); |
| 393 | return; | 619 | return; |
| 394 | } | 620 | } |
| 395 | 621 | ||
| @@ -397,15 +623,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) | |||
| 397 | ev = NLMSG_DATA(nlh); | 623 | ev = NLMSG_DATA(nlh); |
| 398 | ev->transport_handle = iscsi_handle(conn->transport); | 624 | ev->transport_handle = iscsi_handle(conn->transport); |
| 399 | ev->type = ISCSI_KEVENT_CONN_ERROR; | 625 | ev->type = ISCSI_KEVENT_CONN_ERROR; |
| 400 | if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat) | 626 | if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) |
| 401 | ev->iferror = -ENOMEM; | 627 | ev->iferror = -ENOMEM; |
| 402 | ev->r.connerror.error = error; | 628 | ev->r.connerror.error = error; |
| 403 | ev->r.connerror.conn_handle = connh; | 629 | ev->r.connerror.conn_handle = connh; |
| 404 | 630 | ||
| 405 | iscsi_unicast_skb(&conn->z_error, skb); | 631 | iscsi_unicast_skb(conn->z_error, skb); |
| 406 | 632 | ||
| 407 | printk(KERN_INFO "iscsi%d: detected conn error (%d)\n", | 633 | dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", |
| 408 | conn->host->host_no, error); | 634 | error); |
| 409 | } | 635 | } |
| 410 | EXPORT_SYMBOL_GPL(iscsi_conn_error); | 636 | EXPORT_SYMBOL_GPL(iscsi_conn_error); |
| 411 | 637 | ||
| @@ -419,9 +645,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, | |||
| 419 | int flags = multi ? NLM_F_MULTI : 0; | 645 | int flags = multi ? NLM_F_MULTI : 0; |
| 420 | int t = done ? NLMSG_DONE : type; | 646 | int t = done ? NLMSG_DONE : type; |
| 421 | 647 | ||
| 422 | mempool_zone_complete(&z_reply); | 648 | mempool_zone_complete(z_reply); |
| 423 | 649 | ||
| 424 | skb = mempool_zone_get_skb(&z_reply); | 650 | skb = mempool_zone_get_skb(z_reply); |
| 425 | /* | 651 | /* |
| 426 | * FIXME: | 652 | * FIXME: |
| 427 | * user is supposed to react on iferror == -ENOMEM; | 653 | * user is supposed to react on iferror == -ENOMEM; |
| @@ -432,366 +658,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, | |||
| 432 | nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); | 658 | nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); |
| 433 | nlh->nlmsg_flags = flags; | 659 | nlh->nlmsg_flags = flags; |
| 434 | memcpy(NLMSG_DATA(nlh), payload, size); | 660 | memcpy(NLMSG_DATA(nlh), payload, size); |
| 435 | return iscsi_unicast_skb(&z_reply, skb); | 661 | return iscsi_unicast_skb(z_reply, skb); |
| 436 | } | 662 | } |
| 437 | 663 | ||
| 438 | /* | 664 | static int |
| 439 | * iSCSI Session's hostdata organization: | 665 | iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, |
| 440 | * | 666 | struct nlmsghdr *nlh) |
| 441 | * *------------------* <== host->hostdata | 667 | { |
| 442 | * | transport | | 668 | struct iscsi_uevent *ev = NLMSG_DATA(nlh); |
| 443 | * |------------------| <== iscsi_hostdata(host->hostdata) | 669 | struct iscsi_stats *stats; |
| 444 | * | transport's data | | 670 | struct sk_buff *skbstat; |
| 445 | * |------------------| <== hostdata_session(host->hostdata) | 671 | struct iscsi_cls_conn *conn; |
| 446 | * | interface's data | | 672 | struct nlmsghdr *nlhstat; |
| 447 | * *------------------* | 673 | struct iscsi_uevent *evstat; |
| 448 | */ | 674 | int len = NLMSG_SPACE(sizeof(*ev) + |
| 675 | sizeof(struct iscsi_stats) + | ||
| 676 | sizeof(struct iscsi_stats_custom) * | ||
| 677 | ISCSI_STATS_CUSTOM_MAX); | ||
| 678 | int err = 0; | ||
| 449 | 679 | ||
| 450 | #define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ | 680 | conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle); |
| 451 | _t->hostdata_size % sizeof(unsigned long) + \ | 681 | if (!conn) |
| 452 | sizeof(struct iscsi_if_session)) | 682 | return -EEXIST; |
| 453 | 683 | ||
| 454 | #define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \ | 684 | do { |
| 455 | ((struct iscsi_transport *) \ | 685 | int actual_size; |
| 456 | iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size) | ||
| 457 | 686 | ||
| 458 | static void iscsi_if_session_dev_release(struct device *dev) | 687 | mempool_zone_complete(conn->z_pdu); |
| 459 | { | ||
| 460 | struct iscsi_if_session *session = iscsi_dev_to_if_session(dev); | ||
| 461 | struct iscsi_transport *transport = session->transport; | ||
| 462 | struct Scsi_Host *shost = iscsi_if_session_to_shost(session); | ||
| 463 | struct iscsi_if_conn *conn, *tmp; | ||
| 464 | unsigned long flags; | ||
| 465 | 688 | ||
| 466 | /* now free connections */ | 689 | skbstat = mempool_zone_get_skb(conn->z_pdu); |
| 467 | spin_lock_irqsave(&connlock, flags); | 690 | if (!skbstat) { |
| 468 | list_for_each_entry_safe(conn, tmp, &session->connections, | 691 | dev_printk(KERN_ERR, &conn->dev, "iscsi: can not " |
| 469 | session_list) { | 692 | "deliver stats: OOM\n"); |
| 470 | list_del(&conn->session_list); | 693 | return -ENOMEM; |
| 471 | mempool_destroy(conn->z_pdu.pool); | 694 | } |
| 472 | mempool_destroy(conn->z_error.pool); | 695 | |
| 473 | kfree(conn); | 696 | nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, |
| 474 | } | 697 | (len - sizeof(*nlhstat)), 0); |
| 475 | spin_unlock_irqrestore(&connlock, flags); | 698 | evstat = NLMSG_DATA(nlhstat); |
| 476 | scsi_host_put(shost); | 699 | memset(evstat, 0, sizeof(*evstat)); |
| 477 | module_put(transport->owner); | 700 | evstat->transport_handle = iscsi_handle(conn->transport); |
| 701 | evstat->type = nlh->nlmsg_type; | ||
| 702 | if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) | ||
| 703 | evstat->iferror = -ENOMEM; | ||
| 704 | evstat->u.get_stats.conn_handle = | ||
| 705 | ev->u.get_stats.conn_handle; | ||
| 706 | stats = (struct iscsi_stats *) | ||
| 707 | ((char*)evstat + sizeof(*evstat)); | ||
| 708 | memset(stats, 0, sizeof(*stats)); | ||
| 709 | |||
| 710 | transport->get_stats(ev->u.get_stats.conn_handle, stats); | ||
| 711 | actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + | ||
| 712 | sizeof(struct iscsi_stats) + | ||
| 713 | sizeof(struct iscsi_stats_custom) * | ||
| 714 | stats->custom_length); | ||
| 715 | actual_size -= sizeof(*nlhstat); | ||
| 716 | actual_size = NLMSG_LENGTH(actual_size); | ||
| 717 | skb_trim(skb, NLMSG_ALIGN(actual_size)); | ||
| 718 | nlhstat->nlmsg_len = actual_size; | ||
| 719 | |||
| 720 | err = iscsi_unicast_skb(conn->z_pdu, skbstat); | ||
| 721 | } while (err < 0 && err != -ECONNREFUSED); | ||
| 722 | |||
| 723 | return err; | ||
| 478 | } | 724 | } |
| 479 | 725 | ||
| 480 | static int | 726 | static int |
| 481 | iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) | 727 | iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) |
| 482 | { | 728 | { |
| 483 | struct iscsi_transport *transport = priv->iscsi_transport; | 729 | struct iscsi_transport *transport = priv->iscsi_transport; |
| 484 | struct iscsi_if_session *session; | ||
| 485 | struct Scsi_Host *shost; | 730 | struct Scsi_Host *shost; |
| 486 | unsigned long flags; | ||
| 487 | int error; | ||
| 488 | |||
| 489 | if (!try_module_get(transport->owner)) | ||
| 490 | return -EPERM; | ||
| 491 | 731 | ||
| 492 | shost = scsi_host_alloc(transport->host_template, | 732 | if (!transport->create_session) |
| 493 | hostdata_privsize(transport)); | 733 | return -EINVAL; |
| 494 | if (!shost) { | ||
| 495 | ev->r.c_session_ret.session_handle = iscsi_handle(NULL); | ||
| 496 | printk(KERN_ERR "iscsi: can not allocate SCSI host for " | ||
| 497 | "session\n"); | ||
| 498 | error = -ENOMEM; | ||
| 499 | goto out_module_put; | ||
| 500 | } | ||
| 501 | shost->max_id = 1; | ||
| 502 | shost->max_channel = 0; | ||
| 503 | shost->max_lun = transport->max_lun; | ||
| 504 | shost->max_cmd_len = transport->max_cmd_len; | ||
| 505 | shost->transportt = &priv->t; | ||
| 506 | |||
| 507 | /* store struct iscsi_transport in hostdata */ | ||
| 508 | *(uint64_t*)shost->hostdata = ev->transport_handle; | ||
| 509 | 734 | ||
| 510 | ev->r.c_session_ret.session_handle = transport->create_session( | 735 | shost = transport->create_session(&priv->t, |
| 511 | ev->u.c_session.initial_cmdsn, shost); | 736 | ev->u.c_session.initial_cmdsn); |
| 512 | if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) { | 737 | if (!shost) |
| 513 | error = 0; | 738 | return -ENOMEM; |
| 514 | goto out_host_put; | ||
| 515 | } | ||
| 516 | 739 | ||
| 517 | /* host_no becomes assigned SID */ | 740 | ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata)); |
| 518 | ev->r.c_session_ret.sid = shost->host_no; | 741 | ev->r.c_session_ret.sid = shost->host_no; |
| 519 | /* initialize session */ | ||
| 520 | session = hostdata_session(shost->hostdata); | ||
| 521 | INIT_LIST_HEAD(&session->connections); | ||
| 522 | INIT_LIST_HEAD(&session->list); | ||
| 523 | session->sessionh = ev->r.c_session_ret.session_handle; | ||
| 524 | session->transport = transport; | ||
| 525 | |||
| 526 | error = scsi_add_host(shost, NULL); | ||
| 527 | if (error) | ||
| 528 | goto out_destroy_session; | ||
| 529 | |||
| 530 | /* | ||
| 531 | * this is released in the dev's release function) | ||
| 532 | */ | ||
| 533 | scsi_host_get(shost); | ||
| 534 | snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); | ||
| 535 | session->dev.parent = &shost->shost_gendev; | ||
| 536 | session->dev.release = iscsi_if_session_dev_release; | ||
| 537 | error = device_register(&session->dev); | ||
| 538 | if (error) { | ||
| 539 | printk(KERN_ERR "iscsi: could not register session%d's dev\n", | ||
| 540 | shost->host_no); | ||
| 541 | goto out_remove_host; | ||
| 542 | } | ||
| 543 | transport_register_device(&session->dev); | ||
| 544 | |||
| 545 | /* add this session to the list of active sessions */ | ||
| 546 | spin_lock_irqsave(&priv->session_lock, flags); | ||
| 547 | list_add(&session->list, &priv->sessions); | ||
| 548 | spin_unlock_irqrestore(&priv->session_lock, flags); | ||
| 549 | |||
| 550 | return 0; | 742 | return 0; |
| 551 | |||
| 552 | out_remove_host: | ||
| 553 | scsi_remove_host(shost); | ||
| 554 | out_destroy_session: | ||
| 555 | transport->destroy_session(ev->r.c_session_ret.session_handle); | ||
| 556 | ev->r.c_session_ret.session_handle = iscsi_handle(NULL); | ||
| 557 | out_host_put: | ||
| 558 | scsi_host_put(shost); | ||
| 559 | out_module_put: | ||
| 560 | module_put(transport->owner); | ||
| 561 | return error; | ||
| 562 | } | 743 | } |
| 563 | 744 | ||
| 564 | static int | 745 | static int |
| 565 | iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) | 746 | iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) |
| 566 | { | 747 | { |
| 567 | struct iscsi_transport *transport = priv->iscsi_transport; | 748 | struct iscsi_transport *transport = priv->iscsi_transport; |
| 749 | |||
| 568 | struct Scsi_Host *shost; | 750 | struct Scsi_Host *shost; |
| 569 | struct iscsi_if_session *session; | 751 | |
| 570 | unsigned long flags; | 752 | if (!transport->destroy_session) |
| 571 | struct iscsi_if_conn *conn; | 753 | return -EINVAL; |
| 572 | int error = 0; | ||
| 573 | 754 | ||
| 574 | shost = scsi_host_lookup(ev->u.d_session.sid); | 755 | shost = scsi_host_lookup(ev->u.d_session.sid); |
| 575 | if (shost == ERR_PTR(-ENXIO)) | 756 | if (shost == ERR_PTR(-ENXIO)) |
| 576 | return -EEXIST; | 757 | return -EEXIST; |
| 577 | session = hostdata_session(shost->hostdata); | ||
| 578 | 758 | ||
| 579 | /* check if we have active connections */ | 759 | if (transport->destroy_session) |
| 580 | spin_lock_irqsave(&connlock, flags); | 760 | transport->destroy_session(shost); |
| 581 | list_for_each_entry(conn, &session->connections, session_list) { | 761 | /* ref from host lookup */ |
| 582 | if (conn->active) { | 762 | scsi_host_put(shost); |
| 583 | printk(KERN_ERR "iscsi%d: can not destroy session: " | 763 | return 0; |
| 584 | "has active connection (%p)\n", | ||
| 585 | shost->host_no, iscsi_ptr(conn->connh)); | ||
| 586 | spin_unlock_irqrestore(&connlock, flags); | ||
| 587 | error = EIO; | ||
| 588 | goto out_release_ref; | ||
| 589 | } | ||
| 590 | } | ||
| 591 | spin_unlock_irqrestore(&connlock, flags); | ||
| 592 | |||
| 593 | scsi_remove_host(shost); | ||
| 594 | transport->destroy_session(ev->u.d_session.session_handle); | ||
| 595 | transport_unregister_device(&session->dev); | ||
| 596 | device_unregister(&session->dev); | ||
| 597 | |||
| 598 | /* remove this session from the list of active sessions */ | ||
| 599 | spin_lock_irqsave(&priv->session_lock, flags); | ||
| 600 | list_del(&session->list); | ||
| 601 | spin_unlock_irqrestore(&priv->session_lock, flags); | ||
| 602 | |||
| 603 | /* ref from host alloc */ | ||
| 604 | scsi_host_put(shost); | ||
| 605 | out_release_ref: | ||
| 606 | /* ref from host lookup */ | ||
| 607 | scsi_host_put(shost); | ||
| 608 | return error; | ||
| 609 | } | ||
| 610 | |||
| 611 | static void iscsi_if_conn_dev_release(struct device *dev) | ||
| 612 | { | ||
| 613 | struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev); | ||
| 614 | struct Scsi_Host *shost = conn->host; | ||
| 615 | |||
| 616 | scsi_host_put(shost); | ||
| 617 | } | 764 | } |
| 618 | 765 | ||
| 619 | static int | 766 | static int |
| 620 | iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) | 767 | iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){ |
| 621 | { | ||
| 622 | struct iscsi_if_session *session; | ||
| 623 | struct Scsi_Host *shost; | 768 | struct Scsi_Host *shost; |
| 624 | struct iscsi_if_conn *conn; | 769 | struct iscsi_cls_conn *conn; |
| 625 | unsigned long flags; | 770 | unsigned long flags; |
| 626 | int error; | 771 | |
| 772 | if (!transport->create_conn) | ||
| 773 | return -EINVAL; | ||
| 627 | 774 | ||
| 628 | shost = scsi_host_lookup(ev->u.c_conn.sid); | 775 | shost = scsi_host_lookup(ev->u.c_conn.sid); |
| 629 | if (shost == ERR_PTR(-ENXIO)) | 776 | if (shost == ERR_PTR(-ENXIO)) |
| 630 | return -EEXIST; | 777 | return -EEXIST; |
| 631 | session = hostdata_session(shost->hostdata); | ||
| 632 | 778 | ||
| 633 | conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL); | 779 | conn = transport->create_conn(shost, ev->u.c_conn.cid); |
| 634 | if (!conn) { | 780 | if (!conn) |
| 635 | error = -ENOMEM; | 781 | goto release_ref; |
| 636 | goto out_release_ref; | ||
| 637 | } | ||
| 638 | memset(conn, 0, sizeof(struct iscsi_if_conn)); | ||
| 639 | INIT_LIST_HEAD(&conn->session_list); | ||
| 640 | INIT_LIST_HEAD(&conn->conn_list); | ||
| 641 | conn->host = shost; | ||
| 642 | conn->transport = transport; | ||
| 643 | 782 | ||
| 644 | error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU, | 783 | conn->z_pdu = mempool_zone_init(Z_MAX_PDU, |
| 645 | NLMSG_SPACE(sizeof(struct iscsi_uevent) + | 784 | NLMSG_SPACE(sizeof(struct iscsi_uevent) + |
| 646 | sizeof(struct iscsi_hdr) + | 785 | sizeof(struct iscsi_hdr) + |
| 647 | DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), | 786 | DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), |
| 648 | Z_HIWAT_PDU); | 787 | Z_HIWAT_PDU); |
| 649 | if (error) { | 788 | if (!conn->z_pdu) { |
| 650 | printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new " | 789 | dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate " |
| 651 | "conn\n", shost->host_no); | 790 | "pdu zone for new conn\n"); |
| 652 | goto out_free_conn; | 791 | goto destroy_conn; |
| 653 | } | 792 | } |
| 654 | error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR, | 793 | |
| 794 | conn->z_error = mempool_zone_init(Z_MAX_ERROR, | ||
| 655 | NLMSG_SPACE(sizeof(struct iscsi_uevent)), | 795 | NLMSG_SPACE(sizeof(struct iscsi_uevent)), |
| 656 | Z_HIWAT_ERROR); | 796 | Z_HIWAT_ERROR); |
| 657 | if (error) { | 797 | if (!conn->z_error) { |
| 658 | printk(KERN_ERR "iscsi%d: can not allocate error zone for " | 798 | dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate " |
| 659 | "new conn\n", shost->host_no); | 799 | "error zone for new conn\n"); |
| 660 | goto out_free_pdu_pool; | 800 | goto free_pdu_pool; |
| 661 | } | ||
| 662 | |||
| 663 | ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle, | ||
| 664 | ev->u.c_conn.cid); | ||
| 665 | if (!ev->r.handle) { | ||
| 666 | error = -ENODEV; | ||
| 667 | goto out_free_error_pool; | ||
| 668 | } | 801 | } |
| 669 | 802 | ||
| 670 | conn->connh = ev->r.handle; | 803 | ev->r.handle = conn->connh = iscsi_handle(conn->dd_data); |
| 671 | |||
| 672 | /* | ||
| 673 | * this is released in the dev's release function | ||
| 674 | */ | ||
| 675 | if (!scsi_host_get(shost)) | ||
| 676 | goto out_destroy_conn; | ||
| 677 | snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", | ||
| 678 | shost->host_no, ev->u.c_conn.cid); | ||
| 679 | conn->dev.parent = &session->dev; | ||
| 680 | conn->dev.release = iscsi_if_conn_dev_release; | ||
| 681 | error = device_register(&conn->dev); | ||
| 682 | if (error) { | ||
| 683 | printk(KERN_ERR "iscsi%d: could not register connections%u " | ||
| 684 | "dev\n", shost->host_no, ev->u.c_conn.cid); | ||
| 685 | goto out_release_parent_ref; | ||
| 686 | } | ||
| 687 | transport_register_device(&conn->dev); | ||
| 688 | 804 | ||
| 689 | spin_lock_irqsave(&connlock, flags); | 805 | spin_lock_irqsave(&connlock, flags); |
| 690 | list_add(&conn->conn_list, &connlist); | 806 | list_add(&conn->conn_list, &connlist); |
| 691 | list_add(&conn->session_list, &session->connections); | ||
| 692 | conn->active = 1; | 807 | conn->active = 1; |
| 693 | spin_unlock_irqrestore(&connlock, flags); | 808 | spin_unlock_irqrestore(&connlock, flags); |
| 694 | 809 | ||
| 695 | scsi_host_put(shost); | 810 | scsi_host_put(shost); |
| 696 | return 0; | 811 | return 0; |
| 697 | 812 | ||
| 698 | out_release_parent_ref: | 813 | free_pdu_pool: |
| 814 | mempool_zone_destroy(conn->z_pdu); | ||
| 815 | destroy_conn: | ||
| 816 | if (transport->destroy_conn) | ||
| 817 | transport->destroy_conn(conn->dd_data); | ||
| 818 | release_ref: | ||
| 699 | scsi_host_put(shost); | 819 | scsi_host_put(shost); |
| 700 | out_destroy_conn: | 820 | return -ENOMEM; |
| 701 | transport->destroy_conn(ev->r.handle); | ||
| 702 | out_free_error_pool: | ||
| 703 | mempool_destroy(conn->z_error.pool); | ||
| 704 | out_free_pdu_pool: | ||
| 705 | mempool_destroy(conn->z_pdu.pool); | ||
| 706 | out_free_conn: | ||
| 707 | kfree(conn); | ||
| 708 | out_release_ref: | ||
| 709 | scsi_host_put(shost); | ||
| 710 | return error; | ||
| 711 | } | 821 | } |
| 712 | 822 | ||
| 713 | static int | 823 | static int |
| 714 | iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) | 824 | iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) |
| 715 | { | 825 | { |
| 716 | unsigned long flags; | 826 | unsigned long flags; |
| 717 | struct iscsi_if_conn *conn; | 827 | struct iscsi_cls_conn *conn; |
| 828 | struct mempool_zone *z_error, *z_pdu; | ||
| 718 | 829 | ||
| 719 | conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); | 830 | conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); |
| 720 | if (!conn) | 831 | if (!conn) |
| 721 | return -EEXIST; | 832 | return -EEXIST; |
| 722 | 833 | ||
| 723 | transport->destroy_conn(ev->u.d_conn.conn_handle); | 834 | if (!transport->destroy_conn) |
| 835 | return -EINVAL; | ||
| 724 | 836 | ||
| 725 | spin_lock_irqsave(&connlock, flags); | 837 | spin_lock_irqsave(&connlock, flags); |
| 726 | conn->active = 0; | 838 | conn->active = 0; |
| 727 | list_del(&conn->conn_list); | 839 | list_del(&conn->conn_list); |
| 728 | spin_unlock_irqrestore(&connlock, flags); | 840 | spin_unlock_irqrestore(&connlock, flags); |
| 729 | 841 | ||
| 730 | transport_unregister_device(&conn->dev); | 842 | z_pdu = conn->z_pdu; |
| 731 | device_unregister(&conn->dev); | 843 | z_error = conn->z_error; |
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 735 | static int | ||
| 736 | iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, | ||
| 737 | struct nlmsghdr *nlh) | ||
| 738 | { | ||
| 739 | struct iscsi_uevent *ev = NLMSG_DATA(nlh); | ||
| 740 | struct iscsi_stats *stats; | ||
| 741 | struct sk_buff *skbstat; | ||
| 742 | struct iscsi_if_conn *conn; | ||
| 743 | struct nlmsghdr *nlhstat; | ||
| 744 | struct iscsi_uevent *evstat; | ||
| 745 | int len = NLMSG_SPACE(sizeof(*ev) + | ||
| 746 | sizeof(struct iscsi_stats) + | ||
| 747 | sizeof(struct iscsi_stats_custom) * | ||
| 748 | ISCSI_STATS_CUSTOM_MAX); | ||
| 749 | int err = 0; | ||
| 750 | |||
| 751 | conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle); | ||
| 752 | if (!conn) | ||
| 753 | return -EEXIST; | ||
| 754 | |||
| 755 | do { | ||
| 756 | int actual_size; | ||
| 757 | |||
| 758 | mempool_zone_complete(&conn->z_pdu); | ||
| 759 | |||
| 760 | skbstat = mempool_zone_get_skb(&conn->z_pdu); | ||
| 761 | if (!skbstat) { | ||
| 762 | printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n", | ||
| 763 | conn->host->host_no); | ||
| 764 | return -ENOMEM; | ||
| 765 | } | ||
| 766 | |||
| 767 | nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, | ||
| 768 | (len - sizeof(*nlhstat)), 0); | ||
| 769 | evstat = NLMSG_DATA(nlhstat); | ||
| 770 | memset(evstat, 0, sizeof(*evstat)); | ||
| 771 | evstat->transport_handle = iscsi_handle(conn->transport); | ||
| 772 | evstat->type = nlh->nlmsg_type; | ||
| 773 | if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) | ||
| 774 | evstat->iferror = -ENOMEM; | ||
| 775 | evstat->u.get_stats.conn_handle = | ||
| 776 | ev->u.get_stats.conn_handle; | ||
| 777 | stats = (struct iscsi_stats *) | ||
| 778 | ((char*)evstat + sizeof(*evstat)); | ||
| 779 | memset(stats, 0, sizeof(*stats)); | ||
| 780 | 844 | ||
| 781 | transport->get_stats(ev->u.get_stats.conn_handle, stats); | 845 | if (transport->destroy_conn) |
| 782 | actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + | 846 | transport->destroy_conn(conn); |
| 783 | sizeof(struct iscsi_stats) + | ||
| 784 | sizeof(struct iscsi_stats_custom) * | ||
| 785 | stats->custom_length); | ||
| 786 | actual_size -= sizeof(*nlhstat); | ||
| 787 | actual_size = NLMSG_LENGTH(actual_size); | ||
| 788 | skb_trim(skb, NLMSG_ALIGN(actual_size)); | ||
| 789 | nlhstat->nlmsg_len = actual_size; | ||
| 790 | 847 | ||
| 791 | err = iscsi_unicast_skb(&conn->z_pdu, skbstat); | 848 | mempool_zone_destroy(z_pdu); |
| 792 | } while (err < 0 && err != -ECONNREFUSED); | 849 | mempool_zone_destroy(z_error); |
| 793 | 850 | ||
| 794 | return err; | 851 | return 0; |
| 795 | } | 852 | } |
| 796 | 853 | ||
| 797 | static int | 854 | static int |
| @@ -881,7 +938,7 @@ iscsi_if_rx(struct sock *sk, int len) | |||
| 881 | { | 938 | { |
| 882 | struct sk_buff *skb; | 939 | struct sk_buff *skb; |
| 883 | 940 | ||
| 884 | down(&rx_queue_sema); | 941 | mutex_lock(&rx_queue_mutex); |
| 885 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { | 942 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
| 886 | while (skb->len >= NLMSG_SPACE(0)) { | 943 | while (skb->len >= NLMSG_SPACE(0)) { |
| 887 | int err; | 944 | int err; |
| @@ -915,17 +972,20 @@ iscsi_if_rx(struct sock *sk, int len) | |||
| 915 | err = iscsi_if_send_reply( | 972 | err = iscsi_if_send_reply( |
| 916 | NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, | 973 | NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, |
| 917 | nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); | 974 | nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); |
| 918 | if (atomic_read(&z_reply.allocated) >= | 975 | if (atomic_read(&z_reply->allocated) >= |
| 919 | z_reply.hiwat) | 976 | z_reply->hiwat) |
| 920 | ev->iferror = -ENOMEM; | 977 | ev->iferror = -ENOMEM; |
| 921 | } while (err < 0 && err != -ECONNREFUSED); | 978 | } while (err < 0 && err != -ECONNREFUSED); |
| 922 | skb_pull(skb, rlen); | 979 | skb_pull(skb, rlen); |
| 923 | } | 980 | } |
| 924 | kfree_skb(skb); | 981 | kfree_skb(skb); |
| 925 | } | 982 | } |
| 926 | up(&rx_queue_sema); | 983 | mutex_unlock(&rx_queue_mutex); |
| 927 | } | 984 | } |
| 928 | 985 | ||
| 986 | #define iscsi_cdev_to_conn(_cdev) \ | ||
| 987 | iscsi_dev_to_conn(_cdev->dev) | ||
| 988 | |||
| 929 | /* | 989 | /* |
| 930 | * iSCSI connection attrs | 990 | * iSCSI connection attrs |
| 931 | */ | 991 | */ |
| @@ -934,12 +994,10 @@ static ssize_t \ | |||
| 934 | show_conn_int_param_##param(struct class_device *cdev, char *buf) \ | 994 | show_conn_int_param_##param(struct class_device *cdev, char *buf) \ |
| 935 | { \ | 995 | { \ |
| 936 | uint32_t value = 0; \ | 996 | uint32_t value = 0; \ |
| 937 | struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \ | 997 | struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ |
| 938 | struct iscsi_internal *priv; \ | 998 | struct iscsi_transport *t = conn->transport; \ |
| 939 | \ | 999 | \ |
| 940 | priv = to_iscsi_internal(conn->host->transportt); \ | 1000 | t->get_conn_param(conn->dd_data, param, &value); \ |
| 941 | if (priv->param_mask & (1 << param)) \ | ||
| 942 | priv->iscsi_transport->get_param(conn->connh, param, &value); \ | ||
| 943 | return snprintf(buf, 20, format"\n", value); \ | 1001 | return snprintf(buf, 20, format"\n", value); \ |
| 944 | } | 1002 | } |
| 945 | 1003 | ||
| @@ -954,6 +1012,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); | |||
| 954 | iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); | 1012 | iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); |
| 955 | iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); | 1013 | iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); |
| 956 | 1014 | ||
| 1015 | #define iscsi_cdev_to_session(_cdev) \ | ||
| 1016 | iscsi_dev_to_session(_cdev->dev) | ||
| 1017 | |||
| 957 | /* | 1018 | /* |
| 958 | * iSCSI session attrs | 1019 | * iSCSI session attrs |
| 959 | */ | 1020 | */ |
| @@ -962,20 +1023,11 @@ static ssize_t \ | |||
| 962 | show_session_int_param_##param(struct class_device *cdev, char *buf) \ | 1023 | show_session_int_param_##param(struct class_device *cdev, char *buf) \ |
| 963 | { \ | 1024 | { \ |
| 964 | uint32_t value = 0; \ | 1025 | uint32_t value = 0; \ |
| 965 | struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \ | 1026 | struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ |
| 966 | struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \ | 1027 | struct Scsi_Host *shost = iscsi_session_to_shost(session); \ |
| 967 | struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \ | 1028 | struct iscsi_transport *t = session->transport; \ |
| 968 | struct iscsi_if_conn *conn = NULL; \ | ||
| 969 | unsigned long flags; \ | ||
| 970 | \ | ||
| 971 | spin_lock_irqsave(&connlock, flags); \ | ||
| 972 | if (!list_empty(&session->connections)) \ | ||
| 973 | conn = list_entry(session->connections.next, \ | ||
| 974 | struct iscsi_if_conn, session_list); \ | ||
| 975 | spin_unlock_irqrestore(&connlock, flags); \ | ||
| 976 | \ | 1029 | \ |
| 977 | if (conn && (priv->param_mask & (1 << param))) \ | 1030 | t->get_session_param(shost, param, &value); \ |
| 978 | priv->iscsi_transport->get_param(conn->connh, param, &value);\ | ||
| 979 | return snprintf(buf, 20, format"\n", value); \ | 1031 | return snprintf(buf, 20, format"\n", value); \ |
| 980 | } | 1032 | } |
| 981 | 1033 | ||
| @@ -1004,23 +1056,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); | |||
| 1004 | count++; \ | 1056 | count++; \ |
| 1005 | } | 1057 | } |
| 1006 | 1058 | ||
| 1007 | static int iscsi_is_session_dev(const struct device *dev) | ||
| 1008 | { | ||
| 1009 | return dev->release == iscsi_if_session_dev_release; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | static int iscsi_session_match(struct attribute_container *cont, | 1059 | static int iscsi_session_match(struct attribute_container *cont, |
| 1013 | struct device *dev) | 1060 | struct device *dev) |
| 1014 | { | 1061 | { |
| 1015 | struct iscsi_if_session *session; | 1062 | struct iscsi_cls_session *session; |
| 1016 | struct Scsi_Host *shost; | 1063 | struct Scsi_Host *shost; |
| 1017 | struct iscsi_internal *priv; | 1064 | struct iscsi_internal *priv; |
| 1018 | 1065 | ||
| 1019 | if (!iscsi_is_session_dev(dev)) | 1066 | if (!iscsi_is_session_dev(dev)) |
| 1020 | return 0; | 1067 | return 0; |
| 1021 | 1068 | ||
| 1022 | session = iscsi_dev_to_if_session(dev); | 1069 | session = iscsi_dev_to_session(dev); |
| 1023 | shost = iscsi_if_session_to_shost(session); | 1070 | shost = iscsi_session_to_shost(session); |
| 1024 | if (!shost->transportt) | 1071 | if (!shost->transportt) |
| 1025 | return 0; | 1072 | return 0; |
| 1026 | 1073 | ||
| @@ -1031,23 +1078,21 @@ static int iscsi_session_match(struct attribute_container *cont, | |||
| 1031 | return &priv->session_cont.ac == cont; | 1078 | return &priv->session_cont.ac == cont; |
| 1032 | } | 1079 | } |
| 1033 | 1080 | ||
| 1034 | static int iscsi_is_conn_dev(const struct device *dev) | ||
| 1035 | { | ||
| 1036 | return dev->release == iscsi_if_conn_dev_release; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | static int iscsi_conn_match(struct attribute_container *cont, | 1081 | static int iscsi_conn_match(struct attribute_container *cont, |
| 1040 | struct device *dev) | 1082 | struct device *dev) |
| 1041 | { | 1083 | { |
| 1042 | struct iscsi_if_conn *conn; | 1084 | struct iscsi_cls_session *session; |
| 1085 | struct iscsi_cls_conn *conn; | ||
| 1043 | struct Scsi_Host *shost; | 1086 | struct Scsi_Host *shost; |
| 1044 | struct iscsi_internal *priv; | 1087 | struct iscsi_internal *priv; |
| 1045 | 1088 | ||
| 1046 | if (!iscsi_is_conn_dev(dev)) | 1089 | if (!iscsi_is_conn_dev(dev)) |
| 1047 | return 0; | 1090 | return 0; |
| 1048 | 1091 | ||
| 1049 | conn = iscsi_dev_to_if_conn(dev); | 1092 | conn = iscsi_dev_to_conn(dev); |
| 1050 | shost = conn->host; | 1093 | session = iscsi_dev_to_session(conn->dev.parent); |
| 1094 | shost = iscsi_session_to_shost(session); | ||
| 1095 | |||
| 1051 | if (!shost->transportt) | 1096 | if (!shost->transportt) |
| 1052 | return 0; | 1097 | return 0; |
| 1053 | 1098 | ||
| @@ -1058,7 +1103,8 @@ static int iscsi_conn_match(struct attribute_container *cont, | |||
| 1058 | return &priv->conn_cont.ac == cont; | 1103 | return &priv->conn_cont.ac == cont; |
| 1059 | } | 1104 | } |
| 1060 | 1105 | ||
| 1061 | int iscsi_register_transport(struct iscsi_transport *tt) | 1106 | struct scsi_transport_template * |
| 1107 | iscsi_register_transport(struct iscsi_transport *tt) | ||
| 1062 | { | 1108 | { |
| 1063 | struct iscsi_internal *priv; | 1109 | struct iscsi_internal *priv; |
| 1064 | unsigned long flags; | 1110 | unsigned long flags; |
| @@ -1068,15 +1114,14 @@ int iscsi_register_transport(struct iscsi_transport *tt) | |||
| 1068 | 1114 | ||
| 1069 | priv = iscsi_if_transport_lookup(tt); | 1115 | priv = iscsi_if_transport_lookup(tt); |
| 1070 | if (priv) | 1116 | if (priv) |
| 1071 | return -EEXIST; | 1117 | return NULL; |
| 1072 | 1118 | ||
| 1073 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); | 1119 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); |
| 1074 | if (!priv) | 1120 | if (!priv) |
| 1075 | return -ENOMEM; | 1121 | return NULL; |
| 1076 | memset(priv, 0, sizeof(*priv)); | 1122 | memset(priv, 0, sizeof(*priv)); |
| 1077 | INIT_LIST_HEAD(&priv->list); | 1123 | INIT_LIST_HEAD(&priv->list); |
| 1078 | INIT_LIST_HEAD(&priv->sessions); | 1124 | INIT_LIST_HEAD(&priv->sessions); |
| 1079 | spin_lock_init(&priv->session_lock); | ||
| 1080 | priv->iscsi_transport = tt; | 1125 | priv->iscsi_transport = tt; |
| 1081 | 1126 | ||
| 1082 | priv->cdev.class = &iscsi_transport_class; | 1127 | priv->cdev.class = &iscsi_transport_class; |
| @@ -1142,13 +1187,13 @@ int iscsi_register_transport(struct iscsi_transport *tt) | |||
| 1142 | spin_unlock_irqrestore(&iscsi_transport_lock, flags); | 1187 | spin_unlock_irqrestore(&iscsi_transport_lock, flags); |
| 1143 | 1188 | ||
| 1144 | printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); | 1189 | printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); |
| 1145 | return 0; | 1190 | return &priv->t; |
| 1146 | 1191 | ||
| 1147 | unregister_cdev: | 1192 | unregister_cdev: |
| 1148 | class_device_unregister(&priv->cdev); | 1193 | class_device_unregister(&priv->cdev); |
| 1149 | free_priv: | 1194 | free_priv: |
| 1150 | kfree(priv); | 1195 | kfree(priv); |
| 1151 | return err; | 1196 | return NULL; |
| 1152 | } | 1197 | } |
| 1153 | EXPORT_SYMBOL_GPL(iscsi_register_transport); | 1198 | EXPORT_SYMBOL_GPL(iscsi_register_transport); |
| 1154 | 1199 | ||
| @@ -1159,19 +1204,11 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) | |||
| 1159 | 1204 | ||
| 1160 | BUG_ON(!tt); | 1205 | BUG_ON(!tt); |
| 1161 | 1206 | ||
| 1162 | down(&rx_queue_sema); | 1207 | mutex_lock(&rx_queue_mutex); |
| 1163 | 1208 | ||
| 1164 | priv = iscsi_if_transport_lookup(tt); | 1209 | priv = iscsi_if_transport_lookup(tt); |
| 1165 | BUG_ON (!priv); | 1210 | BUG_ON (!priv); |
| 1166 | 1211 | ||
| 1167 | spin_lock_irqsave(&priv->session_lock, flags); | ||
| 1168 | if (!list_empty(&priv->sessions)) { | ||
| 1169 | spin_unlock_irqrestore(&priv->session_lock, flags); | ||
| 1170 | up(&rx_queue_sema); | ||
| 1171 | return -EPERM; | ||
| 1172 | } | ||
| 1173 | spin_unlock_irqrestore(&priv->session_lock, flags); | ||
| 1174 | |||
| 1175 | spin_lock_irqsave(&iscsi_transport_lock, flags); | 1212 | spin_lock_irqsave(&iscsi_transport_lock, flags); |
| 1176 | list_del(&priv->list); | 1213 | list_del(&priv->list); |
| 1177 | spin_unlock_irqrestore(&iscsi_transport_lock, flags); | 1214 | spin_unlock_irqrestore(&iscsi_transport_lock, flags); |
| @@ -1181,7 +1218,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) | |||
| 1181 | 1218 | ||
| 1182 | sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); | 1219 | sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); |
| 1183 | class_device_unregister(&priv->cdev); | 1220 | class_device_unregister(&priv->cdev); |
| 1184 | up(&rx_queue_sema); | 1221 | mutex_unlock(&rx_queue_mutex); |
| 1185 | 1222 | ||
| 1186 | return 0; | 1223 | return 0; |
| 1187 | } | 1224 | } |
| @@ -1194,14 +1231,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) | |||
| 1194 | 1231 | ||
| 1195 | if (event == NETLINK_URELEASE && | 1232 | if (event == NETLINK_URELEASE && |
| 1196 | n->protocol == NETLINK_ISCSI && n->pid) { | 1233 | n->protocol == NETLINK_ISCSI && n->pid) { |
| 1197 | struct iscsi_if_conn *conn; | 1234 | struct iscsi_cls_conn *conn; |
| 1198 | unsigned long flags; | 1235 | unsigned long flags; |
| 1199 | 1236 | ||
| 1200 | mempool_zone_complete(&z_reply); | 1237 | mempool_zone_complete(z_reply); |
| 1201 | spin_lock_irqsave(&connlock, flags); | 1238 | spin_lock_irqsave(&connlock, flags); |
| 1202 | list_for_each_entry(conn, &connlist, conn_list) { | 1239 | list_for_each_entry(conn, &connlist, conn_list) { |
| 1203 | mempool_zone_complete(&conn->z_error); | 1240 | mempool_zone_complete(conn->z_error); |
| 1204 | mempool_zone_complete(&conn->z_pdu); | 1241 | mempool_zone_complete(conn->z_pdu); |
| 1205 | } | 1242 | } |
| 1206 | spin_unlock_irqrestore(&connlock, flags); | 1243 | spin_unlock_irqrestore(&connlock, flags); |
| 1207 | } | 1244 | } |
| @@ -1234,15 +1271,15 @@ static __init int iscsi_transport_init(void) | |||
| 1234 | goto unregister_session_class; | 1271 | goto unregister_session_class; |
| 1235 | 1272 | ||
| 1236 | nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, | 1273 | nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, |
| 1237 | THIS_MODULE); | 1274 | THIS_MODULE); |
| 1238 | if (!nls) { | 1275 | if (!nls) { |
| 1239 | err = -ENOBUFS; | 1276 | err = -ENOBUFS; |
| 1240 | goto unregister_notifier; | 1277 | goto unregister_notifier; |
| 1241 | } | 1278 | } |
| 1242 | 1279 | ||
| 1243 | err = mempool_zone_init(&z_reply, Z_MAX_REPLY, | 1280 | z_reply = mempool_zone_init(Z_MAX_REPLY, |
| 1244 | NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); | 1281 | NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); |
| 1245 | if (!err) | 1282 | if (z_reply) |
| 1246 | return 0; | 1283 | return 0; |
| 1247 | 1284 | ||
| 1248 | sock_release(nls->sk_socket); | 1285 | sock_release(nls->sk_socket); |
| @@ -1259,7 +1296,7 @@ unregister_transport_class: | |||
| 1259 | 1296 | ||
| 1260 | static void __exit iscsi_transport_exit(void) | 1297 | static void __exit iscsi_transport_exit(void) |
| 1261 | { | 1298 | { |
| 1262 | mempool_destroy(z_reply.pool); | 1299 | mempool_zone_destroy(z_reply); |
| 1263 | sock_release(nls->sk_socket); | 1300 | sock_release(nls->sk_socket); |
| 1264 | netlink_unregister_notifier(&iscsi_nl_notifier); | 1301 | netlink_unregister_notifier(&iscsi_nl_notifier); |
| 1265 | transport_class_unregister(&iscsi_connection_class); | 1302 | transport_class_unregister(&iscsi_connection_class); |
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index edabbd05d258..a3e0b7bc2d7b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
| 31 | 31 | ||
| 32 | #include <scsi/scsi.h> | ||
| 32 | #include <scsi/scsi_device.h> | 33 | #include <scsi/scsi_device.h> |
| 33 | #include <scsi/scsi_host.h> | 34 | #include <scsi/scsi_host.h> |
| 34 | #include <scsi/scsi_transport.h> | 35 | #include <scsi/scsi_transport.h> |
| @@ -62,7 +63,7 @@ struct sas_internal { | |||
| 62 | 63 | ||
| 63 | struct sas_host_attrs { | 64 | struct sas_host_attrs { |
| 64 | struct list_head rphy_list; | 65 | struct list_head rphy_list; |
| 65 | spinlock_t lock; | 66 | struct mutex lock; |
| 66 | u32 next_target_id; | 67 | u32 next_target_id; |
| 67 | }; | 68 | }; |
| 68 | #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) | 69 | #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) |
| @@ -165,7 +166,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, | |||
| 165 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 166 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
| 166 | 167 | ||
| 167 | INIT_LIST_HEAD(&sas_host->rphy_list); | 168 | INIT_LIST_HEAD(&sas_host->rphy_list); |
| 168 | spin_lock_init(&sas_host->lock); | 169 | mutex_init(&sas_host->lock); |
| 169 | sas_host->next_target_id = 0; | 170 | sas_host->next_target_id = 0; |
| 170 | return 0; | 171 | return 0; |
| 171 | } | 172 | } |
| @@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy) | |||
| 626 | transport_add_device(&rphy->dev); | 627 | transport_add_device(&rphy->dev); |
| 627 | transport_configure_device(&rphy->dev); | 628 | transport_configure_device(&rphy->dev); |
| 628 | 629 | ||
| 629 | spin_lock(&sas_host->lock); | 630 | mutex_lock(&sas_host->lock); |
| 630 | list_add_tail(&rphy->list, &sas_host->rphy_list); | 631 | list_add_tail(&rphy->list, &sas_host->rphy_list); |
| 631 | if (identify->device_type == SAS_END_DEVICE && | 632 | if (identify->device_type == SAS_END_DEVICE && |
| 632 | (identify->target_port_protocols & | 633 | (identify->target_port_protocols & |
| @@ -634,10 +635,10 @@ int sas_rphy_add(struct sas_rphy *rphy) | |||
| 634 | rphy->scsi_target_id = sas_host->next_target_id++; | 635 | rphy->scsi_target_id = sas_host->next_target_id++; |
| 635 | else | 636 | else |
| 636 | rphy->scsi_target_id = -1; | 637 | rphy->scsi_target_id = -1; |
| 637 | spin_unlock(&sas_host->lock); | 638 | mutex_unlock(&sas_host->lock); |
| 638 | 639 | ||
| 639 | if (rphy->scsi_target_id != -1) { | 640 | if (rphy->scsi_target_id != -1) { |
| 640 | scsi_scan_target(&rphy->dev, parent->number, | 641 | scsi_scan_target(&rphy->dev, parent->port_identifier, |
| 641 | rphy->scsi_target_id, ~0, 0); | 642 | rphy->scsi_target_id, ~0, 0); |
| 642 | } | 643 | } |
| 643 | 644 | ||
| @@ -661,9 +662,9 @@ void sas_rphy_free(struct sas_rphy *rphy) | |||
| 661 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | 662 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); |
| 662 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 663 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
| 663 | 664 | ||
| 664 | spin_lock(&sas_host->lock); | 665 | mutex_lock(&sas_host->lock); |
| 665 | list_del(&rphy->list); | 666 | list_del(&rphy->list); |
| 666 | spin_unlock(&sas_host->lock); | 667 | mutex_unlock(&sas_host->lock); |
| 667 | 668 | ||
| 668 | transport_destroy_device(&rphy->dev); | 669 | transport_destroy_device(&rphy->dev); |
| 669 | put_device(rphy->dev.parent); | 670 | put_device(rphy->dev.parent); |
| @@ -687,15 +688,27 @@ sas_rphy_delete(struct sas_rphy *rphy) | |||
| 687 | struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); | 688 | struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); |
| 688 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 689 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
| 689 | 690 | ||
| 690 | scsi_remove_target(dev); | 691 | switch (rphy->identify.device_type) { |
| 692 | case SAS_END_DEVICE: | ||
| 693 | scsi_remove_target(dev); | ||
| 694 | break; | ||
| 695 | case SAS_EDGE_EXPANDER_DEVICE: | ||
| 696 | case SAS_FANOUT_EXPANDER_DEVICE: | ||
| 697 | device_for_each_child(dev, NULL, do_sas_phy_delete); | ||
| 698 | break; | ||
| 699 | default: | ||
| 700 | break; | ||
| 701 | } | ||
| 691 | 702 | ||
| 692 | transport_remove_device(dev); | 703 | transport_remove_device(dev); |
| 693 | device_del(dev); | 704 | device_del(dev); |
| 694 | transport_destroy_device(dev); | 705 | transport_destroy_device(dev); |
| 695 | 706 | ||
| 696 | spin_lock(&sas_host->lock); | 707 | mutex_lock(&sas_host->lock); |
| 697 | list_del(&rphy->list); | 708 | list_del(&rphy->list); |
| 698 | spin_unlock(&sas_host->lock); | 709 | mutex_unlock(&sas_host->lock); |
| 710 | |||
| 711 | parent->rphy = NULL; | ||
| 699 | 712 | ||
| 700 | put_device(&parent->dev); | 713 | put_device(&parent->dev); |
| 701 | } | 714 | } |
| @@ -719,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy); | |||
| 719 | * SCSI scan helper | 732 | * SCSI scan helper |
| 720 | */ | 733 | */ |
| 721 | 734 | ||
| 722 | static struct device *sas_target_parent(struct Scsi_Host *shost, | 735 | static int sas_user_scan(struct Scsi_Host *shost, uint channel, |
| 723 | int channel, uint id) | 736 | uint id, uint lun) |
| 724 | { | 737 | { |
| 725 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | 738 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); |
| 726 | struct sas_rphy *rphy; | 739 | struct sas_rphy *rphy; |
| 727 | struct device *dev = NULL; | ||
| 728 | 740 | ||
| 729 | spin_lock(&sas_host->lock); | 741 | mutex_lock(&sas_host->lock); |
| 730 | list_for_each_entry(rphy, &sas_host->rphy_list, list) { | 742 | list_for_each_entry(rphy, &sas_host->rphy_list, list) { |
| 731 | struct sas_phy *parent = dev_to_phy(rphy->dev.parent); | 743 | struct sas_phy *parent = dev_to_phy(rphy->dev.parent); |
| 732 | if (parent->number == channel && | 744 | |
| 733 | rphy->scsi_target_id == id) | 745 | if (rphy->scsi_target_id == -1) |
| 734 | dev = &rphy->dev; | 746 | continue; |
| 747 | |||
| 748 | if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) && | ||
| 749 | (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { | ||
| 750 | scsi_scan_target(&rphy->dev, parent->port_identifier, | ||
| 751 | rphy->scsi_target_id, lun, 1); | ||
| 752 | } | ||
| 735 | } | 753 | } |
| 736 | spin_unlock(&sas_host->lock); | 754 | mutex_unlock(&sas_host->lock); |
| 737 | 755 | ||
| 738 | return dev; | 756 | return 0; |
| 739 | } | 757 | } |
| 740 | 758 | ||
| 741 | 759 | ||
| @@ -780,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft) | |||
| 780 | return NULL; | 798 | return NULL; |
| 781 | memset(i, 0, sizeof(struct sas_internal)); | 799 | memset(i, 0, sizeof(struct sas_internal)); |
| 782 | 800 | ||
| 783 | i->t.target_parent = sas_target_parent; | 801 | i->t.user_scan = sas_user_scan; |
| 784 | 802 | ||
| 785 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; | 803 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; |
| 786 | i->t.host_attrs.ac.class = &sas_host_class.class; | 804 | i->t.host_attrs.ac.class = &sas_host_class.class; |
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 46da6fe10ad5..7ee95eb83dda 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
| 26 | #include <linux/blkdev.h> | 26 | #include <linux/blkdev.h> |
| 27 | #include <asm/semaphore.h> | 27 | #include <linux/mutex.h> |
| 28 | #include <scsi/scsi.h> | 28 | #include <scsi/scsi.h> |
| 29 | #include "scsi_priv.h" | 29 | #include "scsi_priv.h" |
| 30 | #include <scsi/scsi_device.h> | 30 | #include <scsi/scsi_device.h> |
| @@ -48,7 +48,7 @@ | |||
| 48 | 48 | ||
| 49 | /* Private data accessors (keep these out of the header file) */ | 49 | /* Private data accessors (keep these out of the header file) */ |
| 50 | #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) | 50 | #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) |
| 51 | #define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) | 51 | #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) |
| 52 | 52 | ||
| 53 | struct spi_internal { | 53 | struct spi_internal { |
| 54 | struct scsi_transport_template t; | 54 | struct scsi_transport_template t; |
| @@ -242,7 +242,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc, | |||
| 242 | spi_hold_mcs(starget) = 0; | 242 | spi_hold_mcs(starget) = 0; |
| 243 | spi_dv_pending(starget) = 0; | 243 | spi_dv_pending(starget) = 0; |
| 244 | spi_initial_dv(starget) = 0; | 244 | spi_initial_dv(starget) = 0; |
| 245 | init_MUTEX(&spi_dv_sem(starget)); | 245 | mutex_init(&spi_dv_mutex(starget)); |
| 246 | 246 | ||
| 247 | return 0; | 247 | return 0; |
| 248 | } | 248 | } |
| @@ -915,7 +915,7 @@ spi_dv_device(struct scsi_device *sdev) | |||
| 915 | scsi_target_quiesce(starget); | 915 | scsi_target_quiesce(starget); |
| 916 | 916 | ||
| 917 | spi_dv_pending(starget) = 1; | 917 | spi_dv_pending(starget) = 1; |
| 918 | down(&spi_dv_sem(starget)); | 918 | mutex_lock(&spi_dv_mutex(starget)); |
| 919 | 919 | ||
| 920 | starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n"); | 920 | starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n"); |
| 921 | 921 | ||
| @@ -923,7 +923,7 @@ spi_dv_device(struct scsi_device *sdev) | |||
| 923 | 923 | ||
| 924 | starget_printk(KERN_INFO, starget, "Ending Domain Validation\n"); | 924 | starget_printk(KERN_INFO, starget, "Ending Domain Validation\n"); |
| 925 | 925 | ||
| 926 | up(&spi_dv_sem(starget)); | 926 | mutex_unlock(&spi_dv_mutex(starget)); |
| 927 | spi_dv_pending(starget) = 0; | 927 | spi_dv_pending(starget) = 0; |
| 928 | 928 | ||
| 929 | scsi_target_resume(starget); | 929 | scsi_target_resume(starget); |
| @@ -1075,7 +1075,7 @@ static const char * const extended_msgs[] = { | |||
| 1075 | /* 0x04 */ "Parallel Protocol Request" | 1075 | /* 0x04 */ "Parallel Protocol Request" |
| 1076 | }; | 1076 | }; |
| 1077 | 1077 | ||
| 1078 | void print_nego(const unsigned char *msg, int per, int off, int width) | 1078 | static void print_nego(const unsigned char *msg, int per, int off, int width) |
| 1079 | { | 1079 | { |
| 1080 | if (per) { | 1080 | if (per) { |
| 1081 | char buf[20]; | 1081 | char buf[20]; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4c5127ed379c..930db398d107 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <linux/blkpg.h> | 49 | #include <linux/blkpg.h> |
| 50 | #include <linux/kref.h> | 50 | #include <linux/kref.h> |
| 51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
| 52 | #include <linux/mutex.h> | ||
| 52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
| 53 | 54 | ||
| 54 | #include <scsi/scsi.h> | 55 | #include <scsi/scsi.h> |
| @@ -111,7 +112,7 @@ static DEFINE_SPINLOCK(sd_index_lock); | |||
| 111 | /* This semaphore is used to mediate the 0->1 reference get in the | 112 | /* This semaphore is used to mediate the 0->1 reference get in the |
| 112 | * face of object destruction (i.e. we can't allow a get on an | 113 | * face of object destruction (i.e. we can't allow a get on an |
| 113 | * object after last put) */ | 114 | * object after last put) */ |
| 114 | static DECLARE_MUTEX(sd_ref_sem); | 115 | static DEFINE_MUTEX(sd_ref_mutex); |
| 115 | 116 | ||
| 116 | static int sd_revalidate_disk(struct gendisk *disk); | 117 | static int sd_revalidate_disk(struct gendisk *disk); |
| 117 | static void sd_rw_intr(struct scsi_cmnd * SCpnt); | 118 | static void sd_rw_intr(struct scsi_cmnd * SCpnt); |
| @@ -193,9 +194,9 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) | |||
| 193 | { | 194 | { |
| 194 | struct scsi_disk *sdkp; | 195 | struct scsi_disk *sdkp; |
| 195 | 196 | ||
| 196 | down(&sd_ref_sem); | 197 | mutex_lock(&sd_ref_mutex); |
| 197 | sdkp = __scsi_disk_get(disk); | 198 | sdkp = __scsi_disk_get(disk); |
| 198 | up(&sd_ref_sem); | 199 | mutex_unlock(&sd_ref_mutex); |
| 199 | return sdkp; | 200 | return sdkp; |
| 200 | } | 201 | } |
| 201 | 202 | ||
| @@ -203,11 +204,11 @@ static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev) | |||
| 203 | { | 204 | { |
| 204 | struct scsi_disk *sdkp; | 205 | struct scsi_disk *sdkp; |
| 205 | 206 | ||
| 206 | down(&sd_ref_sem); | 207 | mutex_lock(&sd_ref_mutex); |
| 207 | sdkp = dev_get_drvdata(dev); | 208 | sdkp = dev_get_drvdata(dev); |
| 208 | if (sdkp) | 209 | if (sdkp) |
| 209 | sdkp = __scsi_disk_get(sdkp->disk); | 210 | sdkp = __scsi_disk_get(sdkp->disk); |
| 210 | up(&sd_ref_sem); | 211 | mutex_unlock(&sd_ref_mutex); |
| 211 | return sdkp; | 212 | return sdkp; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| @@ -215,10 +216,10 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
| 215 | { | 216 | { |
| 216 | struct scsi_device *sdev = sdkp->device; | 217 | struct scsi_device *sdev = sdkp->device; |
| 217 | 218 | ||
| 218 | down(&sd_ref_sem); | 219 | mutex_lock(&sd_ref_mutex); |
| 219 | kref_put(&sdkp->kref, scsi_disk_release); | 220 | kref_put(&sdkp->kref, scsi_disk_release); |
| 220 | scsi_device_put(sdev); | 221 | scsi_device_put(sdev); |
| 221 | up(&sd_ref_sem); | 222 | mutex_unlock(&sd_ref_mutex); |
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | /** | 225 | /** |
| @@ -231,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
| 231 | **/ | 232 | **/ |
| 232 | static int sd_init_command(struct scsi_cmnd * SCpnt) | 233 | static int sd_init_command(struct scsi_cmnd * SCpnt) |
| 233 | { | 234 | { |
| 234 | unsigned int this_count, timeout; | ||
| 235 | struct gendisk *disk; | ||
| 236 | sector_t block; | ||
| 237 | struct scsi_device *sdp = SCpnt->device; | 235 | struct scsi_device *sdp = SCpnt->device; |
| 238 | struct request *rq = SCpnt->request; | 236 | struct request *rq = SCpnt->request; |
| 239 | 237 | struct gendisk *disk = rq->rq_disk; | |
| 240 | timeout = sdp->timeout; | 238 | sector_t block = rq->sector; |
| 241 | 239 | unsigned int this_count = SCpnt->request_bufflen >> 9; | |
| 242 | /* | 240 | unsigned int timeout = sdp->timeout; |
| 243 | * SG_IO from block layer already setup, just copy cdb basically | ||
| 244 | */ | ||
| 245 | if (blk_pc_request(rq)) { | ||
| 246 | scsi_setup_blk_pc_cmnd(SCpnt); | ||
| 247 | if (rq->timeout) | ||
| 248 | timeout = rq->timeout; | ||
| 249 | |||
| 250 | goto queue; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * we only do REQ_CMD and REQ_BLOCK_PC | ||
| 255 | */ | ||
| 256 | if (!blk_fs_request(rq)) | ||
| 257 | return 0; | ||
| 258 | |||
| 259 | disk = rq->rq_disk; | ||
| 260 | block = rq->sector; | ||
| 261 | this_count = SCpnt->request_bufflen >> 9; | ||
| 262 | 241 | ||
| 263 | SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " | 242 | SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " |
| 264 | "count=%d\n", disk->disk_name, | 243 | "count=%d\n", disk->disk_name, |
| @@ -401,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
| 401 | SCpnt->transfersize = sdp->sector_size; | 380 | SCpnt->transfersize = sdp->sector_size; |
| 402 | SCpnt->underflow = this_count << 9; | 381 | SCpnt->underflow = this_count << 9; |
| 403 | SCpnt->allowed = SD_MAX_RETRIES; | 382 | SCpnt->allowed = SD_MAX_RETRIES; |
| 404 | |||
| 405 | queue: | ||
| 406 | SCpnt->timeout_per_command = timeout; | 383 | SCpnt->timeout_per_command = timeout; |
| 407 | 384 | ||
| 408 | /* | 385 | /* |
| @@ -836,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
| 836 | relatively rare error condition, no care is taken to avoid | 813 | relatively rare error condition, no care is taken to avoid |
| 837 | unnecessary additional work such as memcpy's that could be avoided. | 814 | unnecessary additional work such as memcpy's that could be avoided. |
| 838 | */ | 815 | */ |
| 839 | 816 | if (driver_byte(result) != 0 && | |
| 840 | /* | ||
| 841 | * If SG_IO from block layer then set good_bytes to stop retries; | ||
| 842 | * else if errors, check them, and if necessary prepare for | ||
| 843 | * (partial) retries. | ||
| 844 | */ | ||
| 845 | if (blk_pc_request(SCpnt->request)) | ||
| 846 | good_bytes = this_count; | ||
| 847 | else if (driver_byte(result) != 0 && | ||
| 848 | sense_valid && !sense_deferred) { | 817 | sense_valid && !sense_deferred) { |
| 849 | switch (sshdr.sense_key) { | 818 | switch (sshdr.sense_key) { |
| 850 | case MEDIUM_ERROR: | 819 | case MEDIUM_ERROR: |
| @@ -1635,10 +1604,10 @@ static int sd_remove(struct device *dev) | |||
| 1635 | del_gendisk(sdkp->disk); | 1604 | del_gendisk(sdkp->disk); |
| 1636 | sd_shutdown(dev); | 1605 | sd_shutdown(dev); |
| 1637 | 1606 | ||
| 1638 | down(&sd_ref_sem); | 1607 | mutex_lock(&sd_ref_mutex); |
| 1639 | dev_set_drvdata(dev, NULL); | 1608 | dev_set_drvdata(dev, NULL); |
| 1640 | kref_put(&sdkp->kref, scsi_disk_release); | 1609 | kref_put(&sdkp->kref, scsi_disk_release); |
| 1641 | up(&sd_ref_sem); | 1610 | mutex_unlock(&sd_ref_mutex); |
| 1642 | 1611 | ||
| 1643 | return 0; | 1612 | return 0; |
| 1644 | } | 1613 | } |
| @@ -1647,7 +1616,7 @@ static int sd_remove(struct device *dev) | |||
| 1647 | * scsi_disk_release - Called to free the scsi_disk structure | 1616 | * scsi_disk_release - Called to free the scsi_disk structure |
| 1648 | * @kref: pointer to embedded kref | 1617 | * @kref: pointer to embedded kref |
| 1649 | * | 1618 | * |
| 1650 | * sd_ref_sem must be held entering this routine. Because it is | 1619 | * sd_ref_mutex must be held entering this routine. Because it is |
| 1651 | * called on last put, you should always use the scsi_disk_get() | 1620 | * called on last put, you should always use the scsi_disk_get() |
| 1652 | * scsi_disk_put() helpers which manipulate the semaphore directly | 1621 | * scsi_disk_put() helpers which manipulate the semaphore directly |
| 1653 | * and never do a direct kref_put(). | 1622 | * and never do a direct kref_put(). |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index a4d9be7c6874..997f8e30509b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
| 45 | #include <linux/init.h> | 45 | #include <linux/init.h> |
| 46 | #include <linux/blkdev.h> | 46 | #include <linux/blkdev.h> |
| 47 | #include <linux/mutex.h> | ||
| 47 | #include <asm/uaccess.h> | 48 | #include <asm/uaccess.h> |
| 48 | 49 | ||
| 49 | #include <scsi/scsi.h> | 50 | #include <scsi/scsi.h> |
| @@ -90,7 +91,7 @@ static DEFINE_SPINLOCK(sr_index_lock); | |||
| 90 | /* This semaphore is used to mediate the 0->1 reference get in the | 91 | /* This semaphore is used to mediate the 0->1 reference get in the |
| 91 | * face of object destruction (i.e. we can't allow a get on an | 92 | * face of object destruction (i.e. we can't allow a get on an |
| 92 | * object after last put) */ | 93 | * object after last put) */ |
| 93 | static DECLARE_MUTEX(sr_ref_sem); | 94 | static DEFINE_MUTEX(sr_ref_mutex); |
| 94 | 95 | ||
| 95 | static int sr_open(struct cdrom_device_info *, int); | 96 | static int sr_open(struct cdrom_device_info *, int); |
| 96 | static void sr_release(struct cdrom_device_info *); | 97 | static void sr_release(struct cdrom_device_info *); |
| @@ -133,7 +134,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) | |||
| 133 | { | 134 | { |
| 134 | struct scsi_cd *cd = NULL; | 135 | struct scsi_cd *cd = NULL; |
| 135 | 136 | ||
| 136 | down(&sr_ref_sem); | 137 | mutex_lock(&sr_ref_mutex); |
| 137 | if (disk->private_data == NULL) | 138 | if (disk->private_data == NULL) |
| 138 | goto out; | 139 | goto out; |
| 139 | cd = scsi_cd(disk); | 140 | cd = scsi_cd(disk); |
| @@ -146,18 +147,18 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) | |||
| 146 | kref_put(&cd->kref, sr_kref_release); | 147 | kref_put(&cd->kref, sr_kref_release); |
| 147 | cd = NULL; | 148 | cd = NULL; |
| 148 | out: | 149 | out: |
| 149 | up(&sr_ref_sem); | 150 | mutex_unlock(&sr_ref_mutex); |
| 150 | return cd; | 151 | return cd; |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | static inline void scsi_cd_put(struct scsi_cd *cd) | 154 | static void scsi_cd_put(struct scsi_cd *cd) |
| 154 | { | 155 | { |
| 155 | struct scsi_device *sdev = cd->device; | 156 | struct scsi_device *sdev = cd->device; |
| 156 | 157 | ||
| 157 | down(&sr_ref_sem); | 158 | mutex_lock(&sr_ref_mutex); |
| 158 | kref_put(&cd->kref, sr_kref_release); | 159 | kref_put(&cd->kref, sr_kref_release); |
| 159 | scsi_device_put(sdev); | 160 | scsi_device_put(sdev); |
| 160 | up(&sr_ref_sem); | 161 | mutex_unlock(&sr_ref_mutex); |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | /* | 164 | /* |
| @@ -237,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt) | |||
| 237 | case ILLEGAL_REQUEST: | 238 | case ILLEGAL_REQUEST: |
| 238 | if (!(SCpnt->sense_buffer[0] & 0x90)) | 239 | if (!(SCpnt->sense_buffer[0] & 0x90)) |
| 239 | break; | 240 | break; |
| 240 | if (!blk_fs_request(SCpnt->request)) | ||
| 241 | break; | ||
| 242 | error_sector = (SCpnt->sense_buffer[3] << 24) | | 241 | error_sector = (SCpnt->sense_buffer[3] << 24) | |
| 243 | (SCpnt->sense_buffer[4] << 16) | | 242 | (SCpnt->sense_buffer[4] << 16) | |
| 244 | (SCpnt->sense_buffer[5] << 8) | | 243 | (SCpnt->sense_buffer[5] << 8) | |
| @@ -317,23 +316,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) | |||
| 317 | } | 316 | } |
| 318 | 317 | ||
| 319 | /* | 318 | /* |
| 320 | * these are already setup, just copy cdb basically | ||
| 321 | */ | ||
| 322 | if (SCpnt->request->flags & REQ_BLOCK_PC) { | ||
| 323 | scsi_setup_blk_pc_cmnd(SCpnt); | ||
| 324 | |||
| 325 | if (SCpnt->timeout_per_command) | ||
| 326 | timeout = SCpnt->timeout_per_command; | ||
| 327 | |||
| 328 | goto queue; | ||
| 329 | } | ||
| 330 | |||
| 331 | if (!(SCpnt->request->flags & REQ_CMD)) { | ||
| 332 | blk_dump_rq_flags(SCpnt->request, "sr unsup command"); | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* | ||
| 337 | * we do lazy blocksize switching (when reading XA sectors, | 319 | * we do lazy blocksize switching (when reading XA sectors, |
| 338 | * see CDROMREADMODE2 ioctl) | 320 | * see CDROMREADMODE2 ioctl) |
| 339 | */ | 321 | */ |
| @@ -421,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) | |||
| 421 | */ | 403 | */ |
| 422 | SCpnt->transfersize = cd->device->sector_size; | 404 | SCpnt->transfersize = cd->device->sector_size; |
| 423 | SCpnt->underflow = this_count << 9; | 405 | SCpnt->underflow = this_count << 9; |
| 424 | |||
| 425 | queue: | ||
| 426 | SCpnt->allowed = MAX_RETRIES; | 406 | SCpnt->allowed = MAX_RETRIES; |
| 427 | SCpnt->timeout_per_command = timeout; | 407 | SCpnt->timeout_per_command = timeout; |
| 428 | 408 | ||
| @@ -762,8 +742,9 @@ static void get_capabilities(struct scsi_cd *cd) | |||
| 762 | /* failed, drive doesn't have capabilities mode page */ | 742 | /* failed, drive doesn't have capabilities mode page */ |
| 763 | cd->cdi.speed = 1; | 743 | cd->cdi.speed = 1; |
| 764 | cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | | 744 | cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | |
| 765 | CDC_DVD | CDC_DVD_RAM | | 745 | CDC_DVD | CDC_DVD_RAM | |
| 766 | CDC_SELECT_DISC | CDC_SELECT_SPEED); | 746 | CDC_SELECT_DISC | CDC_SELECT_SPEED | |
| 747 | CDC_MRW | CDC_MRW_W | CDC_RAM); | ||
| 767 | kfree(buffer); | 748 | kfree(buffer); |
| 768 | printk("%s: scsi-1 drive\n", cd->cdi.name); | 749 | printk("%s: scsi-1 drive\n", cd->cdi.name); |
| 769 | return; | 750 | return; |
| @@ -845,7 +826,7 @@ static int sr_packet(struct cdrom_device_info *cdi, | |||
| 845 | * sr_kref_release - Called to free the scsi_cd structure | 826 | * sr_kref_release - Called to free the scsi_cd structure |
| 846 | * @kref: pointer to embedded kref | 827 | * @kref: pointer to embedded kref |
| 847 | * | 828 | * |
| 848 | * sr_ref_sem must be held entering this routine. Because it is | 829 | * sr_ref_mutex must be held entering this routine. Because it is |
| 849 | * called on last put, you should always use the scsi_cd_get() | 830 | * called on last put, you should always use the scsi_cd_get() |
| 850 | * scsi_cd_put() helpers which manipulate the semaphore directly | 831 | * scsi_cd_put() helpers which manipulate the semaphore directly |
| 851 | * and never do a direct kref_put(). | 832 | * and never do a direct kref_put(). |
| @@ -874,9 +855,9 @@ static int sr_remove(struct device *dev) | |||
| 874 | 855 | ||
| 875 | del_gendisk(cd->disk); | 856 | del_gendisk(cd->disk); |
| 876 | 857 | ||
| 877 | down(&sr_ref_sem); | 858 | mutex_lock(&sr_ref_mutex); |
| 878 | kref_put(&cd->kref, sr_kref_release); | 859 | kref_put(&cd->kref, sr_kref_release); |
| 879 | up(&sr_ref_sem); | 860 | mutex_unlock(&sr_ref_mutex); |
| 880 | 861 | ||
| 881 | return 0; | 862 | return 0; |
| 882 | } | 863 | } |
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 6e45ac3c43c5..5d02ff4db6cc 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c | |||
| @@ -31,6 +31,79 @@ static int xa_test = 0; | |||
| 31 | 31 | ||
| 32 | module_param(xa_test, int, S_IRUGO | S_IWUSR); | 32 | module_param(xa_test, int, S_IRUGO | S_IWUSR); |
| 33 | 33 | ||
| 34 | /* primitive to determine whether we need to have GFP_DMA set based on | ||
| 35 | * the status of the unchecked_isa_dma flag in the host structure */ | ||
| 36 | #define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) | ||
| 37 | |||
| 38 | |||
| 39 | static int sr_read_tochdr(struct cdrom_device_info *cdi, | ||
| 40 | struct cdrom_tochdr *tochdr) | ||
| 41 | { | ||
| 42 | struct scsi_cd *cd = cdi->handle; | ||
| 43 | struct packet_command cgc; | ||
| 44 | int result; | ||
| 45 | unsigned char *buffer; | ||
| 46 | |||
| 47 | buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); | ||
| 48 | if (!buffer) | ||
| 49 | return -ENOMEM; | ||
| 50 | |||
| 51 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
| 52 | cgc.timeout = IOCTL_TIMEOUT; | ||
| 53 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | ||
| 54 | cgc.cmd[8] = 12; /* LSB of length */ | ||
| 55 | cgc.buffer = buffer; | ||
| 56 | cgc.buflen = 12; | ||
| 57 | cgc.quiet = 1; | ||
| 58 | cgc.data_direction = DMA_FROM_DEVICE; | ||
| 59 | |||
| 60 | result = sr_do_ioctl(cd, &cgc); | ||
| 61 | |||
| 62 | tochdr->cdth_trk0 = buffer[2]; | ||
| 63 | tochdr->cdth_trk1 = buffer[3]; | ||
| 64 | |||
| 65 | kfree(buffer); | ||
| 66 | return result; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int sr_read_tocentry(struct cdrom_device_info *cdi, | ||
| 70 | struct cdrom_tocentry *tocentry) | ||
| 71 | { | ||
| 72 | struct scsi_cd *cd = cdi->handle; | ||
| 73 | struct packet_command cgc; | ||
| 74 | int result; | ||
| 75 | unsigned char *buffer; | ||
| 76 | |||
| 77 | buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); | ||
| 78 | if (!buffer) | ||
| 79 | return -ENOMEM; | ||
| 80 | |||
| 81 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
| 82 | cgc.timeout = IOCTL_TIMEOUT; | ||
| 83 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | ||
| 84 | cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; | ||
| 85 | cgc.cmd[6] = tocentry->cdte_track; | ||
| 86 | cgc.cmd[8] = 12; /* LSB of length */ | ||
| 87 | cgc.buffer = buffer; | ||
| 88 | cgc.buflen = 12; | ||
| 89 | cgc.data_direction = DMA_FROM_DEVICE; | ||
| 90 | |||
| 91 | result = sr_do_ioctl(cd, &cgc); | ||
| 92 | |||
| 93 | tocentry->cdte_ctrl = buffer[5] & 0xf; | ||
| 94 | tocentry->cdte_adr = buffer[5] >> 4; | ||
| 95 | tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; | ||
| 96 | if (tocentry->cdte_format == CDROM_MSF) { | ||
| 97 | tocentry->cdte_addr.msf.minute = buffer[9]; | ||
| 98 | tocentry->cdte_addr.msf.second = buffer[10]; | ||
| 99 | tocentry->cdte_addr.msf.frame = buffer[11]; | ||
| 100 | } else | ||
| 101 | tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) | ||
| 102 | + buffer[10]) << 8) + buffer[11]; | ||
| 103 | |||
| 104 | kfree(buffer); | ||
| 105 | return result; | ||
| 106 | } | ||
| 34 | 107 | ||
| 35 | #define IOCTL_RETRIES 3 | 108 | #define IOCTL_RETRIES 3 |
| 36 | 109 | ||
| @@ -45,7 +118,8 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti | |||
| 45 | struct packet_command cgc; | 118 | struct packet_command cgc; |
| 46 | int ntracks, ret; | 119 | int ntracks, ret; |
| 47 | 120 | ||
| 48 | if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))) | 121 | ret = sr_read_tochdr(cdi, &tochdr); |
| 122 | if (ret) | ||
| 49 | return ret; | 123 | return ret; |
| 50 | 124 | ||
| 51 | ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; | 125 | ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; |
| @@ -60,9 +134,11 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti | |||
| 60 | trk1_te.cdte_track = ti->cdti_trk1; | 134 | trk1_te.cdte_track = ti->cdti_trk1; |
| 61 | trk1_te.cdte_format = CDROM_MSF; | 135 | trk1_te.cdte_format = CDROM_MSF; |
| 62 | 136 | ||
| 63 | if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te))) | 137 | ret = sr_read_tocentry(cdi, &trk0_te); |
| 138 | if (ret) | ||
| 64 | return ret; | 139 | return ret; |
| 65 | if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te))) | 140 | ret = sr_read_tocentry(cdi, &trk1_te); |
| 141 | if (ret) | ||
| 66 | return ret; | 142 | return ret; |
| 67 | 143 | ||
| 68 | memset(&cgc, 0, sizeof(struct packet_command)); | 144 | memset(&cgc, 0, sizeof(struct packet_command)); |
| @@ -78,6 +154,30 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti | |||
| 78 | return sr_do_ioctl(cdi->handle, &cgc); | 154 | return sr_do_ioctl(cdi->handle, &cgc); |
| 79 | } | 155 | } |
| 80 | 156 | ||
| 157 | static int sr_play_trkind(struct cdrom_device_info *cdi, | ||
| 158 | struct cdrom_ti *ti) | ||
| 159 | |||
| 160 | { | ||
| 161 | struct scsi_cd *cd = cdi->handle; | ||
| 162 | struct packet_command cgc; | ||
| 163 | int result; | ||
| 164 | |||
| 165 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
| 166 | cgc.timeout = IOCTL_TIMEOUT; | ||
| 167 | cgc.cmd[0] = GPCMD_PLAYAUDIO_TI; | ||
| 168 | cgc.cmd[4] = ti->cdti_trk0; | ||
| 169 | cgc.cmd[5] = ti->cdti_ind0; | ||
| 170 | cgc.cmd[7] = ti->cdti_trk1; | ||
| 171 | cgc.cmd[8] = ti->cdti_ind1; | ||
| 172 | cgc.data_direction = DMA_NONE; | ||
| 173 | |||
| 174 | result = sr_do_ioctl(cd, &cgc); | ||
| 175 | if (result == -EDRIVE_CANT_DO_THIS) | ||
| 176 | result = sr_fake_playtrkind(cdi, ti); | ||
| 177 | |||
| 178 | return result; | ||
| 179 | } | ||
| 180 | |||
| 81 | /* We do our own retries because we want to know what the specific | 181 | /* We do our own retries because we want to know what the specific |
| 82 | error code is. Normally the UNIT_ATTENTION code will automatically | 182 | error code is. Normally the UNIT_ATTENTION code will automatically |
| 83 | clear after one error */ | 183 | clear after one error */ |
| @@ -229,13 +329,14 @@ int sr_disk_status(struct cdrom_device_info *cdi) | |||
| 229 | int i, rc, have_datatracks = 0; | 329 | int i, rc, have_datatracks = 0; |
| 230 | 330 | ||
| 231 | /* look for data tracks */ | 331 | /* look for data tracks */ |
| 232 | if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))) | 332 | rc = sr_read_tochdr(cdi, &toc_h); |
| 333 | if (rc) | ||
| 233 | return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; | 334 | return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; |
| 234 | 335 | ||
| 235 | for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { | 336 | for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { |
| 236 | toc_e.cdte_track = i; | 337 | toc_e.cdte_track = i; |
| 237 | toc_e.cdte_format = CDROM_LBA; | 338 | toc_e.cdte_format = CDROM_LBA; |
| 238 | if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e)) | 339 | if (sr_read_tocentry(cdi, &toc_e)) |
| 239 | return CDS_NO_INFO; | 340 | return CDS_NO_INFO; |
| 240 | if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { | 341 | if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { |
| 241 | have_datatracks = 1; | 342 | have_datatracks = 1; |
| @@ -262,10 +363,6 @@ int sr_get_last_session(struct cdrom_device_info *cdi, | |||
| 262 | return 0; | 363 | return 0; |
| 263 | } | 364 | } |
| 264 | 365 | ||
| 265 | /* primitive to determine whether we need to have GFP_DMA set based on | ||
| 266 | * the status of the unchecked_isa_dma flag in the host structure */ | ||
| 267 | #define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) | ||
| 268 | |||
| 269 | int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | 366 | int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) |
| 270 | { | 367 | { |
| 271 | Scsi_CD *cd = cdi->handle; | 368 | Scsi_CD *cd = cdi->handle; |
| @@ -329,93 +426,16 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed) | |||
| 329 | 426 | ||
| 330 | int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) | 427 | int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) |
| 331 | { | 428 | { |
| 332 | Scsi_CD *cd = cdi->handle; | ||
| 333 | struct packet_command cgc; | ||
| 334 | int result; | ||
| 335 | unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); | ||
| 336 | |||
| 337 | if (!buffer) | ||
| 338 | return -ENOMEM; | ||
| 339 | |||
| 340 | memset(&cgc, 0, sizeof(struct packet_command)); | ||
| 341 | cgc.timeout = IOCTL_TIMEOUT; | ||
| 342 | |||
| 343 | switch (cmd) { | 429 | switch (cmd) { |
| 344 | case CDROMREADTOCHDR: | 430 | case CDROMREADTOCHDR: |
| 345 | { | 431 | return sr_read_tochdr(cdi, arg); |
| 346 | struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; | ||
| 347 | |||
| 348 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | ||
| 349 | cgc.cmd[8] = 12; /* LSB of length */ | ||
| 350 | cgc.buffer = buffer; | ||
| 351 | cgc.buflen = 12; | ||
| 352 | cgc.quiet = 1; | ||
| 353 | cgc.data_direction = DMA_FROM_DEVICE; | ||
| 354 | |||
| 355 | result = sr_do_ioctl(cd, &cgc); | ||
| 356 | |||
| 357 | tochdr->cdth_trk0 = buffer[2]; | ||
| 358 | tochdr->cdth_trk1 = buffer[3]; | ||
| 359 | |||
| 360 | break; | ||
| 361 | } | ||
| 362 | |||
| 363 | case CDROMREADTOCENTRY: | 432 | case CDROMREADTOCENTRY: |
| 364 | { | 433 | return sr_read_tocentry(cdi, arg); |
| 365 | struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; | 434 | case CDROMPLAYTRKIND: |
| 366 | 435 | return sr_play_trkind(cdi, arg); | |
| 367 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | ||
| 368 | cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; | ||
| 369 | cgc.cmd[6] = tocentry->cdte_track; | ||
| 370 | cgc.cmd[8] = 12; /* LSB of length */ | ||
| 371 | cgc.buffer = buffer; | ||
| 372 | cgc.buflen = 12; | ||
| 373 | cgc.data_direction = DMA_FROM_DEVICE; | ||
| 374 | |||
| 375 | result = sr_do_ioctl(cd, &cgc); | ||
| 376 | |||
| 377 | tocentry->cdte_ctrl = buffer[5] & 0xf; | ||
| 378 | tocentry->cdte_adr = buffer[5] >> 4; | ||
| 379 | tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; | ||
| 380 | if (tocentry->cdte_format == CDROM_MSF) { | ||
| 381 | tocentry->cdte_addr.msf.minute = buffer[9]; | ||
| 382 | tocentry->cdte_addr.msf.second = buffer[10]; | ||
| 383 | tocentry->cdte_addr.msf.frame = buffer[11]; | ||
| 384 | } else | ||
| 385 | tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) | ||
| 386 | + buffer[10]) << 8) + buffer[11]; | ||
| 387 | |||
| 388 | break; | ||
| 389 | } | ||
| 390 | |||
| 391 | case CDROMPLAYTRKIND: { | ||
| 392 | struct cdrom_ti* ti = (struct cdrom_ti*)arg; | ||
| 393 | |||
| 394 | cgc.cmd[0] = GPCMD_PLAYAUDIO_TI; | ||
| 395 | cgc.cmd[4] = ti->cdti_trk0; | ||
| 396 | cgc.cmd[5] = ti->cdti_ind0; | ||
| 397 | cgc.cmd[7] = ti->cdti_trk1; | ||
| 398 | cgc.cmd[8] = ti->cdti_ind1; | ||
| 399 | cgc.data_direction = DMA_NONE; | ||
| 400 | |||
| 401 | result = sr_do_ioctl(cd, &cgc); | ||
| 402 | if (result == -EDRIVE_CANT_DO_THIS) | ||
| 403 | result = sr_fake_playtrkind(cdi, ti); | ||
| 404 | |||
| 405 | break; | ||
| 406 | } | ||
| 407 | |||
| 408 | default: | 436 | default: |
| 409 | result = -EINVAL; | 437 | return -EINVAL; |
| 410 | } | 438 | } |
| 411 | |||
| 412 | #if 0 | ||
| 413 | if (result) | ||
| 414 | printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result); | ||
| 415 | #endif | ||
| 416 | |||
| 417 | kfree(buffer); | ||
| 418 | return result; | ||
| 419 | } | 439 | } |
| 420 | 440 | ||
| 421 | /* ----------------------------------------------------------------------- | 441 | /* ----------------------------------------------------------------------- |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index c4aade8f5345..13b1d3aac265 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
| @@ -38,6 +38,7 @@ static const char *verstr = "20050830"; | |||
| 38 | #include <linux/devfs_fs_kernel.h> | 38 | #include <linux/devfs_fs_kernel.h> |
| 39 | #include <linux/cdev.h> | 39 | #include <linux/cdev.h> |
| 40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
| 41 | #include <linux/mutex.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
| 43 | #include <asm/dma.h> | 44 | #include <asm/dma.h> |
| @@ -193,7 +194,6 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int); | |||
| 193 | 194 | ||
| 194 | static int st_probe(struct device *); | 195 | static int st_probe(struct device *); |
| 195 | static int st_remove(struct device *); | 196 | static int st_remove(struct device *); |
| 196 | static int st_init_command(struct scsi_cmnd *); | ||
| 197 | 197 | ||
| 198 | static void do_create_driverfs_files(void); | 198 | static void do_create_driverfs_files(void); |
| 199 | static void do_remove_driverfs_files(void); | 199 | static void do_remove_driverfs_files(void); |
| @@ -206,7 +206,6 @@ static struct scsi_driver st_template = { | |||
| 206 | .probe = st_probe, | 206 | .probe = st_probe, |
| 207 | .remove = st_remove, | 207 | .remove = st_remove, |
| 208 | }, | 208 | }, |
| 209 | .init_command = st_init_command, | ||
| 210 | }; | 209 | }; |
| 211 | 210 | ||
| 212 | static int st_compression(struct scsi_tape *, int); | 211 | static int st_compression(struct scsi_tape *, int); |
| @@ -220,7 +219,7 @@ static void scsi_tape_release(struct kref *); | |||
| 220 | 219 | ||
| 221 | #define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref) | 220 | #define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref) |
| 222 | 221 | ||
| 223 | static DECLARE_MUTEX(st_ref_sem); | 222 | static DEFINE_MUTEX(st_ref_mutex); |
| 224 | 223 | ||
| 225 | 224 | ||
| 226 | #include "osst_detect.h" | 225 | #include "osst_detect.h" |
| @@ -237,7 +236,7 @@ static struct scsi_tape *scsi_tape_get(int dev) | |||
| 237 | { | 236 | { |
| 238 | struct scsi_tape *STp = NULL; | 237 | struct scsi_tape *STp = NULL; |
| 239 | 238 | ||
| 240 | down(&st_ref_sem); | 239 | mutex_lock(&st_ref_mutex); |
| 241 | write_lock(&st_dev_arr_lock); | 240 | write_lock(&st_dev_arr_lock); |
| 242 | 241 | ||
| 243 | if (dev < st_dev_max && scsi_tapes != NULL) | 242 | if (dev < st_dev_max && scsi_tapes != NULL) |
| @@ -259,7 +258,7 @@ out_put: | |||
| 259 | STp = NULL; | 258 | STp = NULL; |
| 260 | out: | 259 | out: |
| 261 | write_unlock(&st_dev_arr_lock); | 260 | write_unlock(&st_dev_arr_lock); |
| 262 | up(&st_ref_sem); | 261 | mutex_unlock(&st_ref_mutex); |
| 263 | return STp; | 262 | return STp; |
| 264 | } | 263 | } |
| 265 | 264 | ||
| @@ -267,10 +266,10 @@ static void scsi_tape_put(struct scsi_tape *STp) | |||
| 267 | { | 266 | { |
| 268 | struct scsi_device *sdev = STp->device; | 267 | struct scsi_device *sdev = STp->device; |
| 269 | 268 | ||
| 270 | down(&st_ref_sem); | 269 | mutex_lock(&st_ref_mutex); |
| 271 | kref_put(&STp->kref, scsi_tape_release); | 270 | kref_put(&STp->kref, scsi_tape_release); |
| 272 | scsi_device_put(sdev); | 271 | scsi_device_put(sdev); |
| 273 | up(&st_ref_sem); | 272 | mutex_unlock(&st_ref_mutex); |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 276 | struct st_reject_data { | 275 | struct st_reject_data { |
| @@ -4141,9 +4140,9 @@ static int st_remove(struct device *dev) | |||
| 4141 | } | 4140 | } |
| 4142 | } | 4141 | } |
| 4143 | 4142 | ||
| 4144 | down(&st_ref_sem); | 4143 | mutex_lock(&st_ref_mutex); |
| 4145 | kref_put(&tpnt->kref, scsi_tape_release); | 4144 | kref_put(&tpnt->kref, scsi_tape_release); |
| 4146 | up(&st_ref_sem); | 4145 | mutex_unlock(&st_ref_mutex); |
| 4147 | return 0; | 4146 | return 0; |
| 4148 | } | 4147 | } |
| 4149 | } | 4148 | } |
| @@ -4156,7 +4155,7 @@ static int st_remove(struct device *dev) | |||
| 4156 | * scsi_tape_release - Called to free the Scsi_Tape structure | 4155 | * scsi_tape_release - Called to free the Scsi_Tape structure |
| 4157 | * @kref: pointer to embedded kref | 4156 | * @kref: pointer to embedded kref |
| 4158 | * | 4157 | * |
| 4159 | * st_ref_sem must be held entering this routine. Because it is | 4158 | * st_ref_mutex must be held entering this routine. Because it is |
| 4160 | * called on last put, you should always use the scsi_tape_get() | 4159 | * called on last put, you should always use the scsi_tape_get() |
| 4161 | * scsi_tape_put() helpers which manipulate the semaphore directly | 4160 | * scsi_tape_put() helpers which manipulate the semaphore directly |
| 4162 | * and never do a direct kref_put(). | 4161 | * and never do a direct kref_put(). |
| @@ -4180,29 +4179,6 @@ static void scsi_tape_release(struct kref *kref) | |||
| 4180 | return; | 4179 | return; |
| 4181 | } | 4180 | } |
| 4182 | 4181 | ||
| 4183 | static void st_intr(struct scsi_cmnd *SCpnt) | ||
| 4184 | { | ||
| 4185 | /* | ||
| 4186 | * The caller should be checking the request's errors | ||
| 4187 | * value. | ||
| 4188 | */ | ||
| 4189 | scsi_io_completion(SCpnt, SCpnt->bufflen, 0); | ||
| 4190 | } | ||
| 4191 | |||
| 4192 | /* | ||
| 4193 | * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO) | ||
| 4194 | * interface for REQ_BLOCK_PC commands. | ||
| 4195 | */ | ||
| 4196 | static int st_init_command(struct scsi_cmnd *SCpnt) | ||
| 4197 | { | ||
| 4198 | if (!(SCpnt->request->flags & REQ_BLOCK_PC)) | ||
| 4199 | return 0; | ||
| 4200 | |||
| 4201 | scsi_setup_blk_pc_cmnd(SCpnt); | ||
| 4202 | SCpnt->done = st_intr; | ||
| 4203 | return 1; | ||
| 4204 | } | ||
| 4205 | |||
| 4206 | static int __init init_st(void) | 4182 | static int __init init_st(void) |
| 4207 | { | 4183 | { |
| 4208 | validate_options(); | 4184 | validate_options(); |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 4dd5c3f98167..8cbf0fc5a225 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
| @@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD; | |||
| 143 | * memory if large numbers of serial ports are open. | 143 | * memory if large numbers of serial ports are open. |
| 144 | */ | 144 | */ |
| 145 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ | 145 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ |
| 146 | DECLARE_MUTEX(tmp_buf_sem); | ||
| 147 | 146 | ||
| 148 | static inline int serial_paranoia_check(struct m68k_serial *info, | 147 | static inline int serial_paranoia_check(struct m68k_serial *info, |
| 149 | char *name, const char *routine) | 148 | char *name, const char *routine) |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 843717275d49..e0685a520514 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -190,7 +190,6 @@ config SERIAL_8250_BOCA | |||
| 190 | To compile this driver as a module, choose M here: the module | 190 | To compile this driver as a module, choose M here: the module |
| 191 | will be called 8250_boca. | 191 | will be called 8250_boca. |
| 192 | 192 | ||
| 193 | |||
| 194 | config SERIAL_8250_HUB6 | 193 | config SERIAL_8250_HUB6 |
| 195 | tristate "Support Hub6 cards" | 194 | tristate "Support Hub6 cards" |
| 196 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS | 195 | depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS |
| @@ -917,4 +916,12 @@ config SERIAL_SGI_IOC4 | |||
| 917 | and wish to use the serial ports on this card, say Y. | 916 | and wish to use the serial ports on this card, say Y. |
| 918 | Otherwise, say N. | 917 | Otherwise, say N. |
| 919 | 918 | ||
| 919 | config SERIAL_SGI_IOC3 | ||
| 920 | tristate "SGI Altix IOC3 serial support" | ||
| 921 | depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3 | ||
| 922 | select SERIAL_CORE | ||
| 923 | help | ||
| 924 | If you have an SGI Altix with an IOC3 serial card, | ||
| 925 | say Y or M. Otherwise, say N. | ||
| 926 | |||
| 920 | endmenu | 927 | endmenu |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 24a583e482bb..eaf8e01db198 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
| @@ -56,4 +56,5 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/ | |||
| 56 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o | 56 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o |
| 57 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o | 57 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o |
| 58 | obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o | 58 | obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o |
| 59 | obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o | ||
| 59 | obj-$(CONFIG_SERIAL_AT91) += at91_serial.o | 60 | obj-$(CONFIG_SERIAL_AT91) += at91_serial.o |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 5c098be9346b..587cc6a95114 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -499,7 +499,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios, | |||
| 499 | ucr2 |= UCR2_STPB; | 499 | ucr2 |= UCR2_STPB; |
| 500 | if (termios->c_cflag & PARENB) { | 500 | if (termios->c_cflag & PARENB) { |
| 501 | ucr2 |= UCR2_PREN; | 501 | ucr2 |= UCR2_PREN; |
| 502 | if (!(termios->c_cflag & PARODD)) | 502 | if (termios->c_cflag & PARODD) |
| 503 | ucr2 |= UCR2_PROE; | 503 | ucr2 |= UCR2_PROE; |
| 504 | } | 504 | } |
| 505 | 505 | ||
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c new file mode 100644 index 000000000000..8097cd91f16b --- /dev/null +++ b/drivers/serial/ioc3_serial.c | |||
| @@ -0,0 +1,2197 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | * This file contains a module version of the ioc3 serial driver. This | ||
| 11 | * includes all the support functions needed (support functions, etc.) | ||
| 12 | * and the serial driver itself. | ||
| 13 | */ | ||
| 14 | #include <linux/errno.h> | ||
| 15 | #include <linux/tty.h> | ||
| 16 | #include <linux/serial.h> | ||
| 17 | #include <linux/circ_buf.h> | ||
| 18 | #include <linux/serial_reg.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/pci.h> | ||
| 21 | #include <linux/serial_core.h> | ||
| 22 | #include <linux/ioc3.h> | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Interesting things about the ioc3 | ||
| 26 | */ | ||
| 27 | |||
| 28 | #define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */ | ||
| 29 | #define PORTS_PER_CARD 2 | ||
| 30 | #define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS) | ||
| 31 | #define MAX_CARDS 8 | ||
| 32 | #define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS) | ||
| 33 | |||
| 34 | /* determine given the sio_ir what port it applies to */ | ||
| 35 | #define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1 | ||
| 36 | |||
| 37 | |||
| 38 | /* | ||
| 39 | * we have 2 logical ports (rs232, rs422) for each physical port | ||
| 40 | * evens are rs232, odds are rs422 | ||
| 41 | */ | ||
| 42 | #define GET_PHYSICAL_PORT(_x) ((_x) >> 1) | ||
| 43 | #define GET_LOGICAL_PORT(_x) ((_x) & 1) | ||
| 44 | #define IS_PHYSICAL_PORT(_x) !((_x) & 1) | ||
| 45 | #define IS_RS232(_x) !((_x) & 1) | ||
| 46 | |||
| 47 | static unsigned int Num_of_ioc3_cards; | ||
| 48 | static unsigned int Submodule_slot; | ||
| 49 | |||
| 50 | /* defining this will get you LOTS of great debug info */ | ||
| 51 | //#define DEBUG_INTERRUPTS | ||
| 52 | #define DPRINT_CONFIG(_x...) ; | ||
| 53 | //#define DPRINT_CONFIG(_x...) printk _x | ||
| 54 | #define NOT_PROGRESS() ; | ||
| 55 | //#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__) | ||
| 56 | |||
| 57 | /* number of characters we want to transmit to the lower level at a time */ | ||
| 58 | #define MAX_CHARS 256 | ||
| 59 | #define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */ | ||
| 60 | |||
| 61 | /* Device name we're using */ | ||
| 62 | #define DEVICE_NAME "ttySIOC" | ||
| 63 | #define DEVICE_MAJOR 204 | ||
| 64 | #define DEVICE_MINOR 116 | ||
| 65 | |||
| 66 | /* flags for next_char_state */ | ||
| 67 | #define NCS_BREAK 0x1 | ||
| 68 | #define NCS_PARITY 0x2 | ||
| 69 | #define NCS_FRAMING 0x4 | ||
| 70 | #define NCS_OVERRUN 0x8 | ||
| 71 | |||
| 72 | /* cause we need SOME parameters ... */ | ||
| 73 | #define MIN_BAUD_SUPPORTED 1200 | ||
| 74 | #define MAX_BAUD_SUPPORTED 115200 | ||
| 75 | |||
| 76 | /* protocol types supported */ | ||
| 77 | #define PROTO_RS232 0 | ||
| 78 | #define PROTO_RS422 1 | ||
| 79 | |||
| 80 | /* Notification types */ | ||
| 81 | #define N_DATA_READY 0x01 | ||
| 82 | #define N_OUTPUT_LOWAT 0x02 | ||
| 83 | #define N_BREAK 0x04 | ||
| 84 | #define N_PARITY_ERROR 0x08 | ||
| 85 | #define N_FRAMING_ERROR 0x10 | ||
| 86 | #define N_OVERRUN_ERROR 0x20 | ||
| 87 | #define N_DDCD 0x40 | ||
| 88 | #define N_DCTS 0x80 | ||
| 89 | |||
| 90 | #define N_ALL_INPUT (N_DATA_READY | N_BREAK \ | ||
| 91 | | N_PARITY_ERROR | N_FRAMING_ERROR \ | ||
| 92 | | N_OVERRUN_ERROR | N_DDCD | N_DCTS) | ||
| 93 | |||
| 94 | #define N_ALL_OUTPUT N_OUTPUT_LOWAT | ||
| 95 | |||
| 96 | #define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \ | ||
| 97 | | N_OVERRUN_ERROR) | ||
| 98 | |||
| 99 | #define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \ | ||
| 100 | | N_PARITY_ERROR | N_FRAMING_ERROR \ | ||
| 101 | | N_OVERRUN_ERROR | N_DDCD | N_DCTS) | ||
| 102 | |||
| 103 | #define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv) | ||
| 104 | #define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16)) | ||
| 105 | #define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div)) | ||
| 106 | |||
| 107 | /* Some masks */ | ||
| 108 | #define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \ | ||
| 109 | | UART_LCR_WLEN7 | UART_LCR_WLEN8) | ||
| 110 | #define LCR_MASK_STOP_BITS (UART_LCR_STOP) | ||
| 111 | |||
| 112 | #define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable) | ||
| 113 | |||
| 114 | #define RING_BUF_SIZE 4096 | ||
| 115 | #define BUF_SIZE_BIT SBBR_L_SIZE | ||
| 116 | #define PROD_CONS_MASK PROD_CONS_PTR_4K | ||
| 117 | |||
| 118 | #define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4) | ||
| 119 | |||
| 120 | /* driver specific - one per card */ | ||
| 121 | struct ioc3_card { | ||
| 122 | struct { | ||
| 123 | /* uart ports are allocated here */ | ||
| 124 | struct uart_port icp_uart_port[LOGICAL_PORTS]; | ||
| 125 | /* the ioc3_port used for this port */ | ||
| 126 | struct ioc3_port *icp_port; | ||
| 127 | } ic_port[PORTS_PER_CARD]; | ||
| 128 | /* currently enabled interrupts */ | ||
| 129 | uint32_t ic_enable; | ||
| 130 | }; | ||
| 131 | |||
| 132 | /* Local port info for each IOC3 serial port */ | ||
| 133 | struct ioc3_port { | ||
| 134 | /* handy reference material */ | ||
| 135 | struct uart_port *ip_port; | ||
| 136 | struct ioc3_card *ip_card; | ||
| 137 | struct ioc3_driver_data *ip_idd; | ||
| 138 | struct ioc3_submodule *ip_is; | ||
| 139 | |||
| 140 | /* pci mem addresses for this port */ | ||
| 141 | struct ioc3_serialregs __iomem *ip_serial_regs; | ||
| 142 | struct ioc3_uartregs __iomem *ip_uart_regs; | ||
| 143 | |||
| 144 | /* Ring buffer page for this port */ | ||
| 145 | dma_addr_t ip_dma_ringbuf; | ||
| 146 | /* vaddr of ring buffer */ | ||
| 147 | struct ring_buffer *ip_cpu_ringbuf; | ||
| 148 | |||
| 149 | /* Rings for this port */ | ||
| 150 | struct ring *ip_inring; | ||
| 151 | struct ring *ip_outring; | ||
| 152 | |||
| 153 | /* Hook to port specific values */ | ||
| 154 | struct port_hooks *ip_hooks; | ||
| 155 | |||
| 156 | spinlock_t ip_lock; | ||
| 157 | |||
| 158 | /* Various rx/tx parameters */ | ||
| 159 | int ip_baud; | ||
| 160 | int ip_tx_lowat; | ||
| 161 | int ip_rx_timeout; | ||
| 162 | |||
| 163 | /* Copy of notification bits */ | ||
| 164 | int ip_notify; | ||
| 165 | |||
| 166 | /* Shadow copies of various registers so we don't need to PIO | ||
| 167 | * read them constantly | ||
| 168 | */ | ||
| 169 | uint32_t ip_sscr; | ||
| 170 | uint32_t ip_tx_prod; | ||
| 171 | uint32_t ip_rx_cons; | ||
| 172 | unsigned char ip_flags; | ||
| 173 | }; | ||
| 174 | |||
| 175 | /* tx low water mark. We need to notify the driver whenever tx is getting | ||
| 176 | * close to empty so it can refill the tx buffer and keep things going. | ||
| 177 | * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll | ||
| 178 | * have no trouble getting in more chars in time (I certainly hope so). | ||
| 179 | */ | ||
| 180 | #define TX_LOWAT_LATENCY 1000 | ||
| 181 | #define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY) | ||
| 182 | #define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ) | ||
| 183 | |||
| 184 | /* Flags per port */ | ||
| 185 | #define INPUT_HIGH 0x01 | ||
| 186 | /* used to signify that we have turned off the rx_high | ||
| 187 | * temporarily - we need to drain the fifo and don't | ||
| 188 | * want to get blasted with interrupts. | ||
| 189 | */ | ||
| 190 | #define DCD_ON 0x02 | ||
| 191 | /* DCD state is on */ | ||
| 192 | #define LOWAT_WRITTEN 0x04 | ||
| 193 | #define READ_ABORTED 0x08 | ||
| 194 | /* the read was aborted - used to avaoid infinate looping | ||
| 195 | * in the interrupt handler | ||
| 196 | */ | ||
| 197 | #define INPUT_ENABLE 0x10 | ||
| 198 | |||
| 199 | /* Since each port has different register offsets and bitmasks | ||
| 200 | * for everything, we'll store those that we need in tables so we | ||
| 201 | * don't have to be constantly checking the port we are dealing with. | ||
| 202 | */ | ||
| 203 | struct port_hooks { | ||
| 204 | uint32_t intr_delta_dcd; | ||
| 205 | uint32_t intr_delta_cts; | ||
| 206 | uint32_t intr_tx_mt; | ||
| 207 | uint32_t intr_rx_timer; | ||
| 208 | uint32_t intr_rx_high; | ||
| 209 | uint32_t intr_tx_explicit; | ||
| 210 | uint32_t intr_clear; | ||
| 211 | uint32_t intr_all; | ||
| 212 | char rs422_select_pin; | ||
| 213 | }; | ||
| 214 | |||
| 215 | static struct port_hooks hooks_array[PORTS_PER_CARD] = { | ||
| 216 | /* values for port A */ | ||
| 217 | { | ||
| 218 | .intr_delta_dcd = SIO_IR_SA_DELTA_DCD, | ||
| 219 | .intr_delta_cts = SIO_IR_SA_DELTA_CTS, | ||
| 220 | .intr_tx_mt = SIO_IR_SA_TX_MT, | ||
| 221 | .intr_rx_timer = SIO_IR_SA_RX_TIMER, | ||
| 222 | .intr_rx_high = SIO_IR_SA_RX_HIGH, | ||
| 223 | .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT, | ||
| 224 | .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL | ||
| 225 | | SIO_IR_SA_RX_HIGH | ||
| 226 | | SIO_IR_SA_RX_TIMER | ||
| 227 | | SIO_IR_SA_DELTA_DCD | ||
| 228 | | SIO_IR_SA_DELTA_CTS | ||
| 229 | | SIO_IR_SA_INT | ||
| 230 | | SIO_IR_SA_TX_EXPLICIT | ||
| 231 | | SIO_IR_SA_MEMERR), | ||
| 232 | .intr_all = SIO_IR_SA, | ||
| 233 | .rs422_select_pin = GPPR_UARTA_MODESEL_PIN, | ||
| 234 | }, | ||
| 235 | |||
| 236 | /* values for port B */ | ||
| 237 | { | ||
| 238 | .intr_delta_dcd = SIO_IR_SB_DELTA_DCD, | ||
| 239 | .intr_delta_cts = SIO_IR_SB_DELTA_CTS, | ||
| 240 | .intr_tx_mt = SIO_IR_SB_TX_MT, | ||
| 241 | .intr_rx_timer = SIO_IR_SB_RX_TIMER, | ||
| 242 | .intr_rx_high = SIO_IR_SB_RX_HIGH, | ||
| 243 | .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT, | ||
| 244 | .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL | ||
| 245 | | SIO_IR_SB_RX_HIGH | ||
| 246 | | SIO_IR_SB_RX_TIMER | ||
| 247 | | SIO_IR_SB_DELTA_DCD | ||
| 248 | | SIO_IR_SB_DELTA_CTS | ||
| 249 | | SIO_IR_SB_INT | ||
| 250 | | SIO_IR_SB_TX_EXPLICIT | ||
| 251 | | SIO_IR_SB_MEMERR), | ||
| 252 | .intr_all = SIO_IR_SB, | ||
| 253 | .rs422_select_pin = GPPR_UARTB_MODESEL_PIN, | ||
| 254 | } | ||
| 255 | }; | ||
| 256 | |||
| 257 | struct ring_entry { | ||
| 258 | union { | ||
| 259 | struct { | ||
| 260 | uint32_t alldata; | ||
| 261 | uint32_t allsc; | ||
| 262 | } all; | ||
| 263 | struct { | ||
| 264 | char data[4]; /* data bytes */ | ||
| 265 | char sc[4]; /* status/control */ | ||
| 266 | } s; | ||
| 267 | } u; | ||
| 268 | }; | ||
| 269 | |||
| 270 | /* Test the valid bits in any of the 4 sc chars using "allsc" member */ | ||
| 271 | #define RING_ANY_VALID \ | ||
| 272 | ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101) | ||
| 273 | |||
| 274 | #define ring_sc u.s.sc | ||
| 275 | #define ring_data u.s.data | ||
| 276 | #define ring_allsc u.all.allsc | ||
| 277 | |||
| 278 | /* Number of entries per ring buffer. */ | ||
| 279 | #define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry)) | ||
| 280 | |||
| 281 | /* An individual ring */ | ||
| 282 | struct ring { | ||
| 283 | struct ring_entry entries[ENTRIES_PER_RING]; | ||
| 284 | }; | ||
| 285 | |||
| 286 | /* The whole enchilada */ | ||
| 287 | struct ring_buffer { | ||
| 288 | struct ring TX_A; | ||
| 289 | struct ring RX_A; | ||
| 290 | struct ring TX_B; | ||
| 291 | struct ring RX_B; | ||
| 292 | }; | ||
| 293 | |||
| 294 | /* Get a ring from a port struct */ | ||
| 295 | #define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh) | ||
| 296 | |||
| 297 | /* for Infinite loop detection */ | ||
| 298 | #define MAXITER 10000000 | ||
| 299 | |||
| 300 | |||
| 301 | /** | ||
| 302 | * set_baud - Baud rate setting code | ||
| 303 | * @port: port to set | ||
| 304 | * @baud: baud rate to use | ||
| 305 | */ | ||
| 306 | static int set_baud(struct ioc3_port *port, int baud) | ||
| 307 | { | ||
| 308 | int divisor; | ||
| 309 | int actual_baud; | ||
| 310 | int diff; | ||
| 311 | int lcr, prediv; | ||
| 312 | struct ioc3_uartregs __iomem *uart; | ||
| 313 | |||
| 314 | for (prediv = 6; prediv < 64; prediv++) { | ||
| 315 | divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv)); | ||
| 316 | if (!divisor) | ||
| 317 | continue; /* invalid divisor */ | ||
| 318 | actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv)); | ||
| 319 | |||
| 320 | diff = actual_baud - baud; | ||
| 321 | if (diff < 0) | ||
| 322 | diff = -diff; | ||
| 323 | |||
| 324 | /* if we're within 1% we've found a match */ | ||
| 325 | if (diff * 100 <= actual_baud) | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* if the above loop completed, we didn't match | ||
| 330 | * the baud rate. give up. | ||
| 331 | */ | ||
| 332 | if (prediv == 64) { | ||
| 333 | NOT_PROGRESS(); | ||
| 334 | return 1; | ||
| 335 | } | ||
| 336 | |||
| 337 | uart = port->ip_uart_regs; | ||
| 338 | lcr = readb(&uart->iu_lcr); | ||
| 339 | |||
| 340 | writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr); | ||
| 341 | writeb((unsigned char)divisor, &uart->iu_dll); | ||
| 342 | writeb((unsigned char)(divisor >> 8), &uart->iu_dlm); | ||
| 343 | writeb((unsigned char)prediv, &uart->iu_scr); | ||
| 344 | writeb((unsigned char)lcr, &uart->iu_lcr); | ||
| 345 | |||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | /** | ||
| 350 | * get_ioc3_port - given a uart port, return the control structure | ||
| 351 | * @the_port: uart port to find | ||
| 352 | */ | ||
| 353 | static struct ioc3_port *get_ioc3_port(struct uart_port *the_port) | ||
| 354 | { | ||
| 355 | struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev); | ||
| 356 | struct ioc3_card *card_ptr = idd->data[Submodule_slot]; | ||
| 357 | int ii, jj; | ||
| 358 | |||
| 359 | if (!card_ptr) { | ||
| 360 | NOT_PROGRESS(); | ||
| 361 | return NULL; | ||
| 362 | } | ||
| 363 | for (ii = 0; ii < PORTS_PER_CARD; ii++) { | ||
| 364 | for (jj = 0; jj < LOGICAL_PORTS; jj++) { | ||
| 365 | if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj]) | ||
| 366 | return card_ptr->ic_port[ii].icp_port; | ||
| 367 | } | ||
| 368 | } | ||
| 369 | NOT_PROGRESS(); | ||
| 370 | return NULL; | ||
| 371 | } | ||
| 372 | |||
| 373 | /** | ||
| 374 | * port_init - Initialize the sio and ioc3 hardware for a given port | ||
| 375 | * called per port from attach... | ||
| 376 | * @port: port to initialize | ||
| 377 | */ | ||
| 378 | static int inline port_init(struct ioc3_port *port) | ||
| 379 | { | ||
| 380 | uint32_t sio_cr; | ||
| 381 | struct port_hooks *hooks = port->ip_hooks; | ||
| 382 | struct ioc3_uartregs __iomem *uart; | ||
| 383 | int reset_loop_counter = 0xfffff; | ||
| 384 | struct ioc3_driver_data *idd = port->ip_idd; | ||
| 385 | |||
| 386 | /* Idle the IOC3 serial interface */ | ||
| 387 | writel(SSCR_RESET, &port->ip_serial_regs->sscr); | ||
| 388 | |||
| 389 | /* Wait until any pending bus activity for this port has ceased */ | ||
| 390 | do { | ||
| 391 | sio_cr = readl(&idd->vma->sio_cr); | ||
| 392 | if (reset_loop_counter-- <= 0) { | ||
| 393 | printk(KERN_WARNING | ||
| 394 | "IOC3 unable to come out of reset" | ||
| 395 | " scr 0x%x\n", sio_cr); | ||
| 396 | return -1; | ||
| 397 | } | ||
| 398 | } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) && | ||
| 399 | (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA) | ||
| 400 | || sio_cr == SIO_CR_ARB_DIAG_TXB | ||
| 401 | || sio_cr == SIO_CR_ARB_DIAG_RXA | ||
| 402 | || sio_cr == SIO_CR_ARB_DIAG_RXB)); | ||
| 403 | |||
| 404 | /* Finish reset sequence */ | ||
| 405 | writel(0, &port->ip_serial_regs->sscr); | ||
| 406 | |||
| 407 | /* Once RESET is done, reload cached tx_prod and rx_cons values | ||
| 408 | * and set rings to empty by making prod == cons | ||
| 409 | */ | ||
| 410 | port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; | ||
| 411 | writel(port->ip_tx_prod, &port->ip_serial_regs->stpir); | ||
| 412 | port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; | ||
| 413 | writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); | ||
| 414 | |||
| 415 | /* Disable interrupts for this 16550 */ | ||
| 416 | uart = port->ip_uart_regs; | ||
| 417 | writeb(0, &uart->iu_lcr); | ||
| 418 | writeb(0, &uart->iu_ier); | ||
| 419 | |||
| 420 | /* Set the default baud */ | ||
| 421 | set_baud(port, port->ip_baud); | ||
| 422 | |||
| 423 | /* Set line control to 8 bits no parity */ | ||
| 424 | writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr); | ||
| 425 | /* UART_LCR_STOP == 1 stop */ | ||
| 426 | |||
| 427 | /* Enable the FIFOs */ | ||
| 428 | writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr); | ||
| 429 | /* then reset 16550 FIFOs */ | ||
| 430 | writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, | ||
| 431 | &uart->iu_fcr); | ||
| 432 | |||
| 433 | /* Clear modem control register */ | ||
| 434 | writeb(0, &uart->iu_mcr); | ||
| 435 | |||
| 436 | /* Clear deltas in modem status register */ | ||
| 437 | writel(0, &port->ip_serial_regs->shadow); | ||
| 438 | |||
| 439 | /* Only do this once per port pair */ | ||
| 440 | if (port->ip_hooks == &hooks_array[0]) { | ||
| 441 | unsigned long ring_pci_addr; | ||
| 442 | uint32_t __iomem *sbbr_l, *sbbr_h; | ||
| 443 | |||
| 444 | sbbr_l = &idd->vma->sbbr_l; | ||
| 445 | sbbr_h = &idd->vma->sbbr_h; | ||
| 446 | ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf; | ||
| 447 | DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n", | ||
| 448 | __FUNCTION__, (void *)ring_pci_addr)); | ||
| 449 | |||
| 450 | writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h); | ||
| 451 | writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l); | ||
| 452 | } | ||
| 453 | |||
| 454 | /* Set the receive timeout value to 10 msec */ | ||
| 455 | writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr); | ||
| 456 | |||
| 457 | /* Set rx threshold, enable DMA */ | ||
| 458 | /* Set high water mark at 3/4 of full ring */ | ||
| 459 | port->ip_sscr = (ENTRIES_PER_RING * 3 / 4); | ||
| 460 | |||
| 461 | /* uart experiences pauses at high baud rate reducing actual | ||
| 462 | * throughput by 10% or so unless we enable high speed polling | ||
| 463 | * XXX when this hardware bug is resolved we should revert to | ||
| 464 | * normal polling speed | ||
| 465 | */ | ||
| 466 | port->ip_sscr |= SSCR_HIGH_SPD; | ||
| 467 | |||
| 468 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 469 | |||
| 470 | /* Disable and clear all serial related interrupt bits */ | ||
| 471 | port->ip_card->ic_enable &= ~hooks->intr_clear; | ||
| 472 | ioc3_disable(port->ip_is, idd, hooks->intr_clear); | ||
| 473 | ioc3_ack(port->ip_is, idd, hooks->intr_clear); | ||
| 474 | return 0; | ||
| 475 | } | ||
| 476 | |||
| 477 | /** | ||
| 478 | * enable_intrs - enable interrupts | ||
| 479 | * @port: port to enable | ||
| 480 | * @mask: mask to use | ||
| 481 | */ | ||
| 482 | static void enable_intrs(struct ioc3_port *port, uint32_t mask) | ||
| 483 | { | ||
| 484 | if ((port->ip_card->ic_enable & mask) != mask) { | ||
| 485 | port->ip_card->ic_enable |= mask; | ||
| 486 | ioc3_enable(port->ip_is, port->ip_idd, mask); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 490 | /** | ||
| 491 | * local_open - local open a port | ||
| 492 | * @port: port to open | ||
| 493 | */ | ||
| 494 | static inline int local_open(struct ioc3_port *port) | ||
| 495 | { | ||
| 496 | int spiniter = 0; | ||
| 497 | |||
| 498 | port->ip_flags = INPUT_ENABLE; | ||
| 499 | |||
| 500 | /* Pause the DMA interface if necessary */ | ||
| 501 | if (port->ip_sscr & SSCR_DMA_EN) { | ||
| 502 | writel(port->ip_sscr | SSCR_DMA_PAUSE, | ||
| 503 | &port->ip_serial_regs->sscr); | ||
| 504 | while ((readl(&port->ip_serial_regs->sscr) | ||
| 505 | & SSCR_PAUSE_STATE) == 0) { | ||
| 506 | spiniter++; | ||
| 507 | if (spiniter > MAXITER) { | ||
| 508 | NOT_PROGRESS(); | ||
| 509 | return -1; | ||
| 510 | } | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | /* Reset the input fifo. If the uart received chars while the port | ||
| 515 | * was closed and DMA is not enabled, the uart may have a bunch of | ||
| 516 | * chars hanging around in its rx fifo which will not be discarded | ||
| 517 | * by rclr in the upper layer. We must get rid of them here. | ||
| 518 | */ | ||
| 519 | writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, | ||
| 520 | &port->ip_uart_regs->iu_fcr); | ||
| 521 | |||
| 522 | writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr); | ||
| 523 | /* UART_LCR_STOP == 1 stop */ | ||
| 524 | |||
| 525 | /* Re-enable DMA, set default threshold to intr whenever there is | ||
| 526 | * data available. | ||
| 527 | */ | ||
| 528 | port->ip_sscr &= ~SSCR_RX_THRESHOLD; | ||
| 529 | port->ip_sscr |= 1; /* default threshold */ | ||
| 530 | |||
| 531 | /* Plug in the new sscr. This implicitly clears the DMA_PAUSE | ||
| 532 | * flag if it was set above | ||
| 533 | */ | ||
| 534 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 535 | port->ip_tx_lowat = 1; | ||
| 536 | return 0; | ||
| 537 | } | ||
| 538 | |||
| 539 | /** | ||
| 540 | * set_rx_timeout - Set rx timeout and threshold values. | ||
| 541 | * @port: port to use | ||
| 542 | * @timeout: timeout value in ticks | ||
| 543 | */ | ||
| 544 | static inline int set_rx_timeout(struct ioc3_port *port, int timeout) | ||
| 545 | { | ||
| 546 | int threshold; | ||
| 547 | |||
| 548 | port->ip_rx_timeout = timeout; | ||
| 549 | |||
| 550 | /* Timeout is in ticks. Let's figure out how many chars we | ||
| 551 | * can receive at the current baud rate in that interval | ||
| 552 | * and set the rx threshold to that amount. There are 4 chars | ||
| 553 | * per ring entry, so we'll divide the number of chars that will | ||
| 554 | * arrive in timeout by 4. | ||
| 555 | * So .... timeout * baud / 10 / HZ / 4, with HZ = 100. | ||
| 556 | */ | ||
| 557 | threshold = timeout * port->ip_baud / 4000; | ||
| 558 | if (threshold == 0) | ||
| 559 | threshold = 1; /* otherwise we'll intr all the time! */ | ||
| 560 | |||
| 561 | if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD) | ||
| 562 | return 1; | ||
| 563 | |||
| 564 | port->ip_sscr &= ~SSCR_RX_THRESHOLD; | ||
| 565 | port->ip_sscr |= threshold; | ||
| 566 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 567 | |||
| 568 | /* Now set the rx timeout to the given value | ||
| 569 | * again timeout * SRTR_HZ / HZ | ||
| 570 | */ | ||
| 571 | timeout = timeout * SRTR_HZ / 100; | ||
| 572 | if (timeout > SRTR_CNT) | ||
| 573 | timeout = SRTR_CNT; | ||
| 574 | writel(timeout, &port->ip_serial_regs->srtr); | ||
| 575 | return 0; | ||
| 576 | } | ||
| 577 | |||
| 578 | /** | ||
| 579 | * config_port - config the hardware | ||
| 580 | * @port: port to config | ||
| 581 | * @baud: baud rate for the port | ||
| 582 | * @byte_size: data size | ||
| 583 | * @stop_bits: number of stop bits | ||
| 584 | * @parenb: parity enable ? | ||
| 585 | * @parodd: odd parity ? | ||
| 586 | */ | ||
| 587 | static inline int | ||
| 588 | config_port(struct ioc3_port *port, | ||
| 589 | int baud, int byte_size, int stop_bits, int parenb, int parodd) | ||
| 590 | { | ||
| 591 | char lcr, sizebits; | ||
| 592 | int spiniter = 0; | ||
| 593 | |||
| 594 | DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d " | ||
| 595 | "parodd %d\n", | ||
| 596 | __FUNCTION__, ((struct uart_port *)port->ip_port)->line, | ||
| 597 | baud, byte_size, stop_bits, parenb, parodd)); | ||
| 598 | |||
| 599 | if (set_baud(port, baud)) | ||
| 600 | return 1; | ||
| 601 | |||
| 602 | switch (byte_size) { | ||
| 603 | case 5: | ||
| 604 | sizebits = UART_LCR_WLEN5; | ||
| 605 | break; | ||
| 606 | case 6: | ||
| 607 | sizebits = UART_LCR_WLEN6; | ||
| 608 | break; | ||
| 609 | case 7: | ||
| 610 | sizebits = UART_LCR_WLEN7; | ||
| 611 | break; | ||
| 612 | case 8: | ||
| 613 | sizebits = UART_LCR_WLEN8; | ||
| 614 | break; | ||
| 615 | default: | ||
| 616 | return 1; | ||
| 617 | } | ||
| 618 | |||
| 619 | /* Pause the DMA interface if necessary */ | ||
| 620 | if (port->ip_sscr & SSCR_DMA_EN) { | ||
| 621 | writel(port->ip_sscr | SSCR_DMA_PAUSE, | ||
| 622 | &port->ip_serial_regs->sscr); | ||
| 623 | while ((readl(&port->ip_serial_regs->sscr) | ||
| 624 | & SSCR_PAUSE_STATE) == 0) { | ||
| 625 | spiniter++; | ||
| 626 | if (spiniter > MAXITER) | ||
| 627 | return -1; | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | /* Clear relevant fields in lcr */ | ||
| 632 | lcr = readb(&port->ip_uart_regs->iu_lcr); | ||
| 633 | lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR | | ||
| 634 | UART_LCR_PARITY | LCR_MASK_STOP_BITS); | ||
| 635 | |||
| 636 | /* Set byte size in lcr */ | ||
| 637 | lcr |= sizebits; | ||
| 638 | |||
| 639 | /* Set parity */ | ||
| 640 | if (parenb) { | ||
| 641 | lcr |= UART_LCR_PARITY; | ||
| 642 | if (!parodd) | ||
| 643 | lcr |= UART_LCR_EPAR; | ||
| 644 | } | ||
| 645 | |||
| 646 | /* Set stop bits */ | ||
| 647 | if (stop_bits) | ||
| 648 | lcr |= UART_LCR_STOP /* 2 stop bits */ ; | ||
| 649 | |||
| 650 | writeb(lcr, &port->ip_uart_regs->iu_lcr); | ||
| 651 | |||
| 652 | /* Re-enable the DMA interface if necessary */ | ||
| 653 | if (port->ip_sscr & SSCR_DMA_EN) { | ||
| 654 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 655 | } | ||
| 656 | port->ip_baud = baud; | ||
| 657 | |||
| 658 | /* When we get within this number of ring entries of filling the | ||
| 659 | * entire ring on tx, place an EXPLICIT intr to generate a lowat | ||
| 660 | * notification when output has drained. | ||
| 661 | */ | ||
| 662 | port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4; | ||
| 663 | if (port->ip_tx_lowat == 0) | ||
| 664 | port->ip_tx_lowat = 1; | ||
| 665 | |||
| 666 | set_rx_timeout(port, 2); | ||
| 667 | return 0; | ||
| 668 | } | ||
| 669 | |||
| 670 | /** | ||
| 671 | * do_write - Write bytes to the port. Returns the number of bytes | ||
| 672 | * actually written. Called from transmit_chars | ||
| 673 | * @port: port to use | ||
| 674 | * @buf: the stuff to write | ||
| 675 | * @len: how many bytes in 'buf' | ||
| 676 | */ | ||
| 677 | static inline int do_write(struct ioc3_port *port, char *buf, int len) | ||
| 678 | { | ||
| 679 | int prod_ptr, cons_ptr, total = 0; | ||
| 680 | struct ring *outring; | ||
| 681 | struct ring_entry *entry; | ||
| 682 | struct port_hooks *hooks = port->ip_hooks; | ||
| 683 | |||
| 684 | BUG_ON(!(len >= 0)); | ||
| 685 | |||
| 686 | prod_ptr = port->ip_tx_prod; | ||
| 687 | cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; | ||
| 688 | outring = port->ip_outring; | ||
| 689 | |||
| 690 | /* Maintain a 1-entry red-zone. The ring buffer is full when | ||
| 691 | * (cons - prod) % ring_size is 1. Rather than do this subtraction | ||
| 692 | * in the body of the loop, I'll do it now. | ||
| 693 | */ | ||
| 694 | cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK; | ||
| 695 | |||
| 696 | /* Stuff the bytes into the output */ | ||
| 697 | while ((prod_ptr != cons_ptr) && (len > 0)) { | ||
| 698 | int xx; | ||
| 699 | |||
| 700 | /* Get 4 bytes (one ring entry) at a time */ | ||
| 701 | entry = (struct ring_entry *)((caddr_t) outring + prod_ptr); | ||
| 702 | |||
| 703 | /* Invalidate all entries */ | ||
| 704 | entry->ring_allsc = 0; | ||
| 705 | |||
| 706 | /* Copy in some bytes */ | ||
| 707 | for (xx = 0; (xx < 4) && (len > 0); xx++) { | ||
| 708 | entry->ring_data[xx] = *buf++; | ||
| 709 | entry->ring_sc[xx] = TXCB_VALID; | ||
| 710 | len--; | ||
| 711 | total++; | ||
| 712 | } | ||
| 713 | |||
| 714 | /* If we are within some small threshold of filling up the | ||
| 715 | * entire ring buffer, we must place an EXPLICIT intr here | ||
| 716 | * to generate a lowat interrupt in case we subsequently | ||
| 717 | * really do fill up the ring and the caller goes to sleep. | ||
| 718 | * No need to place more than one though. | ||
| 719 | */ | ||
| 720 | if (!(port->ip_flags & LOWAT_WRITTEN) && | ||
| 721 | ((cons_ptr - prod_ptr) & PROD_CONS_MASK) | ||
| 722 | <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) { | ||
| 723 | port->ip_flags |= LOWAT_WRITTEN; | ||
| 724 | entry->ring_sc[0] |= TXCB_INT_WHEN_DONE; | ||
| 725 | } | ||
| 726 | |||
| 727 | /* Go on to next entry */ | ||
| 728 | prod_ptr += sizeof(struct ring_entry); | ||
| 729 | prod_ptr &= PROD_CONS_MASK; | ||
| 730 | } | ||
| 731 | |||
| 732 | /* If we sent something, start DMA if necessary */ | ||
| 733 | if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) { | ||
| 734 | port->ip_sscr |= SSCR_DMA_EN; | ||
| 735 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 736 | } | ||
| 737 | |||
| 738 | /* Store the new producer pointer. If tx is disabled, we stuff the | ||
| 739 | * data into the ring buffer, but we don't actually start tx. | ||
| 740 | */ | ||
| 741 | if (!uart_tx_stopped(port->ip_port)) { | ||
| 742 | writel(prod_ptr, &port->ip_serial_regs->stpir); | ||
| 743 | |||
| 744 | /* If we are now transmitting, enable tx_mt interrupt so we | ||
| 745 | * can disable DMA if necessary when the tx finishes. | ||
| 746 | */ | ||
| 747 | if (total > 0) | ||
| 748 | enable_intrs(port, hooks->intr_tx_mt); | ||
| 749 | } | ||
| 750 | port->ip_tx_prod = prod_ptr; | ||
| 751 | |||
| 752 | return total; | ||
| 753 | } | ||
| 754 | |||
| 755 | /** | ||
| 756 | * disable_intrs - disable interrupts | ||
| 757 | * @port: port to enable | ||
| 758 | * @mask: mask to use | ||
| 759 | */ | ||
| 760 | static inline void disable_intrs(struct ioc3_port *port, uint32_t mask) | ||
| 761 | { | ||
| 762 | if (port->ip_card->ic_enable & mask) { | ||
| 763 | ioc3_disable(port->ip_is, port->ip_idd, mask); | ||
| 764 | port->ip_card->ic_enable &= ~mask; | ||
| 765 | } | ||
| 766 | } | ||
| 767 | |||
| 768 | /** | ||
| 769 | * set_notification - Modify event notification | ||
| 770 | * @port: port to use | ||
| 771 | * @mask: events mask | ||
| 772 | * @set_on: set ? | ||
| 773 | */ | ||
| 774 | static int set_notification(struct ioc3_port *port, int mask, int set_on) | ||
| 775 | { | ||
| 776 | struct port_hooks *hooks = port->ip_hooks; | ||
| 777 | uint32_t intrbits, sscrbits; | ||
| 778 | |||
| 779 | BUG_ON(!mask); | ||
| 780 | |||
| 781 | intrbits = sscrbits = 0; | ||
| 782 | |||
| 783 | if (mask & N_DATA_READY) | ||
| 784 | intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high); | ||
| 785 | if (mask & N_OUTPUT_LOWAT) | ||
| 786 | intrbits |= hooks->intr_tx_explicit; | ||
| 787 | if (mask & N_DDCD) { | ||
| 788 | intrbits |= hooks->intr_delta_dcd; | ||
| 789 | sscrbits |= SSCR_RX_RING_DCD; | ||
| 790 | } | ||
| 791 | if (mask & N_DCTS) | ||
| 792 | intrbits |= hooks->intr_delta_cts; | ||
| 793 | |||
| 794 | if (set_on) { | ||
| 795 | enable_intrs(port, intrbits); | ||
| 796 | port->ip_notify |= mask; | ||
| 797 | port->ip_sscr |= sscrbits; | ||
| 798 | } else { | ||
| 799 | disable_intrs(port, intrbits); | ||
| 800 | port->ip_notify &= ~mask; | ||
| 801 | port->ip_sscr &= ~sscrbits; | ||
| 802 | } | ||
| 803 | |||
| 804 | /* We require DMA if either DATA_READY or DDCD notification is | ||
| 805 | * currently requested. If neither of these is requested and | ||
| 806 | * there is currently no tx in progress, DMA may be disabled. | ||
| 807 | */ | ||
| 808 | if (port->ip_notify & (N_DATA_READY | N_DDCD)) | ||
| 809 | port->ip_sscr |= SSCR_DMA_EN; | ||
| 810 | else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt)) | ||
| 811 | port->ip_sscr &= ~SSCR_DMA_EN; | ||
| 812 | |||
| 813 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 814 | return 0; | ||
| 815 | } | ||
| 816 | |||
| 817 | /** | ||
| 818 | * set_mcr - set the master control reg | ||
| 819 | * @the_port: port to use | ||
| 820 | * @mask1: mcr mask | ||
| 821 | * @mask2: shadow mask | ||
| 822 | */ | ||
| 823 | static inline int set_mcr(struct uart_port *the_port, | ||
| 824 | int mask1, int mask2) | ||
| 825 | { | ||
| 826 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 827 | uint32_t shadow; | ||
| 828 | int spiniter = 0; | ||
| 829 | char mcr; | ||
| 830 | |||
| 831 | if (!port) | ||
| 832 | return -1; | ||
| 833 | |||
| 834 | /* Pause the DMA interface if necessary */ | ||
| 835 | if (port->ip_sscr & SSCR_DMA_EN) { | ||
| 836 | writel(port->ip_sscr | SSCR_DMA_PAUSE, | ||
| 837 | &port->ip_serial_regs->sscr); | ||
| 838 | while ((readl(&port->ip_serial_regs->sscr) | ||
| 839 | & SSCR_PAUSE_STATE) == 0) { | ||
| 840 | spiniter++; | ||
| 841 | if (spiniter > MAXITER) | ||
| 842 | return -1; | ||
| 843 | } | ||
| 844 | } | ||
| 845 | shadow = readl(&port->ip_serial_regs->shadow); | ||
| 846 | mcr = (shadow & 0xff000000) >> 24; | ||
| 847 | |||
| 848 | /* Set new value */ | ||
| 849 | mcr |= mask1; | ||
| 850 | shadow |= mask2; | ||
| 851 | writeb(mcr, &port->ip_uart_regs->iu_mcr); | ||
| 852 | writel(shadow, &port->ip_serial_regs->shadow); | ||
| 853 | |||
| 854 | /* Re-enable the DMA interface if necessary */ | ||
| 855 | if (port->ip_sscr & SSCR_DMA_EN) { | ||
| 856 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 857 | } | ||
| 858 | return 0; | ||
| 859 | } | ||
| 860 | |||
| 861 | /** | ||
| 862 | * ioc3_set_proto - set the protocol for the port | ||
| 863 | * @port: port to use | ||
| 864 | * @proto: protocol to use | ||
| 865 | */ | ||
| 866 | static int ioc3_set_proto(struct ioc3_port *port, int proto) | ||
| 867 | { | ||
| 868 | struct port_hooks *hooks = port->ip_hooks; | ||
| 869 | |||
| 870 | switch (proto) { | ||
| 871 | default: | ||
| 872 | case PROTO_RS232: | ||
| 873 | /* Clear the appropriate GIO pin */ | ||
| 874 | DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__)); | ||
| 875 | writel(0, (&port->ip_idd->vma->gppr[0] | ||
| 876 | + hooks->rs422_select_pin)); | ||
| 877 | break; | ||
| 878 | |||
| 879 | case PROTO_RS422: | ||
| 880 | /* Set the appropriate GIO pin */ | ||
| 881 | DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__)); | ||
| 882 | writel(1, (&port->ip_idd->vma->gppr[0] | ||
| 883 | + hooks->rs422_select_pin)); | ||
| 884 | break; | ||
| 885 | } | ||
| 886 | return 0; | ||
| 887 | } | ||
| 888 | |||
| 889 | /** | ||
| 890 | * transmit_chars - upper level write, called with the_port->lock | ||
| 891 | * @the_port: port to write | ||
| 892 | */ | ||
| 893 | static void transmit_chars(struct uart_port *the_port) | ||
| 894 | { | ||
| 895 | int xmit_count, tail, head; | ||
| 896 | int result; | ||
| 897 | char *start; | ||
| 898 | struct tty_struct *tty; | ||
| 899 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 900 | struct uart_info *info; | ||
| 901 | |||
| 902 | if (!the_port) | ||
| 903 | return; | ||
| 904 | if (!port) | ||
| 905 | return; | ||
| 906 | |||
| 907 | info = the_port->info; | ||
| 908 | tty = info->tty; | ||
| 909 | |||
| 910 | if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) { | ||
| 911 | /* Nothing to do or hw stopped */ | ||
| 912 | set_notification(port, N_ALL_OUTPUT, 0); | ||
| 913 | return; | ||
| 914 | } | ||
| 915 | |||
| 916 | head = info->xmit.head; | ||
| 917 | tail = info->xmit.tail; | ||
| 918 | start = (char *)&info->xmit.buf[tail]; | ||
| 919 | |||
| 920 | /* write out all the data or until the end of the buffer */ | ||
| 921 | xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail); | ||
| 922 | if (xmit_count > 0) { | ||
| 923 | result = do_write(port, start, xmit_count); | ||
| 924 | if (result > 0) { | ||
| 925 | /* booking */ | ||
| 926 | xmit_count -= result; | ||
| 927 | the_port->icount.tx += result; | ||
| 928 | /* advance the pointers */ | ||
| 929 | tail += result; | ||
| 930 | tail &= UART_XMIT_SIZE - 1; | ||
| 931 | info->xmit.tail = tail; | ||
| 932 | start = (char *)&info->xmit.buf[tail]; | ||
| 933 | } | ||
| 934 | } | ||
| 935 | if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS) | ||
| 936 | uart_write_wakeup(the_port); | ||
| 937 | |||
| 938 | if (uart_circ_empty(&info->xmit)) { | ||
| 939 | set_notification(port, N_OUTPUT_LOWAT, 0); | ||
| 940 | } else { | ||
| 941 | set_notification(port, N_OUTPUT_LOWAT, 1); | ||
| 942 | } | ||
| 943 | } | ||
| 944 | |||
| 945 | /** | ||
| 946 | * ioc3_change_speed - change the speed of the port | ||
| 947 | * @the_port: port to change | ||
| 948 | * @new_termios: new termios settings | ||
| 949 | * @old_termios: old termios settings | ||
| 950 | */ | ||
| 951 | static void | ||
| 952 | ioc3_change_speed(struct uart_port *the_port, | ||
| 953 | struct termios *new_termios, struct termios *old_termios) | ||
| 954 | { | ||
| 955 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 956 | unsigned int cflag; | ||
| 957 | int baud; | ||
| 958 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; | ||
| 959 | struct uart_info *info = the_port->info; | ||
| 960 | |||
| 961 | cflag = new_termios->c_cflag; | ||
| 962 | |||
| 963 | switch (cflag & CSIZE) { | ||
| 964 | case CS5: | ||
| 965 | new_data = 5; | ||
| 966 | break; | ||
| 967 | case CS6: | ||
| 968 | new_data = 6; | ||
| 969 | break; | ||
| 970 | case CS7: | ||
| 971 | new_data = 7; | ||
| 972 | break; | ||
| 973 | case CS8: | ||
| 974 | new_data = 8; | ||
| 975 | break; | ||
| 976 | default: | ||
| 977 | /* cuz we always need a default ... */ | ||
| 978 | new_data = 5; | ||
| 979 | break; | ||
| 980 | } | ||
| 981 | if (cflag & CSTOPB) { | ||
| 982 | new_stop = 1; | ||
| 983 | } | ||
| 984 | if (cflag & PARENB) { | ||
| 985 | new_parity_enable = 1; | ||
| 986 | if (cflag & PARODD) | ||
| 987 | new_parity = 1; | ||
| 988 | } | ||
| 989 | baud = uart_get_baud_rate(the_port, new_termios, old_termios, | ||
| 990 | MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED); | ||
| 991 | DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud, | ||
| 992 | the_port->line)); | ||
| 993 | |||
| 994 | if (!the_port->fifosize) | ||
| 995 | the_port->fifosize = FIFO_SIZE; | ||
| 996 | uart_update_timeout(the_port, cflag, baud); | ||
| 997 | |||
| 998 | the_port->ignore_status_mask = N_ALL_INPUT; | ||
| 999 | |||
| 1000 | info->tty->low_latency = 1; | ||
| 1001 | |||
| 1002 | if (I_IGNPAR(info->tty)) | ||
| 1003 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | ||
| 1004 | | N_FRAMING_ERROR); | ||
| 1005 | if (I_IGNBRK(info->tty)) { | ||
| 1006 | the_port->ignore_status_mask &= ~N_BREAK; | ||
| 1007 | if (I_IGNPAR(info->tty)) | ||
| 1008 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; | ||
| 1009 | } | ||
| 1010 | if (!(cflag & CREAD)) { | ||
| 1011 | /* ignore everything */ | ||
| 1012 | the_port->ignore_status_mask &= ~N_DATA_READY; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | if (cflag & CRTSCTS) { | ||
| 1016 | /* enable hardware flow control */ | ||
| 1017 | port->ip_sscr |= SSCR_HFC_EN; | ||
| 1018 | } | ||
| 1019 | else { | ||
| 1020 | /* disable hardware flow control */ | ||
| 1021 | port->ip_sscr &= ~SSCR_HFC_EN; | ||
| 1022 | } | ||
| 1023 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 1024 | |||
| 1025 | /* Set the configuration and proper notification call */ | ||
| 1026 | DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o " | ||
| 1027 | "config_port(baud %d data %d stop %d penable %d " | ||
| 1028 | " parity %d), notification 0x%x\n", | ||
| 1029 | __FUNCTION__, (void *)port, the_port->line, cflag, baud, | ||
| 1030 | new_data, new_stop, new_parity_enable, new_parity, | ||
| 1031 | the_port->ignore_status_mask)); | ||
| 1032 | |||
| 1033 | if ((config_port(port, baud, /* baud */ | ||
| 1034 | new_data, /* byte size */ | ||
| 1035 | new_stop, /* stop bits */ | ||
| 1036 | new_parity_enable, /* set parity */ | ||
| 1037 | new_parity)) >= 0) { /* parity 1==odd */ | ||
| 1038 | set_notification(port, the_port->ignore_status_mask, 1); | ||
| 1039 | } | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /** | ||
| 1043 | * ic3_startup_local - Start up the serial port - returns >= 0 if no errors | ||
| 1044 | * @the_port: Port to operate on | ||
| 1045 | */ | ||
| 1046 | static inline int ic3_startup_local(struct uart_port *the_port) | ||
| 1047 | { | ||
| 1048 | struct ioc3_port *port; | ||
| 1049 | |||
| 1050 | if (!the_port) { | ||
| 1051 | NOT_PROGRESS(); | ||
| 1052 | return -1; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | port = get_ioc3_port(the_port); | ||
| 1056 | if (!port) { | ||
| 1057 | NOT_PROGRESS(); | ||
| 1058 | return -1; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | local_open(port); | ||
| 1062 | |||
| 1063 | /* set the protocol */ | ||
| 1064 | ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 : | ||
| 1065 | PROTO_RS422); | ||
| 1066 | return 0; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | /* | ||
| 1070 | * ioc3_cb_output_lowat - called when the output low water mark is hit | ||
| 1071 | * @port: port to output | ||
| 1072 | */ | ||
| 1073 | static void ioc3_cb_output_lowat(struct ioc3_port *port) | ||
| 1074 | { | ||
| 1075 | unsigned long pflags; | ||
| 1076 | |||
| 1077 | /* the_port->lock is set on the call here */ | ||
| 1078 | if (port->ip_port) { | ||
| 1079 | spin_lock_irqsave(&port->ip_port->lock, pflags); | ||
| 1080 | transmit_chars(port->ip_port); | ||
| 1081 | spin_unlock_irqrestore(&port->ip_port->lock, pflags); | ||
| 1082 | } | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | /* | ||
| 1086 | * ioc3_cb_post_ncs - called for some basic errors | ||
| 1087 | * @port: port to use | ||
| 1088 | * @ncs: event | ||
| 1089 | */ | ||
| 1090 | static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs) | ||
| 1091 | { | ||
| 1092 | struct uart_icount *icount; | ||
| 1093 | |||
| 1094 | icount = &the_port->icount; | ||
| 1095 | |||
| 1096 | if (ncs & NCS_BREAK) | ||
| 1097 | icount->brk++; | ||
| 1098 | if (ncs & NCS_FRAMING) | ||
| 1099 | icount->frame++; | ||
| 1100 | if (ncs & NCS_OVERRUN) | ||
| 1101 | icount->overrun++; | ||
| 1102 | if (ncs & NCS_PARITY) | ||
| 1103 | icount->parity++; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | /** | ||
| 1107 | * do_read - Read in bytes from the port. Return the number of bytes | ||
| 1108 | * actually read. | ||
| 1109 | * @the_port: port to use | ||
| 1110 | * @buf: place to put the stuff we read | ||
| 1111 | * @len: how big 'buf' is | ||
| 1112 | */ | ||
| 1113 | |||
| 1114 | static inline int do_read(struct uart_port *the_port, char *buf, int len) | ||
| 1115 | { | ||
| 1116 | int prod_ptr, cons_ptr, total; | ||
| 1117 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1118 | struct ring *inring; | ||
| 1119 | struct ring_entry *entry; | ||
| 1120 | struct port_hooks *hooks = port->ip_hooks; | ||
| 1121 | int byte_num; | ||
| 1122 | char *sc; | ||
| 1123 | int loop_counter; | ||
| 1124 | |||
| 1125 | BUG_ON(!(len >= 0)); | ||
| 1126 | BUG_ON(!port); | ||
| 1127 | |||
| 1128 | /* There is a nasty timing issue in the IOC3. When the rx_timer | ||
| 1129 | * expires or the rx_high condition arises, we take an interrupt. | ||
| 1130 | * At some point while servicing the interrupt, we read bytes from | ||
| 1131 | * the ring buffer and re-arm the rx_timer. However the rx_timer is | ||
| 1132 | * not started until the first byte is received *after* it is armed, | ||
| 1133 | * and any bytes pending in the rx construction buffers are not drained | ||
| 1134 | * to memory until either there are 4 bytes available or the rx_timer | ||
| 1135 | * expires. This leads to a potential situation where data is left | ||
| 1136 | * in the construction buffers forever - 1 to 3 bytes were received | ||
| 1137 | * after the interrupt was generated but before the rx_timer was | ||
| 1138 | * re-armed. At that point as long as no subsequent bytes are received | ||
| 1139 | * the timer will never be started and the bytes will remain in the | ||
| 1140 | * construction buffer forever. The solution is to execute a DRAIN | ||
| 1141 | * command after rearming the timer. This way any bytes received before | ||
| 1142 | * the DRAIN will be drained to memory, and any bytes received after | ||
| 1143 | * the DRAIN will start the TIMER and be drained when it expires. | ||
| 1144 | * Luckily, this only needs to be done when the DMA buffer is empty | ||
| 1145 | * since there is no requirement that this function return all | ||
| 1146 | * available data as long as it returns some. | ||
| 1147 | */ | ||
| 1148 | /* Re-arm the timer */ | ||
| 1149 | |||
| 1150 | writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); | ||
| 1151 | |||
| 1152 | prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; | ||
| 1153 | cons_ptr = port->ip_rx_cons; | ||
| 1154 | |||
| 1155 | if (prod_ptr == cons_ptr) { | ||
| 1156 | int reset_dma = 0; | ||
| 1157 | |||
| 1158 | /* Input buffer appears empty, do a flush. */ | ||
| 1159 | |||
| 1160 | /* DMA must be enabled for this to work. */ | ||
| 1161 | if (!(port->ip_sscr & SSCR_DMA_EN)) { | ||
| 1162 | port->ip_sscr |= SSCR_DMA_EN; | ||
| 1163 | reset_dma = 1; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | /* Potential race condition: we must reload the srpir after | ||
| 1167 | * issuing the drain command, otherwise we could think the rx | ||
| 1168 | * buffer is empty, then take a very long interrupt, and when | ||
| 1169 | * we come back it's full and we wait forever for the drain to | ||
| 1170 | * complete. | ||
| 1171 | */ | ||
| 1172 | writel(port->ip_sscr | SSCR_RX_DRAIN, | ||
| 1173 | &port->ip_serial_regs->sscr); | ||
| 1174 | prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; | ||
| 1175 | |||
| 1176 | /* We must not wait for the DRAIN to complete unless there are | ||
| 1177 | * at least 8 bytes (2 ring entries) available to receive the | ||
| 1178 | * data otherwise the DRAIN will never complete and we'll | ||
| 1179 | * deadlock here. | ||
| 1180 | * In fact, to make things easier, I'll just ignore the flush if | ||
| 1181 | * there is any data at all now available. | ||
| 1182 | */ | ||
| 1183 | if (prod_ptr == cons_ptr) { | ||
| 1184 | loop_counter = 0; | ||
| 1185 | while (readl(&port->ip_serial_regs->sscr) & | ||
| 1186 | SSCR_RX_DRAIN) { | ||
| 1187 | loop_counter++; | ||
| 1188 | if (loop_counter > MAXITER) | ||
| 1189 | return -1; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | /* SIGH. We have to reload the prod_ptr *again* since | ||
| 1193 | * the drain may have caused it to change | ||
| 1194 | */ | ||
| 1195 | prod_ptr = readl(&port->ip_serial_regs->srpir) | ||
| 1196 | & PROD_CONS_MASK; | ||
| 1197 | } | ||
| 1198 | if (reset_dma) { | ||
| 1199 | port->ip_sscr &= ~SSCR_DMA_EN; | ||
| 1200 | writel(port->ip_sscr, &port->ip_serial_regs->sscr); | ||
| 1201 | } | ||
| 1202 | } | ||
| 1203 | inring = port->ip_inring; | ||
| 1204 | port->ip_flags &= ~READ_ABORTED; | ||
| 1205 | |||
| 1206 | total = 0; | ||
| 1207 | loop_counter = 0xfffff; /* to avoid hangs */ | ||
| 1208 | |||
| 1209 | /* Grab bytes from the hardware */ | ||
| 1210 | while ((prod_ptr != cons_ptr) && (len > 0)) { | ||
| 1211 | entry = (struct ring_entry *)((caddr_t) inring + cons_ptr); | ||
| 1212 | |||
| 1213 | if (loop_counter-- <= 0) { | ||
| 1214 | printk(KERN_WARNING "IOC3 serial: " | ||
| 1215 | "possible hang condition/" | ||
| 1216 | "port stuck on read (line %d).\n", | ||
| 1217 | the_port->line); | ||
| 1218 | break; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /* According to the producer pointer, this ring entry | ||
| 1222 | * must contain some data. But if the PIO happened faster | ||
| 1223 | * than the DMA, the data may not be available yet, so let's | ||
| 1224 | * wait until it arrives. | ||
| 1225 | */ | ||
| 1226 | if ((entry->ring_allsc & RING_ANY_VALID) == 0) { | ||
| 1227 | /* Indicate the read is aborted so we don't disable | ||
| 1228 | * the interrupt thinking that the consumer is | ||
| 1229 | * congested. | ||
| 1230 | */ | ||
| 1231 | port->ip_flags |= READ_ABORTED; | ||
| 1232 | len = 0; | ||
| 1233 | break; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | /* Load the bytes/status out of the ring entry */ | ||
| 1237 | for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) { | ||
| 1238 | sc = &(entry->ring_sc[byte_num]); | ||
| 1239 | |||
| 1240 | /* Check for change in modem state or overrun */ | ||
| 1241 | if ((*sc & RXSB_MODEM_VALID) | ||
| 1242 | && (port->ip_notify & N_DDCD)) { | ||
| 1243 | /* Notify upper layer if DCD dropped */ | ||
| 1244 | if ((port->ip_flags & DCD_ON) | ||
| 1245 | && !(*sc & RXSB_DCD)) { | ||
| 1246 | /* If we have already copied some data, | ||
| 1247 | * return it. We'll pick up the carrier | ||
| 1248 | * drop on the next pass. That way we | ||
| 1249 | * don't throw away the data that has | ||
| 1250 | * already been copied back to | ||
| 1251 | * the caller's buffer. | ||
| 1252 | */ | ||
| 1253 | if (total > 0) { | ||
| 1254 | len = 0; | ||
| 1255 | break; | ||
| 1256 | } | ||
| 1257 | port->ip_flags &= ~DCD_ON; | ||
| 1258 | |||
| 1259 | /* Turn off this notification so the | ||
| 1260 | * carrier drop protocol won't see it | ||
| 1261 | * again when it does a read. | ||
| 1262 | */ | ||
| 1263 | *sc &= ~RXSB_MODEM_VALID; | ||
| 1264 | |||
| 1265 | /* To keep things consistent, we need | ||
| 1266 | * to update the consumer pointer so | ||
| 1267 | * the next reader won't come in and | ||
| 1268 | * try to read the same ring entries | ||
| 1269 | * again. This must be done here before | ||
| 1270 | * the dcd change. | ||
| 1271 | */ | ||
| 1272 | |||
| 1273 | if ((entry->ring_allsc & RING_ANY_VALID) | ||
| 1274 | == 0) { | ||
| 1275 | cons_ptr += (int)sizeof | ||
| 1276 | (struct ring_entry); | ||
| 1277 | cons_ptr &= PROD_CONS_MASK; | ||
| 1278 | } | ||
| 1279 | writel(cons_ptr, | ||
| 1280 | &port->ip_serial_regs->srcir); | ||
| 1281 | port->ip_rx_cons = cons_ptr; | ||
| 1282 | |||
| 1283 | /* Notify upper layer of carrier drop */ | ||
| 1284 | if ((port->ip_notify & N_DDCD) | ||
| 1285 | && port->ip_port) { | ||
| 1286 | uart_handle_dcd_change | ||
| 1287 | (port->ip_port, 0); | ||
| 1288 | wake_up_interruptible | ||
| 1289 | (&the_port->info-> | ||
| 1290 | delta_msr_wait); | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | /* If we had any data to return, we | ||
| 1294 | * would have returned it above. | ||
| 1295 | */ | ||
| 1296 | return 0; | ||
| 1297 | } | ||
| 1298 | } | ||
| 1299 | if (*sc & RXSB_MODEM_VALID) { | ||
| 1300 | /* Notify that an input overrun occurred */ | ||
| 1301 | if ((*sc & RXSB_OVERRUN) | ||
| 1302 | && (port->ip_notify & N_OVERRUN_ERROR)) { | ||
| 1303 | ioc3_cb_post_ncs(the_port, NCS_OVERRUN); | ||
| 1304 | } | ||
| 1305 | /* Don't look at this byte again */ | ||
| 1306 | *sc &= ~RXSB_MODEM_VALID; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | /* Check for valid data or RX errors */ | ||
| 1310 | if ((*sc & RXSB_DATA_VALID) && | ||
| 1311 | ((*sc & (RXSB_PAR_ERR | ||
| 1312 | | RXSB_FRAME_ERR | RXSB_BREAK)) | ||
| 1313 | && (port->ip_notify & (N_PARITY_ERROR | ||
| 1314 | | N_FRAMING_ERROR | ||
| 1315 | | N_BREAK)))) { | ||
| 1316 | /* There is an error condition on the next byte. | ||
| 1317 | * If we have already transferred some bytes, | ||
| 1318 | * we'll stop here. Otherwise if this is the | ||
| 1319 | * first byte to be read, we'll just transfer | ||
| 1320 | * it alone after notifying the | ||
| 1321 | * upper layer of its status. | ||
| 1322 | */ | ||
| 1323 | if (total > 0) { | ||
| 1324 | len = 0; | ||
| 1325 | break; | ||
| 1326 | } else { | ||
| 1327 | if ((*sc & RXSB_PAR_ERR) && | ||
| 1328 | (port-> | ||
| 1329 | ip_notify & N_PARITY_ERROR)) { | ||
| 1330 | ioc3_cb_post_ncs(the_port, | ||
| 1331 | NCS_PARITY); | ||
| 1332 | } | ||
| 1333 | if ((*sc & RXSB_FRAME_ERR) && | ||
| 1334 | (port-> | ||
| 1335 | ip_notify & N_FRAMING_ERROR)) { | ||
| 1336 | ioc3_cb_post_ncs(the_port, | ||
| 1337 | NCS_FRAMING); | ||
| 1338 | } | ||
| 1339 | if ((*sc & RXSB_BREAK) | ||
| 1340 | && (port->ip_notify & N_BREAK)) { | ||
| 1341 | ioc3_cb_post_ncs | ||
| 1342 | (the_port, NCS_BREAK); | ||
| 1343 | } | ||
| 1344 | len = 1; | ||
| 1345 | } | ||
| 1346 | } | ||
| 1347 | if (*sc & RXSB_DATA_VALID) { | ||
| 1348 | *sc &= ~RXSB_DATA_VALID; | ||
| 1349 | *buf = entry->ring_data[byte_num]; | ||
| 1350 | buf++; | ||
| 1351 | len--; | ||
| 1352 | total++; | ||
| 1353 | } | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | /* If we used up this entry entirely, go on to the next one, | ||
| 1357 | * otherwise we must have run out of buffer space, so | ||
| 1358 | * leave the consumer pointer here for the next read in case | ||
| 1359 | * there are still unread bytes in this entry. | ||
| 1360 | */ | ||
| 1361 | if ((entry->ring_allsc & RING_ANY_VALID) == 0) { | ||
| 1362 | cons_ptr += (int)sizeof(struct ring_entry); | ||
| 1363 | cons_ptr &= PROD_CONS_MASK; | ||
| 1364 | } | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | /* Update consumer pointer and re-arm rx timer interrupt */ | ||
| 1368 | writel(cons_ptr, &port->ip_serial_regs->srcir); | ||
| 1369 | port->ip_rx_cons = cons_ptr; | ||
| 1370 | |||
| 1371 | /* If we have now dipped below the rx high water mark and we have | ||
| 1372 | * rx_high interrupt turned off, we can now turn it back on again. | ||
| 1373 | */ | ||
| 1374 | if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr) | ||
| 1375 | & PROD_CONS_MASK) < | ||
| 1376 | ((port-> | ||
| 1377 | ip_sscr & | ||
| 1378 | SSCR_RX_THRESHOLD) | ||
| 1379 | << PROD_CONS_PTR_OFF))) { | ||
| 1380 | port->ip_flags &= ~INPUT_HIGH; | ||
| 1381 | enable_intrs(port, hooks->intr_rx_high); | ||
| 1382 | } | ||
| 1383 | return total; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | /** | ||
| 1387 | * receive_chars - upper level read. | ||
| 1388 | * @the_port: port to read from | ||
| 1389 | */ | ||
| 1390 | static int receive_chars(struct uart_port *the_port) | ||
| 1391 | { | ||
| 1392 | struct tty_struct *tty; | ||
| 1393 | unsigned char ch[MAX_CHARS]; | ||
| 1394 | int read_count = 0, read_room, flip = 0; | ||
| 1395 | struct uart_info *info = the_port->info; | ||
| 1396 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1397 | unsigned long pflags; | ||
| 1398 | |||
| 1399 | /* Make sure all the pointers are "good" ones */ | ||
| 1400 | if (!info) | ||
| 1401 | return 0; | ||
| 1402 | if (!info->tty) | ||
| 1403 | return 0; | ||
| 1404 | |||
| 1405 | if (!(port->ip_flags & INPUT_ENABLE)) | ||
| 1406 | return 0; | ||
| 1407 | |||
| 1408 | spin_lock_irqsave(&the_port->lock, pflags); | ||
| 1409 | tty = info->tty; | ||
| 1410 | |||
| 1411 | read_count = do_read(the_port, ch, MAX_CHARS); | ||
| 1412 | if (read_count > 0) { | ||
| 1413 | flip = 1; | ||
| 1414 | read_room = tty_buffer_request_room(tty, read_count); | ||
| 1415 | tty_insert_flip_string(tty, ch, read_room); | ||
| 1416 | the_port->icount.rx += read_count; | ||
| 1417 | } | ||
| 1418 | spin_unlock_irqrestore(&the_port->lock, pflags); | ||
| 1419 | |||
| 1420 | if (flip) | ||
| 1421 | tty_flip_buffer_push(tty); | ||
| 1422 | |||
| 1423 | return read_count; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | /** | ||
| 1427 | * ioc3uart_intr_one - lowest level (per port) interrupt handler. | ||
| 1428 | * @is : submodule | ||
| 1429 | * @idd: driver data | ||
| 1430 | * @pending: interrupts to handle | ||
| 1431 | * @regs: pt_regs | ||
| 1432 | */ | ||
| 1433 | |||
| 1434 | static int inline | ||
| 1435 | ioc3uart_intr_one(struct ioc3_submodule *is, | ||
| 1436 | struct ioc3_driver_data *idd, | ||
| 1437 | unsigned int pending, struct pt_regs *regs) | ||
| 1438 | { | ||
| 1439 | int port_num = GET_PORT_FROM_SIO_IR(pending); | ||
| 1440 | struct port_hooks *hooks; | ||
| 1441 | unsigned int rx_high_rd_aborted = 0; | ||
| 1442 | unsigned long flags; | ||
| 1443 | struct uart_port *the_port; | ||
| 1444 | struct ioc3_port *port; | ||
| 1445 | int loop_counter; | ||
| 1446 | struct ioc3_card *card_ptr; | ||
| 1447 | unsigned int sio_ir; | ||
| 1448 | |||
| 1449 | card_ptr = idd->data[is->id]; | ||
| 1450 | port = card_ptr->ic_port[port_num].icp_port; | ||
| 1451 | hooks = port->ip_hooks; | ||
| 1452 | |||
| 1453 | /* Possible race condition here: The tx_mt interrupt bit may be | ||
| 1454 | * cleared without the intervention of the interrupt handler, | ||
| 1455 | * e.g. by a write. If the top level interrupt handler reads a | ||
| 1456 | * tx_mt, then some other processor does a write, starting up | ||
| 1457 | * output, then we come in here, see the tx_mt and stop DMA, the | ||
| 1458 | * output started by the other processor will hang. Thus we can | ||
| 1459 | * only rely on tx_mt being legitimate if it is read while the | ||
| 1460 | * port lock is held. Therefore this bit must be ignored in the | ||
| 1461 | * passed in interrupt mask which was read by the top level | ||
| 1462 | * interrupt handler since the port lock was not held at the time | ||
| 1463 | * it was read. We can only rely on this bit being accurate if it | ||
| 1464 | * is read while the port lock is held. So we'll clear it for now, | ||
| 1465 | * and reload it later once we have the port lock. | ||
| 1466 | */ | ||
| 1467 | |||
| 1468 | sio_ir = pending & ~(hooks->intr_tx_mt); | ||
| 1469 | spin_lock_irqsave(&port->ip_lock, flags); | ||
| 1470 | |||
| 1471 | loop_counter = MAXITER; /* to avoid hangs */ | ||
| 1472 | |||
| 1473 | do { | ||
| 1474 | uint32_t shadow; | ||
| 1475 | |||
| 1476 | if (loop_counter-- <= 0) { | ||
| 1477 | printk(KERN_WARNING "IOC3 serial: " | ||
| 1478 | "possible hang condition/" | ||
| 1479 | "port stuck on interrupt (line %d).\n", | ||
| 1480 | ((struct uart_port *)port->ip_port)->line); | ||
| 1481 | break; | ||
| 1482 | } | ||
| 1483 | /* Handle a DCD change */ | ||
| 1484 | if (sio_ir & hooks->intr_delta_dcd) { | ||
| 1485 | ioc3_ack(is, idd, hooks->intr_delta_dcd); | ||
| 1486 | shadow = readl(&port->ip_serial_regs->shadow); | ||
| 1487 | |||
| 1488 | if ((port->ip_notify & N_DDCD) | ||
| 1489 | && (shadow & SHADOW_DCD) | ||
| 1490 | && (port->ip_port)) { | ||
| 1491 | the_port = port->ip_port; | ||
| 1492 | uart_handle_dcd_change(the_port, | ||
| 1493 | shadow & SHADOW_DCD); | ||
| 1494 | wake_up_interruptible | ||
| 1495 | (&the_port->info->delta_msr_wait); | ||
| 1496 | } else if ((port->ip_notify & N_DDCD) | ||
| 1497 | && !(shadow & SHADOW_DCD)) { | ||
| 1498 | /* Flag delta DCD/no DCD */ | ||
| 1499 | uart_handle_dcd_change(port->ip_port, | ||
| 1500 | shadow & SHADOW_DCD); | ||
| 1501 | port->ip_flags |= DCD_ON; | ||
| 1502 | } | ||
| 1503 | } | ||
| 1504 | |||
| 1505 | /* Handle a CTS change */ | ||
| 1506 | if (sio_ir & hooks->intr_delta_cts) { | ||
| 1507 | ioc3_ack(is, idd, hooks->intr_delta_cts); | ||
| 1508 | shadow = readl(&port->ip_serial_regs->shadow); | ||
| 1509 | |||
| 1510 | if ((port->ip_notify & N_DCTS) && (port->ip_port)) { | ||
| 1511 | the_port = port->ip_port; | ||
| 1512 | uart_handle_cts_change(the_port, shadow | ||
| 1513 | & SHADOW_CTS); | ||
| 1514 | wake_up_interruptible | ||
| 1515 | (&the_port->info->delta_msr_wait); | ||
| 1516 | } | ||
| 1517 | } | ||
| 1518 | |||
| 1519 | /* rx timeout interrupt. Must be some data available. Put this | ||
| 1520 | * before the check for rx_high since servicing this condition | ||
| 1521 | * may cause that condition to clear. | ||
| 1522 | */ | ||
| 1523 | if (sio_ir & hooks->intr_rx_timer) { | ||
| 1524 | ioc3_ack(is, idd, hooks->intr_rx_timer); | ||
| 1525 | if ((port->ip_notify & N_DATA_READY) | ||
| 1526 | && (port->ip_port)) { | ||
| 1527 | receive_chars(port->ip_port); | ||
| 1528 | } | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | /* rx high interrupt. Must be after rx_timer. */ | ||
| 1532 | else if (sio_ir & hooks->intr_rx_high) { | ||
| 1533 | /* Data available, notify upper layer */ | ||
| 1534 | if ((port->ip_notify & N_DATA_READY) && port->ip_port) { | ||
| 1535 | receive_chars(port->ip_port); | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | /* We can't ACK this interrupt. If receive_chars didn't | ||
| 1539 | * cause the condition to clear, we'll have to disable | ||
| 1540 | * the interrupt until the data is drained. | ||
| 1541 | * If the read was aborted, don't disable the interrupt | ||
| 1542 | * as this may cause us to hang indefinitely. An | ||
| 1543 | * aborted read generally means that this interrupt | ||
| 1544 | * hasn't been delivered to the cpu yet anyway, even | ||
| 1545 | * though we see it as asserted when we read the sio_ir. | ||
| 1546 | */ | ||
| 1547 | if ((sio_ir = PENDING(card_ptr, idd)) | ||
| 1548 | & hooks->intr_rx_high) { | ||
| 1549 | if (port->ip_flags & READ_ABORTED) { | ||
| 1550 | rx_high_rd_aborted++; | ||
| 1551 | } | ||
| 1552 | else { | ||
| 1553 | card_ptr->ic_enable &= ~hooks->intr_rx_high; | ||
| 1554 | port->ip_flags |= INPUT_HIGH; | ||
| 1555 | } | ||
| 1556 | } | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | /* We got a low water interrupt: notify upper layer to | ||
| 1560 | * send more data. Must come before tx_mt since servicing | ||
| 1561 | * this condition may cause that condition to clear. | ||
| 1562 | */ | ||
| 1563 | if (sio_ir & hooks->intr_tx_explicit) { | ||
| 1564 | port->ip_flags &= ~LOWAT_WRITTEN; | ||
| 1565 | ioc3_ack(is, idd, hooks->intr_tx_explicit); | ||
| 1566 | if (port->ip_notify & N_OUTPUT_LOWAT) | ||
| 1567 | ioc3_cb_output_lowat(port); | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | /* Handle tx_mt. Must come after tx_explicit. */ | ||
| 1571 | else if (sio_ir & hooks->intr_tx_mt) { | ||
| 1572 | /* If we are expecting a lowat notification | ||
| 1573 | * and we get to this point it probably means that for | ||
| 1574 | * some reason the tx_explicit didn't work as expected | ||
| 1575 | * (that can legitimately happen if the output buffer is | ||
| 1576 | * filled up in just the right way). | ||
| 1577 | * So send the notification now. | ||
| 1578 | */ | ||
| 1579 | if (port->ip_notify & N_OUTPUT_LOWAT) { | ||
| 1580 | ioc3_cb_output_lowat(port); | ||
| 1581 | |||
| 1582 | /* We need to reload the sio_ir since the lowat | ||
| 1583 | * call may have caused another write to occur, | ||
| 1584 | * clearing the tx_mt condition. | ||
| 1585 | */ | ||
| 1586 | sio_ir = PENDING(card_ptr, idd); | ||
| 1587 | } | ||
| 1588 | |||
| 1589 | /* If the tx_mt condition still persists even after the | ||
| 1590 | * lowat call, we've got some work to do. | ||
| 1591 | */ | ||
| 1592 | if (sio_ir & hooks->intr_tx_mt) { | ||
| 1593 | /* If we are not currently expecting DMA input, | ||
| 1594 | * and the transmitter has just gone idle, | ||
| 1595 | * there is no longer any reason for DMA, so | ||
| 1596 | * disable it. | ||
| 1597 | */ | ||
| 1598 | if (!(port->ip_notify | ||
| 1599 | & (N_DATA_READY | N_DDCD))) { | ||
| 1600 | BUG_ON(!(port->ip_sscr | ||
| 1601 | & SSCR_DMA_EN)); | ||
| 1602 | port->ip_sscr &= ~SSCR_DMA_EN; | ||
| 1603 | writel(port->ip_sscr, | ||
| 1604 | &port->ip_serial_regs->sscr); | ||
| 1605 | } | ||
| 1606 | /* Prevent infinite tx_mt interrupt */ | ||
| 1607 | card_ptr->ic_enable &= ~hooks->intr_tx_mt; | ||
| 1608 | } | ||
| 1609 | } | ||
| 1610 | sio_ir = PENDING(card_ptr, idd); | ||
| 1611 | |||
| 1612 | /* if the read was aborted and only hooks->intr_rx_high, | ||
| 1613 | * clear hooks->intr_rx_high, so we do not loop forever. | ||
| 1614 | */ | ||
| 1615 | |||
| 1616 | if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) { | ||
| 1617 | sio_ir &= ~hooks->intr_rx_high; | ||
| 1618 | } | ||
| 1619 | } while (sio_ir & hooks->intr_all); | ||
| 1620 | |||
| 1621 | spin_unlock_irqrestore(&port->ip_lock, flags); | ||
| 1622 | ioc3_enable(is, idd, card_ptr->ic_enable); | ||
| 1623 | return 0; | ||
| 1624 | } | ||
| 1625 | |||
| 1626 | /** | ||
| 1627 | * ioc3uart_intr - field all serial interrupts | ||
| 1628 | * @is : submodule | ||
| 1629 | * @idd: driver data | ||
| 1630 | * @pending: interrupts to handle | ||
| 1631 | * @regs: pt_regs | ||
| 1632 | * | ||
| 1633 | */ | ||
| 1634 | |||
| 1635 | static int ioc3uart_intr(struct ioc3_submodule *is, | ||
| 1636 | struct ioc3_driver_data *idd, | ||
| 1637 | unsigned int pending, struct pt_regs *regs) | ||
| 1638 | { | ||
| 1639 | int ret = 0; | ||
| 1640 | |||
| 1641 | /* | ||
| 1642 | * The upper level interrupt handler sends interrupts for both ports | ||
| 1643 | * here. So we need to call for each port with its interrupts. | ||
| 1644 | */ | ||
| 1645 | |||
| 1646 | if (pending & SIO_IR_SA) | ||
| 1647 | ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs); | ||
| 1648 | if (pending & SIO_IR_SB) | ||
| 1649 | ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs); | ||
| 1650 | |||
| 1651 | return ret; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | /** | ||
| 1655 | * ic3_type | ||
| 1656 | * @port: Port to operate with (we ignore since we only have one port) | ||
| 1657 | * | ||
| 1658 | */ | ||
| 1659 | static const char *ic3_type(struct uart_port *the_port) | ||
| 1660 | { | ||
| 1661 | if (IS_RS232(the_port->line)) | ||
| 1662 | return "SGI IOC3 Serial [rs232]"; | ||
| 1663 | else | ||
| 1664 | return "SGI IOC3 Serial [rs422]"; | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | /** | ||
| 1668 | * ic3_tx_empty - Is the transmitter empty? | ||
| 1669 | * @port: Port to operate on | ||
| 1670 | * | ||
| 1671 | */ | ||
| 1672 | static unsigned int ic3_tx_empty(struct uart_port *the_port) | ||
| 1673 | { | ||
| 1674 | unsigned int ret = 0; | ||
| 1675 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1676 | |||
| 1677 | if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT) | ||
| 1678 | ret = TIOCSER_TEMT; | ||
| 1679 | return ret; | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | /** | ||
| 1683 | * ic3_stop_tx - stop the transmitter | ||
| 1684 | * @port: Port to operate on | ||
| 1685 | * | ||
| 1686 | */ | ||
| 1687 | static void ic3_stop_tx(struct uart_port *the_port) | ||
| 1688 | { | ||
| 1689 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1690 | |||
| 1691 | if (port) | ||
| 1692 | set_notification(port, N_OUTPUT_LOWAT, 0); | ||
| 1693 | } | ||
| 1694 | |||
| 1695 | /** | ||
| 1696 | * ic3_stop_rx - stop the receiver | ||
| 1697 | * @port: Port to operate on | ||
| 1698 | * | ||
| 1699 | */ | ||
| 1700 | static void ic3_stop_rx(struct uart_port *the_port) | ||
| 1701 | { | ||
| 1702 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1703 | |||
| 1704 | if (port) | ||
| 1705 | port->ip_flags &= ~INPUT_ENABLE; | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | /** | ||
| 1709 | * null_void_function | ||
| 1710 | * @port: Port to operate on | ||
| 1711 | * | ||
| 1712 | */ | ||
| 1713 | static void null_void_function(struct uart_port *the_port) | ||
| 1714 | { | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | /** | ||
| 1718 | * ic3_shutdown - shut down the port - free irq and disable | ||
| 1719 | * @port: port to shut down | ||
| 1720 | * | ||
| 1721 | */ | ||
| 1722 | static void ic3_shutdown(struct uart_port *the_port) | ||
| 1723 | { | ||
| 1724 | unsigned long port_flags; | ||
| 1725 | struct ioc3_port *port; | ||
| 1726 | struct uart_info *info; | ||
| 1727 | |||
| 1728 | port = get_ioc3_port(the_port); | ||
| 1729 | if (!port) | ||
| 1730 | return; | ||
| 1731 | |||
| 1732 | info = the_port->info; | ||
| 1733 | wake_up_interruptible(&info->delta_msr_wait); | ||
| 1734 | |||
| 1735 | spin_lock_irqsave(&the_port->lock, port_flags); | ||
| 1736 | set_notification(port, N_ALL, 0); | ||
| 1737 | spin_unlock_irqrestore(&the_port->lock, port_flags); | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | /** | ||
| 1741 | * ic3_set_mctrl - set control lines (dtr, rts, etc) | ||
| 1742 | * @port: Port to operate on | ||
| 1743 | * @mctrl: Lines to set/unset | ||
| 1744 | * | ||
| 1745 | */ | ||
| 1746 | static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl) | ||
| 1747 | { | ||
| 1748 | unsigned char mcr = 0; | ||
| 1749 | |||
| 1750 | if (mctrl & TIOCM_RTS) | ||
| 1751 | mcr |= UART_MCR_RTS; | ||
| 1752 | if (mctrl & TIOCM_DTR) | ||
| 1753 | mcr |= UART_MCR_DTR; | ||
| 1754 | if (mctrl & TIOCM_OUT1) | ||
| 1755 | mcr |= UART_MCR_OUT1; | ||
| 1756 | if (mctrl & TIOCM_OUT2) | ||
| 1757 | mcr |= UART_MCR_OUT2; | ||
| 1758 | if (mctrl & TIOCM_LOOP) | ||
| 1759 | mcr |= UART_MCR_LOOP; | ||
| 1760 | |||
| 1761 | set_mcr(the_port, mcr, SHADOW_DTR); | ||
| 1762 | } | ||
| 1763 | |||
| 1764 | /** | ||
| 1765 | * ic3_get_mctrl - get control line info | ||
| 1766 | * @port: port to operate on | ||
| 1767 | * | ||
| 1768 | */ | ||
| 1769 | static unsigned int ic3_get_mctrl(struct uart_port *the_port) | ||
| 1770 | { | ||
| 1771 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1772 | uint32_t shadow; | ||
| 1773 | unsigned int ret = 0; | ||
| 1774 | |||
| 1775 | if (!port) | ||
| 1776 | return 0; | ||
| 1777 | |||
| 1778 | shadow = readl(&port->ip_serial_regs->shadow); | ||
| 1779 | if (shadow & SHADOW_DCD) | ||
| 1780 | ret |= TIOCM_CD; | ||
| 1781 | if (shadow & SHADOW_DR) | ||
| 1782 | ret |= TIOCM_DSR; | ||
| 1783 | if (shadow & SHADOW_CTS) | ||
| 1784 | ret |= TIOCM_CTS; | ||
| 1785 | return ret; | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | /** | ||
| 1789 | * ic3_start_tx - Start transmitter. Called with the_port->lock | ||
| 1790 | * @port: Port to operate on | ||
| 1791 | * | ||
| 1792 | */ | ||
| 1793 | static void ic3_start_tx(struct uart_port *the_port) | ||
| 1794 | { | ||
| 1795 | struct ioc3_port *port = get_ioc3_port(the_port); | ||
| 1796 | |||
| 1797 | if (port) { | ||
| 1798 | set_notification(port, N_OUTPUT_LOWAT, 1); | ||
| 1799 | enable_intrs(port, port->ip_hooks->intr_tx_mt); | ||
| 1800 | } | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | /** | ||
| 1804 | * ic3_break_ctl - handle breaks | ||
| 1805 | * @port: Port to operate on | ||
| 1806 | * @break_state: Break state | ||
| 1807 | * | ||
| 1808 | */ | ||
| 1809 | static void ic3_break_ctl(struct uart_port *the_port, int break_state) | ||
| 1810 | { | ||
| 1811 | } | ||
| 1812 | |||
| 1813 | /** | ||
| 1814 | * ic3_startup - Start up the serial port - always return 0 (We're always on) | ||
| 1815 | * @port: Port to operate on | ||
| 1816 | * | ||
| 1817 | */ | ||
| 1818 | static int ic3_startup(struct uart_port *the_port) | ||
| 1819 | { | ||
| 1820 | int retval; | ||
| 1821 | struct ioc3_port *port; | ||
| 1822 | struct ioc3_card *card_ptr; | ||
| 1823 | unsigned long port_flags; | ||
| 1824 | |||
| 1825 | if (!the_port) { | ||
| 1826 | NOT_PROGRESS(); | ||
| 1827 | return -ENODEV; | ||
| 1828 | } | ||
| 1829 | port = get_ioc3_port(the_port); | ||
| 1830 | if (!port) { | ||
| 1831 | NOT_PROGRESS(); | ||
| 1832 | return -ENODEV; | ||
| 1833 | } | ||
| 1834 | card_ptr = port->ip_card; | ||
| 1835 | port->ip_port = the_port; | ||
| 1836 | |||
| 1837 | if (!card_ptr) { | ||
| 1838 | NOT_PROGRESS(); | ||
| 1839 | return -ENODEV; | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | /* Start up the serial port */ | ||
| 1843 | spin_lock_irqsave(&the_port->lock, port_flags); | ||
| 1844 | retval = ic3_startup_local(the_port); | ||
| 1845 | spin_unlock_irqrestore(&the_port->lock, port_flags); | ||
| 1846 | return retval; | ||
| 1847 | } | ||
| 1848 | |||
| 1849 | /** | ||
| 1850 | * ic3_set_termios - set termios stuff | ||
| 1851 | * @port: port to operate on | ||
| 1852 | * @termios: New settings | ||
| 1853 | * @termios: Old | ||
| 1854 | * | ||
| 1855 | */ | ||
| 1856 | static void | ||
| 1857 | ic3_set_termios(struct uart_port *the_port, | ||
| 1858 | struct termios *termios, struct termios *old_termios) | ||
| 1859 | { | ||
| 1860 | unsigned long port_flags; | ||
| 1861 | |||
| 1862 | spin_lock_irqsave(&the_port->lock, port_flags); | ||
| 1863 | ioc3_change_speed(the_port, termios, old_termios); | ||
| 1864 | spin_unlock_irqrestore(&the_port->lock, port_flags); | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | /** | ||
| 1868 | * ic3_request_port - allocate resources for port - no op.... | ||
| 1869 | * @port: port to operate on | ||
| 1870 | * | ||
| 1871 | */ | ||
| 1872 | static int ic3_request_port(struct uart_port *port) | ||
| 1873 | { | ||
| 1874 | return 0; | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | /* Associate the uart functions above - given to serial core */ | ||
| 1878 | static struct uart_ops ioc3_ops = { | ||
| 1879 | .tx_empty = ic3_tx_empty, | ||
| 1880 | .set_mctrl = ic3_set_mctrl, | ||
| 1881 | .get_mctrl = ic3_get_mctrl, | ||
| 1882 | .stop_tx = ic3_stop_tx, | ||
| 1883 | .start_tx = ic3_start_tx, | ||
| 1884 | .stop_rx = ic3_stop_rx, | ||
| 1885 | .enable_ms = null_void_function, | ||
| 1886 | .break_ctl = ic3_break_ctl, | ||
| 1887 | .startup = ic3_startup, | ||
| 1888 | .shutdown = ic3_shutdown, | ||
| 1889 | .set_termios = ic3_set_termios, | ||
| 1890 | .type = ic3_type, | ||
| 1891 | .release_port = null_void_function, | ||
| 1892 | .request_port = ic3_request_port, | ||
| 1893 | }; | ||
| 1894 | |||
| 1895 | /* | ||
| 1896 | * Boot-time initialization code | ||
| 1897 | */ | ||
| 1898 | |||
| 1899 | static struct uart_driver ioc3_uart = { | ||
| 1900 | .owner = THIS_MODULE, | ||
| 1901 | .driver_name = "ioc3_serial", | ||
| 1902 | .dev_name = DEVICE_NAME, | ||
| 1903 | .major = DEVICE_MAJOR, | ||
| 1904 | .minor = DEVICE_MINOR, | ||
| 1905 | .nr = MAX_LOGICAL_PORTS | ||
| 1906 | }; | ||
| 1907 | |||
| 1908 | /** | ||
| 1909 | * ioc3_serial_core_attach - register with serial core | ||
| 1910 | * This is done during pci probing | ||
| 1911 | * @is: submodule struct for this | ||
| 1912 | * @idd: handle for this card | ||
| 1913 | */ | ||
| 1914 | static inline int ioc3_serial_core_attach( struct ioc3_submodule *is, | ||
| 1915 | struct ioc3_driver_data *idd) | ||
| 1916 | { | ||
| 1917 | struct ioc3_port *port; | ||
| 1918 | struct uart_port *the_port; | ||
| 1919 | struct ioc3_card *card_ptr = idd->data[is->id]; | ||
| 1920 | int ii, phys_port; | ||
| 1921 | struct pci_dev *pdev = idd->pdev; | ||
| 1922 | |||
| 1923 | DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n", | ||
| 1924 | __FUNCTION__, pdev, (void *)card_ptr)); | ||
| 1925 | |||
| 1926 | if (!card_ptr) | ||
| 1927 | return -ENODEV; | ||
| 1928 | |||
| 1929 | /* once around for each logical port on this card */ | ||
| 1930 | for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { | ||
| 1931 | phys_port = GET_PHYSICAL_PORT(ii); | ||
| 1932 | the_port = &card_ptr->ic_port[phys_port]. | ||
| 1933 | icp_uart_port[GET_LOGICAL_PORT(ii)]; | ||
| 1934 | port = card_ptr->ic_port[phys_port].icp_port; | ||
| 1935 | port->ip_port = the_port; | ||
| 1936 | |||
| 1937 | DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n", | ||
| 1938 | __FUNCTION__, (void *)the_port, (void *)port, | ||
| 1939 | phys_port, ii)); | ||
| 1940 | |||
| 1941 | /* membase, iobase and mapbase just need to be non-0 */ | ||
| 1942 | the_port->membase = (unsigned char __iomem *)1; | ||
| 1943 | the_port->iobase = (pdev->bus->number << 16) | ii; | ||
| 1944 | the_port->line = (Num_of_ioc3_cards << 2) | ii; | ||
| 1945 | the_port->mapbase = 1; | ||
| 1946 | the_port->type = PORT_16550A; | ||
| 1947 | the_port->fifosize = FIFO_SIZE; | ||
| 1948 | the_port->ops = &ioc3_ops; | ||
| 1949 | the_port->irq = idd->irq_io; | ||
| 1950 | the_port->dev = &pdev->dev; | ||
| 1951 | |||
| 1952 | if (uart_add_one_port(&ioc3_uart, the_port) < 0) { | ||
| 1953 | printk(KERN_WARNING | ||
| 1954 | "%s: unable to add port %d bus %d\n", | ||
| 1955 | __FUNCTION__, the_port->line, pdev->bus->number); | ||
| 1956 | } else { | ||
| 1957 | DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n", | ||
| 1958 | the_port->line, the_port->irq, pdev->bus->number)); | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | /* all ports are rs232 for now */ | ||
| 1962 | if (IS_PHYSICAL_PORT(ii)) | ||
| 1963 | ioc3_set_proto(port, PROTO_RS232); | ||
| 1964 | } | ||
| 1965 | return 0; | ||
| 1966 | } | ||
| 1967 | |||
| 1968 | /** | ||
| 1969 | * ioc3uart_remove - register detach function | ||
| 1970 | * @is: submodule struct for this submodule | ||
| 1971 | * @idd: ioc3 driver data for this submodule | ||
| 1972 | */ | ||
| 1973 | |||
| 1974 | static int ioc3uart_remove(struct ioc3_submodule *is, | ||
| 1975 | struct ioc3_driver_data *idd) | ||
| 1976 | { | ||
| 1977 | struct ioc3_card *card_ptr = idd->data[is->id]; | ||
| 1978 | struct uart_port *the_port; | ||
| 1979 | struct ioc3_port *port; | ||
| 1980 | int ii; | ||
| 1981 | |||
| 1982 | if (card_ptr) { | ||
| 1983 | for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { | ||
| 1984 | the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. | ||
| 1985 | icp_uart_port[GET_LOGICAL_PORT(ii)]; | ||
| 1986 | if (the_port) | ||
| 1987 | uart_remove_one_port(&ioc3_uart, the_port); | ||
| 1988 | port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port; | ||
| 1989 | if (port && IS_PHYSICAL_PORT(ii) | ||
| 1990 | && (GET_PHYSICAL_PORT(ii) == 0)) { | ||
| 1991 | pci_free_consistent(port->ip_idd->pdev, | ||
| 1992 | TOTAL_RING_BUF_SIZE, | ||
| 1993 | (void *)port->ip_cpu_ringbuf, | ||
| 1994 | port->ip_dma_ringbuf); | ||
| 1995 | kfree(port); | ||
| 1996 | card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. | ||
| 1997 | icp_port = NULL; | ||
| 1998 | } | ||
| 1999 | } | ||
| 2000 | kfree(card_ptr); | ||
| 2001 | idd->data[is->id] = NULL; | ||
| 2002 | } | ||
| 2003 | return 0; | ||
| 2004 | } | ||
| 2005 | |||
| 2006 | /** | ||
| 2007 | * ioc3uart_probe - card probe function called from shim driver | ||
| 2008 | * @is: submodule struct for this submodule | ||
| 2009 | * @idd: ioc3 driver data for this card | ||
| 2010 | */ | ||
| 2011 | |||
| 2012 | static int __devinit | ||
| 2013 | ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | ||
| 2014 | { | ||
| 2015 | struct pci_dev *pdev = idd->pdev; | ||
| 2016 | struct ioc3_card *card_ptr; | ||
| 2017 | int ret = 0; | ||
| 2018 | struct ioc3_port *port; | ||
| 2019 | struct ioc3_port *ports[PORTS_PER_CARD]; | ||
| 2020 | int phys_port; | ||
| 2021 | |||
| 2022 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd)); | ||
| 2023 | |||
| 2024 | card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL); | ||
| 2025 | if (!card_ptr) { | ||
| 2026 | printk(KERN_WARNING "ioc3_attach_one" | ||
| 2027 | ": unable to get memory for the IOC3\n"); | ||
| 2028 | return -ENOMEM; | ||
| 2029 | } | ||
| 2030 | memset(card_ptr, 0, sizeof(struct ioc3_card)); | ||
| 2031 | idd->data[is->id] = card_ptr; | ||
| 2032 | Submodule_slot = is->id; | ||
| 2033 | |||
| 2034 | writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) | | ||
| 2035 | ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) | | ||
| 2036 | (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr); | ||
| 2037 | |||
| 2038 | pci_write_config_dword(pdev, PCI_LAT, 0xff00); | ||
| 2039 | |||
| 2040 | /* Enable serial port mode select generic PIO pins as outputs */ | ||
| 2041 | ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL); | ||
| 2042 | |||
| 2043 | /* Create port structures for each port */ | ||
| 2044 | for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) { | ||
| 2045 | port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL); | ||
| 2046 | if (!port) { | ||
| 2047 | printk(KERN_WARNING | ||
| 2048 | "IOC3 serial memory not available for port\n"); | ||
| 2049 | goto out4; | ||
| 2050 | } | ||
| 2051 | memset(port, 0, sizeof(struct ioc3_port)); | ||
| 2052 | spin_lock_init(&port->ip_lock); | ||
| 2053 | |||
| 2054 | /* we need to remember the previous ones, to point back to | ||
| 2055 | * them farther down - setting up the ring buffers. | ||
| 2056 | */ | ||
| 2057 | ports[phys_port] = port; | ||
| 2058 | |||
| 2059 | /* init to something useful */ | ||
| 2060 | card_ptr->ic_port[phys_port].icp_port = port; | ||
| 2061 | port->ip_is = is; | ||
| 2062 | port->ip_idd = idd; | ||
| 2063 | port->ip_baud = 9600; | ||
| 2064 | port->ip_card = card_ptr; | ||
| 2065 | port->ip_hooks = &hooks_array[phys_port]; | ||
| 2066 | |||
| 2067 | /* Setup each port */ | ||
| 2068 | if (phys_port == 0) { | ||
| 2069 | port->ip_serial_regs = &idd->vma->port_a; | ||
| 2070 | port->ip_uart_regs = &idd->vma->sregs.uarta; | ||
| 2071 | |||
| 2072 | DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p " | ||
| 2073 | "ip_uart_regs 0x%p\n", | ||
| 2074 | __FUNCTION__, | ||
| 2075 | (void *)port->ip_serial_regs, | ||
| 2076 | (void *)port->ip_uart_regs)); | ||
| 2077 | |||
| 2078 | /* setup ring buffers */ | ||
| 2079 | port->ip_cpu_ringbuf = pci_alloc_consistent(pdev, | ||
| 2080 | TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf); | ||
| 2081 | |||
| 2082 | BUG_ON(!((((int64_t) port->ip_dma_ringbuf) & | ||
| 2083 | (TOTAL_RING_BUF_SIZE - 1)) == 0)); | ||
| 2084 | port->ip_inring = RING(port, RX_A); | ||
| 2085 | port->ip_outring = RING(port, TX_A); | ||
| 2086 | DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p " | ||
| 2087 | "ip_dma_ringbuf 0x%p, ip_inring 0x%p " | ||
| 2088 | "ip_outring 0x%p\n", | ||
| 2089 | __FUNCTION__, | ||
| 2090 | (void *)port->ip_cpu_ringbuf, | ||
| 2091 | (void *)port->ip_dma_ringbuf, | ||
| 2092 | (void *)port->ip_inring, | ||
| 2093 | (void *)port->ip_outring)); | ||
| 2094 | } | ||
| 2095 | else { | ||
| 2096 | port->ip_serial_regs = &idd->vma->port_b; | ||
| 2097 | port->ip_uart_regs = &idd->vma->sregs.uartb; | ||
| 2098 | |||
| 2099 | DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p " | ||
| 2100 | "ip_uart_regs 0x%p\n", | ||
| 2101 | __FUNCTION__, | ||
| 2102 | (void *)port->ip_serial_regs, | ||
| 2103 | (void *)port->ip_uart_regs)); | ||
| 2104 | |||
| 2105 | /* share the ring buffers */ | ||
| 2106 | port->ip_dma_ringbuf = | ||
| 2107 | ports[phys_port - 1]->ip_dma_ringbuf; | ||
| 2108 | port->ip_cpu_ringbuf = | ||
| 2109 | ports[phys_port - 1]->ip_cpu_ringbuf; | ||
| 2110 | port->ip_inring = RING(port, RX_B); | ||
| 2111 | port->ip_outring = RING(port, TX_B); | ||
| 2112 | DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p " | ||
| 2113 | "ip_dma_ringbuf 0x%p, ip_inring 0x%p " | ||
| 2114 | "ip_outring 0x%p\n", | ||
| 2115 | __FUNCTION__, | ||
| 2116 | (void *)port->ip_cpu_ringbuf, | ||
| 2117 | (void *)port->ip_dma_ringbuf, | ||
| 2118 | (void *)port->ip_inring, | ||
| 2119 | (void *)port->ip_outring)); | ||
| 2120 | } | ||
| 2121 | |||
| 2122 | DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p", | ||
| 2123 | __FUNCTION__, | ||
| 2124 | phys_port, (void *)port, (void *)card_ptr)); | ||
| 2125 | DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n", | ||
| 2126 | (void *)port->ip_serial_regs, | ||
| 2127 | (void *)port->ip_uart_regs)); | ||
| 2128 | |||
| 2129 | /* Initialize the hardware for IOC3 */ | ||
| 2130 | port_init(port); | ||
| 2131 | |||
| 2132 | DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p " | ||
| 2133 | "outring 0x%p\n", | ||
| 2134 | __FUNCTION__, | ||
| 2135 | phys_port, (void *)port, | ||
| 2136 | (void *)port->ip_inring, | ||
| 2137 | (void *)port->ip_outring)); | ||
| 2138 | |||
| 2139 | } | ||
| 2140 | |||
| 2141 | /* register port with the serial core */ | ||
| 2142 | |||
| 2143 | if ((ret = ioc3_serial_core_attach(is, idd))) | ||
| 2144 | goto out4; | ||
| 2145 | |||
| 2146 | Num_of_ioc3_cards++; | ||
| 2147 | |||
| 2148 | return ret; | ||
| 2149 | |||
| 2150 | /* error exits that give back resources */ | ||
| 2151 | out4: | ||
| 2152 | kfree(card_ptr); | ||
| 2153 | return ret; | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | static struct ioc3_submodule ioc3uart_submodule = { | ||
| 2157 | .name = "IOC3uart", | ||
| 2158 | .probe = ioc3uart_probe, | ||
| 2159 | .remove = ioc3uart_remove, | ||
| 2160 | /* call .intr for both ports initially */ | ||
| 2161 | .irq_mask = SIO_IR_SA | SIO_IR_SB, | ||
| 2162 | .intr = ioc3uart_intr, | ||
| 2163 | .owner = THIS_MODULE, | ||
| 2164 | }; | ||
| 2165 | |||
| 2166 | /** | ||
| 2167 | * ioc3_detect - module init called, | ||
| 2168 | */ | ||
| 2169 | static int __devinit ioc3uart_init(void) | ||
| 2170 | { | ||
| 2171 | int ret; | ||
| 2172 | |||
| 2173 | /* register with serial core */ | ||
| 2174 | if ((ret = uart_register_driver(&ioc3_uart)) < 0) { | ||
| 2175 | printk(KERN_WARNING | ||
| 2176 | "%s: Couldn't register IOC3 uart serial driver\n", | ||
| 2177 | __FUNCTION__); | ||
| 2178 | return ret; | ||
| 2179 | } | ||
| 2180 | ret = ioc3_register_submodule(&ioc3uart_submodule); | ||
| 2181 | if (ret) | ||
| 2182 | uart_unregister_driver(&ioc3_uart); | ||
| 2183 | return ret; | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | static void __devexit ioc3uart_exit(void) | ||
| 2187 | { | ||
| 2188 | ioc3_unregister_submodule(&ioc3uart_submodule); | ||
| 2189 | uart_unregister_driver(&ioc3_uart); | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | module_init(ioc3uart_init); | ||
| 2193 | module_exit(ioc3uart_exit); | ||
| 2194 | |||
| 2195 | MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); | ||
| 2196 | MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card"); | ||
| 2197 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 7bdab2a7f59c..94b229031198 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c | |||
| @@ -175,8 +175,6 @@ int superhyway_register_driver(struct superhyway_driver *drv) | |||
| 175 | { | 175 | { |
| 176 | drv->drv.name = drv->name; | 176 | drv->drv.name = drv->name; |
| 177 | drv->drv.bus = &superhyway_bus_type; | 177 | drv->drv.bus = &superhyway_bus_type; |
| 178 | drv->drv.probe = superhyway_device_probe; | ||
| 179 | drv->drv.remove = superhyway_device_remove; | ||
| 180 | 178 | ||
| 181 | return driver_register(&drv->drv); | 179 | return driver_register(&drv->drv); |
| 182 | } | 180 | } |
| @@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = { | |||
| 213 | #ifdef CONFIG_SYSFS | 211 | #ifdef CONFIG_SYSFS |
| 214 | .dev_attrs = superhyway_dev_attrs, | 212 | .dev_attrs = superhyway_dev_attrs, |
| 215 | #endif | 213 | #endif |
| 214 | .probe = superhyway_device_probe, | ||
| 215 | .remove = superhyway_device_remove, | ||
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | static int __init superhyway_bus_init(void) | 218 | static int __init superhyway_bus_init(void) |
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig index 13b8d249da5c..d95265b187a3 100644 --- a/drivers/sn/Kconfig +++ b/drivers/sn/Kconfig | |||
| @@ -17,4 +17,18 @@ config SGI_IOC4 | |||
| 17 | If you have an SGI Altix with an IOC4-based | 17 | If you have an SGI Altix with an IOC4-based |
| 18 | I/O controller say Y. Otherwise say N. | 18 | I/O controller say Y. Otherwise say N. |
| 19 | 19 | ||
| 20 | config SGI_IOC3 | ||
| 21 | tristate "SGI IOC3 Base IO support" | ||
| 22 | depends on (IA64_GENERIC || IA64_SGI_SN2) | ||
| 23 | default m | ||
| 24 | ---help--- | ||
| 25 | This option enables basic support for the SGI IOC3-based Base IO | ||
| 26 | controller card. This option does not enable any specific | ||
| 27 | functions on such a card, but provides necessary infrastructure | ||
| 28 | for other drivers to utilize. | ||
| 29 | |||
| 30 | If you have an SGI Altix with an IOC3-based | ||
| 31 | I/O controller or a PCI IOC3 serial card say Y. | ||
| 32 | Otherwise say N. | ||
| 33 | |||
| 20 | endmenu | 34 | endmenu |
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile index c2a284185372..2cda011597c0 100644 --- a/drivers/sn/Makefile +++ b/drivers/sn/Makefile | |||
| @@ -4,3 +4,4 @@ | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_SGI_IOC4) += ioc4.o | 6 | obj-$(CONFIG_SGI_IOC4) += ioc4.o |
| 7 | obj-$(CONFIG_SGI_IOC3) += ioc3.o | ||
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c new file mode 100644 index 000000000000..aaa009f4a7bf --- /dev/null +++ b/drivers/sn/ioc3.c | |||
| @@ -0,0 +1,851 @@ | |||
| 1 | /* | ||
| 2 | * SGI IOC3 master driver and IRQ demuxer | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org> | ||
| 5 | * Heavily based on similar work by: | ||
| 6 | * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver | ||
| 7 | * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/config.h> | ||
| 11 | #include <linux/errno.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/pci.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/spinlock.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/ioc3.h> | ||
| 18 | #include <linux/rwsem.h> | ||
| 19 | |||
| 20 | #define IOC3_PCI_SIZE 0x100000 | ||
| 21 | |||
| 22 | static LIST_HEAD(ioc3_devices); | ||
| 23 | static int ioc3_counter; | ||
| 24 | static DECLARE_RWSEM(ioc3_devices_rwsem); | ||
| 25 | |||
| 26 | static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES]; | ||
| 27 | static struct ioc3_submodule *ioc3_ethernet; | ||
| 28 | static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED; | ||
| 29 | |||
| 30 | /* NIC probing code */ | ||
| 31 | |||
| 32 | #define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */ | ||
| 33 | |||
| 34 | static inline unsigned mcr_pack(unsigned pulse, unsigned sample) | ||
| 35 | { | ||
| 36 | return (pulse << 10) | (sample << 2); | ||
| 37 | } | ||
| 38 | |||
| 39 | static int nic_wait(struct ioc3_driver_data *idd) | ||
| 40 | { | ||
| 41 | volatile unsigned mcr; | ||
| 42 | |||
| 43 | do { | ||
| 44 | mcr = (volatile unsigned)idd->vma->mcr; | ||
| 45 | } while (!(mcr & 2)); | ||
| 46 | |||
| 47 | return mcr & 1; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int nic_reset(struct ioc3_driver_data *idd) | ||
| 51 | { | ||
| 52 | int presence; | ||
| 53 | unsigned long flags; | ||
| 54 | |||
| 55 | local_irq_save(flags); | ||
| 56 | idd->vma->mcr = mcr_pack(500, 65); | ||
| 57 | presence = nic_wait(idd); | ||
| 58 | local_irq_restore(flags); | ||
| 59 | |||
| 60 | udelay(500); | ||
| 61 | |||
| 62 | return presence; | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline int nic_read_bit(struct ioc3_driver_data *idd) | ||
| 66 | { | ||
| 67 | int result; | ||
| 68 | unsigned long flags; | ||
| 69 | |||
| 70 | local_irq_save(flags); | ||
| 71 | idd->vma->mcr = mcr_pack(6, 13); | ||
| 72 | result = nic_wait(idd); | ||
| 73 | local_irq_restore(flags); | ||
| 74 | |||
| 75 | udelay(500); | ||
| 76 | |||
| 77 | return result; | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit) | ||
| 81 | { | ||
| 82 | if (bit) | ||
| 83 | idd->vma->mcr = mcr_pack(6, 110); | ||
| 84 | else | ||
| 85 | idd->vma->mcr = mcr_pack(80, 30); | ||
| 86 | |||
| 87 | nic_wait(idd); | ||
| 88 | } | ||
| 89 | |||
| 90 | static unsigned nic_read_byte(struct ioc3_driver_data *idd) | ||
| 91 | { | ||
| 92 | unsigned result = 0; | ||
| 93 | int i; | ||
| 94 | |||
| 95 | for (i = 0; i < 8; i++) | ||
| 96 | result = (result >> 1) | (nic_read_bit(idd) << 7); | ||
| 97 | |||
| 98 | return result; | ||
| 99 | } | ||
| 100 | |||
| 101 | static void nic_write_byte(struct ioc3_driver_data *idd, int byte) | ||
| 102 | { | ||
| 103 | int i, bit; | ||
| 104 | |||
| 105 | for (i = 8; i; i--) { | ||
| 106 | bit = byte & 1; | ||
| 107 | byte >>= 1; | ||
| 108 | |||
| 109 | nic_write_bit(idd, bit); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | static unsigned long | ||
| 114 | nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr) | ||
| 115 | { | ||
| 116 | int a, b, index, disc; | ||
| 117 | |||
| 118 | nic_reset(idd); | ||
| 119 | |||
| 120 | /* Search ROM. */ | ||
| 121 | nic_write_byte(idd, 0xF0); | ||
| 122 | |||
| 123 | /* Algorithm from ``Book of iButton Standards''. */ | ||
| 124 | for (index = 0, disc = 0; index < 64; index++) { | ||
| 125 | a = nic_read_bit(idd); | ||
| 126 | b = nic_read_bit(idd); | ||
| 127 | |||
| 128 | if (a && b) { | ||
| 129 | printk(KERN_WARNING "IOC3 NIC search failed.\n"); | ||
| 130 | *last = 0; | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (!a && !b) { | ||
| 135 | if (index == *last) { | ||
| 136 | addr |= 1UL << index; | ||
| 137 | } else if (index > *last) { | ||
| 138 | addr &= ~(1UL << index); | ||
| 139 | disc = index; | ||
| 140 | } else if ((addr & (1UL << index)) == 0) | ||
| 141 | disc = index; | ||
| 142 | nic_write_bit(idd, (addr>>index)&1); | ||
| 143 | continue; | ||
| 144 | } else { | ||
| 145 | if (a) | ||
| 146 | addr |= 1UL << index; | ||
| 147 | else | ||
| 148 | addr &= ~(1UL << index); | ||
| 149 | nic_write_bit(idd, a); | ||
| 150 | continue; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | *last = disc; | ||
| 154 | return addr; | ||
| 155 | } | ||
| 156 | |||
| 157 | static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr) | ||
| 158 | { | ||
| 159 | int index; | ||
| 160 | |||
| 161 | nic_reset(idd); | ||
| 162 | nic_write_byte(idd, 0xF0); | ||
| 163 | for (index = 0; index < 64; index++) { | ||
| 164 | nic_read_bit(idd); | ||
| 165 | nic_read_bit(idd); | ||
| 166 | nic_write_bit(idd, (addr>>index)&1); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | static void crc16_byte(unsigned int *crc, unsigned char db) | ||
| 171 | { | ||
| 172 | int i; | ||
| 173 | |||
| 174 | for(i=0;i<8;i++) { | ||
| 175 | *crc <<= 1; | ||
| 176 | if((db^(*crc>>16)) & 1) | ||
| 177 | *crc ^= 0x8005; | ||
| 178 | db >>= 1; | ||
| 179 | } | ||
| 180 | *crc &= 0xFFFF; | ||
| 181 | } | ||
| 182 | |||
| 183 | static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc) | ||
| 184 | { | ||
| 185 | while(size--) | ||
| 186 | crc16_byte(&crc, *(dbs++)); | ||
| 187 | return crc; | ||
| 188 | } | ||
| 189 | |||
| 190 | static void crc8_byte(unsigned int *crc, unsigned char db) | ||
| 191 | { | ||
| 192 | int i,f; | ||
| 193 | |||
| 194 | for(i=0;i<8;i++) { | ||
| 195 | f = (*crc ^ db) & 1; | ||
| 196 | *crc >>= 1; | ||
| 197 | db >>= 1; | ||
| 198 | if(f) | ||
| 199 | *crc ^= 0x8c; | ||
| 200 | } | ||
| 201 | *crc &= 0xff; | ||
| 202 | } | ||
| 203 | |||
| 204 | static unsigned int crc8_addr(unsigned long addr) | ||
| 205 | { | ||
| 206 | int i; | ||
| 207 | unsigned int crc = 0x00; | ||
| 208 | |||
| 209 | for(i=0;i<8;i++) | ||
| 210 | crc8_byte(&crc, addr>>(i<<3)); | ||
| 211 | return crc; | ||
| 212 | } | ||
| 213 | |||
| 214 | static void | ||
| 215 | read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page, | ||
| 216 | unsigned char *redir, unsigned char *data) | ||
| 217 | { | ||
| 218 | int loops = 16, i; | ||
| 219 | |||
| 220 | while(redir[page] != 0xFF) { | ||
| 221 | page = redir[page]^0xFF; | ||
| 222 | loops--; | ||
| 223 | if(loops<0) { | ||
| 224 | printk(KERN_ERR "IOC3: NIC circular redirection\n"); | ||
| 225 | return; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | loops = 3; | ||
| 229 | while(loops>0) { | ||
| 230 | nic_addr(idd, addr); | ||
| 231 | nic_write_byte(idd, 0xF0); | ||
| 232 | nic_write_byte(idd, (page << 5) & 0xE0); | ||
| 233 | nic_write_byte(idd, (page >> 3) & 0x1F); | ||
| 234 | for(i=0;i<0x20;i++) | ||
| 235 | data[i] = nic_read_byte(idd); | ||
| 236 | if(crc16_area(data, 0x20, 0x0000) == 0x800d) | ||
| 237 | return; | ||
| 238 | loops--; | ||
| 239 | } | ||
| 240 | printk(KERN_ERR "IOC3: CRC error in data page\n"); | ||
| 241 | for(i=0;i<0x20;i++) | ||
| 242 | data[i] = 0x00; | ||
| 243 | } | ||
| 244 | |||
| 245 | static void | ||
| 246 | read_redir_map(struct ioc3_driver_data *idd, unsigned long addr, | ||
| 247 | unsigned char *redir) | ||
| 248 | { | ||
| 249 | int i,j,loops = 3,crc_ok; | ||
| 250 | unsigned int crc; | ||
| 251 | |||
| 252 | while(loops>0) { | ||
| 253 | crc_ok = 1; | ||
| 254 | nic_addr(idd, addr); | ||
| 255 | nic_write_byte(idd, 0xAA); | ||
| 256 | nic_write_byte(idd, 0x00); | ||
| 257 | nic_write_byte(idd, 0x01); | ||
| 258 | for(i=0;i<64;i+=8) { | ||
| 259 | for(j=0;j<8;j++) | ||
| 260 | redir[i+j] = nic_read_byte(idd); | ||
| 261 | crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000); | ||
| 262 | crc16_byte(&crc, nic_read_byte(idd)); | ||
| 263 | crc16_byte(&crc, nic_read_byte(idd)); | ||
| 264 | if(crc != 0x800d) | ||
| 265 | crc_ok = 0; | ||
| 266 | } | ||
| 267 | if(crc_ok) | ||
| 268 | return; | ||
| 269 | loops--; | ||
| 270 | } | ||
| 271 | printk(KERN_ERR "IOC3: CRC error in redirection page\n"); | ||
| 272 | for(i=0;i<64;i++) | ||
| 273 | redir[i] = 0xFF; | ||
| 274 | } | ||
| 275 | |||
| 276 | static void read_nic(struct ioc3_driver_data *idd, unsigned long addr) | ||
| 277 | { | ||
| 278 | unsigned char redir[64]; | ||
| 279 | unsigned char data[64],part[32]; | ||
| 280 | int i,j; | ||
| 281 | |||
| 282 | /* read redirections */ | ||
| 283 | read_redir_map(idd, addr, redir); | ||
| 284 | /* read data pages */ | ||
| 285 | read_redir_page(idd, addr, 0, redir, data); | ||
| 286 | read_redir_page(idd, addr, 1, redir, data+32); | ||
| 287 | /* assemble the part # */ | ||
| 288 | j=0; | ||
| 289 | for(i=0;i<19;i++) | ||
| 290 | if(data[i+11] != ' ') | ||
| 291 | part[j++] = data[i+11]; | ||
| 292 | for(i=0;i<6;i++) | ||
| 293 | if(data[i+32] != ' ') | ||
| 294 | part[j++] = data[i+32]; | ||
| 295 | part[j] = 0; | ||
| 296 | /* skip Octane power supplies */ | ||
| 297 | if(!strncmp(part, "060-0035-", 9)) | ||
| 298 | return; | ||
| 299 | if(!strncmp(part, "060-0038-", 9)) | ||
| 300 | return; | ||
| 301 | strcpy(idd->nic_part, part); | ||
| 302 | /* assemble the serial # */ | ||
| 303 | j=0; | ||
| 304 | for(i=0;i<10;i++) | ||
| 305 | if(data[i+1] != ' ') | ||
| 306 | idd->nic_serial[j++] = data[i+1]; | ||
| 307 | idd->nic_serial[j] = 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | static void read_mac(struct ioc3_driver_data *idd, unsigned long addr) | ||
| 311 | { | ||
| 312 | int i, loops = 3; | ||
| 313 | unsigned char data[13]; | ||
| 314 | |||
| 315 | while(loops>0) { | ||
| 316 | nic_addr(idd, addr); | ||
| 317 | nic_write_byte(idd, 0xF0); | ||
| 318 | nic_write_byte(idd, 0x00); | ||
| 319 | nic_write_byte(idd, 0x00); | ||
| 320 | nic_read_byte(idd); | ||
| 321 | for(i=0;i<13;i++) | ||
| 322 | data[i] = nic_read_byte(idd); | ||
| 323 | if(crc16_area(data, 13, 0x0000) == 0x800d) { | ||
| 324 | for(i=10;i>4;i--) | ||
| 325 | idd->nic_mac[10-i] = data[i]; | ||
| 326 | return; | ||
| 327 | } | ||
| 328 | loops--; | ||
| 329 | } | ||
| 330 | printk(KERN_ERR "IOC3: CRC error in MAC address\n"); | ||
| 331 | for(i=0;i<6;i++) | ||
| 332 | idd->nic_mac[i] = 0x00; | ||
| 333 | } | ||
| 334 | |||
| 335 | static void probe_nic(struct ioc3_driver_data *idd) | ||
| 336 | { | ||
| 337 | int save = 0, loops = 3; | ||
| 338 | unsigned long first, addr; | ||
| 339 | |||
| 340 | idd->vma->gpcr_s = GPCR_MLAN_EN; | ||
| 341 | |||
| 342 | while(loops>0) { | ||
| 343 | idd->nic_part[0] = 0; | ||
| 344 | idd->nic_serial[0] = 0; | ||
| 345 | addr = first = nic_find(idd, &save, 0); | ||
| 346 | if(!first) | ||
| 347 | return; | ||
| 348 | while(1) { | ||
| 349 | if(crc8_addr(addr)) | ||
| 350 | break; | ||
| 351 | else { | ||
| 352 | switch(addr & 0xFF) { | ||
| 353 | case 0x0B: | ||
| 354 | read_nic(idd, addr); | ||
| 355 | break; | ||
| 356 | case 0x09: | ||
| 357 | case 0x89: | ||
| 358 | case 0x91: | ||
| 359 | read_mac(idd, addr); | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | addr = nic_find(idd, &save, addr); | ||
| 364 | if(addr == first) | ||
| 365 | return; | ||
| 366 | } | ||
| 367 | loops--; | ||
| 368 | } | ||
| 369 | printk(KERN_ERR "IOC3: CRC error in NIC address\n"); | ||
| 370 | } | ||
| 371 | |||
| 372 | /* Interrupts */ | ||
| 373 | |||
| 374 | static inline void | ||
| 375 | write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which) | ||
| 376 | { | ||
| 377 | unsigned long flags; | ||
| 378 | |||
| 379 | spin_lock_irqsave(&idd->ir_lock, flags); | ||
| 380 | switch (which) { | ||
| 381 | case IOC3_W_IES: | ||
| 382 | writel(val, &idd->vma->sio_ies); | ||
| 383 | break; | ||
| 384 | case IOC3_W_IEC: | ||
| 385 | writel(val, &idd->vma->sio_iec); | ||
| 386 | break; | ||
| 387 | } | ||
| 388 | spin_unlock_irqrestore(&idd->ir_lock, flags); | ||
| 389 | } | ||
| 390 | static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd) | ||
| 391 | { | ||
| 392 | unsigned long flag; | ||
| 393 | uint32_t intrs = 0; | ||
| 394 | |||
| 395 | spin_lock_irqsave(&idd->ir_lock, flag); | ||
| 396 | intrs = readl(&idd->vma->sio_ir); | ||
| 397 | intrs &= readl(&idd->vma->sio_ies); | ||
| 398 | spin_unlock_irqrestore(&idd->ir_lock, flag); | ||
| 399 | return intrs; | ||
| 400 | } | ||
| 401 | |||
| 402 | static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs) | ||
| 403 | { | ||
| 404 | unsigned long flags; | ||
| 405 | struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg; | ||
| 406 | int handled = 1, id; | ||
| 407 | unsigned int pending; | ||
| 408 | |||
| 409 | read_lock_irqsave(&ioc3_submodules_lock, flags); | ||
| 410 | |||
| 411 | if(idd->dual_irq && idd->vma->eisr) { | ||
| 412 | /* send Ethernet IRQ to the driver */ | ||
| 413 | if(ioc3_ethernet && idd->active[ioc3_ethernet->id] && | ||
| 414 | ioc3_ethernet->intr) { | ||
| 415 | handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, | ||
| 416 | idd, 0, regs); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | pending = get_pending_intrs(idd); /* look at the IO IRQs */ | ||
| 420 | |||
| 421 | for(id=0;id<IOC3_MAX_SUBMODULES;id++) { | ||
| 422 | if(idd->active[id] && ioc3_submodules[id] | ||
| 423 | && (pending & ioc3_submodules[id]->irq_mask) | ||
| 424 | && ioc3_submodules[id]->intr) { | ||
| 425 | write_ireg(idd, ioc3_submodules[id]->irq_mask, | ||
| 426 | IOC3_W_IEC); | ||
| 427 | if(!ioc3_submodules[id]->intr(ioc3_submodules[id], | ||
| 428 | idd, pending & ioc3_submodules[id]->irq_mask, | ||
| 429 | regs)) | ||
| 430 | pending &= ~ioc3_submodules[id]->irq_mask; | ||
| 431 | if (ioc3_submodules[id]->reset_mask) | ||
| 432 | write_ireg(idd, ioc3_submodules[id]->irq_mask, | ||
| 433 | IOC3_W_IES); | ||
| 434 | } | ||
| 435 | } | ||
| 436 | read_unlock_irqrestore(&ioc3_submodules_lock, flags); | ||
| 437 | if(pending) { | ||
| 438 | printk(KERN_WARNING | ||
| 439 | "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending); | ||
| 440 | write_ireg(idd, pending, IOC3_W_IEC); | ||
| 441 | handled = 1; | ||
| 442 | } | ||
| 443 | return handled?IRQ_HANDLED:IRQ_NONE; | ||
| 444 | } | ||
| 445 | |||
| 446 | static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs) | ||
| 447 | { | ||
| 448 | unsigned long flags; | ||
| 449 | struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg; | ||
| 450 | int handled = 1; | ||
| 451 | |||
| 452 | if(!idd->dual_irq) | ||
| 453 | return IRQ_NONE; | ||
| 454 | read_lock_irqsave(&ioc3_submodules_lock, flags); | ||
| 455 | if(ioc3_ethernet && idd->active[ioc3_ethernet->id] | ||
| 456 | && ioc3_ethernet->intr) | ||
| 457 | handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0, | ||
| 458 | regs); | ||
| 459 | read_unlock_irqrestore(&ioc3_submodules_lock, flags); | ||
| 460 | return handled?IRQ_HANDLED:IRQ_NONE; | ||
| 461 | } | ||
| 462 | |||
| 463 | void ioc3_enable(struct ioc3_submodule *is, | ||
| 464 | struct ioc3_driver_data *idd, unsigned int irqs) | ||
| 465 | { | ||
| 466 | write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES); | ||
| 467 | } | ||
| 468 | |||
| 469 | void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd, | ||
| 470 | unsigned int irqs) | ||
| 471 | { | ||
| 472 | writel(irqs & is->irq_mask, &idd->vma->sio_ir); | ||
| 473 | } | ||
| 474 | |||
| 475 | void ioc3_disable(struct ioc3_submodule *is, | ||
| 476 | struct ioc3_driver_data *idd, unsigned int irqs) | ||
| 477 | { | ||
| 478 | write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC); | ||
| 479 | } | ||
| 480 | |||
| 481 | void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val) | ||
| 482 | { | ||
| 483 | unsigned long flags; | ||
| 484 | spin_lock_irqsave(&idd->gpio_lock, flags); | ||
| 485 | writel(val, &idd->vma->gpcr_s); | ||
| 486 | spin_unlock_irqrestore(&idd->gpio_lock, flags); | ||
| 487 | } | ||
| 488 | |||
| 489 | /* Keep it simple, stupid! */ | ||
| 490 | static int find_slot(void **tab, int max) | ||
| 491 | { | ||
| 492 | int i; | ||
| 493 | for(i=0;i<max;i++) | ||
| 494 | if(!(tab[i])) | ||
| 495 | return i; | ||
| 496 | return -1; | ||
| 497 | } | ||
| 498 | |||
| 499 | /* Register an IOC3 submodule */ | ||
| 500 | int ioc3_register_submodule(struct ioc3_submodule *is) | ||
| 501 | { | ||
| 502 | struct ioc3_driver_data *idd; | ||
| 503 | int alloc_id; | ||
| 504 | unsigned long flags; | ||
| 505 | |||
| 506 | write_lock_irqsave(&ioc3_submodules_lock, flags); | ||
| 507 | alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES); | ||
| 508 | if(alloc_id != -1) { | ||
| 509 | ioc3_submodules[alloc_id] = is; | ||
| 510 | if(is->ethernet) { | ||
| 511 | if(ioc3_ethernet==NULL) | ||
| 512 | ioc3_ethernet=is; | ||
| 513 | else | ||
| 514 | printk(KERN_WARNING | ||
| 515 | "IOC3 Ethernet module already registered!\n"); | ||
| 516 | } | ||
| 517 | } | ||
| 518 | write_unlock_irqrestore(&ioc3_submodules_lock, flags); | ||
| 519 | |||
| 520 | if(alloc_id == -1) { | ||
| 521 | printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n"); | ||
| 522 | return -ENOMEM; | ||
| 523 | } | ||
| 524 | |||
| 525 | is->id=alloc_id; | ||
| 526 | |||
| 527 | /* Initialize submodule for each IOC3 */ | ||
| 528 | if (!is->probe) | ||
| 529 | return 0; | ||
| 530 | |||
| 531 | down_read(&ioc3_devices_rwsem); | ||
| 532 | list_for_each_entry(idd, &ioc3_devices, list) { | ||
| 533 | /* set to 1 for IRQs in probe */ | ||
| 534 | idd->active[alloc_id] = 1; | ||
| 535 | idd->active[alloc_id] = !is->probe(is, idd); | ||
| 536 | } | ||
| 537 | up_read(&ioc3_devices_rwsem); | ||
| 538 | |||
| 539 | return 0; | ||
| 540 | } | ||
| 541 | |||
| 542 | /* Unregister an IOC3 submodule */ | ||
| 543 | void ioc3_unregister_submodule(struct ioc3_submodule *is) | ||
| 544 | { | ||
| 545 | struct ioc3_driver_data *idd; | ||
| 546 | unsigned long flags; | ||
| 547 | |||
| 548 | write_lock_irqsave(&ioc3_submodules_lock, flags); | ||
| 549 | if(ioc3_submodules[is->id]==is) | ||
| 550 | ioc3_submodules[is->id]=NULL; | ||
| 551 | else | ||
| 552 | printk(KERN_WARNING | ||
| 553 | "IOC3 submodule %s has wrong ID.\n",is->name); | ||
| 554 | if(ioc3_ethernet==is) | ||
| 555 | ioc3_ethernet = NULL; | ||
| 556 | write_unlock_irqrestore(&ioc3_submodules_lock, flags); | ||
| 557 | |||
| 558 | /* Remove submodule for each IOC3 */ | ||
| 559 | down_read(&ioc3_devices_rwsem); | ||
| 560 | list_for_each_entry(idd, &ioc3_devices, list) | ||
| 561 | if(idd->active[is->id]) { | ||
| 562 | if(is->remove) | ||
| 563 | if(is->remove(is, idd)) | ||
| 564 | printk(KERN_WARNING | ||
| 565 | "%s: IOC3 submodule %s remove failed " | ||
| 566 | "for pci_dev %s.\n", | ||
| 567 | __FUNCTION__, module_name(is->owner), | ||
| 568 | pci_name(idd->pdev)); | ||
| 569 | idd->active[is->id] = 0; | ||
| 570 | if(is->irq_mask) | ||
| 571 | write_ireg(idd, is->irq_mask, IOC3_W_IEC); | ||
| 572 | } | ||
| 573 | up_read(&ioc3_devices_rwsem); | ||
| 574 | } | ||
| 575 | |||
| 576 | /********************* | ||
| 577 | * Device management * | ||
| 578 | *********************/ | ||
| 579 | |||
| 580 | static char * | ||
| 581 | ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3", | ||
| 582 | "MENET 4", "CADduo", "Altix Serial"}; | ||
| 583 | |||
| 584 | static int ioc3_class(struct ioc3_driver_data *idd) | ||
| 585 | { | ||
| 586 | int res = IOC3_CLASS_NONE; | ||
| 587 | /* NIC-based logic */ | ||
| 588 | if(!strncmp(idd->nic_part, "030-0891-", 9)) | ||
| 589 | res = IOC3_CLASS_BASE_IP30; | ||
| 590 | if(!strncmp(idd->nic_part, "030-1155-", 9)) | ||
| 591 | res = IOC3_CLASS_CADDUO; | ||
| 592 | if(!strncmp(idd->nic_part, "030-1657-", 9)) | ||
| 593 | res = IOC3_CLASS_SERIAL; | ||
| 594 | if(!strncmp(idd->nic_part, "030-1664-", 9)) | ||
| 595 | res = IOC3_CLASS_SERIAL; | ||
| 596 | /* total random heuristics */ | ||
| 597 | #ifdef CONFIG_SGI_IP27 | ||
| 598 | if(!idd->nic_part[0]) | ||
| 599 | res = IOC3_CLASS_BASE_IP27; | ||
| 600 | #endif | ||
| 601 | /* print educational message */ | ||
| 602 | printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n", | ||
| 603 | idd->nic_part, idd->nic_serial, ioc3_class_names[res]); | ||
| 604 | return res; | ||
| 605 | } | ||
| 606 | /* Adds a new instance of an IOC3 card */ | ||
| 607 | static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | ||
| 608 | { | ||
| 609 | struct ioc3_driver_data *idd; | ||
| 610 | uint32_t pcmd; | ||
| 611 | int ret, id; | ||
| 612 | |||
| 613 | /* Enable IOC3 and take ownership of it */ | ||
| 614 | if ((ret = pci_enable_device(pdev))) { | ||
| 615 | printk(KERN_WARNING | ||
| 616 | "%s: Failed to enable IOC3 device for pci_dev %s.\n", | ||
| 617 | __FUNCTION__, pci_name(pdev)); | ||
| 618 | goto out; | ||
| 619 | } | ||
| 620 | pci_set_master(pdev); | ||
| 621 | |||
| 622 | #ifdef USE_64BIT_DMA | ||
| 623 | ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); | ||
| 624 | if (!ret) { | ||
| 625 | ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); | ||
| 626 | if (ret < 0) { | ||
| 627 | printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA " | ||
| 628 | "for consistent allocations\n", | ||
| 629 | __FUNCTION__); | ||
| 630 | } | ||
| 631 | } | ||
| 632 | #endif | ||
| 633 | |||
| 634 | /* Set up per-IOC3 data */ | ||
| 635 | idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL); | ||
| 636 | if (!idd) { | ||
| 637 | printk(KERN_WARNING | ||
| 638 | "%s: Failed to allocate IOC3 data for pci_dev %s.\n", | ||
| 639 | __FUNCTION__, pci_name(pdev)); | ||
| 640 | ret = -ENODEV; | ||
| 641 | goto out_idd; | ||
| 642 | } | ||
| 643 | memset(idd, 0, sizeof(struct ioc3_driver_data)); | ||
| 644 | spin_lock_init(&idd->ir_lock); | ||
| 645 | spin_lock_init(&idd->gpio_lock); | ||
| 646 | idd->pdev = pdev; | ||
| 647 | |||
| 648 | /* Map all IOC3 registers. These are shared between subdevices | ||
| 649 | * so the main IOC3 module manages them. | ||
| 650 | */ | ||
| 651 | idd->pma = pci_resource_start(pdev, 0); | ||
| 652 | if (!idd->pma) { | ||
| 653 | printk(KERN_WARNING | ||
| 654 | "%s: Unable to find IOC3 resource " | ||
| 655 | "for pci_dev %s.\n", | ||
| 656 | __FUNCTION__, pci_name(pdev)); | ||
| 657 | ret = -ENODEV; | ||
| 658 | goto out_pci; | ||
| 659 | } | ||
| 660 | if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) { | ||
| 661 | printk(KERN_WARNING | ||
| 662 | "%s: Unable to request IOC3 region " | ||
| 663 | "for pci_dev %s.\n", | ||
| 664 | __FUNCTION__, pci_name(pdev)); | ||
| 665 | ret = -ENODEV; | ||
| 666 | goto out_pci; | ||
| 667 | } | ||
| 668 | idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE); | ||
| 669 | if (!idd->vma) { | ||
| 670 | printk(KERN_WARNING | ||
| 671 | "%s: Unable to remap IOC3 region " | ||
| 672 | "for pci_dev %s.\n", | ||
| 673 | __FUNCTION__, pci_name(pdev)); | ||
| 674 | ret = -ENODEV; | ||
| 675 | goto out_misc_region; | ||
| 676 | } | ||
| 677 | |||
| 678 | /* Track PCI-device specific data */ | ||
| 679 | pci_set_drvdata(pdev, idd); | ||
| 680 | down_write(&ioc3_devices_rwsem); | ||
| 681 | list_add(&idd->list, &ioc3_devices); | ||
| 682 | idd->id = ioc3_counter++; | ||
| 683 | up_write(&ioc3_devices_rwsem); | ||
| 684 | |||
| 685 | idd->gpdr_shadow = idd->vma->gpdr; | ||
| 686 | |||
| 687 | /* Read IOC3 NIC contents */ | ||
| 688 | probe_nic(idd); | ||
| 689 | |||
| 690 | /* Detect IOC3 class */ | ||
| 691 | idd->class = ioc3_class(idd); | ||
| 692 | |||
| 693 | /* Initialize IOC3 */ | ||
| 694 | pci_read_config_dword(pdev, PCI_COMMAND, &pcmd); | ||
| 695 | pci_write_config_dword(pdev, PCI_COMMAND, | ||
| 696 | pcmd | PCI_COMMAND_MEMORY | | ||
| 697 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | | ||
| 698 | PCI_SCR_DROP_MODE_EN); | ||
| 699 | |||
| 700 | write_ireg(idd, ~0, IOC3_W_IEC); | ||
| 701 | writel(~0, &idd->vma->sio_ir); | ||
| 702 | |||
| 703 | /* Set up IRQs */ | ||
| 704 | if(idd->class == IOC3_CLASS_BASE_IP30 | ||
| 705 | || idd->class == IOC3_CLASS_BASE_IP27) { | ||
| 706 | writel(0, &idd->vma->eier); | ||
| 707 | writel(~0, &idd->vma->eisr); | ||
| 708 | |||
| 709 | idd->dual_irq = 1; | ||
| 710 | if (!request_irq(pdev->irq, ioc3_intr_eth, SA_SHIRQ, | ||
| 711 | "ioc3-eth", (void *)idd)) { | ||
| 712 | idd->irq_eth = pdev->irq; | ||
| 713 | } else { | ||
| 714 | printk(KERN_WARNING | ||
| 715 | "%s : request_irq fails for IRQ 0x%x\n ", | ||
| 716 | __FUNCTION__, pdev->irq); | ||
| 717 | } | ||
| 718 | if (!request_irq(pdev->irq+2, ioc3_intr_io, SA_SHIRQ, | ||
| 719 | "ioc3-io", (void *)idd)) { | ||
| 720 | idd->irq_io = pdev->irq+2; | ||
| 721 | } else { | ||
| 722 | printk(KERN_WARNING | ||
| 723 | "%s : request_irq fails for IRQ 0x%x\n ", | ||
| 724 | __FUNCTION__, pdev->irq+2); | ||
| 725 | } | ||
| 726 | } else { | ||
| 727 | if (!request_irq(pdev->irq, ioc3_intr_io, SA_SHIRQ, | ||
| 728 | "ioc3", (void *)idd)) { | ||
| 729 | idd->irq_io = pdev->irq; | ||
| 730 | } else { | ||
| 731 | printk(KERN_WARNING | ||
| 732 | "%s : request_irq fails for IRQ 0x%x\n ", | ||
| 733 | __FUNCTION__, pdev->irq); | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | /* Add this IOC3 to all submodules */ | ||
| 738 | read_lock(&ioc3_submodules_lock); | ||
| 739 | for(id=0;id<IOC3_MAX_SUBMODULES;id++) | ||
| 740 | if(ioc3_submodules[id] && ioc3_submodules[id]->probe) { | ||
| 741 | idd->active[id] = 1; | ||
| 742 | idd->active[id] = !ioc3_submodules[id]->probe | ||
| 743 | (ioc3_submodules[id], idd); | ||
| 744 | } | ||
| 745 | read_unlock(&ioc3_submodules_lock); | ||
| 746 | |||
| 747 | printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev)); | ||
| 748 | |||
| 749 | return 0; | ||
| 750 | |||
| 751 | out_misc_region: | ||
| 752 | release_region(idd->pma, IOC3_PCI_SIZE); | ||
| 753 | out_pci: | ||
| 754 | kfree(idd); | ||
| 755 | out_idd: | ||
| 756 | pci_disable_device(pdev); | ||
| 757 | out: | ||
| 758 | return ret; | ||
| 759 | } | ||
| 760 | |||
| 761 | /* Removes a particular instance of an IOC3 card. */ | ||
| 762 | static void ioc3_remove(struct pci_dev *pdev) | ||
| 763 | { | ||
| 764 | int id; | ||
| 765 | struct ioc3_driver_data *idd; | ||
| 766 | |||
| 767 | idd = pci_get_drvdata(pdev); | ||
| 768 | |||
| 769 | /* Remove this IOC3 from all submodules */ | ||
| 770 | read_lock(&ioc3_submodules_lock); | ||
| 771 | for(id=0;id<IOC3_MAX_SUBMODULES;id++) | ||
| 772 | if(idd->active[id]) { | ||
| 773 | if(ioc3_submodules[id] && ioc3_submodules[id]->remove) | ||
| 774 | if(ioc3_submodules[id]->remove(ioc3_submodules[id], | ||
| 775 | idd)) | ||
| 776 | printk(KERN_WARNING | ||
| 777 | "%s: IOC3 submodule 0x%s remove failed " | ||
| 778 | "for pci_dev %s.\n", | ||
| 779 | __FUNCTION__, | ||
| 780 | module_name(ioc3_submodules[id]->owner), | ||
| 781 | pci_name(pdev)); | ||
| 782 | idd->active[id] = 0; | ||
| 783 | } | ||
| 784 | read_unlock(&ioc3_submodules_lock); | ||
| 785 | |||
| 786 | /* Clear and disable all IRQs */ | ||
| 787 | write_ireg(idd, ~0, IOC3_W_IEC); | ||
| 788 | writel(~0, &idd->vma->sio_ir); | ||
| 789 | |||
| 790 | /* Release resources */ | ||
| 791 | free_irq(idd->irq_io, (void *)idd); | ||
| 792 | if(idd->dual_irq) | ||
| 793 | free_irq(idd->irq_eth, (void *)idd); | ||
| 794 | iounmap(idd->vma); | ||
| 795 | release_region(idd->pma, IOC3_PCI_SIZE); | ||
| 796 | |||
| 797 | /* Disable IOC3 and relinquish */ | ||
| 798 | pci_disable_device(pdev); | ||
| 799 | |||
| 800 | /* Remove and free driver data */ | ||
| 801 | down_write(&ioc3_devices_rwsem); | ||
| 802 | list_del(&idd->list); | ||
| 803 | up_write(&ioc3_devices_rwsem); | ||
| 804 | kfree(idd); | ||
| 805 | } | ||
| 806 | |||
| 807 | static struct pci_device_id ioc3_id_table[] = { | ||
| 808 | {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID}, | ||
| 809 | {0} | ||
| 810 | }; | ||
| 811 | |||
| 812 | static struct pci_driver ioc3_driver = { | ||
| 813 | .name = "IOC3", | ||
| 814 | .id_table = ioc3_id_table, | ||
| 815 | .probe = ioc3_probe, | ||
| 816 | .remove = ioc3_remove, | ||
| 817 | }; | ||
| 818 | |||
| 819 | MODULE_DEVICE_TABLE(pci, ioc3_id_table); | ||
| 820 | |||
| 821 | /********************* | ||
| 822 | * Module management * | ||
| 823 | *********************/ | ||
| 824 | |||
| 825 | /* Module load */ | ||
| 826 | static int __devinit ioc3_init(void) | ||
| 827 | { | ||
| 828 | if (ia64_platform_is("sn2")) | ||
| 829 | return pci_register_driver(&ioc3_driver); | ||
| 830 | return 0; | ||
| 831 | } | ||
| 832 | |||
| 833 | /* Module unload */ | ||
| 834 | static void __devexit ioc3_exit(void) | ||
| 835 | { | ||
| 836 | pci_unregister_driver(&ioc3_driver); | ||
| 837 | } | ||
| 838 | |||
| 839 | module_init(ioc3_init); | ||
| 840 | module_exit(ioc3_exit); | ||
| 841 | |||
| 842 | MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>"); | ||
| 843 | MODULE_DESCRIPTION("PCI driver for SGI IOC3"); | ||
| 844 | MODULE_LICENSE("GPL"); | ||
| 845 | |||
| 846 | EXPORT_SYMBOL(ioc3_register_submodule); | ||
| 847 | EXPORT_SYMBOL(ioc3_unregister_submodule); | ||
| 848 | EXPORT_SYMBOL(ioc3_ack); | ||
| 849 | EXPORT_SYMBOL(ioc3_gpcr_set); | ||
| 850 | EXPORT_SYMBOL(ioc3_disable); | ||
| 851 | EXPORT_SYMBOL(ioc3_enable); | ||
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig new file mode 100644 index 000000000000..b77dbd63e596 --- /dev/null +++ b/drivers/spi/Kconfig | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | # | ||
| 2 | # SPI driver configuration | ||
| 3 | # | ||
| 4 | # NOTE: the reason this doesn't show SPI slave support is mostly that | ||
| 5 | # nobody's needed a slave side API yet. The master-role API is not | ||
| 6 | # fully appropriate there, so it'd need some thought to do well. | ||
| 7 | # | ||
| 8 | menu "SPI support" | ||
| 9 | |||
| 10 | config SPI | ||
| 11 | bool "SPI support" | ||
| 12 | help | ||
| 13 | The "Serial Peripheral Interface" is a low level synchronous | ||
| 14 | protocol. Chips that support SPI can have data transfer rates | ||
| 15 | up to several tens of Mbit/sec. Chips are addressed with a | ||
| 16 | controller and a chipselect. Most SPI slaves don't support | ||
| 17 | dynamic device discovery; some are even write-only or read-only. | ||
| 18 | |||
| 19 | SPI is widely used by microcontollers to talk with sensors, | ||
| 20 | eeprom and flash memory, codecs and various other controller | ||
| 21 | chips, analog to digital (and d-to-a) converters, and more. | ||
| 22 | MMC and SD cards can be accessed using SPI protocol; and for | ||
| 23 | DataFlash cards used in MMC sockets, SPI must always be used. | ||
| 24 | |||
| 25 | SPI is one of a family of similar protocols using a four wire | ||
| 26 | interface (select, clock, data in, data out) including Microwire | ||
| 27 | (half duplex), SSP, SSI, and PSP. This driver framework should | ||
| 28 | work with most such devices and controllers. | ||
| 29 | |||
| 30 | config SPI_DEBUG | ||
| 31 | boolean "Debug support for SPI drivers" | ||
| 32 | depends on SPI && DEBUG_KERNEL | ||
| 33 | help | ||
| 34 | Say "yes" to enable debug messaging (like dev_dbg and pr_debug), | ||
| 35 | sysfs, and debugfs support in SPI controller and protocol drivers. | ||
| 36 | |||
| 37 | # | ||
| 38 | # MASTER side ... talking to discrete SPI slave chips including microcontrollers | ||
| 39 | # | ||
| 40 | |||
| 41 | config SPI_MASTER | ||
| 42 | # boolean "SPI Master Support" | ||
| 43 | boolean | ||
| 44 | default SPI | ||
| 45 | help | ||
| 46 | If your system has an master-capable SPI controller (which | ||
| 47 | provides the clock and chipselect), you can enable that | ||
| 48 | controller and the protocol drivers for the SPI slave chips | ||
| 49 | that are connected. | ||
| 50 | |||
| 51 | comment "SPI Master Controller Drivers" | ||
| 52 | depends on SPI_MASTER | ||
| 53 | |||
| 54 | config SPI_BITBANG | ||
| 55 | tristate "Bitbanging SPI master" | ||
| 56 | depends on SPI_MASTER && EXPERIMENTAL | ||
| 57 | help | ||
| 58 | With a few GPIO pins, your system can bitbang the SPI protocol. | ||
| 59 | Select this to get SPI support through I/O pins (GPIO, parallel | ||
| 60 | port, etc). Or, some systems' SPI master controller drivers use | ||
| 61 | this code to manage the per-word or per-transfer accesses to the | ||
| 62 | hardware shift registers. | ||
| 63 | |||
| 64 | This is library code, and is automatically selected by drivers that | ||
| 65 | need it. You only need to select this explicitly to support driver | ||
| 66 | modules that aren't part of this kernel tree. | ||
| 67 | |||
| 68 | config SPI_BUTTERFLY | ||
| 69 | tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" | ||
| 70 | depends on SPI_MASTER && PARPORT && EXPERIMENTAL | ||
| 71 | select SPI_BITBANG | ||
| 72 | help | ||
| 73 | This uses a custom parallel port cable to connect to an AVR | ||
| 74 | Butterfly <http://www.atmel.com/products/avr/butterfly>, an | ||
| 75 | inexpensive battery powered microcontroller evaluation board. | ||
| 76 | This same cable can be used to flash new firmware. | ||
| 77 | |||
| 78 | config SPI_BUTTERFLY | ||
| 79 | tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" | ||
| 80 | depends on SPI_MASTER && PARPORT && EXPERIMENTAL | ||
| 81 | select SPI_BITBANG | ||
| 82 | help | ||
| 83 | This uses a custom parallel port cable to connect to an AVR | ||
| 84 | Butterfly <http://www.atmel.com/products/avr/butterfly>, an | ||
| 85 | inexpensive battery powered microcontroller evaluation board. | ||
| 86 | This same cable can be used to flash new firmware. | ||
| 87 | |||
| 88 | # | ||
| 89 | # Add new SPI master controllers in alphabetical order above this line | ||
| 90 | # | ||
| 91 | |||
| 92 | |||
| 93 | # | ||
| 94 | # There are lots of SPI device types, with sensors and memory | ||
| 95 | # being probably the most widely used ones. | ||
| 96 | # | ||
| 97 | comment "SPI Protocol Masters" | ||
| 98 | depends on SPI_MASTER | ||
| 99 | |||
| 100 | |||
| 101 | # | ||
| 102 | # Add new SPI protocol masters in alphabetical order above this line | ||
| 103 | # | ||
| 104 | |||
| 105 | |||
| 106 | # (slave support would go here) | ||
| 107 | |||
| 108 | endmenu # "SPI support" | ||
| 109 | |||
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile new file mode 100644 index 000000000000..c2c87e845abf --- /dev/null +++ b/drivers/spi/Makefile | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | # | ||
| 2 | # Makefile for kernel SPI drivers. | ||
| 3 | # | ||
| 4 | |||
| 5 | ifeq ($(CONFIG_SPI_DEBUG),y) | ||
| 6 | EXTRA_CFLAGS += -DDEBUG | ||
| 7 | endif | ||
| 8 | |||
| 9 | # small core, mostly translating board-specific | ||
| 10 | # config declarations into driver model code | ||
| 11 | obj-$(CONFIG_SPI_MASTER) += spi.o | ||
| 12 | |||
| 13 | # SPI master controller drivers (bus) | ||
| 14 | obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o | ||
| 15 | obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o | ||
| 16 | # ... add above this line ... | ||
| 17 | |||
| 18 | # SPI protocol drivers (device/link on bus) | ||
| 19 | # ... add above this line ... | ||
| 20 | |||
| 21 | # SPI slave controller drivers (upstream link) | ||
| 22 | # ... add above this line ... | ||
| 23 | |||
| 24 | # SPI slave drivers (protocol for that link) | ||
| 25 | # ... add above this line ... | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c new file mode 100644 index 000000000000..791c4dc550ae --- /dev/null +++ b/drivers/spi/spi.c | |||
| @@ -0,0 +1,642 @@ | |||
| 1 | /* | ||
| 2 | * spi.c - SPI init/core code | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 David Brownell | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/autoconf.h> | ||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/device.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/cache.h> | ||
| 26 | #include <linux/spi/spi.h> | ||
| 27 | |||
| 28 | |||
| 29 | /* SPI bustype and spi_master class are registered after board init code | ||
| 30 | * provides the SPI device tables, ensuring that both are present by the | ||
| 31 | * time controller driver registration causes spi_devices to "enumerate". | ||
| 32 | */ | ||
| 33 | static void spidev_release(struct device *dev) | ||
| 34 | { | ||
| 35 | const struct spi_device *spi = to_spi_device(dev); | ||
| 36 | |||
| 37 | /* spi masters may cleanup for released devices */ | ||
| 38 | if (spi->master->cleanup) | ||
| 39 | spi->master->cleanup(spi); | ||
| 40 | |||
| 41 | spi_master_put(spi->master); | ||
| 42 | kfree(dev); | ||
| 43 | } | ||
| 44 | |||
| 45 | static ssize_t | ||
| 46 | modalias_show(struct device *dev, struct device_attribute *a, char *buf) | ||
| 47 | { | ||
| 48 | const struct spi_device *spi = to_spi_device(dev); | ||
| 49 | |||
| 50 | return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias); | ||
| 51 | } | ||
| 52 | |||
| 53 | static struct device_attribute spi_dev_attrs[] = { | ||
| 54 | __ATTR_RO(modalias), | ||
| 55 | __ATTR_NULL, | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, | ||
| 59 | * and the sysfs version makes coldplug work too. | ||
| 60 | */ | ||
| 61 | |||
| 62 | static int spi_match_device(struct device *dev, struct device_driver *drv) | ||
| 63 | { | ||
| 64 | const struct spi_device *spi = to_spi_device(dev); | ||
| 65 | |||
| 66 | return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int spi_uevent(struct device *dev, char **envp, int num_envp, | ||
| 70 | char *buffer, int buffer_size) | ||
| 71 | { | ||
| 72 | const struct spi_device *spi = to_spi_device(dev); | ||
| 73 | |||
| 74 | envp[0] = buffer; | ||
| 75 | snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); | ||
| 76 | envp[1] = NULL; | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | #ifdef CONFIG_PM | ||
| 81 | |||
| 82 | /* | ||
| 83 | * NOTE: the suspend() method for an spi_master controller driver | ||
| 84 | * should verify that all its child devices are marked as suspended; | ||
| 85 | * suspend requests delivered through sysfs power/state files don't | ||
| 86 | * enforce such constraints. | ||
| 87 | */ | ||
| 88 | static int spi_suspend(struct device *dev, pm_message_t message) | ||
| 89 | { | ||
| 90 | int value; | ||
| 91 | struct spi_driver *drv = to_spi_driver(dev->driver); | ||
| 92 | |||
| 93 | if (!drv->suspend) | ||
| 94 | return 0; | ||
| 95 | |||
| 96 | /* suspend will stop irqs and dma; no more i/o */ | ||
| 97 | value = drv->suspend(to_spi_device(dev), message); | ||
| 98 | if (value == 0) | ||
| 99 | dev->power.power_state = message; | ||
| 100 | return value; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int spi_resume(struct device *dev) | ||
| 104 | { | ||
| 105 | int value; | ||
| 106 | struct spi_driver *drv = to_spi_driver(dev->driver); | ||
| 107 | |||
| 108 | if (!drv->resume) | ||
| 109 | return 0; | ||
| 110 | |||
| 111 | /* resume may restart the i/o queue */ | ||
| 112 | value = drv->resume(to_spi_device(dev)); | ||
| 113 | if (value == 0) | ||
| 114 | dev->power.power_state = PMSG_ON; | ||
| 115 | return value; | ||
| 116 | } | ||
| 117 | |||
| 118 | #else | ||
| 119 | #define spi_suspend NULL | ||
| 120 | #define spi_resume NULL | ||
| 121 | #endif | ||
| 122 | |||
| 123 | struct bus_type spi_bus_type = { | ||
| 124 | .name = "spi", | ||
| 125 | .dev_attrs = spi_dev_attrs, | ||
| 126 | .match = spi_match_device, | ||
| 127 | .uevent = spi_uevent, | ||
| 128 | .suspend = spi_suspend, | ||
| 129 | .resume = spi_resume, | ||
| 130 | }; | ||
| 131 | EXPORT_SYMBOL_GPL(spi_bus_type); | ||
| 132 | |||
| 133 | |||
| 134 | static int spi_drv_probe(struct device *dev) | ||
| 135 | { | ||
| 136 | const struct spi_driver *sdrv = to_spi_driver(dev->driver); | ||
| 137 | |||
| 138 | return sdrv->probe(to_spi_device(dev)); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int spi_drv_remove(struct device *dev) | ||
| 142 | { | ||
| 143 | const struct spi_driver *sdrv = to_spi_driver(dev->driver); | ||
| 144 | |||
| 145 | return sdrv->remove(to_spi_device(dev)); | ||
| 146 | } | ||
| 147 | |||
| 148 | static void spi_drv_shutdown(struct device *dev) | ||
| 149 | { | ||
| 150 | const struct spi_driver *sdrv = to_spi_driver(dev->driver); | ||
| 151 | |||
| 152 | sdrv->shutdown(to_spi_device(dev)); | ||
| 153 | } | ||
| 154 | |||
| 155 | int spi_register_driver(struct spi_driver *sdrv) | ||
| 156 | { | ||
| 157 | sdrv->driver.bus = &spi_bus_type; | ||
| 158 | if (sdrv->probe) | ||
| 159 | sdrv->driver.probe = spi_drv_probe; | ||
| 160 | if (sdrv->remove) | ||
| 161 | sdrv->driver.remove = spi_drv_remove; | ||
| 162 | if (sdrv->shutdown) | ||
| 163 | sdrv->driver.shutdown = spi_drv_shutdown; | ||
| 164 | return driver_register(&sdrv->driver); | ||
| 165 | } | ||
| 166 | EXPORT_SYMBOL_GPL(spi_register_driver); | ||
| 167 | |||
| 168 | /*-------------------------------------------------------------------------*/ | ||
| 169 | |||
| 170 | /* SPI devices should normally not be created by SPI device drivers; that | ||
| 171 | * would make them board-specific. Similarly with SPI master drivers. | ||
| 172 | * Device registration normally goes into like arch/.../mach.../board-YYY.c | ||
| 173 | * with other readonly (flashable) information about mainboard devices. | ||
| 174 | */ | ||
| 175 | |||
| 176 | struct boardinfo { | ||
| 177 | struct list_head list; | ||
| 178 | unsigned n_board_info; | ||
| 179 | struct spi_board_info board_info[0]; | ||
| 180 | }; | ||
| 181 | |||
| 182 | static LIST_HEAD(board_list); | ||
| 183 | static DECLARE_MUTEX(board_lock); | ||
| 184 | |||
| 185 | |||
| 186 | /* On typical mainboards, this is purely internal; and it's not needed | ||
| 187 | * after board init creates the hard-wired devices. Some development | ||
| 188 | * platforms may not be able to use spi_register_board_info though, and | ||
| 189 | * this is exported so that for example a USB or parport based adapter | ||
| 190 | * driver could add devices (which it would learn about out-of-band). | ||
| 191 | */ | ||
| 192 | struct spi_device *__init_or_module | ||
| 193 | spi_new_device(struct spi_master *master, struct spi_board_info *chip) | ||
| 194 | { | ||
| 195 | struct spi_device *proxy; | ||
| 196 | struct device *dev = master->cdev.dev; | ||
| 197 | int status; | ||
| 198 | |||
| 199 | /* NOTE: caller did any chip->bus_num checks necessary */ | ||
| 200 | |||
| 201 | if (!spi_master_get(master)) | ||
| 202 | return NULL; | ||
| 203 | |||
| 204 | proxy = kzalloc(sizeof *proxy, GFP_KERNEL); | ||
| 205 | if (!proxy) { | ||
| 206 | dev_err(dev, "can't alloc dev for cs%d\n", | ||
| 207 | chip->chip_select); | ||
| 208 | goto fail; | ||
| 209 | } | ||
| 210 | proxy->master = master; | ||
| 211 | proxy->chip_select = chip->chip_select; | ||
| 212 | proxy->max_speed_hz = chip->max_speed_hz; | ||
| 213 | proxy->irq = chip->irq; | ||
| 214 | proxy->modalias = chip->modalias; | ||
| 215 | |||
| 216 | snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, | ||
| 217 | "%s.%u", master->cdev.class_id, | ||
| 218 | chip->chip_select); | ||
| 219 | proxy->dev.parent = dev; | ||
| 220 | proxy->dev.bus = &spi_bus_type; | ||
| 221 | proxy->dev.platform_data = (void *) chip->platform_data; | ||
| 222 | proxy->controller_data = chip->controller_data; | ||
| 223 | proxy->controller_state = NULL; | ||
| 224 | proxy->dev.release = spidev_release; | ||
| 225 | |||
| 226 | /* drivers may modify this default i/o setup */ | ||
| 227 | status = master->setup(proxy); | ||
| 228 | if (status < 0) { | ||
| 229 | dev_dbg(dev, "can't %s %s, status %d\n", | ||
| 230 | "setup", proxy->dev.bus_id, status); | ||
| 231 | goto fail; | ||
| 232 | } | ||
| 233 | |||
| 234 | /* driver core catches callers that misbehave by defining | ||
| 235 | * devices that already exist. | ||
| 236 | */ | ||
| 237 | status = device_register(&proxy->dev); | ||
| 238 | if (status < 0) { | ||
| 239 | dev_dbg(dev, "can't %s %s, status %d\n", | ||
| 240 | "add", proxy->dev.bus_id, status); | ||
| 241 | goto fail; | ||
| 242 | } | ||
| 243 | dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); | ||
| 244 | return proxy; | ||
| 245 | |||
| 246 | fail: | ||
| 247 | spi_master_put(master); | ||
| 248 | kfree(proxy); | ||
| 249 | return NULL; | ||
| 250 | } | ||
| 251 | EXPORT_SYMBOL_GPL(spi_new_device); | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Board-specific early init code calls this (probably during arch_initcall) | ||
| 255 | * with segments of the SPI device table. Any device nodes are created later, | ||
| 256 | * after the relevant parent SPI controller (bus_num) is defined. We keep | ||
| 257 | * this table of devices forever, so that reloading a controller driver will | ||
| 258 | * not make Linux forget about these hard-wired devices. | ||
| 259 | * | ||
| 260 | * Other code can also call this, e.g. a particular add-on board might provide | ||
| 261 | * SPI devices through its expansion connector, so code initializing that board | ||
| 262 | * would naturally declare its SPI devices. | ||
| 263 | * | ||
| 264 | * The board info passed can safely be __initdata ... but be careful of | ||
| 265 | * any embedded pointers (platform_data, etc), they're copied as-is. | ||
| 266 | */ | ||
| 267 | int __init | ||
| 268 | spi_register_board_info(struct spi_board_info const *info, unsigned n) | ||
| 269 | { | ||
| 270 | struct boardinfo *bi; | ||
| 271 | |||
| 272 | bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL); | ||
| 273 | if (!bi) | ||
| 274 | return -ENOMEM; | ||
| 275 | bi->n_board_info = n; | ||
| 276 | memcpy(bi->board_info, info, n * sizeof *info); | ||
| 277 | |||
| 278 | down(&board_lock); | ||
| 279 | list_add_tail(&bi->list, &board_list); | ||
| 280 | up(&board_lock); | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | EXPORT_SYMBOL_GPL(spi_register_board_info); | ||
| 284 | |||
| 285 | /* FIXME someone should add support for a __setup("spi", ...) that | ||
| 286 | * creates board info from kernel command lines | ||
| 287 | */ | ||
| 288 | |||
| 289 | static void __init_or_module | ||
| 290 | scan_boardinfo(struct spi_master *master) | ||
| 291 | { | ||
| 292 | struct boardinfo *bi; | ||
| 293 | struct device *dev = master->cdev.dev; | ||
| 294 | |||
| 295 | down(&board_lock); | ||
| 296 | list_for_each_entry(bi, &board_list, list) { | ||
| 297 | struct spi_board_info *chip = bi->board_info; | ||
| 298 | unsigned n; | ||
| 299 | |||
| 300 | for (n = bi->n_board_info; n > 0; n--, chip++) { | ||
| 301 | if (chip->bus_num != master->bus_num) | ||
| 302 | continue; | ||
| 303 | /* some controllers only have one chip, so they | ||
| 304 | * might not use chipselects. otherwise, the | ||
| 305 | * chipselects are numbered 0..max. | ||
| 306 | */ | ||
| 307 | if (chip->chip_select >= master->num_chipselect | ||
| 308 | && master->num_chipselect) { | ||
| 309 | dev_dbg(dev, "cs%d > max %d\n", | ||
| 310 | chip->chip_select, | ||
| 311 | master->num_chipselect); | ||
| 312 | continue; | ||
| 313 | } | ||
| 314 | (void) spi_new_device(master, chip); | ||
| 315 | } | ||
| 316 | } | ||
| 317 | up(&board_lock); | ||
| 318 | } | ||
| 319 | |||
| 320 | /*-------------------------------------------------------------------------*/ | ||
| 321 | |||
| 322 | static void spi_master_release(struct class_device *cdev) | ||
| 323 | { | ||
| 324 | struct spi_master *master; | ||
| 325 | |||
| 326 | master = container_of(cdev, struct spi_master, cdev); | ||
| 327 | kfree(master); | ||
| 328 | } | ||
| 329 | |||
| 330 | static struct class spi_master_class = { | ||
| 331 | .name = "spi_master", | ||
| 332 | .owner = THIS_MODULE, | ||
| 333 | .release = spi_master_release, | ||
| 334 | }; | ||
| 335 | |||
| 336 | |||
| 337 | /** | ||
| 338 | * spi_alloc_master - allocate SPI master controller | ||
| 339 | * @dev: the controller, possibly using the platform_bus | ||
| 340 | * @size: how much driver-private data to preallocate; the pointer to this | ||
| 341 | * memory is in the class_data field of the returned class_device, | ||
| 342 | * accessible with spi_master_get_devdata(). | ||
| 343 | * | ||
| 344 | * This call is used only by SPI master controller drivers, which are the | ||
| 345 | * only ones directly touching chip registers. It's how they allocate | ||
| 346 | * an spi_master structure, prior to calling spi_add_master(). | ||
| 347 | * | ||
| 348 | * This must be called from context that can sleep. It returns the SPI | ||
| 349 | * master structure on success, else NULL. | ||
| 350 | * | ||
| 351 | * The caller is responsible for assigning the bus number and initializing | ||
| 352 | * the master's methods before calling spi_add_master(); and (after errors | ||
| 353 | * adding the device) calling spi_master_put() to prevent a memory leak. | ||
| 354 | */ | ||
| 355 | struct spi_master * __init_or_module | ||
| 356 | spi_alloc_master(struct device *dev, unsigned size) | ||
| 357 | { | ||
| 358 | struct spi_master *master; | ||
| 359 | |||
| 360 | if (!dev) | ||
| 361 | return NULL; | ||
| 362 | |||
| 363 | master = kzalloc(size + sizeof *master, SLAB_KERNEL); | ||
| 364 | if (!master) | ||
| 365 | return NULL; | ||
| 366 | |||
| 367 | class_device_initialize(&master->cdev); | ||
| 368 | master->cdev.class = &spi_master_class; | ||
| 369 | master->cdev.dev = get_device(dev); | ||
| 370 | spi_master_set_devdata(master, &master[1]); | ||
| 371 | |||
| 372 | return master; | ||
| 373 | } | ||
| 374 | EXPORT_SYMBOL_GPL(spi_alloc_master); | ||
| 375 | |||
| 376 | /** | ||
| 377 | * spi_register_master - register SPI master controller | ||
| 378 | * @master: initialized master, originally from spi_alloc_master() | ||
| 379 | * | ||
| 380 | * SPI master controllers connect to their drivers using some non-SPI bus, | ||
| 381 | * such as the platform bus. The final stage of probe() in that code | ||
| 382 | * includes calling spi_register_master() to hook up to this SPI bus glue. | ||
| 383 | * | ||
| 384 | * SPI controllers use board specific (often SOC specific) bus numbers, | ||
| 385 | * and board-specific addressing for SPI devices combines those numbers | ||
| 386 | * with chip select numbers. Since SPI does not directly support dynamic | ||
| 387 | * device identification, boards need configuration tables telling which | ||
| 388 | * chip is at which address. | ||
| 389 | * | ||
| 390 | * This must be called from context that can sleep. It returns zero on | ||
| 391 | * success, else a negative error code (dropping the master's refcount). | ||
| 392 | * After a successful return, the caller is responsible for calling | ||
| 393 | * spi_unregister_master(). | ||
| 394 | */ | ||
| 395 | int __init_or_module | ||
| 396 | spi_register_master(struct spi_master *master) | ||
| 397 | { | ||
| 398 | static atomic_t dyn_bus_id = ATOMIC_INIT(0); | ||
| 399 | struct device *dev = master->cdev.dev; | ||
| 400 | int status = -ENODEV; | ||
| 401 | int dynamic = 0; | ||
| 402 | |||
| 403 | if (!dev) | ||
| 404 | return -ENODEV; | ||
| 405 | |||
| 406 | /* convention: dynamically assigned bus IDs count down from the max */ | ||
| 407 | if (master->bus_num == 0) { | ||
| 408 | master->bus_num = atomic_dec_return(&dyn_bus_id); | ||
| 409 | dynamic = 1; | ||
| 410 | } | ||
| 411 | |||
| 412 | /* register the device, then userspace will see it. | ||
| 413 | * registration fails if the bus ID is in use. | ||
| 414 | */ | ||
| 415 | snprintf(master->cdev.class_id, sizeof master->cdev.class_id, | ||
| 416 | "spi%u", master->bus_num); | ||
| 417 | status = class_device_add(&master->cdev); | ||
| 418 | if (status < 0) | ||
| 419 | goto done; | ||
| 420 | dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, | ||
| 421 | dynamic ? " (dynamic)" : ""); | ||
| 422 | |||
| 423 | /* populate children from any spi device tables */ | ||
| 424 | scan_boardinfo(master); | ||
| 425 | status = 0; | ||
| 426 | done: | ||
| 427 | return status; | ||
| 428 | } | ||
| 429 | EXPORT_SYMBOL_GPL(spi_register_master); | ||
| 430 | |||
| 431 | |||
| 432 | static int __unregister(struct device *dev, void *unused) | ||
| 433 | { | ||
| 434 | /* note: before about 2.6.14-rc1 this would corrupt memory: */ | ||
| 435 | spi_unregister_device(to_spi_device(dev)); | ||
| 436 | return 0; | ||
| 437 | } | ||
| 438 | |||
| 439 | /** | ||
| 440 | * spi_unregister_master - unregister SPI master controller | ||
| 441 | * @master: the master being unregistered | ||
| 442 | * | ||
| 443 | * This call is used only by SPI master controller drivers, which are the | ||
| 444 | * only ones directly touching chip registers. | ||
| 445 | * | ||
| 446 | * This must be called from context that can sleep. | ||
| 447 | */ | ||
| 448 | void spi_unregister_master(struct spi_master *master) | ||
| 449 | { | ||
| 450 | (void) device_for_each_child(master->cdev.dev, NULL, __unregister); | ||
| 451 | class_device_unregister(&master->cdev); | ||
| 452 | master->cdev.dev = NULL; | ||
| 453 | } | ||
| 454 | EXPORT_SYMBOL_GPL(spi_unregister_master); | ||
| 455 | |||
| 456 | /** | ||
| 457 | * spi_busnum_to_master - look up master associated with bus_num | ||
| 458 | * @bus_num: the master's bus number | ||
| 459 | * | ||
| 460 | * This call may be used with devices that are registered after | ||
| 461 | * arch init time. It returns a refcounted pointer to the relevant | ||
| 462 | * spi_master (which the caller must release), or NULL if there is | ||
| 463 | * no such master registered. | ||
| 464 | */ | ||
| 465 | struct spi_master *spi_busnum_to_master(u16 bus_num) | ||
| 466 | { | ||
| 467 | if (bus_num) { | ||
| 468 | char name[8]; | ||
| 469 | struct kobject *bus; | ||
| 470 | |||
| 471 | snprintf(name, sizeof name, "spi%u", bus_num); | ||
| 472 | bus = kset_find_obj(&spi_master_class.subsys.kset, name); | ||
| 473 | if (bus) | ||
| 474 | return container_of(bus, struct spi_master, cdev.kobj); | ||
| 475 | } | ||
| 476 | return NULL; | ||
| 477 | } | ||
| 478 | EXPORT_SYMBOL_GPL(spi_busnum_to_master); | ||
| 479 | |||
| 480 | |||
| 481 | /*-------------------------------------------------------------------------*/ | ||
| 482 | |||
| 483 | static void spi_complete(void *arg) | ||
| 484 | { | ||
| 485 | complete(arg); | ||
| 486 | } | ||
| 487 | |||
| 488 | /** | ||
| 489 | * spi_sync - blocking/synchronous SPI data transfers | ||
| 490 | * @spi: device with which data will be exchanged | ||
| 491 | * @message: describes the data transfers | ||
| 492 | * | ||
| 493 | * This call may only be used from a context that may sleep. The sleep | ||
| 494 | * is non-interruptible, and has no timeout. Low-overhead controller | ||
| 495 | * drivers may DMA directly into and out of the message buffers. | ||
| 496 | * | ||
| 497 | * Note that the SPI device's chip select is active during the message, | ||
| 498 | * and then is normally disabled between messages. Drivers for some | ||
| 499 | * frequently-used devices may want to minimize costs of selecting a chip, | ||
| 500 | * by leaving it selected in anticipation that the next message will go | ||
| 501 | * to the same chip. (That may increase power usage.) | ||
| 502 | * | ||
| 503 | * Also, the caller is guaranteeing that the memory associated with the | ||
| 504 | * message will not be freed before this call returns. | ||
| 505 | * | ||
| 506 | * The return value is a negative error code if the message could not be | ||
| 507 | * submitted, else zero. When the value is zero, then message->status is | ||
| 508 | * also defined: it's the completion code for the transfer, either zero | ||
| 509 | * or a negative error code from the controller driver. | ||
| 510 | */ | ||
| 511 | int spi_sync(struct spi_device *spi, struct spi_message *message) | ||
| 512 | { | ||
| 513 | DECLARE_COMPLETION(done); | ||
| 514 | int status; | ||
| 515 | |||
| 516 | message->complete = spi_complete; | ||
| 517 | message->context = &done; | ||
| 518 | status = spi_async(spi, message); | ||
| 519 | if (status == 0) | ||
| 520 | wait_for_completion(&done); | ||
| 521 | message->context = NULL; | ||
| 522 | return status; | ||
| 523 | } | ||
| 524 | EXPORT_SYMBOL_GPL(spi_sync); | ||
| 525 | |||
| 526 | #define SPI_BUFSIZ (SMP_CACHE_BYTES) | ||
| 527 | |||
| 528 | static u8 *buf; | ||
| 529 | |||
| 530 | /** | ||
| 531 | * spi_write_then_read - SPI synchronous write followed by read | ||
| 532 | * @spi: device with which data will be exchanged | ||
| 533 | * @txbuf: data to be written (need not be dma-safe) | ||
| 534 | * @n_tx: size of txbuf, in bytes | ||
| 535 | * @rxbuf: buffer into which data will be read | ||
| 536 | * @n_rx: size of rxbuf, in bytes (need not be dma-safe) | ||
| 537 | * | ||
| 538 | * This performs a half duplex MicroWire style transaction with the | ||
| 539 | * device, sending txbuf and then reading rxbuf. The return value | ||
| 540 | * is zero for success, else a negative errno status code. | ||
| 541 | * This call may only be used from a context that may sleep. | ||
| 542 | * | ||
| 543 | * Parameters to this routine are always copied using a small buffer; | ||
| 544 | * performance-sensitive or bulk transfer code should instead use | ||
| 545 | * spi_{async,sync}() calls with dma-safe buffers. | ||
| 546 | */ | ||
| 547 | int spi_write_then_read(struct spi_device *spi, | ||
| 548 | const u8 *txbuf, unsigned n_tx, | ||
| 549 | u8 *rxbuf, unsigned n_rx) | ||
| 550 | { | ||
| 551 | static DECLARE_MUTEX(lock); | ||
| 552 | |||
| 553 | int status; | ||
| 554 | struct spi_message message; | ||
| 555 | struct spi_transfer x[2]; | ||
| 556 | u8 *local_buf; | ||
| 557 | |||
| 558 | /* Use preallocated DMA-safe buffer. We can't avoid copying here, | ||
| 559 | * (as a pure convenience thing), but we can keep heap costs | ||
| 560 | * out of the hot path ... | ||
| 561 | */ | ||
| 562 | if ((n_tx + n_rx) > SPI_BUFSIZ) | ||
| 563 | return -EINVAL; | ||
| 564 | |||
| 565 | spi_message_init(&message); | ||
| 566 | memset(x, 0, sizeof x); | ||
| 567 | if (n_tx) { | ||
| 568 | x[0].len = n_tx; | ||
| 569 | spi_message_add_tail(&x[0], &message); | ||
| 570 | } | ||
| 571 | if (n_rx) { | ||
| 572 | x[1].len = n_rx; | ||
| 573 | spi_message_add_tail(&x[1], &message); | ||
| 574 | } | ||
| 575 | |||
| 576 | /* ... unless someone else is using the pre-allocated buffer */ | ||
| 577 | if (down_trylock(&lock)) { | ||
| 578 | local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); | ||
| 579 | if (!local_buf) | ||
| 580 | return -ENOMEM; | ||
| 581 | } else | ||
| 582 | local_buf = buf; | ||
| 583 | |||
| 584 | memcpy(local_buf, txbuf, n_tx); | ||
| 585 | x[0].tx_buf = local_buf; | ||
| 586 | x[1].rx_buf = local_buf + n_tx; | ||
| 587 | |||
| 588 | /* do the i/o */ | ||
| 589 | status = spi_sync(spi, &message); | ||
| 590 | if (status == 0) { | ||
| 591 | memcpy(rxbuf, x[1].rx_buf, n_rx); | ||
| 592 | status = message.status; | ||
| 593 | } | ||
| 594 | |||
| 595 | if (x[0].tx_buf == buf) | ||
| 596 | up(&lock); | ||
| 597 | else | ||
| 598 | kfree(local_buf); | ||
| 599 | |||
| 600 | return status; | ||
| 601 | } | ||
| 602 | EXPORT_SYMBOL_GPL(spi_write_then_read); | ||
| 603 | |||
| 604 | /*-------------------------------------------------------------------------*/ | ||
| 605 | |||
| 606 | static int __init spi_init(void) | ||
| 607 | { | ||
| 608 | int status; | ||
| 609 | |||
| 610 | buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); | ||
| 611 | if (!buf) { | ||
| 612 | status = -ENOMEM; | ||
| 613 | goto err0; | ||
| 614 | } | ||
| 615 | |||
| 616 | status = bus_register(&spi_bus_type); | ||
| 617 | if (status < 0) | ||
| 618 | goto err1; | ||
| 619 | |||
| 620 | status = class_register(&spi_master_class); | ||
| 621 | if (status < 0) | ||
| 622 | goto err2; | ||
| 623 | return 0; | ||
| 624 | |||
| 625 | err2: | ||
| 626 | bus_unregister(&spi_bus_type); | ||
| 627 | err1: | ||
| 628 | kfree(buf); | ||
| 629 | buf = NULL; | ||
| 630 | err0: | ||
| 631 | return status; | ||
| 632 | } | ||
| 633 | |||
| 634 | /* board_info is normally registered in arch_initcall(), | ||
| 635 | * but even essential drivers wait till later | ||
| 636 | * | ||
| 637 | * REVISIT only boardinfo really needs static linking. the rest (device and | ||
| 638 | * driver registration) _could_ be dynamically linked (modular) ... costs | ||
| 639 | * include needing to have boardinfo data structures be much more public. | ||
| 640 | */ | ||
| 641 | subsys_initcall(spi_init); | ||
| 642 | |||
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c new file mode 100644 index 000000000000..f037e5593269 --- /dev/null +++ b/drivers/spi/spi_bitbang.c | |||
| @@ -0,0 +1,472 @@ | |||
| 1 | /* | ||
| 2 | * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/config.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/spinlock.h> | ||
| 22 | #include <linux/workqueue.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/errno.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | |||
| 28 | #include <linux/spi/spi.h> | ||
| 29 | #include <linux/spi/spi_bitbang.h> | ||
| 30 | |||
| 31 | |||
| 32 | /*----------------------------------------------------------------------*/ | ||
| 33 | |||
| 34 | /* | ||
| 35 | * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support. | ||
| 36 | * Use this for GPIO or shift-register level hardware APIs. | ||
| 37 | * | ||
| 38 | * spi_bitbang_cs is in spi_device->controller_state, which is unavailable | ||
| 39 | * to glue code. These bitbang setup() and cleanup() routines are always | ||
| 40 | * used, though maybe they're called from controller-aware code. | ||
| 41 | * | ||
| 42 | * chipselect() and friends may use use spi_device->controller_data and | ||
| 43 | * controller registers as appropriate. | ||
| 44 | * | ||
| 45 | * | ||
| 46 | * NOTE: SPI controller pins can often be used as GPIO pins instead, | ||
| 47 | * which means you could use a bitbang driver either to get hardware | ||
| 48 | * working quickly, or testing for differences that aren't speed related. | ||
| 49 | */ | ||
| 50 | |||
| 51 | struct spi_bitbang_cs { | ||
| 52 | unsigned nsecs; /* (clock cycle time)/2 */ | ||
| 53 | u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, | ||
| 54 | u32 word, u8 bits); | ||
| 55 | unsigned (*txrx_bufs)(struct spi_device *, | ||
| 56 | u32 (*txrx_word)( | ||
| 57 | struct spi_device *spi, | ||
| 58 | unsigned nsecs, | ||
| 59 | u32 word, u8 bits), | ||
| 60 | unsigned, struct spi_transfer *); | ||
| 61 | }; | ||
| 62 | |||
| 63 | static unsigned bitbang_txrx_8( | ||
| 64 | struct spi_device *spi, | ||
| 65 | u32 (*txrx_word)(struct spi_device *spi, | ||
| 66 | unsigned nsecs, | ||
| 67 | u32 word, u8 bits), | ||
| 68 | unsigned ns, | ||
| 69 | struct spi_transfer *t | ||
| 70 | ) { | ||
| 71 | unsigned bits = spi->bits_per_word; | ||
| 72 | unsigned count = t->len; | ||
| 73 | const u8 *tx = t->tx_buf; | ||
| 74 | u8 *rx = t->rx_buf; | ||
| 75 | |||
| 76 | while (likely(count > 0)) { | ||
| 77 | u8 word = 0; | ||
| 78 | |||
| 79 | if (tx) | ||
| 80 | word = *tx++; | ||
| 81 | word = txrx_word(spi, ns, word, bits); | ||
| 82 | if (rx) | ||
| 83 | *rx++ = word; | ||
| 84 | count -= 1; | ||
| 85 | } | ||
| 86 | return t->len - count; | ||
| 87 | } | ||
| 88 | |||
| 89 | static unsigned bitbang_txrx_16( | ||
| 90 | struct spi_device *spi, | ||
| 91 | u32 (*txrx_word)(struct spi_device *spi, | ||
| 92 | unsigned nsecs, | ||
| 93 | u32 word, u8 bits), | ||
| 94 | unsigned ns, | ||
| 95 | struct spi_transfer *t | ||
| 96 | ) { | ||
| 97 | unsigned bits = spi->bits_per_word; | ||
| 98 | unsigned count = t->len; | ||
| 99 | const u16 *tx = t->tx_buf; | ||
| 100 | u16 *rx = t->rx_buf; | ||
| 101 | |||
| 102 | while (likely(count > 1)) { | ||
| 103 | u16 word = 0; | ||
| 104 | |||
| 105 | if (tx) | ||
| 106 | word = *tx++; | ||
| 107 | word = txrx_word(spi, ns, word, bits); | ||
| 108 | if (rx) | ||
| 109 | *rx++ = word; | ||
| 110 | count -= 2; | ||
| 111 | } | ||
| 112 | return t->len - count; | ||
| 113 | } | ||
| 114 | |||
| 115 | static unsigned bitbang_txrx_32( | ||
| 116 | struct spi_device *spi, | ||
| 117 | u32 (*txrx_word)(struct spi_device *spi, | ||
| 118 | unsigned nsecs, | ||
| 119 | u32 word, u8 bits), | ||
| 120 | unsigned ns, | ||
| 121 | struct spi_transfer *t | ||
| 122 | ) { | ||
| 123 | unsigned bits = spi->bits_per_word; | ||
| 124 | unsigned count = t->len; | ||
| 125 | const u32 *tx = t->tx_buf; | ||
| 126 | u32 *rx = t->rx_buf; | ||
| 127 | |||
| 128 | while (likely(count > 3)) { | ||
| 129 | u32 word = 0; | ||
| 130 | |||
| 131 | if (tx) | ||
| 132 | word = *tx++; | ||
| 133 | word = txrx_word(spi, ns, word, bits); | ||
| 134 | if (rx) | ||
| 135 | *rx++ = word; | ||
| 136 | count -= 4; | ||
| 137 | } | ||
| 138 | return t->len - count; | ||
| 139 | } | ||
| 140 | |||
| 141 | /** | ||
| 142 | * spi_bitbang_setup - default setup for per-word I/O loops | ||
| 143 | */ | ||
| 144 | int spi_bitbang_setup(struct spi_device *spi) | ||
| 145 | { | ||
| 146 | struct spi_bitbang_cs *cs = spi->controller_state; | ||
| 147 | struct spi_bitbang *bitbang; | ||
| 148 | |||
| 149 | if (!spi->max_speed_hz) | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | if (!cs) { | ||
| 153 | cs = kzalloc(sizeof *cs, SLAB_KERNEL); | ||
| 154 | if (!cs) | ||
| 155 | return -ENOMEM; | ||
| 156 | spi->controller_state = cs; | ||
| 157 | } | ||
| 158 | bitbang = spi_master_get_devdata(spi->master); | ||
| 159 | |||
| 160 | if (!spi->bits_per_word) | ||
| 161 | spi->bits_per_word = 8; | ||
| 162 | |||
| 163 | /* spi_transfer level calls that work per-word */ | ||
| 164 | if (spi->bits_per_word <= 8) | ||
| 165 | cs->txrx_bufs = bitbang_txrx_8; | ||
| 166 | else if (spi->bits_per_word <= 16) | ||
| 167 | cs->txrx_bufs = bitbang_txrx_16; | ||
| 168 | else if (spi->bits_per_word <= 32) | ||
| 169 | cs->txrx_bufs = bitbang_txrx_32; | ||
| 170 | else | ||
| 171 | return -EINVAL; | ||
| 172 | |||
| 173 | /* per-word shift register access, in hardware or bitbanging */ | ||
| 174 | cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)]; | ||
| 175 | if (!cs->txrx_word) | ||
| 176 | return -EINVAL; | ||
| 177 | |||
| 178 | /* nsecs = (clock period)/2 */ | ||
| 179 | cs->nsecs = (1000000000/2) / (spi->max_speed_hz); | ||
| 180 | if (cs->nsecs > MAX_UDELAY_MS * 1000) | ||
| 181 | return -EINVAL; | ||
| 182 | |||
| 183 | dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", | ||
| 184 | __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), | ||
| 185 | spi->bits_per_word, 2 * cs->nsecs); | ||
| 186 | |||
| 187 | /* NOTE we _need_ to call chipselect() early, ideally with adapter | ||
| 188 | * setup, unless the hardware defaults cooperate to avoid confusion | ||
| 189 | * between normal (active low) and inverted chipselects. | ||
| 190 | */ | ||
| 191 | |||
| 192 | /* deselect chip (low or high) */ | ||
| 193 | spin_lock(&bitbang->lock); | ||
| 194 | if (!bitbang->busy) { | ||
| 195 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
| 196 | ndelay(cs->nsecs); | ||
| 197 | } | ||
| 198 | spin_unlock(&bitbang->lock); | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | EXPORT_SYMBOL_GPL(spi_bitbang_setup); | ||
| 203 | |||
| 204 | /** | ||
| 205 | * spi_bitbang_cleanup - default cleanup for per-word I/O loops | ||
| 206 | */ | ||
| 207 | void spi_bitbang_cleanup(const struct spi_device *spi) | ||
| 208 | { | ||
| 209 | kfree(spi->controller_state); | ||
| 210 | } | ||
| 211 | EXPORT_SYMBOL_GPL(spi_bitbang_cleanup); | ||
| 212 | |||
| 213 | static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) | ||
| 214 | { | ||
| 215 | struct spi_bitbang_cs *cs = spi->controller_state; | ||
| 216 | unsigned nsecs = cs->nsecs; | ||
| 217 | |||
| 218 | return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t); | ||
| 219 | } | ||
| 220 | |||
| 221 | /*----------------------------------------------------------------------*/ | ||
| 222 | |||
| 223 | /* | ||
| 224 | * SECOND PART ... simple transfer queue runner. | ||
| 225 | * | ||
| 226 | * This costs a task context per controller, running the queue by | ||
| 227 | * performing each transfer in sequence. Smarter hardware can queue | ||
| 228 | * several DMA transfers at once, and process several controller queues | ||
| 229 | * in parallel; this driver doesn't match such hardware very well. | ||
| 230 | * | ||
| 231 | * Drivers can provide word-at-a-time i/o primitives, or provide | ||
| 232 | * transfer-at-a-time ones to leverage dma or fifo hardware. | ||
| 233 | */ | ||
| 234 | static void bitbang_work(void *_bitbang) | ||
| 235 | { | ||
| 236 | struct spi_bitbang *bitbang = _bitbang; | ||
| 237 | unsigned long flags; | ||
| 238 | |||
| 239 | spin_lock_irqsave(&bitbang->lock, flags); | ||
| 240 | bitbang->busy = 1; | ||
| 241 | while (!list_empty(&bitbang->queue)) { | ||
| 242 | struct spi_message *m; | ||
| 243 | struct spi_device *spi; | ||
| 244 | unsigned nsecs; | ||
| 245 | struct spi_transfer *t = NULL; | ||
| 246 | unsigned tmp; | ||
| 247 | unsigned cs_change; | ||
| 248 | int status; | ||
| 249 | |||
| 250 | m = container_of(bitbang->queue.next, struct spi_message, | ||
| 251 | queue); | ||
| 252 | list_del_init(&m->queue); | ||
| 253 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
| 254 | |||
| 255 | /* FIXME this is made-up ... the correct value is known to | ||
| 256 | * word-at-a-time bitbang code, and presumably chipselect() | ||
| 257 | * should enforce these requirements too? | ||
| 258 | */ | ||
| 259 | nsecs = 100; | ||
| 260 | |||
| 261 | spi = m->spi; | ||
| 262 | tmp = 0; | ||
| 263 | cs_change = 1; | ||
| 264 | status = 0; | ||
| 265 | |||
| 266 | list_for_each_entry (t, &m->transfers, transfer_list) { | ||
| 267 | if (bitbang->shutdown) { | ||
| 268 | status = -ESHUTDOWN; | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | |||
| 272 | /* set up default clock polarity, and activate chip; | ||
| 273 | * this implicitly updates clock and spi modes as | ||
| 274 | * previously recorded for this device via setup(). | ||
| 275 | * (and also deselects any other chip that might be | ||
| 276 | * selected ...) | ||
| 277 | */ | ||
| 278 | if (cs_change) { | ||
| 279 | bitbang->chipselect(spi, BITBANG_CS_ACTIVE); | ||
| 280 | ndelay(nsecs); | ||
| 281 | } | ||
| 282 | cs_change = t->cs_change; | ||
| 283 | if (!t->tx_buf && !t->rx_buf && t->len) { | ||
| 284 | status = -EINVAL; | ||
| 285 | break; | ||
| 286 | } | ||
| 287 | |||
| 288 | /* transfer data. the lower level code handles any | ||
| 289 | * new dma mappings it needs. our caller always gave | ||
| 290 | * us dma-safe buffers. | ||
| 291 | */ | ||
| 292 | if (t->len) { | ||
| 293 | /* REVISIT dma API still needs a designated | ||
| 294 | * DMA_ADDR_INVALID; ~0 might be better. | ||
| 295 | */ | ||
| 296 | if (!m->is_dma_mapped) | ||
| 297 | t->rx_dma = t->tx_dma = 0; | ||
| 298 | status = bitbang->txrx_bufs(spi, t); | ||
| 299 | } | ||
| 300 | if (status != t->len) { | ||
| 301 | if (status > 0) | ||
| 302 | status = -EMSGSIZE; | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | m->actual_length += status; | ||
| 306 | status = 0; | ||
| 307 | |||
| 308 | /* protocol tweaks before next transfer */ | ||
| 309 | if (t->delay_usecs) | ||
| 310 | udelay(t->delay_usecs); | ||
| 311 | |||
| 312 | if (!cs_change) | ||
| 313 | continue; | ||
| 314 | if (t->transfer_list.next == &m->transfers) | ||
| 315 | break; | ||
| 316 | |||
| 317 | /* sometimes a short mid-message deselect of the chip | ||
| 318 | * may be needed to terminate a mode or command | ||
| 319 | */ | ||
| 320 | ndelay(nsecs); | ||
| 321 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
| 322 | ndelay(nsecs); | ||
| 323 | } | ||
| 324 | |||
| 325 | m->status = status; | ||
| 326 | m->complete(m->context); | ||
| 327 | |||
| 328 | /* normally deactivate chipselect ... unless no error and | ||
| 329 | * cs_change has hinted that the next message will probably | ||
| 330 | * be for this chip too. | ||
| 331 | */ | ||
| 332 | if (!(status == 0 && cs_change)) { | ||
| 333 | ndelay(nsecs); | ||
| 334 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
| 335 | ndelay(nsecs); | ||
| 336 | } | ||
| 337 | |||
| 338 | spin_lock_irqsave(&bitbang->lock, flags); | ||
| 339 | } | ||
| 340 | bitbang->busy = 0; | ||
| 341 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
| 342 | } | ||
| 343 | |||
| 344 | /** | ||
| 345 | * spi_bitbang_transfer - default submit to transfer queue | ||
| 346 | */ | ||
| 347 | int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | ||
| 348 | { | ||
| 349 | struct spi_bitbang *bitbang; | ||
| 350 | unsigned long flags; | ||
| 351 | |||
| 352 | m->actual_length = 0; | ||
| 353 | m->status = -EINPROGRESS; | ||
| 354 | |||
| 355 | bitbang = spi_master_get_devdata(spi->master); | ||
| 356 | if (bitbang->shutdown) | ||
| 357 | return -ESHUTDOWN; | ||
| 358 | |||
| 359 | spin_lock_irqsave(&bitbang->lock, flags); | ||
| 360 | list_add_tail(&m->queue, &bitbang->queue); | ||
| 361 | queue_work(bitbang->workqueue, &bitbang->work); | ||
| 362 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
| 363 | |||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | EXPORT_SYMBOL_GPL(spi_bitbang_transfer); | ||
| 367 | |||
| 368 | /*----------------------------------------------------------------------*/ | ||
| 369 | |||
| 370 | /** | ||
| 371 | * spi_bitbang_start - start up a polled/bitbanging SPI master driver | ||
| 372 | * @bitbang: driver handle | ||
| 373 | * | ||
| 374 | * Caller should have zero-initialized all parts of the structure, and then | ||
| 375 | * provided callbacks for chip selection and I/O loops. If the master has | ||
| 376 | * a transfer method, its final step should call spi_bitbang_transfer; or, | ||
| 377 | * that's the default if the transfer routine is not initialized. It should | ||
| 378 | * also set up the bus number and number of chipselects. | ||
| 379 | * | ||
| 380 | * For i/o loops, provide callbacks either per-word (for bitbanging, or for | ||
| 381 | * hardware that basically exposes a shift register) or per-spi_transfer | ||
| 382 | * (which takes better advantage of hardware like fifos or DMA engines). | ||
| 383 | * | ||
| 384 | * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and | ||
| 385 | * spi_bitbang_cleanup to handle those spi master methods. Those methods are | ||
| 386 | * the defaults if the bitbang->txrx_bufs routine isn't initialized. | ||
| 387 | * | ||
| 388 | * This routine registers the spi_master, which will process requests in a | ||
| 389 | * dedicated task, keeping IRQs unblocked most of the time. To stop | ||
| 390 | * processing those requests, call spi_bitbang_stop(). | ||
| 391 | */ | ||
| 392 | int spi_bitbang_start(struct spi_bitbang *bitbang) | ||
| 393 | { | ||
| 394 | int status; | ||
| 395 | |||
| 396 | if (!bitbang->master || !bitbang->chipselect) | ||
| 397 | return -EINVAL; | ||
| 398 | |||
| 399 | INIT_WORK(&bitbang->work, bitbang_work, bitbang); | ||
| 400 | spin_lock_init(&bitbang->lock); | ||
| 401 | INIT_LIST_HEAD(&bitbang->queue); | ||
| 402 | |||
| 403 | if (!bitbang->master->transfer) | ||
| 404 | bitbang->master->transfer = spi_bitbang_transfer; | ||
| 405 | if (!bitbang->txrx_bufs) { | ||
| 406 | bitbang->use_dma = 0; | ||
| 407 | bitbang->txrx_bufs = spi_bitbang_bufs; | ||
| 408 | if (!bitbang->master->setup) { | ||
| 409 | bitbang->master->setup = spi_bitbang_setup; | ||
| 410 | bitbang->master->cleanup = spi_bitbang_cleanup; | ||
| 411 | } | ||
| 412 | } else if (!bitbang->master->setup) | ||
| 413 | return -EINVAL; | ||
| 414 | |||
| 415 | /* this task is the only thing to touch the SPI bits */ | ||
| 416 | bitbang->busy = 0; | ||
| 417 | bitbang->workqueue = create_singlethread_workqueue( | ||
| 418 | bitbang->master->cdev.dev->bus_id); | ||
| 419 | if (bitbang->workqueue == NULL) { | ||
| 420 | status = -EBUSY; | ||
| 421 | goto err1; | ||
| 422 | } | ||
| 423 | |||
| 424 | /* driver may get busy before register() returns, especially | ||
| 425 | * if someone registered boardinfo for devices | ||
| 426 | */ | ||
| 427 | status = spi_register_master(bitbang->master); | ||
| 428 | if (status < 0) | ||
| 429 | goto err2; | ||
| 430 | |||
| 431 | return status; | ||
| 432 | |||
| 433 | err2: | ||
| 434 | destroy_workqueue(bitbang->workqueue); | ||
| 435 | err1: | ||
| 436 | return status; | ||
| 437 | } | ||
| 438 | EXPORT_SYMBOL_GPL(spi_bitbang_start); | ||
| 439 | |||
| 440 | /** | ||
| 441 | * spi_bitbang_stop - stops the task providing spi communication | ||
| 442 | */ | ||
| 443 | int spi_bitbang_stop(struct spi_bitbang *bitbang) | ||
| 444 | { | ||
| 445 | unsigned limit = 500; | ||
| 446 | |||
| 447 | spin_lock_irq(&bitbang->lock); | ||
| 448 | bitbang->shutdown = 0; | ||
| 449 | while (!list_empty(&bitbang->queue) && limit--) { | ||
| 450 | spin_unlock_irq(&bitbang->lock); | ||
| 451 | |||
| 452 | dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); | ||
| 453 | msleep(10); | ||
| 454 | |||
| 455 | spin_lock_irq(&bitbang->lock); | ||
| 456 | } | ||
| 457 | spin_unlock_irq(&bitbang->lock); | ||
| 458 | if (!list_empty(&bitbang->queue)) { | ||
| 459 | dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); | ||
| 460 | return -EBUSY; | ||
| 461 | } | ||
| 462 | |||
| 463 | destroy_workqueue(bitbang->workqueue); | ||
| 464 | |||
| 465 | spi_unregister_master(bitbang->master); | ||
| 466 | |||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); | ||
| 470 | |||
| 471 | MODULE_LICENSE("GPL"); | ||
| 472 | |||
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c new file mode 100644 index 000000000000..79a3c59615ab --- /dev/null +++ b/drivers/spi/spi_butterfly.c | |||
| @@ -0,0 +1,423 @@ | |||
| 1 | /* | ||
| 2 | * spi_butterfly.c - parport-to-butterfly adapter | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 David Brownell | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | */ | ||
| 20 | #include <linux/config.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/delay.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/parport.h> | ||
| 26 | |||
| 27 | #include <linux/spi/spi.h> | ||
| 28 | #include <linux/spi/spi_bitbang.h> | ||
| 29 | #include <linux/spi/flash.h> | ||
| 30 | |||
| 31 | #include <linux/mtd/partitions.h> | ||
| 32 | |||
| 33 | |||
| 34 | /* | ||
| 35 | * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card | ||
| 36 | * with a battery powered AVR microcontroller and lots of goodies. You | ||
| 37 | * can use GCC to develop firmware for this. | ||
| 38 | * | ||
| 39 | * See Documentation/spi/butterfly for information about how to build | ||
| 40 | * and use this custom parallel port cable. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #undef HAVE_USI /* nyet */ | ||
| 44 | |||
| 45 | |||
| 46 | /* DATA output bits (pins 2..9 == D0..D7) */ | ||
| 47 | #define butterfly_nreset (1 << 1) /* pin 3 */ | ||
| 48 | |||
| 49 | #define spi_sck_bit (1 << 0) /* pin 2 */ | ||
| 50 | #define spi_mosi_bit (1 << 7) /* pin 9 */ | ||
| 51 | |||
| 52 | #define usi_sck_bit (1 << 3) /* pin 5 */ | ||
| 53 | #define usi_mosi_bit (1 << 4) /* pin 6 */ | ||
| 54 | |||
| 55 | #define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */ | ||
| 56 | |||
| 57 | /* STATUS input bits */ | ||
| 58 | #define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */ | ||
| 59 | |||
| 60 | #define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */ | ||
| 61 | |||
| 62 | /* CONTROL output bits */ | ||
| 63 | #define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ | ||
| 64 | /* USI uses no chipselect */ | ||
| 65 | |||
| 66 | |||
| 67 | |||
| 68 | static inline struct butterfly *spidev_to_pp(struct spi_device *spi) | ||
| 69 | { | ||
| 70 | return spi->controller_data; | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline int is_usidev(struct spi_device *spi) | ||
| 74 | { | ||
| 75 | #ifdef HAVE_USI | ||
| 76 | return spi->chip_select != 1; | ||
| 77 | #else | ||
| 78 | return 0; | ||
| 79 | #endif | ||
| 80 | } | ||
| 81 | |||
| 82 | |||
| 83 | struct butterfly { | ||
| 84 | /* REVISIT ... for now, this must be first */ | ||
| 85 | struct spi_bitbang bitbang; | ||
| 86 | |||
| 87 | struct parport *port; | ||
| 88 | struct pardevice *pd; | ||
| 89 | |||
| 90 | u8 lastbyte; | ||
| 91 | |||
| 92 | struct spi_device *dataflash; | ||
| 93 | struct spi_device *butterfly; | ||
| 94 | struct spi_board_info info[2]; | ||
| 95 | |||
| 96 | }; | ||
| 97 | |||
| 98 | /*----------------------------------------------------------------------*/ | ||
| 99 | |||
| 100 | /* | ||
| 101 | * these routines may be slower than necessary because they're hiding | ||
| 102 | * the fact that there are two different SPI busses on this cable: one | ||
| 103 | * to the DataFlash chip (or AVR SPI controller), the other to the | ||
| 104 | * AVR USI controller. | ||
| 105 | */ | ||
| 106 | |||
| 107 | static inline void | ||
| 108 | setsck(struct spi_device *spi, int is_on) | ||
| 109 | { | ||
| 110 | struct butterfly *pp = spidev_to_pp(spi); | ||
| 111 | u8 bit, byte = pp->lastbyte; | ||
| 112 | |||
| 113 | if (is_usidev(spi)) | ||
| 114 | bit = usi_sck_bit; | ||
| 115 | else | ||
| 116 | bit = spi_sck_bit; | ||
| 117 | |||
| 118 | if (is_on) | ||
| 119 | byte |= bit; | ||
| 120 | else | ||
| 121 | byte &= ~bit; | ||
| 122 | parport_write_data(pp->port, byte); | ||
| 123 | pp->lastbyte = byte; | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline void | ||
| 127 | setmosi(struct spi_device *spi, int is_on) | ||
| 128 | { | ||
| 129 | struct butterfly *pp = spidev_to_pp(spi); | ||
| 130 | u8 bit, byte = pp->lastbyte; | ||
| 131 | |||
| 132 | if (is_usidev(spi)) | ||
| 133 | bit = usi_mosi_bit; | ||
| 134 | else | ||
| 135 | bit = spi_mosi_bit; | ||
| 136 | |||
| 137 | if (is_on) | ||
| 138 | byte |= bit; | ||
| 139 | else | ||
| 140 | byte &= ~bit; | ||
| 141 | parport_write_data(pp->port, byte); | ||
| 142 | pp->lastbyte = byte; | ||
| 143 | } | ||
| 144 | |||
| 145 | static inline int getmiso(struct spi_device *spi) | ||
| 146 | { | ||
| 147 | struct butterfly *pp = spidev_to_pp(spi); | ||
| 148 | int value; | ||
| 149 | u8 bit; | ||
| 150 | |||
| 151 | if (is_usidev(spi)) | ||
| 152 | bit = usi_miso_bit; | ||
| 153 | else | ||
| 154 | bit = spi_miso_bit; | ||
| 155 | |||
| 156 | /* only STATUS_BUSY is NOT negated */ | ||
| 157 | value = !(parport_read_status(pp->port) & bit); | ||
| 158 | return (bit == PARPORT_STATUS_BUSY) ? value : !value; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void butterfly_chipselect(struct spi_device *spi, int value) | ||
| 162 | { | ||
| 163 | struct butterfly *pp = spidev_to_pp(spi); | ||
| 164 | |||
| 165 | /* set default clock polarity */ | ||
| 166 | if (value) | ||
| 167 | setsck(spi, spi->mode & SPI_CPOL); | ||
| 168 | |||
| 169 | /* no chipselect on this USI link config */ | ||
| 170 | if (is_usidev(spi)) | ||
| 171 | return; | ||
| 172 | |||
| 173 | /* here, value == "activate or not" */ | ||
| 174 | |||
| 175 | /* most PARPORT_CONTROL_* bits are negated */ | ||
| 176 | if (spi_cs_bit == PARPORT_CONTROL_INIT) | ||
| 177 | value = !value; | ||
| 178 | |||
| 179 | /* here, value == "bit value to write in control register" */ | ||
| 180 | |||
| 181 | parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); | ||
| 182 | } | ||
| 183 | |||
| 184 | |||
| 185 | /* we only needed to implement one mode here, and choose SPI_MODE_0 */ | ||
| 186 | |||
| 187 | #define spidelay(X) do{}while(0) | ||
| 188 | //#define spidelay ndelay | ||
| 189 | |||
| 190 | #define EXPAND_BITBANG_TXRX | ||
| 191 | #include <linux/spi/spi_bitbang.h> | ||
| 192 | |||
| 193 | static u32 | ||
| 194 | butterfly_txrx_word_mode0(struct spi_device *spi, | ||
| 195 | unsigned nsecs, | ||
| 196 | u32 word, u8 bits) | ||
| 197 | { | ||
| 198 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | ||
| 199 | } | ||
| 200 | |||
| 201 | /*----------------------------------------------------------------------*/ | ||
| 202 | |||
| 203 | /* override default partitioning with cmdlinepart */ | ||
| 204 | static struct mtd_partition partitions[] = { { | ||
| 205 | /* JFFS2 wants partitions of 4*N blocks for this device ... */ | ||
| 206 | |||
| 207 | /* sector 0 = 8 pages * 264 bytes/page (1 block) | ||
| 208 | * sector 1 = 248 pages * 264 bytes/page | ||
| 209 | */ | ||
| 210 | .name = "bookkeeping", // 66 KB | ||
| 211 | .offset = 0, | ||
| 212 | .size = (8 + 248) * 264, | ||
| 213 | // .mask_flags = MTD_WRITEABLE, | ||
| 214 | }, { | ||
| 215 | /* sector 2 = 256 pages * 264 bytes/page | ||
| 216 | * sectors 3-5 = 512 pages * 264 bytes/page | ||
| 217 | */ | ||
| 218 | .name = "filesystem", // 462 KB | ||
| 219 | .offset = MTDPART_OFS_APPEND, | ||
| 220 | .size = MTDPART_SIZ_FULL, | ||
| 221 | } }; | ||
| 222 | |||
| 223 | static struct flash_platform_data flash = { | ||
| 224 | .name = "butterflash", | ||
| 225 | .parts = partitions, | ||
| 226 | .nr_parts = ARRAY_SIZE(partitions), | ||
| 227 | }; | ||
| 228 | |||
| 229 | |||
| 230 | /* REVISIT remove this ugly global and its "only one" limitation */ | ||
| 231 | static struct butterfly *butterfly; | ||
| 232 | |||
| 233 | static void butterfly_attach(struct parport *p) | ||
| 234 | { | ||
| 235 | struct pardevice *pd; | ||
| 236 | int status; | ||
| 237 | struct butterfly *pp; | ||
| 238 | struct spi_master *master; | ||
| 239 | struct platform_device *pdev; | ||
| 240 | |||
| 241 | if (butterfly) | ||
| 242 | return; | ||
| 243 | |||
| 244 | /* REVISIT: this just _assumes_ a butterfly is there ... no probe, | ||
| 245 | * and no way to be selective about what it binds to. | ||
| 246 | */ | ||
| 247 | |||
| 248 | /* FIXME where should master->cdev.dev come from? | ||
| 249 | * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc | ||
| 250 | * setting up a platform device like this is an ugly kluge... | ||
| 251 | */ | ||
| 252 | pdev = platform_device_register_simple("butterfly", -1, NULL, 0); | ||
| 253 | |||
| 254 | master = spi_alloc_master(&pdev->dev, sizeof *pp); | ||
| 255 | if (!master) { | ||
| 256 | status = -ENOMEM; | ||
| 257 | goto done; | ||
| 258 | } | ||
| 259 | pp = spi_master_get_devdata(master); | ||
| 260 | |||
| 261 | /* | ||
| 262 | * SPI and bitbang hookup | ||
| 263 | * | ||
| 264 | * use default setup(), cleanup(), and transfer() methods; and | ||
| 265 | * only bother implementing mode 0. Start it later. | ||
| 266 | */ | ||
| 267 | master->bus_num = 42; | ||
| 268 | master->num_chipselect = 2; | ||
| 269 | |||
| 270 | pp->bitbang.master = spi_master_get(master); | ||
| 271 | pp->bitbang.chipselect = butterfly_chipselect; | ||
| 272 | pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; | ||
| 273 | |||
| 274 | /* | ||
| 275 | * parport hookup | ||
| 276 | */ | ||
| 277 | pp->port = p; | ||
| 278 | pd = parport_register_device(p, "spi_butterfly", | ||
| 279 | NULL, NULL, NULL, | ||
| 280 | 0 /* FLAGS */, pp); | ||
| 281 | if (!pd) { | ||
| 282 | status = -ENOMEM; | ||
| 283 | goto clean0; | ||
| 284 | } | ||
| 285 | pp->pd = pd; | ||
| 286 | |||
| 287 | status = parport_claim(pd); | ||
| 288 | if (status < 0) | ||
| 289 | goto clean1; | ||
| 290 | |||
| 291 | /* | ||
| 292 | * Butterfly reset, powerup, run firmware | ||
| 293 | */ | ||
| 294 | pr_debug("%s: powerup/reset Butterfly\n", p->name); | ||
| 295 | |||
| 296 | /* nCS for dataflash (this bit is inverted on output) */ | ||
| 297 | parport_frob_control(pp->port, spi_cs_bit, 0); | ||
| 298 | |||
| 299 | /* stabilize power with chip in reset (nRESET), and | ||
| 300 | * both spi_sck_bit and usi_sck_bit clear (CPOL=0) | ||
| 301 | */ | ||
| 302 | pp->lastbyte |= vcc_bits; | ||
| 303 | parport_write_data(pp->port, pp->lastbyte); | ||
| 304 | msleep(5); | ||
| 305 | |||
| 306 | /* take it out of reset; assume long reset delay */ | ||
| 307 | pp->lastbyte |= butterfly_nreset; | ||
| 308 | parport_write_data(pp->port, pp->lastbyte); | ||
| 309 | msleep(100); | ||
| 310 | |||
| 311 | |||
| 312 | /* | ||
| 313 | * Start SPI ... for now, hide that we're two physical busses. | ||
| 314 | */ | ||
| 315 | status = spi_bitbang_start(&pp->bitbang); | ||
| 316 | if (status < 0) | ||
| 317 | goto clean2; | ||
| 318 | |||
| 319 | /* Bus 1 lets us talk to at45db041b (firmware disables AVR) | ||
| 320 | * or AVR (firmware resets at45, acts as spi slave) | ||
| 321 | */ | ||
| 322 | pp->info[0].max_speed_hz = 15 * 1000 * 1000; | ||
| 323 | strcpy(pp->info[0].modalias, "mtd_dataflash"); | ||
| 324 | pp->info[0].platform_data = &flash; | ||
| 325 | pp->info[0].chip_select = 1; | ||
| 326 | pp->info[0].controller_data = pp; | ||
| 327 | pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); | ||
| 328 | if (pp->dataflash) | ||
| 329 | pr_debug("%s: dataflash at %s\n", p->name, | ||
| 330 | pp->dataflash->dev.bus_id); | ||
| 331 | |||
| 332 | #ifdef HAVE_USI | ||
| 333 | /* even more custom AVR firmware */ | ||
| 334 | pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; | ||
| 335 | strcpy(pp->info[1].modalias, "butterfly"); | ||
| 336 | // pp->info[1].platform_data = ... TBD ... ; | ||
| 337 | pp->info[1].chip_select = 2, | ||
| 338 | pp->info[1].controller_data = pp; | ||
| 339 | pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]); | ||
| 340 | if (pp->butterfly) | ||
| 341 | pr_debug("%s: butterfly at %s\n", p->name, | ||
| 342 | pp->butterfly->dev.bus_id); | ||
| 343 | |||
| 344 | /* FIXME setup ACK for the IRQ line ... */ | ||
| 345 | #endif | ||
| 346 | |||
| 347 | // dev_info(_what?_, ...) | ||
| 348 | pr_info("%s: AVR Butterfly\n", p->name); | ||
| 349 | butterfly = pp; | ||
| 350 | return; | ||
| 351 | |||
| 352 | clean2: | ||
| 353 | /* turn off VCC */ | ||
| 354 | parport_write_data(pp->port, 0); | ||
| 355 | |||
| 356 | parport_release(pp->pd); | ||
| 357 | clean1: | ||
| 358 | parport_unregister_device(pd); | ||
| 359 | clean0: | ||
| 360 | (void) spi_master_put(pp->bitbang.master); | ||
| 361 | done: | ||
| 362 | platform_device_unregister(pdev); | ||
| 363 | pr_debug("%s: butterfly probe, fail %d\n", p->name, status); | ||
| 364 | } | ||
| 365 | |||
| 366 | static void butterfly_detach(struct parport *p) | ||
| 367 | { | ||
| 368 | struct butterfly *pp; | ||
| 369 | struct platform_device *pdev; | ||
| 370 | int status; | ||
| 371 | |||
| 372 | /* FIXME this global is ugly ... but, how to quickly get from | ||
| 373 | * the parport to the "struct butterfly" associated with it? | ||
| 374 | * "old school" driver-internal device lists? | ||
| 375 | */ | ||
| 376 | if (!butterfly || butterfly->port != p) | ||
| 377 | return; | ||
| 378 | pp = butterfly; | ||
| 379 | butterfly = NULL; | ||
| 380 | |||
| 381 | #ifdef HAVE_USI | ||
| 382 | spi_unregister_device(pp->butterfly); | ||
| 383 | pp->butterfly = NULL; | ||
| 384 | #endif | ||
| 385 | spi_unregister_device(pp->dataflash); | ||
| 386 | pp->dataflash = NULL; | ||
| 387 | |||
| 388 | status = spi_bitbang_stop(&pp->bitbang); | ||
| 389 | |||
| 390 | /* turn off VCC */ | ||
| 391 | parport_write_data(pp->port, 0); | ||
| 392 | msleep(10); | ||
| 393 | |||
| 394 | parport_release(pp->pd); | ||
| 395 | parport_unregister_device(pp->pd); | ||
| 396 | |||
| 397 | pdev = to_platform_device(pp->bitbang.master->cdev.dev); | ||
| 398 | |||
| 399 | (void) spi_master_put(pp->bitbang.master); | ||
| 400 | |||
| 401 | platform_device_unregister(pdev); | ||
| 402 | } | ||
| 403 | |||
| 404 | static struct parport_driver butterfly_driver = { | ||
| 405 | .name = "spi_butterfly", | ||
| 406 | .attach = butterfly_attach, | ||
| 407 | .detach = butterfly_detach, | ||
| 408 | }; | ||
| 409 | |||
| 410 | |||
| 411 | static int __init butterfly_init(void) | ||
| 412 | { | ||
| 413 | return parport_register_driver(&butterfly_driver); | ||
| 414 | } | ||
| 415 | device_initcall(butterfly_init); | ||
| 416 | |||
| 417 | static void __exit butterfly_exit(void) | ||
| 418 | { | ||
| 419 | parport_unregister_driver(&butterfly_driver); | ||
| 420 | } | ||
| 421 | module_exit(butterfly_exit); | ||
| 422 | |||
| 423 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 9baa6296fc95..7af1883d4bf9 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c | |||
| @@ -207,7 +207,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 207 | ** urbs ** | 207 | ** urbs ** |
| 208 | ************/ | 208 | ************/ |
| 209 | 209 | ||
| 210 | static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) | 210 | static struct urb *usbatm_pop_urb(struct usbatm_channel *channel) |
| 211 | { | 211 | { |
| 212 | struct urb *urb; | 212 | struct urb *urb; |
| 213 | 213 | ||
| @@ -224,7 +224,7 @@ static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) | |||
| 224 | return urb; | 224 | return urb; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | static inline int usbatm_submit_urb(struct urb *urb) | 227 | static int usbatm_submit_urb(struct urb *urb) |
| 228 | { | 228 | { |
| 229 | struct usbatm_channel *channel = urb->context; | 229 | struct usbatm_channel *channel = urb->context; |
| 230 | int ret; | 230 | int ret; |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 8f402f85e1ca..afc84cfb61f9 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
| @@ -2534,9 +2534,6 @@ static struct usb_gadget_driver eth_driver = { | |||
| 2534 | .driver = { | 2534 | .driver = { |
| 2535 | .name = (char *) shortname, | 2535 | .name = (char *) shortname, |
| 2536 | .owner = THIS_MODULE, | 2536 | .owner = THIS_MODULE, |
| 2537 | // .shutdown = ... | ||
| 2538 | // .suspend = ... | ||
| 2539 | // .resume = ... | ||
| 2540 | }, | 2537 | }, |
| 2541 | }; | 2538 | }; |
| 2542 | 2539 | ||
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index c6c279de832e..9a4edc5657aa 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
| @@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs_driver = { | |||
| 1738 | 1738 | ||
| 1739 | .driver = { | 1739 | .driver = { |
| 1740 | .name = (char *) shortname, | 1740 | .name = (char *) shortname, |
| 1741 | // .shutdown = ... | ||
| 1742 | // .suspend = ... | ||
| 1743 | // .resume = ... | ||
| 1744 | }, | 1741 | }, |
| 1745 | }; | 1742 | }; |
| 1746 | 1743 | ||
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 2e6926b33455..ba9acd531024 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
| @@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadget_driver = { | |||
| 374 | .disconnect = gs_disconnect, | 374 | .disconnect = gs_disconnect, |
| 375 | .driver = { | 375 | .driver = { |
| 376 | .name = GS_SHORT_NAME, | 376 | .name = GS_SHORT_NAME, |
| 377 | /* .shutdown = ... */ | ||
| 378 | /* .suspend = ... */ | ||
| 379 | /* .resume = ... */ | ||
| 380 | }, | 377 | }, |
| 381 | }; | 378 | }; |
| 382 | 379 | ||
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6c58636e914b..2fc110d3ad5a 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
| @@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_driver = { | |||
| 1303 | .driver = { | 1303 | .driver = { |
| 1304 | .name = (char *) shortname, | 1304 | .name = (char *) shortname, |
| 1305 | .owner = THIS_MODULE, | 1305 | .owner = THIS_MODULE, |
| 1306 | // .shutdown = ... | ||
| 1307 | // .suspend = ... | ||
| 1308 | // .resume = ... | ||
| 1309 | }, | 1306 | }, |
| 1310 | }; | 1307 | }; |
| 1311 | 1308 | ||
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 509dd0a04c54..5246b35301de 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
| @@ -37,6 +37,16 @@ config USB_HIDINPUT | |||
| 37 | 37 | ||
| 38 | If unsure, say Y. | 38 | If unsure, say Y. |
| 39 | 39 | ||
| 40 | config USB_HIDINPUT_POWERBOOK | ||
| 41 | bool "Enable support for iBook/PowerBook special keys" | ||
| 42 | default n | ||
| 43 | depends on USB_HIDINPUT | ||
| 44 | help | ||
| 45 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
| 46 | Apple iBooks and PowerBooks. | ||
| 47 | |||
| 48 | If unsure, say N. | ||
| 49 | |||
| 40 | config HID_FF | 50 | config HID_FF |
| 41 | bool "Force feedback support (EXPERIMENTAL)" | 51 | bool "Force feedback support (EXPERIMENTAL)" |
| 42 | depends on USB_HIDINPUT && EXPERIMENTAL | 52 | depends on USB_HIDINPUT && EXPERIMENTAL |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5f52979af1c7..a91e72c41415 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
| @@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid) | |||
| 1450 | #define USB_VENDOR_ID_APPLE 0x05ac | 1450 | #define USB_VENDOR_ID_APPLE 0x05ac |
| 1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 | 1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 |
| 1452 | 1452 | ||
| 1453 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
| 1454 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
| 1455 | |||
| 1453 | /* | 1456 | /* |
| 1454 | * Alphabetically sorted blacklist by quirk type. | 1457 | * Alphabetically sorted blacklist by quirk type. |
| 1455 | */ | 1458 | */ |
| @@ -1580,6 +1583,16 @@ static const struct hid_blacklist { | |||
| 1580 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | 1583 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, |
| 1581 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | 1584 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, |
| 1582 | 1585 | ||
| 1586 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
| 1587 | |||
| 1588 | { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1589 | { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1590 | { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1591 | { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1592 | { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1593 | { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1594 | { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
| 1595 | |||
| 1583 | { 0, 0 } | 1596 | { 0, 0 } |
| 1584 | }; | 1597 | }; |
| 1585 | 1598 | ||
| @@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | |||
| 1626 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); | 1639 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); |
| 1627 | } | 1640 | } |
| 1628 | 1641 | ||
| 1642 | /* | ||
| 1643 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
| 1644 | * that needs fixing before we can parse it. | ||
| 1645 | */ | ||
| 1646 | |||
| 1647 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
| 1648 | { | ||
| 1649 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
| 1650 | info("Fixing up Cherry Cymotion report descriptor"); | ||
| 1651 | rdesc[11] = rdesc[16] = 0xff; | ||
| 1652 | rdesc[12] = rdesc[17] = 0x03; | ||
| 1653 | } | ||
| 1654 | } | ||
| 1655 | |||
| 1629 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 1656 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
| 1630 | { | 1657 | { |
| 1631 | struct usb_host_interface *interface = intf->cur_altsetting; | 1658 | struct usb_host_interface *interface = intf->cur_altsetting; |
| @@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
| 1673 | return NULL; | 1700 | return NULL; |
| 1674 | } | 1701 | } |
| 1675 | 1702 | ||
| 1703 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
| 1704 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
| 1705 | |||
| 1676 | #ifdef DEBUG_DATA | 1706 | #ifdef DEBUG_DATA |
| 1677 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | 1707 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |
| 1678 | for (n = 0; n < rsize; n++) | 1708 | for (n = 0; n < rsize; n++) |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 192a03b28971..cb0d80f49252 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
| @@ -73,6 +73,160 @@ static const struct { | |||
| 73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
| 74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) | 74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) |
| 75 | 75 | ||
| 76 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
| 77 | |||
| 78 | struct hidinput_key_translation { | ||
| 79 | u16 from; | ||
| 80 | u16 to; | ||
| 81 | u8 flags; | ||
| 82 | }; | ||
| 83 | |||
| 84 | #define POWERBOOK_FLAG_FKEY 0x01 | ||
| 85 | |||
| 86 | static struct hidinput_key_translation powerbook_fn_keys[] = { | ||
| 87 | { KEY_BACKSPACE, KEY_DELETE }, | ||
| 88 | { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, | ||
| 89 | { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, | ||
| 90 | { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, | ||
| 91 | { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, | ||
| 92 | { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, | ||
| 93 | { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, | ||
| 94 | { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, | ||
| 95 | { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, | ||
| 96 | { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, | ||
| 97 | { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, | ||
| 98 | { KEY_UP, KEY_PAGEUP }, | ||
| 99 | { KEY_DOWN, KEY_PAGEDOWN }, | ||
| 100 | { KEY_LEFT, KEY_HOME }, | ||
| 101 | { KEY_RIGHT, KEY_END }, | ||
| 102 | { } | ||
| 103 | }; | ||
| 104 | |||
| 105 | static struct hidinput_key_translation powerbook_numlock_keys[] = { | ||
| 106 | { KEY_J, KEY_KP1 }, | ||
| 107 | { KEY_K, KEY_KP2 }, | ||
| 108 | { KEY_L, KEY_KP3 }, | ||
| 109 | { KEY_U, KEY_KP4 }, | ||
| 110 | { KEY_I, KEY_KP5 }, | ||
| 111 | { KEY_O, KEY_KP6 }, | ||
| 112 | { KEY_7, KEY_KP7 }, | ||
| 113 | { KEY_8, KEY_KP8 }, | ||
| 114 | { KEY_9, KEY_KP9 }, | ||
| 115 | { KEY_M, KEY_KP0 }, | ||
| 116 | { KEY_DOT, KEY_KPDOT }, | ||
| 117 | { KEY_SLASH, KEY_KPPLUS }, | ||
| 118 | { KEY_SEMICOLON, KEY_KPMINUS }, | ||
| 119 | { KEY_P, KEY_KPASTERISK }, | ||
| 120 | { KEY_MINUS, KEY_KPEQUAL }, | ||
| 121 | { KEY_0, KEY_KPSLASH }, | ||
| 122 | { KEY_F6, KEY_NUMLOCK }, | ||
| 123 | { KEY_KPENTER, KEY_KPENTER }, | ||
| 124 | { KEY_BACKSPACE, KEY_BACKSPACE }, | ||
| 125 | { } | ||
| 126 | }; | ||
| 127 | |||
| 128 | static int usbhid_pb_fnmode = 1; | ||
| 129 | module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); | ||
| 130 | MODULE_PARM_DESC(pb_fnmode, | ||
| 131 | "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); | ||
| 132 | |||
| 133 | static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) | ||
| 134 | { | ||
| 135 | struct hidinput_key_translation *trans; | ||
| 136 | |||
| 137 | /* Look for the translation */ | ||
| 138 | for (trans = table; trans->from; trans++) | ||
| 139 | if (trans->from == from) | ||
| 140 | return trans; | ||
| 141 | |||
| 142 | return NULL; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
| 146 | struct hid_usage *usage, __s32 value) | ||
| 147 | { | ||
| 148 | struct hidinput_key_translation *trans; | ||
| 149 | |||
| 150 | if (usage->code == KEY_FN) { | ||
| 151 | if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON; | ||
| 152 | else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON; | ||
| 153 | |||
| 154 | input_event(input, usage->type, usage->code, value); | ||
| 155 | |||
| 156 | return 1; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (usbhid_pb_fnmode) { | ||
| 160 | int do_translate; | ||
| 161 | |||
| 162 | trans = find_translation(powerbook_fn_keys, usage->code); | ||
| 163 | if (trans) { | ||
| 164 | if (test_bit(usage->code, hid->pb_pressed_fn)) | ||
| 165 | do_translate = 1; | ||
| 166 | else if (trans->flags & POWERBOOK_FLAG_FKEY) | ||
| 167 | do_translate = | ||
| 168 | (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || | ||
| 169 | (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); | ||
| 170 | else | ||
| 171 | do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); | ||
| 172 | |||
| 173 | if (do_translate) { | ||
| 174 | if (value) | ||
| 175 | set_bit(usage->code, hid->pb_pressed_fn); | ||
| 176 | else | ||
| 177 | clear_bit(usage->code, hid->pb_pressed_fn); | ||
| 178 | |||
| 179 | input_event(input, usage->type, trans->to, value); | ||
| 180 | |||
| 181 | return 1; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | if (test_bit(usage->code, hid->pb_pressed_numlock) || | ||
| 186 | test_bit(LED_NUML, input->led)) { | ||
| 187 | trans = find_translation(powerbook_numlock_keys, usage->code); | ||
| 188 | |||
| 189 | if (trans) { | ||
| 190 | if (value) | ||
| 191 | set_bit(usage->code, hid->pb_pressed_numlock); | ||
| 192 | else | ||
| 193 | clear_bit(usage->code, hid->pb_pressed_numlock); | ||
| 194 | |||
| 195 | input_event(input, usage->type, trans->to, value); | ||
| 196 | } | ||
| 197 | |||
| 198 | return 1; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static void hidinput_pb_setup(struct input_dev *input) | ||
| 206 | { | ||
| 207 | struct hidinput_key_translation *trans; | ||
| 208 | |||
| 209 | set_bit(KEY_NUMLOCK, input->keybit); | ||
| 210 | |||
| 211 | /* Enable all needed keys */ | ||
| 212 | for (trans = powerbook_fn_keys; trans->from; trans++) | ||
| 213 | set_bit(trans->to, input->keybit); | ||
| 214 | |||
| 215 | for (trans = powerbook_numlock_keys; trans->from; trans++) | ||
| 216 | set_bit(trans->to, input->keybit); | ||
| 217 | } | ||
| 218 | #else | ||
| 219 | static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
| 220 | struct hid_usage *usage, __s32 value) | ||
| 221 | { | ||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static inline void hidinput_pb_setup(struct input_dev *input) | ||
| 226 | { | ||
| 227 | } | ||
| 228 | #endif | ||
| 229 | |||
| 76 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 230 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
| 77 | struct hid_usage *usage) | 231 | struct hid_usage *usage) |
| 78 | { | 232 | { |
| @@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 135 | case HID_UP_SIMULATION: | 289 | case HID_UP_SIMULATION: |
| 136 | 290 | ||
| 137 | switch (usage->hid & 0xffff) { | 291 | switch (usage->hid & 0xffff) { |
| 138 | case 0xba: map_abs(ABS_RUDDER); break; | 292 | case 0xba: map_abs(ABS_RUDDER); break; |
| 139 | case 0xbb: map_abs(ABS_THROTTLE); break; | 293 | case 0xbb: map_abs(ABS_THROTTLE); break; |
| 294 | case 0xc4: map_abs(ABS_GAS); break; | ||
| 295 | case 0xc5: map_abs(ABS_BRAKE); break; | ||
| 296 | case 0xc8: map_abs(ABS_WHEEL); break; | ||
| 140 | default: goto ignore; | 297 | default: goto ignore; |
| 141 | } | 298 | } |
| 142 | break; | 299 | break; |
| @@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 289 | case 0x226: map_key_clear(KEY_STOP); break; | 446 | case 0x226: map_key_clear(KEY_STOP); break; |
| 290 | case 0x227: map_key_clear(KEY_REFRESH); break; | 447 | case 0x227: map_key_clear(KEY_REFRESH); break; |
| 291 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; | 448 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; |
| 449 | case 0x233: map_key_clear(KEY_SCROLLUP); break; | ||
| 450 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; | ||
| 292 | case 0x238: map_rel(REL_HWHEEL); break; | 451 | case 0x238: map_rel(REL_HWHEEL); break; |
| 293 | case 0x279: map_key_clear(KEY_REDO); break; | 452 | case 0x279: map_key_clear(KEY_REDO); break; |
| 294 | case 0x289: map_key_clear(KEY_REPLY); break; | 453 | case 0x289: map_key_clear(KEY_REPLY); break; |
| 295 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; | 454 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; |
| 296 | case 0x28c: map_key_clear(KEY_SEND); break; | 455 | case 0x28c: map_key_clear(KEY_SEND); break; |
| 456 | |||
| 457 | /* Reported on a Cherry Cymotion keyboard */ | ||
| 458 | case 0x301: map_key_clear(KEY_PROG1); break; | ||
| 459 | case 0x302: map_key_clear(KEY_PROG2); break; | ||
| 460 | case 0x303: map_key_clear(KEY_PROG3); break; | ||
| 461 | |||
| 297 | default: goto ignore; | 462 | default: goto ignore; |
| 298 | } | 463 | } |
| 299 | break; | 464 | break; |
| @@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 325 | 490 | ||
| 326 | set_bit(EV_REP, input->evbit); | 491 | set_bit(EV_REP, input->evbit); |
| 327 | switch(usage->hid & HID_USAGE) { | 492 | switch(usage->hid & HID_USAGE) { |
| 328 | case 0x003: map_key_clear(KEY_FN); break; | 493 | case 0x003: |
| 494 | /* The fn key on Apple PowerBooks */ | ||
| 495 | map_key_clear(KEY_FN); | ||
| 496 | hidinput_pb_setup(input); | ||
| 497 | break; | ||
| 498 | |||
| 329 | default: goto ignore; | 499 | default: goto ignore; |
| 330 | } | 500 | } |
| 331 | break; | 501 | break; |
| @@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
| 482 | return; | 652 | return; |
| 483 | } | 653 | } |
| 484 | 654 | ||
| 655 | if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value)) | ||
| 656 | return; | ||
| 657 | |||
| 485 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 658 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
| 486 | int hat_dir = usage->hat_dir; | 659 | int hat_dir = usage->hat_dir; |
| 487 | if (!hat_dir) | 660 | if (!hat_dir) |
| @@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
| 524 | return; | 697 | return; |
| 525 | } | 698 | } |
| 526 | 699 | ||
| 527 | if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ | 700 | if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ |
| 528 | return; | 701 | return; |
| 529 | 702 | ||
| 530 | input_event(input, usage->type, usage->code, value); | 703 | input_event(input, usage->type, usage->code, value); |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ee48a2276104..8b0d4346ce9c 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
| @@ -235,17 +235,20 @@ struct hid_item { | |||
| 235 | * HID device quirks. | 235 | * HID device quirks. |
| 236 | */ | 236 | */ |
| 237 | 237 | ||
| 238 | #define HID_QUIRK_INVERT 0x001 | 238 | #define HID_QUIRK_INVERT 0x00000001 |
| 239 | #define HID_QUIRK_NOTOUCH 0x002 | 239 | #define HID_QUIRK_NOTOUCH 0x00000002 |
| 240 | #define HID_QUIRK_IGNORE 0x004 | 240 | #define HID_QUIRK_IGNORE 0x00000004 |
| 241 | #define HID_QUIRK_NOGET 0x008 | 241 | #define HID_QUIRK_NOGET 0x00000008 |
| 242 | #define HID_QUIRK_HIDDEV 0x010 | 242 | #define HID_QUIRK_HIDDEV 0x00000010 |
| 243 | #define HID_QUIRK_BADPAD 0x020 | 243 | #define HID_QUIRK_BADPAD 0x00000020 |
| 244 | #define HID_QUIRK_MULTI_INPUT 0x040 | 244 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
| 245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 | 245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 |
| 246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 | 246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 |
| 247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 | 247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 |
| 248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 | 248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 |
| 249 | #define HID_QUIRK_CYMOTION 0x00000800 | ||
| 250 | #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 | ||
| 251 | #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 | ||
| 249 | 252 | ||
| 250 | /* | 253 | /* |
| 251 | * This is the global environment of the parser. This information is | 254 | * This is the global environment of the parser. This information is |
| @@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */ | |||
| 431 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ | 434 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ |
| 432 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, | 435 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, |
| 433 | unsigned int type, unsigned int code, int value); | 436 | unsigned int type, unsigned int code, int value); |
| 437 | |||
| 438 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
| 439 | unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; | ||
| 440 | unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; | ||
| 441 | #endif | ||
| 434 | }; | 442 | }; |
| 435 | 443 | ||
| 436 | #define HID_GLOBAL_STACK_SIZE 4 | 444 | #define HID_GLOBAL_STACK_SIZE 4 |
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index 19e015d171aa..d9d9f656b8c9 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c | |||
| @@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, | |||
| 259 | int hid_pid_init(struct hid_device *hid) | 259 | int hid_pid_init(struct hid_device *hid) |
| 260 | { | 260 | { |
| 261 | struct hid_ff_pid *private; | 261 | struct hid_ff_pid *private; |
| 262 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); | 262 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); |
| 263 | struct input_dev *input_dev = hidinput->input; | 263 | struct input_dev *input_dev = hidinput->input; |
| 264 | 264 | ||
| 265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); | 265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 48df4cfd5a42..d3e15df9e815 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
| @@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
| 95 | enum { | 95 | enum { |
| 96 | PENPARTNER = 0, | 96 | PENPARTNER = 0, |
| 97 | GRAPHIRE, | 97 | GRAPHIRE, |
| 98 | G4, | 98 | WACOM_G4, |
| 99 | PL, | 99 | PL, |
| 100 | INTUOS, | 100 | INTUOS, |
| 101 | INTUOS3, | 101 | INTUOS3, |
| @@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
| 373 | 373 | ||
| 374 | case 2: /* Mouse with wheel */ | 374 | case 2: /* Mouse with wheel */ |
| 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
| 376 | if (wacom->features->type == G4) { | 376 | if (wacom->features->type == WACOM_G4) { |
| 377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); | 377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); |
| 378 | input_report_rel(dev, REL_WHEEL, rw); | 378 | input_report_rel(dev, REL_WHEEL, rw); |
| 379 | } else | 379 | } else |
| @@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
| 385 | id = CURSOR_DEVICE_ID; | 385 | id = CURSOR_DEVICE_ID; |
| 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); |
| 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); |
| 388 | if (wacom->features->type == G4) | 388 | if (wacom->features->type == WACOM_G4) |
| 389 | input_report_abs(dev, ABS_DISTANCE, data[6]); | 389 | input_report_abs(dev, ABS_DISTANCE, data[6]); |
| 390 | else | 390 | else |
| 391 | input_report_abs(dev, ABS_DISTANCE, data[7]); | 391 | input_report_abs(dev, ABS_DISTANCE, data[7]); |
| @@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
| 410 | input_sync(dev); | 410 | input_sync(dev); |
| 411 | 411 | ||
| 412 | /* send pad data */ | 412 | /* send pad data */ |
| 413 | if (wacom->features->type == G4) { | 413 | if (wacom->features->type == WACOM_G4) { |
| 414 | /* fist time sending pad data */ | 414 | /* fist time sending pad data */ |
| 415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { | 415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
| 416 | wacom->id[1] = 0; | 416 | wacom->id[1] = 0; |
| @@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = { | |||
| 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, | 716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, |
| 717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, | 717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, |
| 718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| 719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | 719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, |
| 720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
| @@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); | 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); |
| 860 | 860 | ||
| 861 | switch (wacom->features->type) { | 861 | switch (wacom->features->type) { |
| 862 | case G4: | 862 | case WACOM_G4: |
| 863 | input_dev->evbit[0] |= BIT(EV_MSC); | 863 | input_dev->evbit[0] |= BIT(EV_MSC); |
| 864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | 864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); |
| 865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | 865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 664139afcfa9..e9f9f4bafa17 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
| @@ -37,11 +37,6 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr | |||
| 37 | return 0; | 37 | return 0; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | struct bus_type usb_serial_bus_type = { | ||
| 41 | .name = "usb-serial", | ||
| 42 | .match = usb_serial_device_match, | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int usb_serial_device_probe (struct device *dev) | 40 | static int usb_serial_device_probe (struct device *dev) |
| 46 | { | 41 | { |
| 47 | struct usb_serial_driver *driver; | 42 | struct usb_serial_driver *driver; |
| @@ -109,14 +104,18 @@ exit: | |||
| 109 | return retval; | 104 | return retval; |
| 110 | } | 105 | } |
| 111 | 106 | ||
| 107 | struct bus_type usb_serial_bus_type = { | ||
| 108 | .name = "usb-serial", | ||
| 109 | .match = usb_serial_device_match, | ||
| 110 | .probe = usb_serial_device_probe, | ||
| 111 | .remove = usb_serial_device_remove, | ||
| 112 | }; | ||
| 113 | |||
| 112 | int usb_serial_bus_register(struct usb_serial_driver *driver) | 114 | int usb_serial_bus_register(struct usb_serial_driver *driver) |
| 113 | { | 115 | { |
| 114 | int retval; | 116 | int retval; |
| 115 | 117 | ||
| 116 | driver->driver.bus = &usb_serial_bus_type; | 118 | driver->driver.bus = &usb_serial_bus_type; |
| 117 | driver->driver.probe = usb_serial_device_probe; | ||
| 118 | driver->driver.remove = usb_serial_device_remove; | ||
| 119 | |||
| 120 | retval = driver_register(&driver->driver); | 119 | retval = driver_register(&driver->driver); |
| 121 | 120 | ||
| 122 | return retval; | 121 | return retval; |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9ffff1938239..0eb883f44ada 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
| @@ -43,8 +43,6 @@ static int debug; | |||
| 43 | #define PL2303_BUF_SIZE 1024 | 43 | #define PL2303_BUF_SIZE 1024 |
| 44 | #define PL2303_TMP_BUF_SIZE 1024 | 44 | #define PL2303_TMP_BUF_SIZE 1024 |
| 45 | 45 | ||
| 46 | static DECLARE_MUTEX(pl2303_tmp_buf_sem); | ||
| 47 | |||
| 48 | struct pl2303_buf { | 46 | struct pl2303_buf { |
| 49 | unsigned int buf_size; | 47 | unsigned int buf_size; |
| 50 | char *buf_buf; | 48 | char *buf_buf; |
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 3b0ddc55236b..78488bb41aeb 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c | |||
| @@ -102,8 +102,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 102 | u_int transp, struct fb_info *info); | 102 | u_int transp, struct fb_info *info); |
| 103 | static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, | 103 | static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, |
| 104 | struct fb_info *info); | 104 | struct fb_info *info); |
| 105 | static int mc68x328fb_mmap(struct fb_info *info, struct file *file, | 105 | static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma); |
| 106 | struct vm_area_struct *vma); | ||
| 107 | 106 | ||
| 108 | static struct fb_ops mc68x328fb_ops = { | 107 | static struct fb_ops mc68x328fb_ops = { |
| 109 | .fb_check_var = mc68x328fb_check_var, | 108 | .fb_check_var = mc68x328fb_check_var, |
| @@ -398,8 +397,7 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, | |||
| 398 | * Most drivers don't need their own mmap function | 397 | * Most drivers don't need their own mmap function |
| 399 | */ | 398 | */ |
| 400 | 399 | ||
| 401 | static int mc68x328fb_mmap(struct fb_info *info, struct file *file, | 400 | static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 402 | struct vm_area_struct *vma) | ||
| 403 | { | 401 | { |
| 404 | #ifndef MMU | 402 | #ifndef MMU |
| 405 | /* this is uClinux (no MMU) specific code */ | 403 | /* this is uClinux (no MMU) specific code */ |
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 750cebb18306..b058273527bb 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c | |||
| @@ -883,7 +883,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 883 | * Note that we are entered with the kernel locked. | 883 | * Note that we are entered with the kernel locked. |
| 884 | */ | 884 | */ |
| 885 | static int | 885 | static int |
| 886 | acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 886 | acornfb_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 887 | { | 887 | { |
| 888 | unsigned long off, start; | 888 | unsigned long off, start; |
| 889 | u32 len; | 889 | u32 len; |
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 0da4083ba908..b2187175d03f 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
| @@ -307,7 +307,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info) | |||
| 307 | return 0; | 307 | return 0; |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | static int clcdfb_mmap(struct fb_info *info, struct file *file, | 310 | static int clcdfb_mmap(struct fb_info *info, |
| 311 | struct vm_area_struct *vma) | 311 | struct vm_area_struct *vma) |
| 312 | { | 312 | { |
| 313 | struct clcd_fb *fb = to_clcd(info); | 313 | struct clcd_fb *fb = to_clcd(info); |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 2c42a812655a..3033c72dea20 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
| @@ -1131,9 +1131,7 @@ static void amifb_copyarea(struct fb_info *info, | |||
| 1131 | const struct fb_copyarea *region); | 1131 | const struct fb_copyarea *region); |
| 1132 | static void amifb_imageblit(struct fb_info *info, | 1132 | static void amifb_imageblit(struct fb_info *info, |
| 1133 | const struct fb_image *image); | 1133 | const struct fb_image *image); |
| 1134 | static int amifb_ioctl(struct inode *inode, struct file *file, | 1134 | static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); |
| 1135 | unsigned int cmd, unsigned long arg, | ||
| 1136 | struct fb_info *info); | ||
| 1137 | 1135 | ||
| 1138 | 1136 | ||
| 1139 | /* | 1137 | /* |
| @@ -2172,9 +2170,8 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
| 2172 | * Amiga Frame Buffer Specific ioctls | 2170 | * Amiga Frame Buffer Specific ioctls |
| 2173 | */ | 2171 | */ |
| 2174 | 2172 | ||
| 2175 | static int amifb_ioctl(struct inode *inode, struct file *file, | 2173 | static int amifb_ioctl(struct fb_info *info, |
| 2176 | unsigned int cmd, unsigned long arg, | 2174 | unsigned int cmd, unsigned long arg) |
| 2177 | struct fb_info *info) | ||
| 2178 | { | 2175 | { |
| 2179 | union { | 2176 | union { |
| 2180 | struct fb_fix_cursorinfo fix; | 2177 | struct fb_fix_cursorinfo fix; |
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 89060b2db8e5..df8e5667b348 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c | |||
| @@ -399,9 +399,8 @@ static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
| 399 | image->height); | 399 | image->height); |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | static int arcfb_ioctl(struct inode *inode, struct file *file, | 402 | static int arcfb_ioctl(struct fb_info *info, |
| 403 | unsigned int cmd, unsigned long arg, | 403 | unsigned int cmd, unsigned long arg) |
| 404 | struct fb_info *info) | ||
| 405 | { | 404 | { |
| 406 | void __user *argp = (void __user *)arg; | 405 | void __user *argp = (void __user *)arg; |
| 407 | struct arcfb_par *par = info->par; | 406 | struct arcfb_par *par = info->par; |
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 15ec1295bc29..e69ab65f7843 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
| @@ -2571,8 +2571,7 @@ atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) | |||
| 2571 | } | 2571 | } |
| 2572 | 2572 | ||
| 2573 | static int | 2573 | static int |
| 2574 | atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 2574 | atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 2575 | unsigned long arg, int con, struct fb_info *info) | ||
| 2576 | { | 2575 | { |
| 2577 | switch (cmd) { | 2576 | switch (cmd) { |
| 2578 | #ifdef FBCMD_GET_CURRENTPAR | 2577 | #ifdef FBCMD_GET_CURRENTPAR |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e686185a076d..bfc8a93b2c73 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
| @@ -431,8 +431,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 431 | static int aty128fb_pan_display(struct fb_var_screeninfo *var, | 431 | static int aty128fb_pan_display(struct fb_var_screeninfo *var, |
| 432 | struct fb_info *fb); | 432 | struct fb_info *fb); |
| 433 | static int aty128fb_blank(int blank, struct fb_info *fb); | 433 | static int aty128fb_blank(int blank, struct fb_info *fb); |
| 434 | static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | 434 | static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg); |
| 435 | u_long arg, struct fb_info *info); | ||
| 436 | static int aty128fb_sync(struct fb_info *info); | 435 | static int aty128fb_sync(struct fb_info *info); |
| 437 | 436 | ||
| 438 | /* | 437 | /* |
| @@ -2108,8 +2107,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 2108 | /* in param: u32* backlight value: 0 to 15 */ | 2107 | /* in param: u32* backlight value: 0 to 15 */ |
| 2109 | #define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32) | 2108 | #define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32) |
| 2110 | 2109 | ||
| 2111 | static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | 2110 | static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
| 2112 | u_long arg, struct fb_info *info) | ||
| 2113 | { | 2111 | { |
| 2114 | struct aty128fb_par *par = info->par; | 2112 | struct aty128fb_par *par = info->par; |
| 2115 | u32 value; | 2113 | u32 value; |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index ed81005cbdba..485be386a8ff 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
| @@ -238,13 +238,12 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 238 | u_int transp, struct fb_info *info); | 238 | u_int transp, struct fb_info *info); |
| 239 | static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); | 239 | static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); |
| 240 | static int atyfb_blank(int blank, struct fb_info *info); | 240 | static int atyfb_blank(int blank, struct fb_info *info); |
| 241 | static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, | 241 | static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); |
| 242 | u_long arg, struct fb_info *info); | ||
| 243 | extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | 242 | extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
| 244 | extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); | 243 | extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); |
| 245 | extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); | 244 | extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); |
| 246 | #ifdef __sparc__ | 245 | #ifdef __sparc__ |
| 247 | static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); | 246 | static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); |
| 248 | #endif | 247 | #endif |
| 249 | static int atyfb_sync(struct fb_info *info); | 248 | static int atyfb_sync(struct fb_info *info); |
| 250 | 249 | ||
| @@ -1739,8 +1738,7 @@ struct atyclk { | |||
| 1739 | #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) | 1738 | #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) |
| 1740 | #endif | 1739 | #endif |
| 1741 | 1740 | ||
| 1742 | static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, | 1741 | static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
| 1743 | u_long arg, struct fb_info *info) | ||
| 1744 | { | 1742 | { |
| 1745 | struct atyfb_par *par = (struct atyfb_par *) info->par; | 1743 | struct atyfb_par *par = (struct atyfb_par *) info->par; |
| 1746 | #ifdef __sparc__ | 1744 | #ifdef __sparc__ |
| @@ -1845,7 +1843,7 @@ static int atyfb_sync(struct fb_info *info) | |||
| 1845 | } | 1843 | } |
| 1846 | 1844 | ||
| 1847 | #ifdef __sparc__ | 1845 | #ifdef __sparc__ |
| 1848 | static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 1846 | static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 1849 | { | 1847 | { |
| 1850 | struct atyfb_par *par = (struct atyfb_par *) info->par; | 1848 | struct atyfb_par *par = (struct atyfb_par *) info->par; |
| 1851 | unsigned int size, page, map_size = 0; | 1849 | unsigned int size, page, map_size = 0; |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 156db84cb363..c9f0c5a07e6e 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
| @@ -864,8 +864,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, | |||
| 864 | } | 864 | } |
| 865 | 865 | ||
| 866 | 866 | ||
| 867 | static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, | 867 | static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, |
| 868 | unsigned long arg, struct fb_info *info) | 868 | unsigned long arg) |
| 869 | { | 869 | { |
| 870 | struct radeonfb_info *rinfo = info->par; | 870 | struct radeonfb_info *rinfo = info->par; |
| 871 | unsigned int tmp; | 871 | unsigned int tmp; |
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index a5129806172f..2406899f1207 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c | |||
| @@ -379,7 +379,7 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle) | |||
| 379 | * Map video memory in user space. We don't use the generic fb_mmap method mainly | 379 | * Map video memory in user space. We don't use the generic fb_mmap method mainly |
| 380 | * to allow the use of the TLB streaming flag (CCA=6) | 380 | * to allow the use of the TLB streaming flag (CCA=6) |
| 381 | */ | 381 | */ |
| 382 | int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) | 382 | int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) |
| 383 | { | 383 | { |
| 384 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | 384 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); |
| 385 | unsigned int len; | 385 | unsigned int len; |
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 9248fe1fbb1a..c029db4646f6 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
| @@ -35,9 +35,8 @@ | |||
| 35 | 35 | ||
| 36 | static int bw2_blank(int, struct fb_info *); | 36 | static int bw2_blank(int, struct fb_info *); |
| 37 | 37 | ||
| 38 | static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 38 | static int bw2_mmap(struct fb_info *, struct vm_area_struct *); |
| 39 | static int bw2_ioctl(struct inode *, struct file *, unsigned int, | 39 | static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 40 | unsigned long, struct fb_info *); | ||
| 41 | 40 | ||
| 42 | /* | 41 | /* |
| 43 | * Frame buffer operations | 42 | * Frame buffer operations |
| @@ -169,7 +168,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = { | |||
| 169 | { .size = 0 } | 168 | { .size = 0 } |
| 170 | }; | 169 | }; |
| 171 | 170 | ||
| 172 | static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 171 | static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 173 | { | 172 | { |
| 174 | struct bw2_par *par = (struct bw2_par *)info->par; | 173 | struct bw2_par *par = (struct bw2_par *)info->par; |
| 175 | 174 | ||
| @@ -181,8 +180,7 @@ static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_stru | |||
| 181 | vma); | 180 | vma); |
| 182 | } | 181 | } |
| 183 | 182 | ||
| 184 | static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 183 | static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 185 | unsigned long arg, struct fb_info *info) | ||
| 186 | { | 184 | { |
| 187 | struct bw2_par *par = (struct bw2_par *) info->par; | 185 | struct bw2_par *par = (struct bw2_par *) info->par; |
| 188 | 186 | ||
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index a56147102abb..63b6c79c8a0a 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
| @@ -31,9 +31,8 @@ | |||
| 31 | static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, | 31 | static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, |
| 32 | unsigned, struct fb_info *); | 32 | unsigned, struct fb_info *); |
| 33 | 33 | ||
| 34 | static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 34 | static int cg14_mmap(struct fb_info *, struct vm_area_struct *); |
| 35 | static int cg14_ioctl(struct inode *, struct file *, unsigned int, | 35 | static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 36 | unsigned long, struct fb_info *); | ||
| 37 | static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); | 36 | static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); |
| 38 | 37 | ||
| 39 | /* | 38 | /* |
| @@ -268,7 +267,7 @@ static int cg14_setcolreg(unsigned regno, | |||
| 268 | return 0; | 267 | return 0; |
| 269 | } | 268 | } |
| 270 | 269 | ||
| 271 | static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 270 | static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 272 | { | 271 | { |
| 273 | struct cg14_par *par = (struct cg14_par *) info->par; | 272 | struct cg14_par *par = (struct cg14_par *) info->par; |
| 274 | 273 | ||
| @@ -277,8 +276,7 @@ static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_str | |||
| 277 | par->iospace, vma); | 276 | par->iospace, vma); |
| 278 | } | 277 | } |
| 279 | 278 | ||
| 280 | static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 279 | static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 281 | unsigned long arg, struct fb_info *info) | ||
| 282 | { | 280 | { |
| 283 | struct cg14_par *par = (struct cg14_par *) info->par; | 281 | struct cg14_par *par = (struct cg14_par *) info->par; |
| 284 | struct cg14_regs __iomem *regs = par->regs; | 282 | struct cg14_regs __iomem *regs = par->regs; |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 9fcd89608ed7..3de6e1b5ab2f 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
| @@ -33,9 +33,8 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, | |||
| 33 | unsigned, struct fb_info *); | 33 | unsigned, struct fb_info *); |
| 34 | static int cg3_blank(int, struct fb_info *); | 34 | static int cg3_blank(int, struct fb_info *); |
| 35 | 35 | ||
| 36 | static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 36 | static int cg3_mmap(struct fb_info *, struct vm_area_struct *); |
| 37 | static int cg3_ioctl(struct inode *, struct file *, unsigned int, | 37 | static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 38 | unsigned long, struct fb_info *); | ||
| 39 | 38 | ||
| 40 | /* | 39 | /* |
| 41 | * Frame buffer operations | 40 | * Frame buffer operations |
| @@ -230,7 +229,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = { | |||
| 230 | { .size = 0 } | 229 | { .size = 0 } |
| 231 | }; | 230 | }; |
| 232 | 231 | ||
| 233 | static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 232 | static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 234 | { | 233 | { |
| 235 | struct cg3_par *par = (struct cg3_par *)info->par; | 234 | struct cg3_par *par = (struct cg3_par *)info->par; |
| 236 | 235 | ||
| @@ -240,8 +239,7 @@ static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_stru | |||
| 240 | vma); | 239 | vma); |
| 241 | } | 240 | } |
| 242 | 241 | ||
| 243 | static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 242 | static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 244 | unsigned long arg, struct fb_info *info) | ||
| 245 | { | 243 | { |
| 246 | struct cg3_par *par = (struct cg3_par *) info->par; | 244 | struct cg3_par *par = (struct cg3_par *) info->par; |
| 247 | 245 | ||
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 050835e39aa3..7aab91ead681 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
| @@ -36,9 +36,8 @@ static int cg6_blank(int, struct fb_info *); | |||
| 36 | static void cg6_imageblit(struct fb_info *, const struct fb_image *); | 36 | static void cg6_imageblit(struct fb_info *, const struct fb_image *); |
| 37 | static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); | 37 | static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); |
| 38 | static int cg6_sync(struct fb_info *); | 38 | static int cg6_sync(struct fb_info *); |
| 39 | static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 39 | static int cg6_mmap(struct fb_info *, struct vm_area_struct *); |
| 40 | static int cg6_ioctl(struct inode *, struct file *, unsigned int, | 40 | static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 41 | unsigned long, struct fb_info *); | ||
| 42 | 41 | ||
| 43 | /* | 42 | /* |
| 44 | * Frame buffer operations | 43 | * Frame buffer operations |
| @@ -524,7 +523,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = { | |||
| 524 | { .size = 0 } | 523 | { .size = 0 } |
| 525 | }; | 524 | }; |
| 526 | 525 | ||
| 527 | static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 526 | static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 528 | { | 527 | { |
| 529 | struct cg6_par *par = (struct cg6_par *)info->par; | 528 | struct cg6_par *par = (struct cg6_par *)info->par; |
| 530 | 529 | ||
| @@ -534,8 +533,7 @@ static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_stru | |||
| 534 | vma); | 533 | vma); |
| 535 | } | 534 | } |
| 536 | 535 | ||
| 537 | static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 536 | static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 538 | unsigned long arg, struct fb_info *info) | ||
| 539 | { | 537 | { |
| 540 | struct cg6_par *par = (struct cg6_par *) info->par; | 538 | struct cg6_par *par = (struct cg6_par *) info->par; |
| 541 | 539 | ||
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 03798e9c882d..655301a8671c 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
| @@ -128,7 +128,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, | |||
| 128 | static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | 128 | static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, |
| 129 | u_int transp, struct fb_info *info); | 129 | u_int transp, struct fb_info *info); |
| 130 | static int controlfb_blank(int blank_mode, struct fb_info *info); | 130 | static int controlfb_blank(int blank_mode, struct fb_info *info); |
| 131 | static int controlfb_mmap(struct fb_info *info, struct file *file, | 131 | static int controlfb_mmap(struct fb_info *info, |
| 132 | struct vm_area_struct *vma); | 132 | struct vm_area_struct *vma); |
| 133 | static int controlfb_set_par (struct fb_info *info); | 133 | static int controlfb_set_par (struct fb_info *info); |
| 134 | static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); | 134 | static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); |
| @@ -280,7 +280,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, | |||
| 280 | * for controlfb. | 280 | * for controlfb. |
| 281 | * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. | 281 | * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. |
| 282 | */ | 282 | */ |
| 283 | static int controlfb_mmap(struct fb_info *info, struct file *file, | 283 | static int controlfb_mmap(struct fb_info *info, |
| 284 | struct vm_area_struct *vma) | 284 | struct vm_area_struct *vma) |
| 285 | { | 285 | { |
| 286 | unsigned long off, start; | 286 | unsigned long off, start; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 32a9b69becc5..d2dede6ed3e5 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -957,7 +957,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 957 | default: | 957 | default: |
| 958 | if (fb->fb_ioctl == NULL) | 958 | if (fb->fb_ioctl == NULL) |
| 959 | return -EINVAL; | 959 | return -EINVAL; |
| 960 | return fb->fb_ioctl(inode, file, cmd, arg, info); | 960 | return fb->fb_ioctl(info, cmd, arg); |
| 961 | } | 961 | } |
| 962 | } | 962 | } |
| 963 | 963 | ||
| @@ -1107,7 +1107,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 1107 | 1107 | ||
| 1108 | default: | 1108 | default: |
| 1109 | if (fb->fb_compat_ioctl) | 1109 | if (fb->fb_compat_ioctl) |
| 1110 | ret = fb->fb_compat_ioctl(file, cmd, arg, info); | 1110 | ret = fb->fb_compat_ioctl(info, cmd, arg); |
| 1111 | break; | 1111 | break; |
| 1112 | } | 1112 | } |
| 1113 | unlock_kernel(); | 1113 | unlock_kernel(); |
| @@ -1135,7 +1135,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) | |||
| 1135 | if (fb->fb_mmap) { | 1135 | if (fb->fb_mmap) { |
| 1136 | int res; | 1136 | int res; |
| 1137 | lock_kernel(); | 1137 | lock_kernel(); |
| 1138 | res = fb->fb_mmap(info, file, vma); | 1138 | res = fb->fb_mmap(info, vma); |
| 1139 | unlock_kernel(); | 1139 | unlock_kernel(); |
| 1140 | return res; | 1140 | return res; |
| 1141 | } | 1141 | } |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index c4870d559afc..9c9b21d469a1 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
| @@ -37,9 +37,8 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *); | |||
| 37 | static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); | 37 | static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); |
| 38 | static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); | 38 | static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); |
| 39 | static int ffb_sync(struct fb_info *); | 39 | static int ffb_sync(struct fb_info *); |
| 40 | static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 40 | static int ffb_mmap(struct fb_info *, struct vm_area_struct *); |
| 41 | static int ffb_ioctl(struct inode *, struct file *, unsigned int, | 41 | static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 42 | unsigned long, struct fb_info *); | ||
| 43 | static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); | 42 | static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); |
| 44 | 43 | ||
| 45 | /* | 44 | /* |
| @@ -839,7 +838,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = { | |||
| 839 | { .size = 0 } | 838 | { .size = 0 } |
| 840 | }; | 839 | }; |
| 841 | 840 | ||
| 842 | static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 841 | static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 843 | { | 842 | { |
| 844 | struct ffb_par *par = (struct ffb_par *)info->par; | 843 | struct ffb_par *par = (struct ffb_par *)info->par; |
| 845 | 844 | ||
| @@ -848,8 +847,7 @@ static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_stru | |||
| 848 | 0, vma); | 847 | 0, vma); |
| 849 | } | 848 | } |
| 850 | 849 | ||
| 851 | static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 850 | static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 852 | unsigned long arg, struct fb_info *info) | ||
| 853 | { | 851 | { |
| 854 | struct ffb_par *par = (struct ffb_par *) info->par; | 852 | struct ffb_par *par = (struct ffb_par *) info->par; |
| 855 | 853 | ||
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index d744c51807b7..38d22729b129 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c | |||
| @@ -979,7 +979,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 979 | return 0; | 979 | return 0; |
| 980 | } | 980 | } |
| 981 | 981 | ||
| 982 | static int gbefb_mmap(struct fb_info *info, struct file *file, | 982 | static int gbefb_mmap(struct fb_info *info, |
| 983 | struct vm_area_struct *vma) | 983 | struct vm_area_struct *vma) |
| 984 | { | 984 | { |
| 985 | unsigned long size = vma->vm_end - vma->vm_start; | 985 | unsigned long size = vma->vm_end - vma->vm_start; |
| @@ -1000,7 +1000,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file, | |||
| 1000 | pgprot_fb(pgprot_val(vma->vm_page_prot)); | 1000 | pgprot_fb(pgprot_val(vma->vm_page_prot)); |
| 1001 | 1001 | ||
| 1002 | vma->vm_flags |= VM_IO | VM_RESERVED; | 1002 | vma->vm_flags |= VM_IO | VM_RESERVED; |
| 1003 | vma->vm_file = file; | ||
| 1004 | 1003 | ||
| 1005 | /* look for the starting tile */ | 1004 | /* look for the starting tile */ |
| 1006 | tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; | 1005 | tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; |
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 8e8da7433994..20e69156d728 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c | |||
| @@ -215,11 +215,11 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d | |||
| 215 | if (ret < 0) | 215 | if (ret < 0) |
| 216 | return ret; | 216 | return ret; |
| 217 | 217 | ||
| 218 | ret = pci_request_region(dev, 1, "gx1fb (video)"); | 218 | ret = pci_request_region(dev, 0, "gx1fb (video)"); |
| 219 | if (ret < 0) | 219 | if (ret < 0) |
| 220 | return ret; | 220 | return ret; |
| 221 | par->vid_regs = ioremap(pci_resource_start(dev, 1), | 221 | par->vid_regs = ioremap(pci_resource_start(dev, 0), |
| 222 | pci_resource_len(dev, 1)); | 222 | pci_resource_len(dev, 0)); |
| 223 | if (!par->vid_regs) | 223 | if (!par->vid_regs) |
| 224 | return -ENOMEM; | 224 | return -ENOMEM; |
| 225 | 225 | ||
| @@ -229,12 +229,9 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d | |||
| 229 | if (!par->dc_regs) | 229 | if (!par->dc_regs) |
| 230 | return -ENOMEM; | 230 | return -ENOMEM; |
| 231 | 231 | ||
| 232 | ret = pci_request_region(dev, 0, "gx1fb (frame buffer)"); | ||
| 233 | if (ret < 0 ) | ||
| 234 | return -EBUSY; | ||
| 235 | if ((fb_len = gx1_frame_buffer_size()) < 0) | 232 | if ((fb_len = gx1_frame_buffer_size()) < 0) |
| 236 | return -ENOMEM; | 233 | return -ENOMEM; |
| 237 | info->fix.smem_start = pci_resource_start(dev, 0); | 234 | info->fix.smem_start = gx_base + 0x800000; |
| 238 | info->fix.smem_len = fb_len; | 235 | info->fix.smem_len = fb_len; |
| 239 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | 236 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); |
| 240 | if (!info->screen_base) | 237 | if (!info->screen_base) |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index e326f44f652d..6b88050d21bf 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
| @@ -219,7 +219,7 @@ static void iga_blank_border(struct iga_par *par) | |||
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | #ifdef __sparc__ | 221 | #ifdef __sparc__ |
| 222 | static int igafb_mmap(struct fb_info *info, struct file *file, | 222 | static int igafb_mmap(struct fb_info *info, |
| 223 | struct vm_area_struct *vma) | 223 | struct vm_area_struct *vma) |
| 224 | { | 224 | { |
| 225 | struct iga_par *par = (struct iga_par *)info->par; | 225 | struct iga_par *par = (struct iga_par *)info->par; |
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index a5d813050db5..ad416ae47596 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c | |||
| @@ -1267,8 +1267,7 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
| 1267 | #define FBIMSTT_GETIDXREG 0x545406 | 1267 | #define FBIMSTT_GETIDXREG 0x545406 |
| 1268 | 1268 | ||
| 1269 | static int | 1269 | static int |
| 1270 | imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd, | 1270 | imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
| 1271 | u_long arg, struct fb_info *info) | ||
| 1272 | { | 1271 | { |
| 1273 | struct imstt_par *par = info->par; | 1272 | struct imstt_par *par = info->par; |
| 1274 | void __user *argp = (void __user *)arg; | 1273 | void __user *argp = (void __user *)arg; |
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 0090544842f5..6b8bd3cdf9c0 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c | |||
| @@ -157,9 +157,8 @@ static int intelfb_cursor(struct fb_info *info, | |||
| 157 | 157 | ||
| 158 | static int intelfb_sync(struct fb_info *info); | 158 | static int intelfb_sync(struct fb_info *info); |
| 159 | 159 | ||
| 160 | static int intelfb_ioctl(struct inode *inode, struct file *file, | 160 | static int intelfb_ioctl(struct fb_info *info, |
| 161 | unsigned int cmd, unsigned long arg, | 161 | unsigned int cmd, unsigned long arg); |
| 162 | struct fb_info *info); | ||
| 163 | 162 | ||
| 164 | static int __devinit intelfb_pci_register(struct pci_dev *pdev, | 163 | static int __devinit intelfb_pci_register(struct pci_dev *pdev, |
| 165 | const struct pci_device_id *ent); | 164 | const struct pci_device_id *ent); |
| @@ -1380,8 +1379,7 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 1380 | 1379 | ||
| 1381 | /* When/if we have our own ioctls. */ | 1380 | /* When/if we have our own ioctls. */ |
| 1382 | static int | 1381 | static int |
| 1383 | intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 1382 | intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 1384 | unsigned long arg, struct fb_info *info) | ||
| 1385 | { | 1383 | { |
| 1386 | int retval = 0; | 1384 | int retval = 0; |
| 1387 | 1385 | ||
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index bcd359b6d4ff..477ad297de4e 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c | |||
| @@ -586,9 +586,8 @@ static int __init kyrofb_setup(char *options) | |||
| 586 | } | 586 | } |
| 587 | #endif | 587 | #endif |
| 588 | 588 | ||
| 589 | static int kyrofb_ioctl(struct inode *inode, struct file *file, | 589 | static int kyrofb_ioctl(struct fb_info *info, |
| 590 | unsigned int cmd, unsigned long arg, | 590 | unsigned int cmd, unsigned long arg) |
| 591 | struct fb_info *info) | ||
| 592 | { | 591 | { |
| 593 | overlay_create ol_create; | 592 | overlay_create ol_create; |
| 594 | overlay_viewport_set ol_viewport_set; | 593 | overlay_viewport_set ol_viewport_set; |
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 494287f8f8bf..a23cfdb9d826 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
| @@ -32,9 +32,8 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, | |||
| 32 | unsigned, struct fb_info *); | 32 | unsigned, struct fb_info *); |
| 33 | static int leo_blank(int, struct fb_info *); | 33 | static int leo_blank(int, struct fb_info *); |
| 34 | 34 | ||
| 35 | static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 35 | static int leo_mmap(struct fb_info *, struct vm_area_struct *); |
| 36 | static int leo_ioctl(struct inode *, struct file *, unsigned int, | 36 | static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 37 | unsigned long, struct fb_info *); | ||
| 38 | static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); | 37 | static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); |
| 39 | 38 | ||
| 40 | /* | 39 | /* |
| @@ -363,7 +362,7 @@ static struct sbus_mmap_map leo_mmap_map[] = { | |||
| 363 | { .size = 0 } | 362 | { .size = 0 } |
| 364 | }; | 363 | }; |
| 365 | 364 | ||
| 366 | static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 365 | static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 367 | { | 366 | { |
| 368 | struct leo_par *par = (struct leo_par *)info->par; | 367 | struct leo_par *par = (struct leo_par *)info->par; |
| 369 | 368 | ||
| @@ -373,8 +372,7 @@ static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_stru | |||
| 373 | vma); | 372 | vma); |
| 374 | } | 373 | } |
| 375 | 374 | ||
| 376 | static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 375 | static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) |
| 377 | unsigned long arg, struct fb_info *info) | ||
| 378 | { | 376 | { |
| 379 | struct leo_par *par = (struct leo_par *) info->par; | 377 | struct leo_par *par = (struct leo_par *) info->par; |
| 380 | 378 | ||
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 1e74f4cca53b..4055ff6f5a81 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
| @@ -865,9 +865,8 @@ static struct matrox_altout panellink_output = { | |||
| 865 | .name = "Panellink output", | 865 | .name = "Panellink output", |
| 866 | }; | 866 | }; |
| 867 | 867 | ||
| 868 | static int matroxfb_ioctl(struct inode *inode, struct file *file, | 868 | static int matroxfb_ioctl(struct fb_info *info, |
| 869 | unsigned int cmd, unsigned long arg, | 869 | unsigned int cmd, unsigned long arg) |
| 870 | struct fb_info *info) | ||
| 871 | { | 870 | { |
| 872 | void __user *argp = (void __user *)arg; | 871 | void __user *argp = (void __user *)arg; |
| 873 | MINFO_FROM_INFO(info); | 872 | MINFO_FROM_INFO(info); |
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index d52d7d825c41..27eb4bb4f89f 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c | |||
| @@ -419,11 +419,10 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru | |||
| 419 | return 0; | 419 | return 0; |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | static int matroxfb_dh_ioctl(struct inode* inode, | 422 | static int matroxfb_dh_ioctl(struct fb_info *info, |
| 423 | struct file* file, | ||
| 424 | unsigned int cmd, | 423 | unsigned int cmd, |
| 425 | unsigned long arg, | 424 | unsigned long arg) |
| 426 | struct fb_info* info) { | 425 | { |
| 427 | #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) | 426 | #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) |
| 428 | MINFO_FROM(m2info->primary_dev); | 427 | MINFO_FROM(m2info->primary_dev); |
| 429 | 428 | ||
| @@ -457,7 +456,7 @@ static int matroxfb_dh_ioctl(struct inode* inode, | |||
| 457 | case MATROXFB_GET_OUTPUT_MODE: | 456 | case MATROXFB_GET_OUTPUT_MODE: |
| 458 | case MATROXFB_GET_ALL_OUTPUTS: | 457 | case MATROXFB_GET_ALL_OUTPUTS: |
| 459 | { | 458 | { |
| 460 | return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, &ACCESS_FBINFO(fbcon)); | 459 | return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg); |
| 461 | } | 460 | } |
| 462 | case MATROXFB_SET_OUTPUT_CONNECTION: | 461 | case MATROXFB_SET_OUTPUT_CONNECTION: |
| 463 | { | 462 | { |
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index a1f2c5e8fc88..6019710dc298 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c | |||
| @@ -968,7 +968,7 @@ static inline int maven_compute_timming(struct maven_data* md, | |||
| 968 | return 0; | 968 | return 0; |
| 969 | } | 969 | } |
| 970 | 970 | ||
| 971 | static inline int maven_program_timming(struct maven_data* md, | 971 | static int maven_program_timming(struct maven_data* md, |
| 972 | const struct mavenregs* m) { | 972 | const struct mavenregs* m) { |
| 973 | struct i2c_client* c = md->client; | 973 | struct i2c_client* c = md->client; |
| 974 | 974 | ||
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index e18c9f98a401..747602aa5615 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
| @@ -853,7 +853,7 @@ static int neofb_set_par(struct fb_info *info) | |||
| 853 | /* If the user did not specify any display devices, then... */ | 853 | /* If the user did not specify any display devices, then... */ |
| 854 | if (par->PanelDispCntlReg1 == 0x00) { | 854 | if (par->PanelDispCntlReg1 == 0x00) { |
| 855 | /* Default to internal (i.e., LCD) only. */ | 855 | /* Default to internal (i.e., LCD) only. */ |
| 856 | par->PanelDispCntlReg1 |= 0x02; | 856 | par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03; |
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | /* If we are using a fixed mode, then tell the chip we are. */ | 859 | /* If we are using a fixed mode, then tell the chip we are. */ |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index b251e754e16c..0d1957505359 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
| @@ -31,9 +31,8 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, | |||
| 31 | unsigned, struct fb_info *); | 31 | unsigned, struct fb_info *); |
| 32 | static int p9100_blank(int, struct fb_info *); | 32 | static int p9100_blank(int, struct fb_info *); |
| 33 | 33 | ||
| 34 | static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 34 | static int p9100_mmap(struct fb_info *, struct vm_area_struct *); |
| 35 | static int p9100_ioctl(struct inode *, struct file *, unsigned int, | 35 | static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 36 | unsigned long, struct fb_info *); | ||
| 37 | 36 | ||
| 38 | /* | 37 | /* |
| 39 | * Frame buffer operations | 38 | * Frame buffer operations |
| @@ -222,7 +221,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = { | |||
| 222 | { 0, 0, 0 } | 221 | { 0, 0, 0 } |
| 223 | }; | 222 | }; |
| 224 | 223 | ||
| 225 | static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 224 | static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 226 | { | 225 | { |
| 227 | struct p9100_par *par = (struct p9100_par *)info->par; | 226 | struct p9100_par *par = (struct p9100_par *)info->par; |
| 228 | 227 | ||
| @@ -232,8 +231,8 @@ static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_st | |||
| 232 | vma); | 231 | vma); |
| 233 | } | 232 | } |
| 234 | 233 | ||
| 235 | static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 234 | static int p9100_ioctl(struct fb_info *info, unsigned int cmd, |
| 236 | unsigned long arg, struct fb_info *info) | 235 | unsigned long arg) |
| 237 | { | 236 | { |
| 238 | struct p9100_par *par = (struct p9100_par *) info->par; | 237 | struct p9100_par *par = (struct p9100_par *) info->par; |
| 239 | 238 | ||
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 2e11b601c488..0e78ddc81583 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
| @@ -657,9 +657,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp, | |||
| 657 | static void pm3fb_detect(void); | 657 | static void pm3fb_detect(void); |
| 658 | static int pm3fb_pan_display(const struct fb_var_screeninfo *var, | 658 | static int pm3fb_pan_display(const struct fb_var_screeninfo *var, |
| 659 | struct fb_info_gen *info); | 659 | struct fb_info_gen *info); |
| 660 | static int pm3fb_ioctl(struct inode *inode, struct file *file, | 660 | static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg); |
| 661 | u_int cmd, u_long arg, int con, | ||
| 662 | struct fb_info *info); | ||
| 663 | 661 | ||
| 664 | 662 | ||
| 665 | /* the struct that hold them together */ | 663 | /* the struct that hold them together */ |
| @@ -3438,9 +3436,7 @@ static int pm3fb_pan_display(const struct fb_var_screeninfo *var, | |||
| 3438 | return 0; | 3436 | return 0; |
| 3439 | } | 3437 | } |
| 3440 | 3438 | ||
| 3441 | static int pm3fb_ioctl(struct inode *inode, struct file *file, | 3439 | static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
| 3442 | u_int cmd, u_long arg, int con, | ||
| 3443 | struct fb_info *info) | ||
| 3444 | { | 3440 | { |
| 3445 | struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; | 3441 | struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; |
| 3446 | u32 cm, i; | 3442 | u32 cm, i; |
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c index 28d1fe5fe340..d92f352211ef 100644 --- a/drivers/video/pmag-aa-fb.c +++ b/drivers/video/pmag-aa-fb.c | |||
| @@ -299,8 +299,7 @@ static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, | |||
| 299 | return -EINVAL; | 299 | return -EINVAL; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static int aafb_ioctl(struct inode *inode, struct file *file, u32 cmd, | 302 | static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg) |
| 303 | unsigned long arg, int con, struct fb_info *info) | ||
| 304 | { | 303 | { |
| 305 | /* TODO: Not yet implemented */ | 304 | /* TODO: Not yet implemented */ |
| 306 | return -ENOIOCTLCMD; | 305 | return -ENOIOCTLCMD; |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 9fc10b9e6f57..53ad61f1038c 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -395,7 +395,7 @@ static int pxafb_blank(int blank, struct fb_info *info) | |||
| 395 | return 0; | 395 | return 0; |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | static int pxafb_mmap(struct fb_info *info, struct file *file, | 398 | static int pxafb_mmap(struct fb_info *info, |
| 399 | struct vm_area_struct *vma) | 399 | struct vm_area_struct *vma) |
| 400 | { | 400 | { |
| 401 | struct pxafb_info *fbi = (struct pxafb_info *)info; | 401 | struct pxafb_info *fbi = (struct pxafb_info *)info; |
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index 600318f708f2..db9fb9074dbc 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c | |||
| @@ -1497,8 +1497,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, | |||
| 1497 | } | 1497 | } |
| 1498 | 1498 | ||
| 1499 | 1499 | ||
| 1500 | static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, | 1500 | static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, |
| 1501 | unsigned long arg, struct fb_info *info) | 1501 | unsigned long arg) |
| 1502 | { | 1502 | { |
| 1503 | struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | 1503 | struct radeonfb_info *rinfo = (struct radeonfb_info *) info; |
| 1504 | unsigned int tmp; | 1504 | unsigned int tmp; |
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 087e58689e4c..8a893ce7040d 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c | |||
| @@ -815,7 +815,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info) | |||
| 815 | return 0; | 815 | return 0; |
| 816 | } | 816 | } |
| 817 | 817 | ||
| 818 | static int sa1100fb_mmap(struct fb_info *info, struct file *file, | 818 | static int sa1100fb_mmap(struct fb_info *info, |
| 819 | struct vm_area_struct *vma) | 819 | struct vm_area_struct *vma) |
| 820 | { | 820 | { |
| 821 | struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; | 821 | struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; |
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 7054660767e4..2e6df1fcb2b9 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c | |||
| @@ -115,7 +115,7 @@ static int sgivwfb_set_par(struct fb_info *info); | |||
| 115 | static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, | 115 | static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, |
| 116 | u_int blue, u_int transp, | 116 | u_int blue, u_int transp, |
| 117 | struct fb_info *info); | 117 | struct fb_info *info); |
| 118 | static int sgivwfb_mmap(struct fb_info *info, struct file *file, | 118 | static int sgivwfb_mmap(struct fb_info *info, |
| 119 | struct vm_area_struct *vma); | 119 | struct vm_area_struct *vma); |
| 120 | 120 | ||
| 121 | static struct fb_ops sgivwfb_ops = { | 121 | static struct fb_ops sgivwfb_ops = { |
| @@ -706,7 +706,7 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, | |||
| 706 | return 0; | 706 | return 0; |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | static int sgivwfb_mmap(struct fb_info *info, struct file *file, | 709 | static int sgivwfb_mmap(struct fb_info *info, |
| 710 | struct vm_area_struct *vma) | 710 | struct vm_area_struct *vma) |
| 711 | { | 711 | { |
| 712 | unsigned long size = vma->vm_end - vma->vm_start; | 712 | unsigned long size = vma->vm_end - vma->vm_start; |
| @@ -723,7 +723,6 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file, | |||
| 723 | if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, | 723 | if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, |
| 724 | size, vma->vm_page_prot)) | 724 | size, vma->vm_page_prot)) |
| 725 | return -EAGAIN; | 725 | return -EAGAIN; |
| 726 | vma->vm_file = file; | ||
| 727 | printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", | 726 | printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", |
| 728 | offset, vma->vm_start); | 727 | offset, vma->vm_start); |
| 729 | return 0; | 728 | return 0; |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index dea1a46c67c4..8adf5bf91eee 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
| @@ -1743,13 +1743,14 @@ sisfb_blank(int blank, struct fb_info *info) | |||
| 1743 | 1743 | ||
| 1744 | /* ----------- FBDev related routines for all series ---------- */ | 1744 | /* ----------- FBDev related routines for all series ---------- */ |
| 1745 | 1745 | ||
| 1746 | static int | 1746 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) |
| 1747 | sisfb_ioctl(struct inode *inode, struct file *file, | 1747 | static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, |
| 1748 | unsigned int cmd, unsigned long arg, | 1748 | unsigned long arg) |
| 1749 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 1749 | #else |
| 1750 | int con, | 1750 | static int sisfb_ioctl(struct inode *inode, struct file *file, |
| 1751 | unsigned int cmd, unsigned long arg, | ||
| 1752 | struct fb_info *info) | ||
| 1751 | #endif | 1753 | #endif |
| 1752 | struct fb_info *info) | ||
| 1753 | { | 1754 | { |
| 1754 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1755 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
| 1755 | struct sis_memreq sismemreq; | 1756 | struct sis_memreq sismemreq; |
| @@ -1924,19 +1925,6 @@ sisfb_ioctl(struct inode *inode, struct file *file, | |||
| 1924 | return 0; | 1925 | return 0; |
| 1925 | } | 1926 | } |
| 1926 | 1927 | ||
| 1927 | #ifdef SIS_NEW_CONFIG_COMPAT | ||
| 1928 | static long | ||
| 1929 | sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info) | ||
| 1930 | { | ||
| 1931 | int ret; | ||
| 1932 | |||
| 1933 | lock_kernel(); | ||
| 1934 | ret = sisfb_ioctl(NULL, f, cmd, arg, info); | ||
| 1935 | unlock_kernel(); | ||
| 1936 | return ret; | ||
| 1937 | } | ||
| 1938 | #endif | ||
| 1939 | |||
| 1940 | static int | 1928 | static int |
| 1941 | sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | 1929 | sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) |
| 1942 | { | 1930 | { |
| @@ -2007,7 +1995,7 @@ static struct fb_ops sisfb_ops = { | |||
| 2007 | #endif | 1995 | #endif |
| 2008 | .fb_sync = fbcon_sis_sync, | 1996 | .fb_sync = fbcon_sis_sync, |
| 2009 | #ifdef SIS_NEW_CONFIG_COMPAT | 1997 | #ifdef SIS_NEW_CONFIG_COMPAT |
| 2010 | .fb_compat_ioctl= sisfb_compat_ioctl, | 1998 | .fb_compat_ioctl= sisfb_ioctl, |
| 2011 | #endif | 1999 | #endif |
| 2012 | .fb_ioctl = sisfb_ioctl | 2000 | .fb_ioctl = sisfb_ioctl |
| 2013 | }; | 2001 | }; |
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h index 445bcbba03ae..70b6df371b8e 100644 --- a/drivers/video/sis/sis_main.h +++ b/drivers/video/sis/sis_main.h | |||
| @@ -727,9 +727,14 @@ static int sisfb_ioctl(struct inode *inode, struct file *file, | |||
| 727 | #endif | 727 | #endif |
| 728 | 728 | ||
| 729 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 729 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
| 730 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) | ||
| 731 | static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, | ||
| 732 | unsigned long arg); | ||
| 733 | #else | ||
| 730 | static int sisfb_ioctl(struct inode *inode, struct file *file, | 734 | static int sisfb_ioctl(struct inode *inode, struct file *file, |
| 731 | unsigned int cmd, unsigned long arg, | 735 | unsigned int cmd, unsigned long arg, |
| 732 | struct fb_info *info); | 736 | struct fb_info *info); |
| 737 | #endif | ||
| 733 | static int sisfb_set_par(struct fb_info *info); | 738 | static int sisfb_set_par(struct fb_info *info); |
| 734 | static int sisfb_blank(int blank, | 739 | static int sisfb_blank(int blank, |
| 735 | struct fb_info *info); | 740 | struct fb_info *info); |
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 8a5ce210bb27..99921df35474 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c | |||
| @@ -771,8 +771,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 771 | return 0; | 771 | return 0; |
| 772 | } | 772 | } |
| 773 | 773 | ||
| 774 | static int sstfb_ioctl(struct inode *inode, struct file *file, | 774 | static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
| 775 | u_int cmd, u_long arg, struct fb_info *info ) | ||
| 776 | { | 775 | { |
| 777 | struct sstfb_par *par = info->par; | 776 | struct sstfb_par *par = info->par; |
| 778 | struct pci_dev *sst_dev = par->dev; | 777 | struct pci_dev *sst_dev = par->dev; |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 2b27b4474001..95b918229d9b 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
| @@ -33,9 +33,8 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned, | |||
| 33 | unsigned, struct fb_info *); | 33 | unsigned, struct fb_info *); |
| 34 | static int tcx_blank(int, struct fb_info *); | 34 | static int tcx_blank(int, struct fb_info *); |
| 35 | 35 | ||
| 36 | static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *); | 36 | static int tcx_mmap(struct fb_info *, struct vm_area_struct *); |
| 37 | static int tcx_ioctl(struct inode *, struct file *, unsigned int, | 37 | static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 38 | unsigned long, struct fb_info *); | ||
| 39 | static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); | 38 | static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); |
| 40 | 39 | ||
| 41 | /* | 40 | /* |
| @@ -302,7 +301,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { | |||
| 302 | { .size = 0 } | 301 | { .size = 0 } |
| 303 | }; | 302 | }; |
| 304 | 303 | ||
| 305 | static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) | 304 | static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| 306 | { | 305 | { |
| 307 | struct tcx_par *par = (struct tcx_par *)info->par; | 306 | struct tcx_par *par = (struct tcx_par *)info->par; |
| 308 | 307 | ||
| @@ -312,8 +311,8 @@ static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_stru | |||
| 312 | vma); | 311 | vma); |
| 313 | } | 312 | } |
| 314 | 313 | ||
| 315 | static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 314 | static int tcx_ioctl(struct fb_info *info, unsigned int cmd, |
| 316 | unsigned long arg, struct fb_info *info) | 315 | unsigned long arg) |
| 317 | { | 316 | { |
| 318 | struct tcx_par *par = (struct tcx_par *) info->par; | 317 | struct tcx_par *par = (struct tcx_par *) info->par; |
| 319 | 318 | ||
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index ffa1ad474226..53208cb58396 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
| @@ -81,7 +81,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 81 | u_int transp, struct fb_info *info); | 81 | u_int transp, struct fb_info *info); |
| 82 | static int vfb_pan_display(struct fb_var_screeninfo *var, | 82 | static int vfb_pan_display(struct fb_var_screeninfo *var, |
| 83 | struct fb_info *info); | 83 | struct fb_info *info); |
| 84 | static int vfb_mmap(struct fb_info *info, struct file *file, | 84 | static int vfb_mmap(struct fb_info *info, |
| 85 | struct vm_area_struct *vma); | 85 | struct vm_area_struct *vma); |
| 86 | 86 | ||
| 87 | static struct fb_ops vfb_ops = { | 87 | static struct fb_ops vfb_ops = { |
| @@ -368,7 +368,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, | |||
| 368 | * Most drivers don't need their own mmap function | 368 | * Most drivers don't need their own mmap function |
| 369 | */ | 369 | */ |
| 370 | 370 | ||
| 371 | static int vfb_mmap(struct fb_info *info, struct file *file, | 371 | static int vfb_mmap(struct fb_info *info, |
| 372 | struct vm_area_struct *vma) | 372 | struct vm_area_struct *vma) |
| 373 | { | 373 | { |
| 374 | return -EINVAL; | 374 | return -EINVAL; |
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index ccba227676f2..fcbee748c592 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c | |||
| @@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_driver *drv) | |||
| 77 | /* initialize common driver fields */ | 77 | /* initialize common driver fields */ |
| 78 | drv->driver.name = drv->name; | 78 | drv->driver.name = drv->name; |
| 79 | drv->driver.bus = &zorro_bus_type; | 79 | drv->driver.bus = &zorro_bus_type; |
| 80 | drv->driver.probe = zorro_device_probe; | ||
| 81 | 80 | ||
| 82 | /* register with core */ | 81 | /* register with core */ |
| 83 | count = driver_register(&drv->driver); | 82 | count = driver_register(&drv->driver); |
| @@ -132,7 +131,8 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) | |||
| 132 | 131 | ||
| 133 | struct bus_type zorro_bus_type = { | 132 | struct bus_type zorro_bus_type = { |
| 134 | .name = "zorro", | 133 | .name = "zorro", |
| 135 | .match = zorro_bus_match | 134 | .match = zorro_bus_match, |
| 135 | .probe = zorro_device_probe, | ||
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| 138 | 138 | ||
