aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 18:08:53 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 18:08:53 -0800
commitf95e6dae6522e0c403bef92405a3577ebd8baee9 (patch)
tree40c9f91e77cba0fddd1c019ae317f5768c267740 /drivers
parentf741676a0eea898c7fd2169df9cfcf65a3f76bd1 (diff)
parentaae7d141676c5d83dbc97732f1cf48839f404774 (diff)
downloadhistory-f95e6dae6522e0c403bef92405a3577ebd8baee9.tar.gz
Merge http://lia64.bkbits.net/linux-ia64-release-2.6.11
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/block/cfq-iosched.c6
-rw-r--r--drivers/block/elevator.c7
-rw-r--r--drivers/block/scsi_ioctl.c3
-rw-r--r--drivers/bluetooth/bluecard_cs.c6
-rw-r--r--drivers/bluetooth/bt3c_cs.c6
-rw-r--r--drivers/bluetooth/btuart_cs.c6
-rw-r--r--drivers/bluetooth/dtl1_cs.c6
-rw-r--r--drivers/char/pcmcia/synclink_cs.c9
-rw-r--r--drivers/ide/legacy/ide-cs.c4
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c9
-rw-r--r--drivers/isdn/hisax/avma1_cs.c9
-rw-r--r--drivers/isdn/hisax/elsa_cs.c6
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c9
-rw-r--r--drivers/isdn/hisax/teles_cs.c6
-rw-r--r--drivers/mtd/maps/pcmciamtd.c31
-rw-r--r--drivers/net/3c515.c2
-rw-r--r--drivers/net/arcnet/arcnet.c3
-rw-r--r--drivers/net/e1000/e1000_ethtool.c2
-rw-r--r--drivers/net/e1000/e1000_main.c4
-rw-r--r--drivers/net/eepro.c144
-rw-r--r--drivers/net/ibm_emac/ibm_emac.h2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c15
-rw-r--r--drivers/net/ibm_emac/ibm_emac_phy.c19
-rw-r--r--drivers/net/ixgb/ixgb.h25
-rw-r--r--drivers/net/ixgb/ixgb_ee.c192
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c518
-rw-r--r--drivers/net/ixgb/ixgb_hw.c231
-rw-r--r--drivers/net/ixgb/ixgb_hw.h50
-rw-r--r--drivers/net/ixgb/ixgb_ids.h21
-rw-r--r--drivers/net/ixgb/ixgb_main.c707
-rw-r--r--drivers/net/ixgb/ixgb_osdep.h10
-rw-r--r--drivers/net/ixgb/ixgb_param.c316
-rw-r--r--drivers/net/pcmcia/3c574_cs.c5
-rw-r--r--drivers/net/pcmcia/3c589_cs.c5
-rw-r--r--drivers/net/pcmcia/axnet_cs.c5
-rw-r--r--drivers/net/pcmcia/com20020_cs.c5
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c5
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c5
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c5
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c5
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c5
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c6
-rw-r--r--drivers/net/s2io.c22
-rw-r--r--drivers/net/s2io.h4
-rw-r--r--drivers/net/smc-ultra.c2
-rw-r--r--drivers/net/smc91x.c16
-rw-r--r--drivers/net/wireless/airo.c20
-rw-r--r--drivers/net/wireless/airo_cs.c13
-rw-r--r--drivers/net/wireless/atmel_cs.c23
-rw-r--r--drivers/net/wireless/netwave_cs.c7
-rw-r--r--drivers/net/wireless/orinoco.c203
-rw-r--r--drivers/net/wireless/orinoco_cs.c11
-rw-r--r--drivers/net/wireless/ray_cs.c5
-rw-r--r--drivers/net/wireless/wavelan_cs.c2
-rw-r--r--drivers/net/wireless/wl3501_cs.c14
-rw-r--r--drivers/parport/parport_cs.c6
-rw-r--r--drivers/pcmcia/Kconfig21
-rw-r--r--drivers/pcmcia/Makefile4
-rw-r--r--drivers/pcmcia/bulkmem.c218
-rw-r--r--drivers/pcmcia/cardbus.c45
-rw-r--r--drivers/pcmcia/cistpl.c50
-rw-r--r--drivers/pcmcia/cs.c417
-rw-r--r--drivers/pcmcia/cs_internal.h46
-rw-r--r--drivers/pcmcia/ds.c1061
-rw-r--r--drivers/pcmcia/hd64465_ss.c1
-rw-r--r--drivers/pcmcia/i82092.c1
-rw-r--r--drivers/pcmcia/i82365.c1
-rw-r--r--drivers/pcmcia/m32r_cfc.c1
-rw-r--r--drivers/pcmcia/m32r_pcc.c1
-rw-r--r--drivers/pcmcia/pcmcia_compat.c20
-rw-r--r--drivers/pcmcia/pd6729.c271
-rw-r--r--drivers/pcmcia/pd6729.h6
-rw-r--r--drivers/pcmcia/rsrc_mgr.c856
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c816
-rw-r--r--drivers/pcmcia/soc_common.c1
-rw-r--r--drivers/pcmcia/tcic.c3
-rw-r--r--drivers/pcmcia/ti113x.h11
-rw-r--r--drivers/pcmcia/yenta_socket.c10
-rw-r--r--drivers/scsi/aacraid/commsup.c27
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c12
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c91
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c4
-rw-r--r--drivers/scsi/constants.c24
-rw-r--r--drivers/scsi/fd_mcs.c58
-rw-r--r--drivers/scsi/fd_mcs.h37
-rw-r--r--drivers/scsi/gdth.c954
-rw-r--r--drivers/scsi/gdth_kcompat.h21
-rw-r--r--drivers/scsi/gdth_proc.c287
-rw-r--r--drivers/scsi/gdth_proc.h6
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c142
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h1
-rw-r--r--drivers/scsi/ipr.c28
-rw-r--r--drivers/scsi/lasi700.c22
-rw-r--r--drivers/scsi/lasi700.h49
-rw-r--r--drivers/scsi/osst.c851
-rw-r--r--drivers/scsi/osst.h15
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c6
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c6
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c5
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c6
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c1
-rw-r--r--drivers/scsi/qla1280.c22
-rw-r--r--drivers/scsi/sata_sil.c2
-rw-r--r--drivers/scsi/scsi.c22
-rw-r--r--drivers/scsi/scsi_lib.c18
-rw-r--r--drivers/scsi/scsi_transport_fc.c36
-rw-r--r--drivers/scsi/scsi_transport_spi.c91
-rw-r--r--drivers/scsi/sd.c7
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_conf.h8
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h34
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c83
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h34
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c469
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h72
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_malloc.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_misc.c98
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c39
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.h6
-rw-r--r--drivers/scsi/sym53c8xx_comm.h2
-rw-r--r--drivers/scsi/zalon.c21
-rw-r--r--drivers/serial/serial_cs.c6
-rw-r--r--drivers/telephony/ixj_pcmcia.c6
125 files changed, 4915 insertions, 5468 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index d60b2c34b10fba..797be2e919a040 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -162,7 +162,7 @@ static void acpi_processor_idle (void)
int sleep_ticks = 0;
u32 t1, t2 = 0;
- pr = processors[smp_processor_id()];
+ pr = processors[_smp_processor_id()];
if (!pr)
return;
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 6c24f236f7f6de..635d93fae58f53 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -622,8 +622,10 @@ static void cfq_requeue_request(request_queue_t *q, struct request *rq)
cfq_sort_rr_list(cfqq, 0);
}
- crq->accounted = 0;
- cfqq->cfqd->rq_in_driver--;
+ if (crq->accounted) {
+ crq->accounted = 0;
+ cfqq->cfqd->rq_in_driver--;
+ }
}
list_add(&rq->queuelist, &q->queue_head);
}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 52e29886f8cf5d..0bf9458f911dfa 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -170,8 +170,6 @@ static void elevator_setup_default(void)
#else
#error "You must build at least 1 IO scheduler into the kernel"
#endif
- printk(KERN_INFO "elevator: using %s as default io scheduler\n",
- chosen_elevator);
}
static int __init elevator_setup(char *str)
@@ -515,7 +513,10 @@ int elv_register(struct elevator_type *e)
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);
- printk(KERN_INFO "io scheduler %s registered\n", e->elevator_name);
+ printk(KERN_INFO "io scheduler %s registered", e->elevator_name);
+ if (!strcmp(e->elevator_name, chosen_elevator))
+ printk(" (default)");
+ printk("\n");
return 0;
}
EXPORT_SYMBOL_GPL(elv_register);
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 1fe57c940d2e62..cdb11fc7ad2513 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -339,7 +339,8 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
{
struct request *rq;
- int err, in_len, out_len, bytes, opcode, cmdlen;
+ int err;
+ unsigned int in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
/*
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 4db1feeefc0b38..325ab5d7678614 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -904,7 +904,6 @@ static dev_link_t *bluecard_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -1117,10 +1116,7 @@ static int __init init_bluecard_cs(void)
static void __exit exit_bluecard_cs(void)
{
pcmcia_unregister_driver(&bluecard_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- bluecard_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_bluecard_cs);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index a50adb67bd5a3a..84977a0605e519 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -709,7 +709,6 @@ static dev_link_t *bt3c_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -967,10 +966,7 @@ static int __init init_bt3c_cs(void)
static void __exit exit_bt3c_cs(void)
{
pcmcia_unregister_driver(&bt3c_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- bt3c_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_bt3c_cs);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 74644df2447702..38dbac8db507fe 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -628,7 +628,6 @@ static dev_link_t *btuart_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -887,10 +886,7 @@ static int __init init_btuart_cs(void)
static void __exit exit_btuart_cs(void)
{
pcmcia_unregister_driver(&btuart_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- btuart_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_btuart_cs);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 87ff7966ffbabb..9fcc8e4d215933 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -607,7 +607,6 @@ static dev_link_t *dtl1_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -839,10 +838,7 @@ static int __init init_dtl1_cs(void)
static void __exit exit_dtl1_cs(void)
{
pcmcia_unregister_driver(&dtl1_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- dtl1_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_dtl1_cs);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 234af616f220a7..c6accb1ab6ac21 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -608,7 +608,6 @@ static dev_link_t *mgslpc_attach(void)
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -3147,13 +3146,7 @@ static void synclink_cs_cleanup(void)
}
pcmcia_unregister_driver(&mgslpc_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- mgslpc_release((u_long)dev_list);
- mgslpc_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
static int __init synclink_cs_init(void)
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index abab060fd230b2..b114113b0acbd6 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -144,7 +144,6 @@ static dev_link_t *ide_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -485,8 +484,7 @@ static int __init init_ide_cs(void)
static void __exit exit_ide_cs(void)
{
pcmcia_unregister_driver(&ide_cs_driver);
- while (dev_list != NULL)
- ide_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_ide_cs);
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 9661806d023939..fbbfb9cfbc4ef2 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -178,7 +178,6 @@ static dev_link_t *avmcs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -521,13 +520,7 @@ static int __init avmcs_init(void)
static void __exit avmcs_exit(void)
{
pcmcia_unregister_driver(&avmcs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- avmcs_release(dev_list);
- avmcs_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(avmcs_init);
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 06ce6605517b10..784df60d1a1f90 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -193,7 +193,6 @@ static dev_link_t *avma1cs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -531,13 +530,7 @@ static int __init init_avma1_cs(void)
static void __exit exit_avma1_cs(void)
{
pcmcia_unregister_driver(&avma1cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- avma1cs_release(dev_list);
- avma1cs_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_avma1_cs);
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 5087eefd1e3dd2..92349814990fb4 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -227,7 +227,6 @@ static dev_link_t *elsa_cs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -541,10 +540,7 @@ static int __init init_elsa_cs(void)
static void __exit exit_elsa_cs(void)
{
pcmcia_unregister_driver(&elsa_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- elsa_cs_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_elsa_cs);
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 44545eaf8333fc..ab4f78a33defef 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -240,7 +240,6 @@ static dev_link_t *sedlbauer_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -648,13 +647,7 @@ static int __init init_sedlbauer_cs(void)
static void __exit exit_sedlbauer_cs(void)
{
pcmcia_unregister_driver(&sedlbauer_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- sedlbauer_release(dev_list);
- sedlbauer_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_sedlbauer_cs);
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index b84b3a21553cd5..c17c25fd47136d 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -208,7 +208,6 @@ static dev_link_t *teles_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -522,10 +521,7 @@ static int __init init_teles_cs(void)
static void __exit exit_teles_cs(void)
{
pcmcia_unregister_driver(&teles_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- teles_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_teles_cs);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index ec63e3b6fa6855..e37b4c1976e57f 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -800,7 +800,6 @@ static dev_link_t *pcmciamtd_attach(void)
/* Register with Card Services */
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
@@ -854,35 +853,7 @@ static void __exit exit_pcmciamtd(void)
{
DEBUG(1, DRIVER_DESC " unloading");
pcmcia_unregister_driver(&pcmciamtd_driver);
-
- while(dev_list) {
- dev_link_t *link = dev_list;
-
- dev_list = link->next;
- if (link) {
- struct pcmciamtd_dev *dev = link->priv;
-
- if(dev) {
- if(link->state & DEV_PRESENT) {
- if (!(link->state & DEV_STALE_LINK)) {
- pcmciamtd_detach(link);
- }
- link->state &= ~DEV_PRESENT;
- if(dev->mtd_info) {
- del_mtd_device(dev->mtd_info);
- info("mtd%d: Removed",
- dev->mtd_info->index);
- }
- }
- if(dev->mtd_info) {
- DEBUG(2, "Destroying map for mtd%d",
- dev->mtd_info->index);
- map_destroy(dev->mtd_info);
- }
- kfree(dev);
- }
- }
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_pcmciamtd);
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index f1a08b5631b015..ad46ab8c31ce9e 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -34,7 +34,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
-static const int rx_copybreak = 200;
+static int rx_copybreak = 200;
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
static const int mtu = 1500;
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 282a678007b3e0..9fd21724f61f8c 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -93,7 +93,6 @@ EXPORT_SYMBOL(arc_raw_proto);
EXPORT_SYMBOL(arc_proto_null);
EXPORT_SYMBOL(arcnet_unregister_proto);
EXPORT_SYMBOL(arcnet_debug);
-EXPORT_SYMBOL(arcdev_setup);
EXPORT_SYMBOL(alloc_arcdev);
EXPORT_SYMBOL(arcnet_interrupt);
@@ -317,7 +316,7 @@ static int choose_mtu(void)
/* Setup a struct device for ARCnet. */
-void arcdev_setup(struct net_device *dev)
+static void arcdev_setup(struct net_device *dev)
{
dev->type = ARPHRD_ARCNET;
dev->hard_header_len = sizeof(struct archdr);
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 9b40cf1c2c9c89..e4061ffc48aaf2 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1666,7 +1666,7 @@ struct ethtool_ops e1000_ethtool_ops = {
.get_ethtool_stats = e1000_get_ethtool_stats,
};
-void set_ethtool_ops(struct net_device *netdev)
+void e1000_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
}
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 216a5b6eb76a39..aa5ad41acf2459 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -151,7 +151,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
-void set_ethtool_ops(struct net_device *netdev);
+void e1000_set_ethtool_ops(struct net_device *netdev);
static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
static void e1000_tx_timeout(struct net_device *dev);
@@ -475,7 +475,7 @@ e1000_probe(struct pci_dev *pdev,
netdev->set_mac_address = &e1000_set_mac;
netdev->change_mtu = &e1000_change_mtu;
netdev->do_ioctl = &e1000_ioctl;
- set_ethtool_ops(netdev);
+ e1000_set_ethtool_ops(netdev);
netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
#ifdef CONFIG_E1000_NAPI
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 3f05a33e7c69df..cd247568302770 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -23,6 +23,7 @@
This is a compatibility hardware problem.
Versions:
+ 0.13b basic ethtool support (aris, 09/13/2004)
0.13a in memory shortage, drop packets also in board
(Michael Westermann <mw@microdata-pos.de>, 07/30/2002)
0.13 irq sharing, rewrote probe function, fixed a nasty bug in
@@ -104,7 +105,7 @@
*/
static const char version[] =
- "eepro.c: v0.13 11/08/2001 aris@cathedrallabs.org\n";
+ "eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n";
#include <linux/module.h>
@@ -146,19 +147,21 @@ static const char version[] =
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/bitops.h>
+#include <linux/ethtool.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/dma.h>
#define DRV_NAME "eepro"
+#define DRV_VERSION "0.13b"
#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
#define SLOW_DOWN inb(0x80)
/* udelay(2) */
#define compat_init_data __initdata
-
+enum iftype { AUI=0, BNC=1, TPE=2 };
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
@@ -214,6 +217,7 @@ struct eepro_local {
short rcv_lower_limit;
short rcv_upper_limit;
unsigned char eeprom_reg;
+ unsigned short word[8];
};
/* The station (ethernet) address prefix, used for IDing the board. */
@@ -608,16 +612,22 @@ out:
}
#endif
-static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
+static void __init printEEPROMInfo(struct net_device *dev)
{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ int ioaddr = dev->base_addr;
unsigned short Word;
int i,j;
- for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
- j+=read_eeprom(ioaddr,i,dev);
+ j = ee_Checksum;
+ for (i = 0; i < 8; i++)
+ j += lp->word[i];
+ for ( ; i < ee_SIZE; i++)
+ j += read_eeprom(ioaddr, i, dev);
+
printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
- Word=read_eeprom(ioaddr, 0, dev);
+ Word = lp->word[0];
printk(KERN_DEBUG "Word0:\n");
printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
@@ -625,7 +635,7 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
if (net_debug>4) {
- Word=read_eeprom(ioaddr, 1, dev);
+ Word = lp->word[1];
printk(KERN_DEBUG "Word1:\n");
printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
@@ -636,7 +646,7 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
}
- Word=read_eeprom(ioaddr, 5, dev);
+ Word = lp->word[5];
printk(KERN_DEBUG "Word5:\n");
printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
@@ -646,12 +656,12 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
printk(KERN_DEBUG "port(s) \n");
- Word=read_eeprom(ioaddr, 6, dev);
+ Word = lp->word[6];
printk(KERN_DEBUG "Word6:\n");
printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
- Word=read_eeprom(ioaddr, 7, dev);
+ Word = lp->word[7];
printk(KERN_DEBUG "Word7:\n");
printk(KERN_DEBUG " INT to IRQ:\n");
@@ -725,7 +735,7 @@ static void __init eepro_print_info (struct net_device *dev)
printk(", %s.\n", ifmap[dev->if_port]);
if (net_debug > 3) {
- i = read_eeprom(dev->base_addr, 5, dev);
+ i = lp->word[5];
if (i & 0x2000) /* bit 13 of EEPROM word 5 */
printk(KERN_DEBUG "%s: Concurrent Processing is "
"enabled but not used!\n", dev->name);
@@ -733,19 +743,20 @@ static void __init eepro_print_info (struct net_device *dev)
/* Check the station address for the manufacturer's code */
if (net_debug>3)
- printEEPROMInfo(dev->base_addr, dev);
+ printEEPROMInfo(dev);
}
+static struct ethtool_ops eepro_ethtool_ops;
+
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probe avoids doing writes, and
verifies that the correct device exists and functions. */
static int __init eepro_probe1(struct net_device *dev, int autoprobe)
{
- unsigned short station_addr[6], id, counter;
+ unsigned short station_addr[3], id, counter;
int i;
struct eepro_local *lp;
- enum iftype { AUI=0, BNC=1, TPE=2 };
int ioaddr = dev->base_addr;
/* Grab the region so we can find another board if autoIRQ fails. */
@@ -796,11 +807,16 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
lp->xmt_bar = XMT_BAR_10;
station_addr[0] = read_eeprom(ioaddr, 2, dev);
}
- station_addr[1] = read_eeprom(ioaddr, 3, dev);
- station_addr[2] = read_eeprom(ioaddr, 4, dev);
+
+ /* get all words at once. will be used here and for ethtool */
+ for (i = 0; i < 8; i++) {
+ lp->word[i] = read_eeprom(ioaddr, i, dev);
+ }
+ station_addr[1] = lp->word[3];
+ station_addr[2] = lp->word[4];
if (!lp->eepro) {
- if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ)
+ if (lp->word[7] == ee_FX_INT2IRQ)
lp->eepro = 2;
else if (station_addr[2] == SA_ADDR1)
lp->eepro = 1;
@@ -817,15 +833,15 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
/* calculate {xmt,rcv}_{lower,upper}_limit */
eepro_recalc(dev);
- if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
+ if (GetBit(lp->word[5], ee_BNC_TPE))
dev->if_port = BNC;
else
dev->if_port = TPE;
if (dev->irq < 2 && lp->eepro != 0) {
/* Mask off INT number */
- int count = read_eeprom(ioaddr, 1, dev) & 7;
- unsigned irqMask = read_eeprom(ioaddr, 7, dev);
+ int count = lp->word[1] & 7;
+ unsigned irqMask = lp->word[7];
while (count--)
irqMask &= irqMask - 1;
@@ -850,6 +866,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
dev->set_multicast_list = &set_multicast_list;
dev->tx_timeout = eepro_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ dev->ethtool_ops = &eepro_ethtool_ops;
/* print boot time info */
eepro_print_info(dev);
@@ -941,7 +958,7 @@ static int eepro_open(struct net_device *dev)
if (net_debug > 3)
printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
- irqMask = read_eeprom(ioaddr,7,dev);
+ irqMask = lp->word[7];
if (lp->eepro == LAN595FX_10ISA) {
if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
@@ -1070,8 +1087,6 @@ static int eepro_open(struct net_device *dev)
old9 = inb(ioaddr + 9);
if (irqMask==ee_FX_INT2IRQ) {
- enum iftype { AUI=0, BNC=1, TPE=2 };
-
if (net_debug > 3) {
printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
printk(KERN_DEBUG "i82595FX detected!\n");
@@ -1701,12 +1716,72 @@ eepro_transmit_interrupt(struct net_device *dev)
}
}
+static int eepro_ethtool_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
+
+ cmd->supported = SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_Autoneg;
+ cmd->advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_Autoneg;
+
+ if (GetBit(lp->word[5], ee_PortTPE)) {
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_TP;
+ }
+ if (GetBit(lp->word[5], ee_PortBNC)) {
+ cmd->supported |= SUPPORTED_BNC;
+ cmd->advertising |= ADVERTISED_BNC;
+ }
+ if (GetBit(lp->word[5], ee_PortAUI)) {
+ cmd->supported |= SUPPORTED_AUI;
+ cmd->advertising |= ADVERTISED_AUI;
+ }
+
+ cmd->speed = SPEED_10;
+
+ if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {
+ cmd->duplex = DUPLEX_FULL;
+ }
+ else {
+ cmd->duplex = DUPLEX_HALF;
+ }
+
+ cmd->port = dev->if_port;
+ cmd->phy_address = dev->base_addr;
+ cmd->transceiver = XCVR_INTERNAL;
+
+ if (lp->word[0] & ee_AutoNeg) {
+ cmd->autoneg = 1;
+ }
+
+ return 0;
+}
+
+static void eepro_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strcpy(drvinfo->driver, DRV_NAME);
+ strcpy(drvinfo->version, DRV_VERSION);
+ sprintf(drvinfo->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static struct ethtool_ops eepro_ethtool_ops = {
+ .get_settings = eepro_ethtool_get_settings,
+ .get_drvinfo = eepro_ethtool_get_drvinfo,
+};
+
#ifdef MODULE
#define MAX_EEPRO 8
static struct net_device *dev_eepro[MAX_EEPRO];
-static int io[MAX_EEPRO];
+static int io[MAX_EEPRO] = {
+ [0 ... MAX_EEPRO-1] = -1
+};
static int irq[MAX_EEPRO];
static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */
[0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
@@ -1716,14 +1791,15 @@ static int autodetect;
static int n_eepro;
/* For linux 2.1.xx */
-MODULE_AUTHOR("Pascal Dupuis, and aris@cathedrallabs.org");
+MODULE_AUTHOR("Pascal Dupuis and others");
MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i");
+static int num_params;
+module_param_array(io, int, &num_params, 0);
+module_param_array(irq, int, &num_params, 0);
+module_param_array(mem, int, &num_params, 0);
+module_param(autodetect, int, 0);
MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
@@ -1734,19 +1810,21 @@ init_module(void)
{
struct net_device *dev;
int i;
- if (io[0] == 0 && autodetect == 0) {
+ if (io[0] == -1 && autodetect == 0) {
printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
- return 1;
+ return -ENODEV;
}
else if (autodetect) {
/* if autodetect is set then we must force detection */
- io[0] = 0;
+ for (i = 0; i < MAX_EEPRO; i++) {
+ io[i] = 0;
+ }
printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
}
- for (i = 0; i < MAX_EEPRO; i++) {
+ for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {
dev = alloc_etherdev(sizeof(struct eepro_local));
if (!dev)
break;
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 7436af6055acdd..9d9b59e61351a8 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -98,7 +98,7 @@ typedef struct emac_regs {
#endif /* CONFIG_IBM_EMAC4 */
#define EMAC_M1_BASE (EMAC_M1_TX_FIFO_2K | \
EMAC_M1_APP | \
- EMAC_M1_TR)
+ EMAC_M1_TR | EMAC_M1_VLE)
/* Transmit Mode Register 0 */
#define EMAC_TMR0_GNP0 0x80000000
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 39c65064c04608..7346ab066dbcea 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1363,6 +1363,9 @@ static void emac_reset_configure(struct ocp_enet_private *fep)
/* set frame gap */
out_be32(&emacp->em0ipgvr, CONFIG_IBM_EMAC_FGAP);
+
+ /* set VLAN Tag Protocol Identifier */
+ out_be32(&emacp->em0vtpid, 0x8100);
/* Init ring buffers */
emac_init_rings(fep->ndev);
@@ -1700,6 +1703,15 @@ struct mal_commac_ops emac_commac_ops = {
.rxde = &emac_rxde_dev,
};
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static int emac_netpoll(struct net_device *ndev)
+{
+ emac_rxeob_dev((void *)ndev, 0);
+ emac_txeob_dev((void *)ndev, 0);
+ return 0;
+}
+#endif
+
static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
{
int deferred_init = 0;
@@ -1882,6 +1894,9 @@ static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
if (emacdata->tah_idx >= 0)
ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = emac_netpoll;
+#endif
SET_MODULE_OWNER(ndev);
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c
index b439087df8ec28..14213f090e914b 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.c
+++ b/drivers/net/ibm_emac/ibm_emac_phy.c
@@ -191,17 +191,18 @@ static int genmii_read_link(struct mii_phy *phy)
u16 lpa;
if (phy->autoneg) {
- lpa = phy_read(phy, MII_LPA);
+ lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
- if (lpa & (LPA_10FULL | LPA_100FULL))
- phy->duplex = DUPLEX_FULL;
- else
- phy->duplex = DUPLEX_HALF;
- if (lpa & (LPA_100FULL | LPA_100HALF))
- phy->speed = SPEED_100;
- else
- phy->speed = SPEED_10;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
phy->pause = 0;
+
+ if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phy->speed = SPEED_100;
+ if (lpa & LPA_100FULL)
+ phy->duplex = DUPLEX_FULL;
+ } else if (lpa & LPA_10FULL)
+ phy->duplex = DUPLEX_FULL;
}
/* On non-aneg, we assume what we put in BMCR is the speed,
* though magic-aneg shouldn't prevent this case from occurring
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index d5c6f477f91676..3426020a915b58 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -46,6 +46,7 @@
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/pagemap.h>
@@ -85,6 +86,20 @@ struct ixgb_adapter;
#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+/* TX/RX descriptor defines */
+#define DEFAULT_TXD 256
+#define MAX_TXD 4096
+#define MIN_TXD 64
+
+/* hardware cannot reliably support more than 512 descriptors owned by
+ * hardware descrioptor cache otherwise an unreliable ring under heavy
+ * recieve load may result */
+/* #define DEFAULT_RXD 1024 */
+/* #define MAX_RXD 4096 */
+#define DEFAULT_RXD 512
+#define MAX_RXD 512
+#define MIN_RXD 64
+
/* Supported Rx Buffer Sizes */
#define IXGB_RXBUFFER_2048 2048
#define IXGB_RXBUFFER_4096 4096
@@ -105,9 +120,9 @@ struct ixgb_adapter;
struct ixgb_buffer {
struct sk_buff *skb;
uint64_t dma;
- unsigned long length;
unsigned long time_stamp;
- unsigned int next_to_watch;
+ uint16_t length;
+ uint16_t next_to_watch;
};
struct ixgb_desc_ring {
@@ -167,7 +182,6 @@ struct ixgb_adapter {
uint64_t hw_csum_rx_error;
uint64_t hw_csum_rx_good;
uint32_t rx_int_delay;
- boolean_t raidc;
boolean_t rx_csum;
/* OS defined structs */
@@ -178,5 +192,8 @@ struct ixgb_adapter {
/* structs defined in ixgb_hw.h */
struct ixgb_hw hw;
struct ixgb_hw_stats stats;
+#ifdef CONFIG_PCI_MSI
+ boolean_t have_msi;
+#endif
};
-#endif /* _IXGB_H_ */
+#endif /* _IXGB_H_ */
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index c8adde5c9b302f..97b5b1665ed6af 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -32,7 +32,8 @@
static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);
static void ixgb_shift_out_bits(struct ixgb_hw *hw,
- uint16_t data, uint16_t count);
+ uint16_t data,
+ uint16_t count);
static void ixgb_standby_eeprom(struct ixgb_hw *hw);
static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
@@ -45,7 +46,9 @@ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
* hw - Struct containing variables accessed by shared code
* eecd_reg - EECD's current value
*****************************************************************************/
-static void ixgb_raise_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
+static void
+ixgb_raise_clock(struct ixgb_hw *hw,
+ uint32_t *eecd_reg)
{
/* Raise the clock input to the EEPROM (by setting the SK bit), and then
* wait 50 microseconds.
@@ -62,7 +65,9 @@ static void ixgb_raise_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
* hw - Struct containing variables accessed by shared code
* eecd_reg - EECD's current value
*****************************************************************************/
-static void ixgb_lower_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
+static void
+ixgb_lower_clock(struct ixgb_hw *hw,
+ uint32_t *eecd_reg)
{
/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
* wait 50 microseconds.
@@ -81,7 +86,9 @@ static void ixgb_lower_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
* count - number of bits to shift out
*****************************************************************************/
static void
-ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
+ixgb_shift_out_bits(struct ixgb_hw *hw,
+ uint16_t data,
+ uint16_t count)
{
uint32_t eecd_reg;
uint32_t mask;
@@ -101,7 +108,7 @@ ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
*/
eecd_reg &= ~IXGB_EECD_DI;
- if (data & mask)
+ if(data & mask)
eecd_reg |= IXGB_EECD_DI;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
@@ -113,7 +120,7 @@ ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
mask = mask >> 1;
- } while (mask);
+ } while(mask);
/* We leave the "DI" bit set to "0" when we leave this routine. */
eecd_reg &= ~IXGB_EECD_DI;
@@ -126,7 +133,8 @@ ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw)
+static uint16_t
+ixgb_shift_in_bits(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
uint32_t i;
@@ -144,14 +152,14 @@ static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw)
eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
data = 0;
- for (i = 0; i < 16; i++) {
+ for(i = 0; i < 16; i++) {
data = data << 1;
ixgb_raise_clock(hw, &eecd_reg);
eecd_reg = IXGB_READ_REG(hw, EECD);
eecd_reg &= ~(IXGB_EECD_DI);
- if (eecd_reg & IXGB_EECD_DO)
+ if(eecd_reg & IXGB_EECD_DO)
data |= 1;
ixgb_lower_clock(hw, &eecd_reg);
@@ -168,7 +176,8 @@ static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw)
* Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
* function should be called before issuing a command to the EEPROM.
*****************************************************************************/
-static void ixgb_setup_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_setup_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -189,7 +198,8 @@ static void ixgb_setup_eeprom(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_standby_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_standby_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -222,7 +232,8 @@ static void ixgb_standby_eeprom(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_clock_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_clock_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -245,7 +256,8 @@ static void ixgb_clock_eeprom(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_cleanup_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -270,7 +282,8 @@ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw)
* TRUE: EEPROM data pin is high before timeout.
* FALSE: Time expired.
*****************************************************************************/
-static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+static boolean_t
+ixgb_wait_eeprom_command(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
uint32_t i;
@@ -284,10 +297,10 @@ static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw)
* signal that the command has been completed by raising the DO signal.
* If DO does not go high in 10 milliseconds, then error out.
*/
- for (i = 0; i < 200; i++) {
+ for(i = 0; i < 200; i++) {
eecd_reg = IXGB_READ_REG(hw, EECD);
- if (eecd_reg & IXGB_EECD_DO)
+ if(eecd_reg & IXGB_EECD_DO)
return (TRUE);
udelay(50);
@@ -309,15 +322,16 @@ static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw)
* TRUE: Checksum is valid
* FALSE: Checksum is not valid.
*****************************************************************************/
-boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw * hw)
+boolean_t
+ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
{
uint16_t checksum = 0;
uint16_t i;
- for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+ for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
checksum += ixgb_read_eeprom(hw, i);
- if (checksum == (uint16_t) EEPROM_SUM)
+ if(checksum == (uint16_t) EEPROM_SUM)
return (TRUE);
else
return (FALSE);
@@ -331,12 +345,13 @@ boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw * hw)
* Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
* Writes the difference to word offset 63 of the EEPROM.
*****************************************************************************/
-void ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+void
+ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
{
uint16_t checksum = 0;
uint16_t i;
- for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
checksum += ixgb_read_eeprom(hw, i);
checksum = (uint16_t) EEPROM_SUM - checksum;
@@ -356,7 +371,10 @@ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
* EEPROM will most likely contain an invalid checksum.
*
*****************************************************************************/
-void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
+void
+ixgb_write_eeprom(struct ixgb_hw *hw,
+ uint16_t offset,
+ uint16_t data)
{
/* Prepare the EEPROM for writing */
ixgb_setup_eeprom(hw);
@@ -404,7 +422,9 @@ void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
* Returns:
* The 16-bit value read from the eeprom
*****************************************************************************/
-uint16_t ixgb_read_eeprom(struct ixgb_hw * hw, uint16_t offset)
+uint16_t
+ixgb_read_eeprom(struct ixgb_hw *hw,
+ uint16_t offset)
{
uint16_t data;
@@ -437,7 +457,8 @@ uint16_t ixgb_read_eeprom(struct ixgb_hw * hw, uint16_t offset)
* TRUE: if eeprom read is successful
* FALSE: otherwise.
*****************************************************************************/
-boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
+boolean_t
+ixgb_get_eeprom_data(struct ixgb_hw *hw)
{
uint16_t i;
uint16_t checksum = 0;
@@ -448,7 +469,7 @@ boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
DEBUGOUT("ixgb_ee: Reading eeprom data\n");
- for (i = 0; i < IXGB_EEPROM_SIZE; i++) {
+ for(i = 0; i < IXGB_EEPROM_SIZE ; i++) {
uint16_t ee_data;
ee_data = ixgb_read_eeprom(hw, i);
checksum += ee_data;
@@ -461,12 +482,12 @@ boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
}
if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
- != le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
+ != le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
DEBUGOUT("ixgb_ee: Signature invalid.\n");
- return (FALSE);
+ return(FALSE);
}
- return (TRUE);
+ return(TRUE);
}
/******************************************************************************
@@ -479,7 +500,8 @@ boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
* TRUE: eeprom signature was good and the eeprom read was successful
* FALSE: otherwise.
******************************************************************************/
-static boolean_t ixgb_check_and_get_eeprom_data(struct ixgb_hw *hw)
+static boolean_t
+ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
@@ -500,15 +522,16 @@ static boolean_t ixgb_check_and_get_eeprom_data(struct ixgb_hw *hw)
* Returns:
* Word at indexed offset in eeprom, if valid, 0 otherwise.
******************************************************************************/
-uint16_t ixgb_get_eeprom_word(struct ixgb_hw * hw, uint16_t index)
+uint16_t
+ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
{
if ((index < IXGB_EEPROM_SIZE) &&
- (ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
- return (hw->eeprom[index]);
+ (ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
+ return(hw->eeprom[index]);
}
- return (0);
+ return(0);
}
/******************************************************************************
@@ -519,7 +542,9 @@ uint16_t ixgb_get_eeprom_word(struct ixgb_hw * hw, uint16_t index)
*
* Returns: None.
******************************************************************************/
-void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t * mac_addr)
+void
+ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+ uint8_t *mac_addr)
{
int i;
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
@@ -542,14 +567,15 @@ void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t * mac_addr)
* Returns:
* compatibility flags if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw)
+uint16_t
+ixgb_get_ee_compatibility(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->compatibility);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->compatibility);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -560,13 +586,14 @@ uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw)
* Returns:
* PBA number if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint32_t ixgb_get_ee_pba_number(struct ixgb_hw * hw)
+uint32_t
+ixgb_get_ee_pba_number(struct ixgb_hw *hw)
{
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
- | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG]) << 16));
+ | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
- return (0);
+ return(0);
}
/******************************************************************************
@@ -577,14 +604,15 @@ uint32_t ixgb_get_ee_pba_number(struct ixgb_hw * hw)
* Returns:
* Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->init_ctrl_reg_1);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->init_ctrl_reg_1);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -595,14 +623,15 @@ uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw * hw)
* Returns:
* Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->init_ctrl_reg_2);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->init_ctrl_reg_2);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -613,14 +642,15 @@ uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw * hw)
* Returns:
* Subsystem Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->subsystem_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->subsystem_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -631,14 +661,15 @@ uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw * hw)
* Returns:
* Sub Vendor Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->subvendor_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->subvendor_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -649,14 +680,15 @@ uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw * hw)
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_device_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_device_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->device_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->device_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -667,14 +699,15 @@ uint16_t ixgb_get_ee_device_id(struct ixgb_hw * hw)
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->vendor_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->vendor_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -685,14 +718,15 @@ uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw * hw)
* Returns:
* SDP Register if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->swdpins_reg);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->swdpins_reg);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -703,14 +737,15 @@ uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw * hw)
* Returns:
* D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint8_t ixgb_get_ee_d3_power(struct ixgb_hw * hw)
+uint8_t
+ixgb_get_ee_d3_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->d3_power);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->d3_power);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -721,12 +756,13 @@ uint8_t ixgb_get_ee_d3_power(struct ixgb_hw * hw)
* Returns:
* D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint8_t ixgb_get_ee_d0_power(struct ixgb_hw * hw)
+uint8_t
+ixgb_get_ee_d0_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->d0_power);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->d0_power);
- return (0);
+ return(0);
}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index e455a5f32164d3..e3ba1410af48fb 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -37,6 +37,12 @@ extern char ixgb_driver_version[];
extern int ixgb_up(struct ixgb_adapter *adapter);
extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+extern void ixgb_reset(struct ixgb_adapter *adapter);
+extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_update_stats(struct ixgb_adapter *adapter);
struct ixgb_stats {
char stat_string[ETH_GSTRING_LEN];
@@ -89,7 +95,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats)
static int
-ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
+ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct ixgb_adapter *adapter = netdev->priv;
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
@@ -97,7 +103,7 @@ ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
- if (netif_carrier_ok(adapter->netdev)) {
+ if(netif_carrier_ok(adapter->netdev)) {
ecmd->speed = SPEED_10000;
ecmd->duplex = DUPLEX_FULL;
} else {
@@ -110,86 +116,140 @@ ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
}
static int
-ixgb_ethtool_sset(struct net_device *netdev, struct ethtool_cmd *ecmd)
+ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct ixgb_adapter *adapter = netdev->priv;
- if (ecmd->autoneg == AUTONEG_ENABLE ||
- ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
+ if(ecmd->autoneg == AUTONEG_ENABLE ||
+ ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
return -EINVAL;
- else {
+
+ if(netif_running(adapter->netdev)) {
ixgb_down(adapter, TRUE);
+ ixgb_reset(adapter);
ixgb_up(adapter);
- }
+ } else
+ ixgb_reset(adapter);
+
return 0;
}
static void
-ixgb_ethtool_gpause(struct net_device *dev,
- struct ethtool_pauseparam *epause)
+ixgb_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
-
- epause->autoneg = AUTONEG_DISABLE;
-
- if (hw->fc.type == ixgb_fc_rx_pause)
- epause->rx_pause = 1;
- else if (hw->fc.type == ixgb_fc_tx_pause)
- epause->tx_pause = 1;
- else if (hw->fc.type == ixgb_fc_full) {
- epause->rx_pause = 1;
- epause->tx_pause = 1;
+
+ pause->autoneg = AUTONEG_DISABLE;
+
+ if(hw->fc.type == ixgb_fc_rx_pause)
+ pause->rx_pause = 1;
+ else if(hw->fc.type == ixgb_fc_tx_pause)
+ pause->tx_pause = 1;
+ else if(hw->fc.type == ixgb_fc_full) {
+ pause->rx_pause = 1;
+ pause->tx_pause = 1;
}
}
static int
-ixgb_ethtool_spause(struct net_device *dev,
- struct ethtool_pauseparam *epause)
+ixgb_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
-
- if (epause->autoneg == AUTONEG_ENABLE)
+
+ if(pause->autoneg == AUTONEG_ENABLE)
return -EINVAL;
- if (epause->rx_pause && epause->tx_pause)
+ if(pause->rx_pause && pause->tx_pause)
hw->fc.type = ixgb_fc_full;
- else if (epause->rx_pause && !epause->tx_pause)
+ else if(pause->rx_pause && !pause->tx_pause)
hw->fc.type = ixgb_fc_rx_pause;
- else if (!epause->rx_pause && epause->tx_pause)
+ else if(!pause->rx_pause && pause->tx_pause)
hw->fc.type = ixgb_fc_tx_pause;
- else if (!epause->rx_pause && !epause->tx_pause)
+ else if(!pause->rx_pause && !pause->tx_pause)
hw->fc.type = ixgb_fc_none;
- ixgb_down(adapter, TRUE);
- ixgb_up(adapter);
-
+ if(netif_running(adapter->netdev)) {
+ ixgb_down(adapter, TRUE);
+ ixgb_up(adapter);
+ } else
+ ixgb_reset(adapter);
+
return 0;
}
-static void
-ixgb_ethtool_gdrvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
+static uint32_t
+ixgb_get_rx_csum(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
- strncpy(drvinfo->driver, ixgb_driver_name, 32);
- strncpy(drvinfo->version, ixgb_driver_version, 32);
- strncpy(drvinfo->fw_version, "N/A", 32);
- strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ return adapter->rx_csum;
+}
+
+static int
+ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+ adapter->rx_csum = data;
+
+ if(netif_running(netdev)) {
+ ixgb_down(adapter,TRUE);
+ ixgb_up(adapter);
+ } else
+ ixgb_reset(adapter);
+ return 0;
+}
+
+static uint32_t
+ixgb_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
}
+static int
+ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
+
+#ifdef NETIF_F_TSO
+static int
+ixgb_set_tso(struct net_device *netdev, uint32_t data)
+{
+ if(data)
+ netdev->features |= NETIF_F_TSO;
+ else
+ netdev->features &= ~NETIF_F_TSO;
+ return 0;
+}
+#endif /* NETIF_F_TSO */
+
#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
+
+static int
+ixgb_get_regs_len(struct net_device *netdev)
+{
+#define IXGB_REG_DUMP_LEN 136*sizeof(uint32_t)
+ return IXGB_REG_DUMP_LEN;
+}
+
static void
-ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+ixgb_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
- uint32_t *reg = buf;
+ uint32_t *reg = p;
uint32_t *reg_start = reg;
uint8_t i;
- regs->version =
- (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
+ regs->version = (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
/* General Registers */
*reg++ = IXGB_READ_REG(hw, CTRL0); /* 0 */
@@ -219,8 +279,8 @@ ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
*reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */
for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
- *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
- *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
+ *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
+ *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
}
/* Transmit */
@@ -316,73 +376,222 @@ ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
}
static int
-ixgb_ethtool_geeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
+ixgb_get_eeprom_len(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = dev->priv;
+ /* return size in bytes */
+ return (IXGB_EEPROM_SIZE << 1);
+}
+
+static int
+ixgb_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, uint8_t *bytes)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
+ uint16_t *eeprom_buff;
+ int i, max_len, first_word, last_word;
+ int ret_val = 0;
+
+ if(eeprom->len == 0) {
+ ret_val = -EINVAL;
+ goto geeprom_error;
+ }
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
- /* use our function to read the eeprom and update our cache */
- ixgb_get_eeprom_data(hw);
- memcpy(data, (char *)hw->eeprom + eeprom->offset, eeprom->len);
- return 0;
+ max_len = ixgb_get_eeprom_len(netdev);
+
+ if(eeprom->offset > eeprom->offset + eeprom->len) {
+ ret_val = -EINVAL;
+ goto geeprom_error;
+ }
+
+ if((eeprom->offset + eeprom->len) > max_len)
+ eeprom->len = (max_len - eeprom->offset);
+
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+ eeprom_buff = kmalloc(sizeof(uint16_t) *
+ (last_word - first_word + 1), GFP_KERNEL);
+ if(!eeprom_buff)
+ return -ENOMEM;
+
+ /* note the eeprom was good because the driver loaded */
+ for(i = 0; i <= (last_word - first_word); i++) {
+ eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
+ }
+
+ memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+geeprom_error:
+ return ret_val;
}
static int
-ixgb_ethtool_seeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
+ixgb_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
- /* We are under rtnl, so static is OK */
- static uint16_t eeprom_buff[IXGB_EEPROM_SIZE];
- int i, first_word, last_word;
- char *ptr;
+ uint16_t *eeprom_buff;
+ void *ptr;
+ int max_len, first_word, last_word;
+ uint16_t i;
+
+ if(eeprom->len == 0)
+ return -EINVAL;
- if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
+ max_len = ixgb_get_eeprom_len(netdev);
+
+ if(eeprom->offset > eeprom->offset + eeprom->len)
+ return -EINVAL;
+
+ if((eeprom->offset + eeprom->len) > max_len)
+ eeprom->len = (max_len - eeprom->offset);
+
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- ptr = (char *)eeprom_buff;
+ eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+ if(!eeprom_buff)
+ return -ENOMEM;
- if (eeprom->offset & 1) {
+ ptr = (void *)eeprom_buff;
+
+ if(eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
ptr++;
}
- if ((eeprom->offset + eeprom->len) & 1) {
+ if((eeprom->offset + eeprom->len) & 1) {
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
- eeprom_buff[last_word - first_word]
- = ixgb_read_eeprom(hw, last_word);
+ eeprom_buff[last_word - first_word]
+ = ixgb_read_eeprom(hw, last_word);
}
- memcpy(ptr, data, eeprom->len);
- for (i = 0; i <= (last_word - first_word); i++)
+ memcpy(ptr, bytes, eeprom->len);
+ for(i = 0; i <= (last_word - first_word); i++)
ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
/* Update the checksum over the first part of the EEPROM if needed */
- if (first_word <= EEPROM_CHECKSUM_REG)
+ if(first_word <= EEPROM_CHECKSUM_REG)
ixgb_update_eeprom_checksum(hw);
+ kfree(eeprom_buff);
return 0;
}
+static void
+ixgb_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+
+ strncpy(drvinfo->driver, ixgb_driver_name, 32);
+ strncpy(drvinfo->version, ixgb_driver_version, 32);
+ strncpy(drvinfo->fw_version, "N/A", 32);
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ drvinfo->n_stats = IXGB_STATS_LEN;
+ drvinfo->regdump_len = ixgb_get_regs_len(netdev);
+ drvinfo->eedump_len = ixgb_get_eeprom_len(netdev);
+}
+
+static void
+ixgb_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+ struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+
+ ring->rx_max_pending = MAX_RXD;
+ ring->tx_max_pending = MAX_TXD;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = rxdr->count;
+ ring->tx_pending = txdr->count;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+static int
+ixgb_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+ struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+ struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
+ int err;
+
+ tx_old = adapter->tx_ring;
+ rx_old = adapter->rx_ring;
+
+ if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ return -EINVAL;
+
+ if(netif_running(adapter->netdev))
+ ixgb_down(adapter,TRUE);
+
+ rxdr->count = max(ring->rx_pending,(uint32_t)MIN_RXD);
+ rxdr->count = min(rxdr->count,(uint32_t)MAX_RXD);
+ IXGB_ROUNDUP(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+ txdr->count = max(ring->tx_pending,(uint32_t)MIN_TXD);
+ txdr->count = min(txdr->count,(uint32_t)MAX_TXD);
+ IXGB_ROUNDUP(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+ if(netif_running(adapter->netdev)) {
+ /* Try to get new resources before deleting old */
+ if((err = ixgb_setup_rx_resources(adapter)))
+ goto err_setup_rx;
+ if((err = ixgb_setup_tx_resources(adapter)))
+ goto err_setup_tx;
+
+ /* save the new, restore the old in order to free it,
+ * then restore the new back again */
+
+ rx_new = adapter->rx_ring;
+ tx_new = adapter->tx_ring;
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ ixgb_free_rx_resources(adapter);
+ ixgb_free_tx_resources(adapter);
+ adapter->rx_ring = rx_new;
+ adapter->tx_ring = tx_new;
+ if((err = ixgb_up(adapter)))
+ return err;
+ }
+
+ return 0;
+err_setup_tx:
+ ixgb_free_rx_resources(adapter);
+err_setup_rx:
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ ixgb_up(adapter);
+ return err;
+}
+
/* toggle LED 4 times per second = 2 "blinks" per second */
#define IXGB_ID_INTERVAL (HZ/4)
/* bit defines for adapter->led_status */
#define IXGB_LED_ON 0
-static void ixgb_led_blink_callback(unsigned long data)
+static void
+ixgb_led_blink_callback(unsigned long data)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
- if (test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
+ if(test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
ixgb_led_off(&adapter->hw);
else
ixgb_led_on(&adapter->hw);
@@ -391,10 +600,14 @@ static void ixgb_led_blink_callback(unsigned long data)
}
static int
-ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
+ixgb_phys_id(struct net_device *netdev, uint32_t data)
{
struct ixgb_adapter *adapter = netdev->priv;
- if (!adapter->blink_timer.function) {
+
+ if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+ data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+ if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = ixgb_led_blink_callback;
adapter->blink_timer.data = (unsigned long)adapter;
@@ -403,7 +616,7 @@ ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
mod_timer(&adapter->blink_timer, jiffies);
set_current_state(TASK_INTERRUPTIBLE);
- if (data)
+ if(data)
schedule_timeout(data * HZ);
else
schedule_timeout(MAX_SCHEDULE_TIMEOUT);
@@ -415,141 +628,74 @@ ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
return 0;
}
-static int ixgb_nway_reset(struct net_device *netdev)
-{
- if (netif_running(netdev)) {
- struct ixgb_adapter *adapter = netdev->priv;
- ixgb_down(adapter, TRUE);
- ixgb_up(adapter);
- }
- return 0;
-}
-
-static int ixgb_get_stats_count(struct net_device *dev)
+static int
+ixgb_get_stats_count(struct net_device *netdev)
{
return IXGB_STATS_LEN;
}
-static void ixgb_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+static void
+ixgb_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, uint64_t *data)
{
+ struct ixgb_adapter *adapter = netdev->priv;
int i;
- for (i = 0; i < IXGB_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- ixgb_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
- }
-}
-static int ixgb_get_regs_len(struct net_device *dev)
-{
- return 136*sizeof(uint32_t);
-}
-
-static int ixgb_get_eeprom_len(struct net_device *dev)
-{
- /* return size in bytes */
- return (IXGB_EEPROM_SIZE << 1);
+ ixgb_update_stats(adapter);
+ for(i = 0; i < IXGB_STATS_LEN; i++) {
+ char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;
+ data[i] = (ixgb_gstrings_stats[i].sizeof_stat ==
+ sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
+ }
}
-static void get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
+static void
+ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
{
- struct ixgb_adapter *adapter = dev->priv;
int i;
- for (i = 0; i < IXGB_STATS_LEN; i++) {
- void *p = (char *)adapter + ixgb_gstrings_stats[i].stat_offset;
- stats->data[i] =
- (ixgb_gstrings_stats[i].sizeof_stat == sizeof(uint64_t))
- ? *(uint64_t *) p
- : *(uint32_t *) p;
+ switch(stringset) {
+ case ETH_SS_STATS:
+ for(i=0; i < IXGB_STATS_LEN; i++) {
+ memcpy(data + i * ETH_GSTRING_LEN,
+ ixgb_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ }
+ break;
}
}
-static u32 ixgb_get_rx_csum(struct net_device *dev)
-{
- struct ixgb_adapter *adapter = dev->priv;
- return adapter->rx_csum;
-}
-
-static int ixgb_set_rx_csum(struct net_device *dev, u32 sum)
-{
- struct ixgb_adapter *adapter = dev->priv;
- adapter->rx_csum = sum;
- ixgb_down(adapter, TRUE);
- ixgb_up(adapter);
- return 0;
-}
-
-static u32 ixgb_get_tx_csum(struct net_device *dev)
-{
- return (dev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int ixgb_set_tx_csum(struct net_device *dev, u32 sum)
-{
- if (sum)
- dev->features |= NETIF_F_HW_CSUM;
- else
- dev->features &= ~NETIF_F_HW_CSUM;
- return 0;
-}
-
-static u32 ixgb_get_sg(struct net_device *dev)
-{
- return (dev->features & NETIF_F_SG) != 0;
-}
-
-static int ixgb_set_sg(struct net_device *dev, u32 sum)
-{
- if (sum)
- dev->features |= NETIF_F_SG;
- else
- dev->features &= ~NETIF_F_SG;
- return 0;
-}
-
-#ifdef NETIF_F_TSO
-static u32 ixgb_get_tso(struct net_device *dev)
-{
- return (dev->features & NETIF_F_TSO) != 0;
-}
-
-static int ixgb_set_tso(struct net_device *dev, u32 sum)
-{
- if (sum)
- dev->features |= NETIF_F_TSO;
- else
- dev->features &= ~NETIF_F_TSO;
- return 0;
-}
-#endif
-
struct ethtool_ops ixgb_ethtool_ops = {
- .get_settings = ixgb_ethtool_gset,
- .set_settings = ixgb_ethtool_sset,
- .get_drvinfo = ixgb_ethtool_gdrvinfo,
- .nway_reset = ixgb_nway_reset,
- .get_link = ethtool_op_get_link,
- .phys_id = ixgb_ethtool_led_blink,
- .get_strings = ixgb_get_strings,
- .get_stats_count = ixgb_get_stats_count,
- .get_regs = ixgb_ethtool_gregs,
+ .get_settings = ixgb_get_settings,
+ .set_settings = ixgb_set_settings,
+ .get_drvinfo = ixgb_get_drvinfo,
.get_regs_len = ixgb_get_regs_len,
+ .get_regs = ixgb_get_regs,
+ .get_link = ethtool_op_get_link,
.get_eeprom_len = ixgb_get_eeprom_len,
- .get_eeprom = ixgb_ethtool_geeprom,
- .set_eeprom = ixgb_ethtool_seeprom,
- .get_pauseparam = ixgb_ethtool_gpause,
- .set_pauseparam = ixgb_ethtool_spause,
- .get_ethtool_stats = get_ethtool_stats,
+ .get_eeprom = ixgb_get_eeprom,
+ .set_eeprom = ixgb_set_eeprom,
+ .get_ringparam = ixgb_get_ringparam,
+ .set_ringparam = ixgb_set_ringparam,
+ .get_pauseparam = ixgb_get_pauseparam,
+ .set_pauseparam = ixgb_set_pauseparam,
.get_rx_csum = ixgb_get_rx_csum,
.set_rx_csum = ixgb_set_rx_csum,
.get_tx_csum = ixgb_get_tx_csum,
.set_tx_csum = ixgb_set_tx_csum,
- .get_sg = ixgb_get_sg,
- .set_sg = ixgb_set_sg,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
#ifdef NETIF_F_TSO
- .get_tso = ixgb_get_tso,
+ .get_tso = ethtool_op_get_tso,
.set_tso = ixgb_set_tso,
#endif
+ .get_strings = ixgb_get_strings,
+ .phys_id = ixgb_phys_id,
+ .get_stats_count = ixgb_get_stats_count,
+ .get_ethtool_stats = ixgb_get_ethtool_stats,
};
+
+void ixgb_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
+}
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index b9998af78ddd3e..230f0d80d2f244 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -53,9 +53,14 @@ uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
- ctrl_reg = IXGB_CTRL0_RST | IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
- IXGB_CTRL0_SDP2_DIR | IXGB_CTRL0_SDP1_DIR | IXGB_CTRL0_SDP0_DIR | IXGB_CTRL0_SDP3 | /* Initial value 1101 */
- IXGB_CTRL0_SDP2 | IXGB_CTRL0_SDP0;
+ ctrl_reg = IXGB_CTRL0_RST |
+ IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
+ IXGB_CTRL0_SDP2_DIR |
+ IXGB_CTRL0_SDP1_DIR |
+ IXGB_CTRL0_SDP0_DIR |
+ IXGB_CTRL0_SDP3 | /* Initial value 1101 */
+ IXGB_CTRL0_SDP2 |
+ IXGB_CTRL0_SDP0;
#ifdef HP_ZX1
/* Workaround for 82597EX reset errata */
@@ -84,7 +89,8 @@ uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
+boolean_t
+ixgb_adapter_stop(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
uint32_t icr_reg;
@@ -94,7 +100,7 @@ boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
/* If we are stopped or resetting exit gracefully and wait to be
* started again before accessing the hardware.
*/
- if (hw->adapter_stopped) {
+ if(hw->adapter_stopped) {
DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
return FALSE;
}
@@ -135,6 +141,7 @@ boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
return (ctrl_reg & IXGB_CTRL0_RST);
}
+
/******************************************************************************
* Identifies the vendor of the optics module on the adapter. The SR adapters
* support two different types of XPAK optics, so it is necessary to determine
@@ -144,7 +151,8 @@ boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
*
* Returns: the vendor of the XPAK optics module.
*****************************************************************************/
-static ixgb_xpak_vendor ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
+static ixgb_xpak_vendor
+ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
{
uint32_t i;
uint16_t vendor_name[5];
@@ -183,7 +191,8 @@ static ixgb_xpak_vendor ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
*
* Returns: the phy type of the adapter.
*****************************************************************************/
-static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
+static ixgb_phy_type
+ixgb_identify_phy(struct ixgb_hw *hw)
{
ixgb_phy_type phy_type;
ixgb_xpak_vendor xpak_vendor;
@@ -210,7 +219,10 @@ static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
phy_type = ixgb_phy_type_g6005;
}
break;
-
+ case IXGB_DEVICE_ID_82597EX_LR:
+ DEBUGOUT("Identified G6104 optics\n");
+ phy_type = ixgb_phy_type_g6104;
+ break;
default:
DEBUGOUT("Unknown physical layer module\n");
phy_type = ixgb_phy_type_unknown;
@@ -237,7 +249,8 @@ static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
* TRUE if successful,
* FALSE if unrecoverable problems were encountered.
*****************************************************************************/
-boolean_t ixgb_init_hw(struct ixgb_hw * hw)
+boolean_t
+ixgb_init_hw(struct ixgb_hw *hw)
{
uint32_t i;
uint32_t ctrl_reg;
@@ -266,7 +279,7 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
msec_delay(IXGB_DELAY_AFTER_EE_RESET);
if (ixgb_get_eeprom_data(hw) == FALSE) {
- return (FALSE);
+ return(FALSE);
}
/* Use the device id to determine the type of phy/transceiver. */
@@ -284,7 +297,7 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
*/
if (!mac_addr_valid(hw->curr_mac_addr)) {
DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
- return (FALSE);
+ return(FALSE);
}
/* tell the routines in this file they can access hardware again */
@@ -295,7 +308,7 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
- for (i = 0; i < IXGB_MC_TBL_SIZE; i++)
+ for(i = 0; i < IXGB_MC_TBL_SIZE; i++)
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* Zero out the VLAN Filter Table Array */
@@ -322,7 +335,8 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
* of the receive addresss registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*****************************************************************************/
-void ixgb_init_rx_addrs(struct ixgb_hw *hw)
+void
+ixgb_init_rx_addrs(struct ixgb_hw *hw)
{
uint32_t i;
@@ -360,7 +374,7 @@ void ixgb_init_rx_addrs(struct ixgb_hw *hw)
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
- for (i = 1; i < IXGB_RAR_ENTRIES; i++) {
+ for(i = 1; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
@@ -383,12 +397,13 @@ void ixgb_init_rx_addrs(struct ixgb_hw *hw)
*****************************************************************************/
void
ixgb_mc_addr_list_update(struct ixgb_hw *hw,
- uint8_t * mc_addr_list,
- uint32_t mc_addr_count, uint32_t pad)
+ uint8_t *mc_addr_list,
+ uint32_t mc_addr_count,
+ uint32_t pad)
{
uint32_t hash_value;
uint32_t i;
- uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
+ uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
DEBUGFUNC("ixgb_mc_addr_list_update");
@@ -397,19 +412,19 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
- for (i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
+ for(i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
- for (i = 0; i < IXGB_MC_TBL_SIZE; i++) {
+ for(i = 0; i < IXGB_MC_TBL_SIZE; i++) {
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
}
/* Add the new addresses */
- for (i = 0; i < mc_addr_count; i++) {
+ for(i = 0; i < mc_addr_count; i++) {
DEBUGOUT(" Adding the multicast addresses:\n");
DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],
@@ -427,7 +442,7 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
/* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
- if (rar_used_count < IXGB_RAR_ENTRIES) {
+ if(rar_used_count < IXGB_RAR_ENTRIES) {
ixgb_rar_set(hw,
mc_addr_list +
(i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),
@@ -460,7 +475,9 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
* Returns:
* The hash value
*****************************************************************************/
-static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr)
+static uint32_t
+ixgb_hash_mc_addr(struct ixgb_hw *hw,
+ uint8_t *mc_addr)
{
uint32_t hash_value = 0;
@@ -506,7 +523,9 @@ static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr)
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*****************************************************************************/
-static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value)
+static void
+ixgb_mta_set(struct ixgb_hw *hw,
+ uint32_t hash_value)
{
uint32_t hash_bit, hash_reg;
uint32_t mta_reg;
@@ -538,7 +557,10 @@ static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value)
* addr - Address to put into receive address register
* index - Receive address register to write
*****************************************************************************/
-void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
+void
+ixgb_rar_set(struct ixgb_hw *hw,
+ uint8_t *addr,
+ uint32_t index)
{
uint32_t rar_low, rar_high;
@@ -548,11 +570,13 @@ void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
* from network order (big endian) to little endian
*/
rar_low = ((uint32_t) addr[0] |
- ((uint32_t) addr[1] << 8) |
- ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+ ((uint32_t)addr[1] << 8) |
+ ((uint32_t)addr[2] << 16) |
+ ((uint32_t)addr[3] << 24));
rar_high = ((uint32_t) addr[4] |
- ((uint32_t) addr[5] << 8) | IXGB_RAH_AV);
+ ((uint32_t)addr[5] << 8) |
+ IXGB_RAH_AV);
IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
@@ -566,7 +590,10 @@ void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
* offset - Offset in VLAN filer table to write
* value - Value to write into VLAN filter table
*****************************************************************************/
-void ixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value)
+void
+ixgb_write_vfta(struct ixgb_hw *hw,
+ uint32_t offset,
+ uint32_t value)
{
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
return;
@@ -577,11 +604,12 @@ void ixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_clear_vfta(struct ixgb_hw *hw)
+void
+ixgb_clear_vfta(struct ixgb_hw *hw)
{
uint32_t offset;
- for (offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
+ for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
return;
}
@@ -592,10 +620,11 @@ void ixgb_clear_vfta(struct ixgb_hw *hw)
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
+boolean_t
+ixgb_setup_fc(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
- uint32_t pap_reg = 0; /* by default, assume no pause time */
+ uint32_t pap_reg = 0; /* by default, assume no pause time */
boolean_t status = TRUE;
DEBUGFUNC("ixgb_setup_fc");
@@ -660,16 +689,16 @@ boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
* ability to transmit pause frames in not enabled, then these
* registers will be set to 0.
*/
- if (!(hw->fc.type & ixgb_fc_tx_pause)) {
+ if(!(hw->fc.type & ixgb_fc_tx_pause)) {
IXGB_WRITE_REG(hw, FCRTL, 0);
IXGB_WRITE_REG(hw, FCRTH, 0);
} else {
- /* We need to set up the Receive Threshold high and low water
- * marks as well as (optionally) enabling the transmission of XON frames.
- */
- if (hw->fc.send_xon) {
+ /* We need to set up the Receive Threshold high and low water
+ * marks as well as (optionally) enabling the transmission of XON
+ * frames. */
+ if(hw->fc.send_xon) {
IXGB_WRITE_REG(hw, FCRTL,
- (hw->fc.low_water | IXGB_FCRTL_XONE));
+ (hw->fc.low_water | IXGB_FCRTL_XONE));
} else {
IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water);
}
@@ -694,9 +723,10 @@ boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
* read command.
*****************************************************************************/
uint16_t
-ixgb_read_phy_reg(struct ixgb_hw * hw,
- uint32_t reg_address,
- uint32_t phy_address, uint32_t device_type)
+ixgb_read_phy_reg(struct ixgb_hw *hw,
+ uint32_t reg_address,
+ uint32_t phy_address,
+ uint32_t device_type)
{
uint32_t i;
uint32_t data;
@@ -721,7 +751,8 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
** from the CPU Write to the Ready bit assertion.
**************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -747,7 +778,8 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
** from the CPU Write to the Ready bit assertion.
**************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -763,7 +795,7 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
*/
data = IXGB_READ_REG(hw, MSRWD);
data >>= IXGB_MSRWD_READ_DATA_SHIFT;
- return ((uint16_t) data);
+ return((uint16_t) data);
}
/******************************************************************************
@@ -785,8 +817,10 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
*****************************************************************************/
void
ixgb_write_phy_reg(struct ixgb_hw *hw,
- uint32_t reg_address,
- uint32_t phy_address, uint32_t device_type, uint16_t data)
+ uint32_t reg_address,
+ uint32_t phy_address,
+ uint32_t device_type,
+ uint16_t data)
{
uint32_t i;
uint32_t command = 0;
@@ -796,24 +830,25 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
/* Put the data in the MDIO Read/Write Data register */
- IXGB_WRITE_REG(hw, MSRWD, (uint32_t) data);
+ IXGB_WRITE_REG(hw, MSRWD, (uint32_t)data);
/* Setup and write the address cycle command */
- command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
- (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
- (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
+ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+ (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+ (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+ (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
- /**************************************************************
- ** Check every 10 usec to see if the address cycle completed
- ** The COMMAND bit will clear when the operation is complete.
- ** This may take as long as 64 usecs (we'll wait 100 usecs max)
- ** from the CPU Write to the Ready bit assertion.
- **************************************************************/
+ /**************************************************************
+ ** Check every 10 usec to see if the address cycle completed
+ ** The COMMAND bit will clear when the operation is complete.
+ ** This may take as long as 64 usecs (we'll wait 100 usecs max)
+ ** from the CPU Write to the Ready bit assertion.
+ **************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -825,21 +860,22 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Address cycle complete, setup and write the write command */
- command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
- (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
- (IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
+ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+ (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+ (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+ (IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
- /**************************************************************
- ** Check every 10 usec to see if the read command completed
- ** The COMMAND bit will clear when the operation is complete.
- ** The write may take as long as 64 usecs (we'll wait 100 usecs max)
- ** from the CPU Write to the Ready bit assertion.
- **************************************************************/
+ /**************************************************************
+ ** Check every 10 usec to see if the read command completed
+ ** The COMMAND bit will clear when the operation is complete.
+ ** The write may take as long as 64 usecs (we'll wait 100 usecs max)
+ ** from the CPU Write to the Ready bit assertion.
+ **************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -860,7 +896,8 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
*
* Called by any function that needs to check the link status of the adapter.
*****************************************************************************/
-void ixgb_check_for_link(struct ixgb_hw *hw)
+void
+ixgb_check_for_link(struct ixgb_hw *hw)
{
uint32_t status_reg;
uint32_t xpcss_reg;
@@ -922,14 +959,15 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+void
+ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
{
volatile uint32_t temp_reg;
DEBUGFUNC("ixgb_clear_hw_cntrs");
/* if we are stopped or resetting exit gracefully */
- if (hw->adapter_stopped) {
+ if(hw->adapter_stopped) {
DEBUGOUT("Exiting because the adapter is stopped!!!\n");
return;
}
@@ -1002,7 +1040,8 @@ void ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_led_on(struct ixgb_hw *hw)
+void
+ixgb_led_on(struct ixgb_hw *hw)
{
uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
@@ -1017,7 +1056,8 @@ void ixgb_led_on(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_led_off(struct ixgb_hw *hw)
+void
+ixgb_led_off(struct ixgb_hw *hw)
{
uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
@@ -1032,18 +1072,19 @@ void ixgb_led_off(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_get_bus_info(struct ixgb_hw *hw)
+static void
+ixgb_get_bus_info(struct ixgb_hw *hw)
{
uint32_t status_reg;
status_reg = IXGB_READ_REG(hw, STATUS);
hw->bus.type = (status_reg & IXGB_STATUS_PCIX_MODE) ?
- ixgb_bus_type_pcix : ixgb_bus_type_pci;
+ ixgb_bus_type_pcix : ixgb_bus_type_pci;
if (hw->bus.type == ixgb_bus_type_pci) {
hw->bus.speed = (status_reg & IXGB_STATUS_PCI_SPD) ?
- ixgb_bus_speed_66 : ixgb_bus_speed_33;
+ ixgb_bus_speed_66 : ixgb_bus_speed_33;
} else {
switch (status_reg & IXGB_STATUS_PCIX_SPD_MASK) {
case IXGB_STATUS_PCIX_SPD_66:
@@ -1062,7 +1103,7 @@ static void ixgb_get_bus_info(struct ixgb_hw *hw)
}
hw->bus.width = (status_reg & IXGB_STATUS_BUS64) ?
- ixgb_bus_width_64 : ixgb_bus_width_32;
+ ixgb_bus_width_64 : ixgb_bus_width_32;
return;
}
@@ -1073,7 +1114,8 @@ static void ixgb_get_bus_info(struct ixgb_hw *hw)
* mac_addr - pointer to MAC address.
*
*****************************************************************************/
-boolean_t mac_addr_valid(uint8_t * mac_addr)
+boolean_t
+mac_addr_valid(uint8_t *mac_addr)
{
boolean_t is_valid = TRUE;
DEBUGFUNC("mac_addr_valid");
@@ -1090,9 +1132,11 @@ boolean_t mac_addr_valid(uint8_t * mac_addr)
}
/* Reject the zero address */
else if (mac_addr[0] == 0 &&
- mac_addr[1] == 0 &&
- mac_addr[2] == 0 &&
- mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
+ mac_addr[1] == 0 &&
+ mac_addr[2] == 0 &&
+ mac_addr[3] == 0 &&
+ mac_addr[4] == 0 &&
+ mac_addr[5] == 0) {
DEBUGOUT("MAC address is all zeros\n");
is_valid = FALSE;
}
@@ -1105,7 +1149,8 @@ boolean_t mac_addr_valid(uint8_t * mac_addr)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t ixgb_link_reset(struct ixgb_hw * hw)
+boolean_t
+ixgb_link_reset(struct ixgb_hw *hw)
{
boolean_t link_status = FALSE;
uint8_t wait_retries = MAX_RESET_ITERATIONS;
@@ -1135,20 +1180,22 @@ boolean_t ixgb_link_reset(struct ixgb_hw * hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_optics_reset(struct ixgb_hw *hw)
+void
+ixgb_optics_reset(struct ixgb_hw *hw)
{
if (hw->phy_type == ixgb_phy_type_txn17401) {
uint16_t mdio_reg;
ixgb_write_phy_reg(hw,
- MDIO_PMA_PMD_CR1,
- IXGB_PHY_ADDRESS,
- MDIO_PMA_PMD_DID, MDIO_PMA_PMD_CR1_RESET);
-
- mdio_reg = ixgb_read_phy_reg(hw,
- MDIO_PMA_PMD_CR1,
- IXGB_PHY_ADDRESS,
- MDIO_PMA_PMD_DID);
+ MDIO_PMA_PMD_CR1,
+ IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID,
+ MDIO_PMA_PMD_CR1_RESET);
+
+ mdio_reg = ixgb_read_phy_reg( hw,
+ MDIO_PMA_PMD_CR1,
+ IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID);
}
return;
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index fad5032d239b7d..28489285e2cefe 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -616,17 +616,17 @@ struct ixgb_context_desc {
#define IXGB_CONTEXT_DESC_STATUS_DD 0x01
/* Filters */
-#define IXGB_RAR_ENTRIES 16 /* Number of entries in Rx Address array */
#define IXGB_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
#define IXGB_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+#define IXGB_RAR_ENTRIES 3 /* Number of entries in Rx Address array */
#define IXGB_MEMORY_REGISTER_BASE_ADDRESS 0
-#define ENET_HEADER_SIZE 14
-#define ENET_FCS_LENGTH 4
-#define IXGB_MAX_NUM_MULTICAST_ADDRESSES 128
-#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS 60
-#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS 1514
-#define IXGB_MAX_JUMBO_FRAME_SIZE 0x3F00
+#define ENET_HEADER_SIZE 14
+#define ENET_FCS_LENGTH 4
+#define IXGB_MAX_NUM_MULTICAST_ADDRESSES 128
+#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS 60
+#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS 1514
+#define IXGB_MAX_JUMBO_FRAME_SIZE 0x3F00
/* Phy Addresses */
#define IXGB_OPTICAL_PHY_ADDR 0x0 /* Optical Module phy address */
@@ -789,32 +789,39 @@ extern void ixgb_check_for_link(struct ixgb_hw *hw);
extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
extern boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
extern void ixgb_clear_hw_cntrs(struct ixgb_hw *hw);
-extern boolean_t mac_addr_valid(uint8_t * mac_addr);
+extern boolean_t mac_addr_valid(uint8_t *mac_addr);
extern uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw,
- uint32_t reg_addr,
- uint32_t phy_addr, uint32_t device_type);
+ uint32_t reg_addr,
+ uint32_t phy_addr,
+ uint32_t device_type);
extern void ixgb_write_phy_reg(struct ixgb_hw *hw,
- uint32_t reg_addr,
- uint32_t phy_addr,
- uint32_t device_type, uint16_t data);
+ uint32_t reg_addr,
+ uint32_t phy_addr,
+ uint32_t device_type,
+ uint16_t data);
+
+extern void ixgb_rar_set(struct ixgb_hw *hw,
+ uint8_t *addr,
+ uint32_t index);
-extern void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index);
/* Filters (multicast, vlan, receive) */
extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
- uint8_t * mc_addr_list,
- uint32_t mc_addr_count, uint32_t pad);
+ uint8_t *mc_addr_list,
+ uint32_t mc_addr_count,
+ uint32_t pad);
/* Vfta functions */
extern void ixgb_write_vfta(struct ixgb_hw *hw,
- uint32_t offset, uint32_t value);
+ uint32_t offset,
+ uint32_t value);
extern void ixgb_clear_vfta(struct ixgb_hw *hw);
/* Access functions to eeprom data */
-void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t * mac_addr);
+void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
@@ -832,6 +839,9 @@ uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
/* Everything else */
void ixgb_led_on(struct ixgb_hw *hw);
void ixgb_led_off(struct ixgb_hw *hw);
-void ixgb_write_pci_cfg(struct ixgb_hw *hw, uint32_t reg, uint16_t * value);
+void ixgb_write_pci_cfg(struct ixgb_hw *hw,
+ uint32_t reg,
+ uint16_t * value);
+
-#endif /* _IXGB_HW_H_ */
+#endif /* _IXGB_HW_H_ */
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
index ea04cee1259dfd..6384643e241343 100644
--- a/drivers/net/ixgb/ixgb_ids.h
+++ b/drivers/net/ixgb/ixgb_ids.h
@@ -33,21 +33,16 @@
** The Device and Vendor IDs for 10 Gigabit MACs
**********************************************************************/
-#define INTEL_VENDOR_ID 0x8086
-#define INTEL_SUBVENDOR_ID 0x8086
+#define INTEL_VENDOR_ID 0x8086
+#define INTEL_SUBVENDOR_ID 0x8086
-#define IXGB_DEVICE_ID_82597EX 0x1048
-#define IXGB_DEVICE_ID_82597EX_SR 0x1A48
-#define IXGB_SUBDEVICE_ID_A11F 0xA11F
-#define IXGB_SUBDEVICE_ID_A01F 0xA01F
+#define IXGB_DEVICE_ID_82597EX 0x1048
+#define IXGB_DEVICE_ID_82597EX_SR 0x1A48
+#define IXGB_DEVICE_ID_82597EX_LR 0x1B48
+#define IXGB_SUBDEVICE_ID_A11F 0xA11F
+#define IXGB_SUBDEVICE_ID_A01F 0xA01F
-#define IXGB_SUBDEVICE_ID_A15F 0xA15F
-#define IXGB_SUBDEVICE_ID_A05F 0xA05F
-
-#define IXGB_SUBDEVICE_ID_A12F 0xA12F
-#define IXGB_SUBDEVICE_ID_A02F 0xA02F
-
-#endif /* #ifndef _IXGB_IDS_H_ */
+#endif /* #ifndef _IXGB_IDS_H_ */
/* End of File */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index bcc10686806c7f..435cfa165a5529 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -28,10 +28,23 @@
#include "ixgb.h"
+/* Change Log
+ * 1.0.84 10/26/04
+ * - reset buffer_info->dma in Tx resource cleanup logic
+ * 1.0.83 10/12/04
+ * - sparse cleanup - shemminger@osdl.org
+ * - fix tx resource cleanup logic
+ */
+
char ixgb_driver_name[] = "ixgb";
char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
-char ixgb_driver_version[] = "1.0.66-k2";
-char ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";
+#ifndef CONFIG_IXGB_NAPI
+#define DRIVERNAPI
+#else
+#define DRIVERNAPI "-NAPI"
+#endif
+char ixgb_driver_version[] = "1.0.87-k2"DRIVERNAPI;
+char ixgb_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
@@ -46,6 +59,8 @@ static struct pci_device_id ixgb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */
{0,}
@@ -55,11 +70,14 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
/* Local Function Prototypes */
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
int ixgb_up(struct ixgb_adapter *adapter);
void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
void ixgb_reset(struct ixgb_adapter *adapter);
+int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_update_stats(struct ixgb_adapter *adapter);
static int ixgb_init_module(void);
static void ixgb_exit_module(void);
@@ -68,27 +86,19 @@ static void __devexit ixgb_remove(struct pci_dev *pdev);
static int ixgb_sw_init(struct ixgb_adapter *adapter);
static int ixgb_open(struct net_device *netdev);
static int ixgb_close(struct net_device *netdev);
-static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
-static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
static void ixgb_configure_tx(struct ixgb_adapter *adapter);
static void ixgb_configure_rx(struct ixgb_adapter *adapter);
static void ixgb_setup_rctl(struct ixgb_adapter *adapter);
static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter);
static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter);
-static void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
-static void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
static void ixgb_set_multi(struct net_device *netdev);
static void ixgb_watchdog(unsigned long data);
static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
static int ixgb_set_mac(struct net_device *netdev, void *p);
-static void ixgb_update_stats(struct ixgb_adapter *adapter);
static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
-static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
- struct ixgb_rx_desc *rx_desc,
- struct sk_buff *skb);
#ifdef CONFIG_IXGB_NAPI
static int ixgb_clean(struct net_device *netdev, int *budget);
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
@@ -97,6 +107,7 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
#endif
static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
+void ixgb_set_ethtool_ops(struct net_device *netdev);
static void ixgb_tx_timeout(struct net_device *dev);
static void ixgb_tx_timeout_task(struct net_device *dev);
static void ixgb_vlan_rx_register(struct net_device *netdev,
@@ -123,7 +134,6 @@ struct notifier_block ixgb_notifier_reboot = {
/* Exported from other modules */
extern void ixgb_check_options(struct ixgb_adapter *adapter);
-extern struct ethtool_ops ixgb_ethtool_ops;
static struct pci_driver ixgb_driver = {
.name = ixgb_driver_name,
@@ -152,7 +162,8 @@ MODULE_LICENSE("GPL");
* loaded. All it does is register with the PCI subsystem.
**/
-static int __init ixgb_init_module(void)
+static int __init
+ixgb_init_module(void)
{
int ret;
printk(KERN_INFO "%s - version %s\n",
@@ -161,7 +172,7 @@ static int __init ixgb_init_module(void)
printk(KERN_INFO "%s\n", ixgb_copyright);
ret = pci_module_init(&ixgb_driver);
- if (ret >= 0) {
+ if(ret >= 0) {
register_reboot_notifier(&ixgb_notifier_reboot);
}
return ret;
@@ -176,7 +187,8 @@ module_init(ixgb_init_module);
* from memory.
**/
-static void __exit ixgb_exit_module(void)
+static void __exit
+ixgb_exit_module(void)
{
unregister_reboot_notifier(&ixgb_notifier_reboot);
pci_unregister_driver(&ixgb_driver);
@@ -189,7 +201,8 @@ module_exit(ixgb_exit_module);
* @adapter: board private structure
**/
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
+static inline void
+ixgb_irq_disable(struct ixgb_adapter *adapter)
{
atomic_inc(&adapter->irq_sem);
IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
@@ -202,17 +215,19 @@ static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
* @adapter: board private structure
**/
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter)
+static inline void
+ixgb_irq_enable(struct ixgb_adapter *adapter)
{
- if (atomic_dec_and_test(&adapter->irq_sem)) {
+ if(atomic_dec_and_test(&adapter->irq_sem)) {
IXGB_WRITE_REG(&adapter->hw, IMS,
- IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
- IXGB_INT_RXO | IXGB_INT_LSC);
+ IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+ IXGB_INT_RXO | IXGB_INT_LSC);
IXGB_WRITE_FLUSH(&adapter->hw);
}
}
-int ixgb_up(struct ixgb_adapter *adapter)
+int
+ixgb_up(struct ixgb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
int err;
@@ -230,27 +245,44 @@ int ixgb_up(struct ixgb_adapter *adapter)
ixgb_configure_rx(adapter);
ixgb_alloc_rx_buffers(adapter);
- if ((err = request_irq(adapter->pdev->irq, &ixgb_intr,
- SA_SHIRQ | SA_SAMPLE_RANDOM,
- netdev->name, netdev)))
+#ifdef CONFIG_PCI_MSI
+ {
+ boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) &
+ IXGB_STATUS_PCIX_MODE) ? TRUE : FALSE;
+ adapter->have_msi = TRUE;
+
+ if (!pcix)
+ adapter->have_msi = FALSE;
+ else if((err = pci_enable_msi(adapter->pdev))) {
+ printk (KERN_ERR
+ "Unable to allocate MSI interrupt Error: %d\n", err);
+ adapter->have_msi = FALSE;
+ /* proceed to try to request regular interrupt */
+ }
+ }
+
+#endif
+ if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
+ SA_SHIRQ | SA_SAMPLE_RANDOM,
+ netdev->name, netdev)))
return err;
/* disable interrupts and get the hardware into a known state */
IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
- if ((hw->max_frame_size != max_frame) ||
- (hw->max_frame_size !=
- (IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT))) {
+ if((hw->max_frame_size != max_frame) ||
+ (hw->max_frame_size !=
+ (IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT))) {
hw->max_frame_size = max_frame;
IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);
- if (hw->max_frame_size >
- IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+ if(hw->max_frame_size >
+ IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);
- if (!(ctrl0 & IXGB_CTRL0_JFE)) {
+ if(!(ctrl0 & IXGB_CTRL0_JFE)) {
ctrl0 |= IXGB_CTRL0_JFE;
IXGB_WRITE_REG(hw, CTRL0, ctrl0);
}
@@ -263,13 +295,19 @@ int ixgb_up(struct ixgb_adapter *adapter)
return 0;
}
-void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
+void
+ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
{
struct net_device *netdev = adapter->netdev;
ixgb_irq_disable(adapter);
free_irq(adapter->pdev->irq, netdev);
- if (kill_watchdog)
+#ifdef CONFIG_PCI_MSI
+ if(adapter->have_msi == TRUE)
+ pci_disable_msi(adapter->pdev);
+
+#endif
+ if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer);
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -281,11 +319,12 @@ void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
ixgb_clean_rx_ring(adapter);
}
-void ixgb_reset(struct ixgb_adapter *adapter)
+void
+ixgb_reset(struct ixgb_adapter *adapter)
{
ixgb_adapter_stop(&adapter->hw);
- if (!ixgb_init_hw(&adapter->hw))
+ if(!ixgb_init_hw(&adapter->hw))
IXGB_DBG("ixgb_init_hw failed.\n");
}
@@ -302,7 +341,8 @@ void ixgb_reset(struct ixgb_adapter *adapter)
**/
static int __devinit
-ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ixgb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
struct ixgb_adapter *adapter;
@@ -313,26 +353,26 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int i;
int err;
- if ((err = pci_enable_device(pdev)))
+ if((err = pci_enable_device(pdev)))
return err;
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
IXGB_ERR("No usable DMA configuration, aborting\n");
return err;
}
pci_using_dac = 0;
}
- if ((err = pci_request_regions(pdev, ixgb_driver_name)))
+ if((err = pci_request_regions(pdev, ixgb_driver_name)))
return err;
pci_set_master(pdev);
netdev = alloc_etherdev(sizeof(struct ixgb_adapter));
- if (!netdev) {
+ if(!netdev) {
err = -ENOMEM;
goto err_alloc_etherdev;
}
@@ -350,15 +390,15 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mmio_len = pci_resource_len(pdev, BAR_0);
adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
- if (!adapter->hw.hw_addr) {
+ if(!adapter->hw.hw_addr) {
err = -EIO;
goto err_ioremap;
}
- for (i = BAR_1; i <= BAR_5; i++) {
- if (pci_resource_len(pdev, i) == 0)
+ for(i = BAR_1; i <= BAR_5; i++) {
+ if(pci_resource_len(pdev, i) == 0)
continue;
- if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
adapter->hw.io_base = pci_resource_start(pdev, i);
break;
}
@@ -371,9 +411,9 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->set_multicast_list = &ixgb_set_multi;
netdev->set_mac_address = &ixgb_set_mac;
netdev->change_mtu = &ixgb_change_mtu;
+ ixgb_set_ethtool_ops(netdev);
netdev->tx_timeout = &ixgb_tx_timeout;
netdev->watchdog_timeo = HZ;
- SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
#ifdef CONFIG_IXGB_NAPI
netdev->poll = &ixgb_clean;
netdev->weight = 64;
@@ -395,22 +435,24 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* setup the private structure */
- if ((err = ixgb_sw_init(adapter)))
+ if((err = ixgb_sw_init(adapter)))
goto err_sw_init;
netdev->features = NETIF_F_SG |
- NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_FILTER;
#ifdef NETIF_F_TSO
netdev->features |= NETIF_F_TSO;
#endif
- if (pci_using_dac)
+ if(pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* make sure the EEPROM is good */
- if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+ if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
@@ -418,7 +460,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
- if (!is_valid_ether_addr(netdev->dev_addr)) {
+ if(!is_valid_ether_addr(netdev->dev_addr)) {
err = -EIO;
goto err_eeprom;
}
@@ -432,7 +474,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->tx_timeout_task,
(void (*)(void *))ixgb_tx_timeout_task, netdev);
- if ((err = register_netdev(netdev)))
+ if((err = register_netdev(netdev)))
goto err_register;
/* we're going to reset, so assume we have no link for now */
@@ -441,7 +483,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netif_stop_queue(netdev);
printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n",
- netdev->name);
+ netdev->name);
ixgb_check_options(adapter);
/* reset the hardware with the new settings */
@@ -450,13 +492,13 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
cards_found++;
return 0;
- err_register:
- err_sw_init:
- err_eeprom:
+err_register:
+err_sw_init:
+err_eeprom:
iounmap(adapter->hw.hw_addr);
- err_ioremap:
+err_ioremap:
free_netdev(netdev);
- err_alloc_etherdev:
+err_alloc_etherdev:
pci_release_regions(pdev);
return err;
}
@@ -471,7 +513,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* memory.
**/
-static void __devexit ixgb_remove(struct pci_dev *pdev)
+static void __devexit
+ixgb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv;
@@ -493,7 +536,8 @@ static void __devexit ixgb_remove(struct pci_dev *pdev)
* OS network device settings (MTU size).
**/
-static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter)
+static int __devinit
+ixgb_sw_init(struct ixgb_adapter *adapter)
{
struct ixgb_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
@@ -510,9 +554,10 @@ static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter)
hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
- if ((hw->device_id == IXGB_DEVICE_ID_82597EX)
- || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
- hw->mac_type = ixgb_82597;
+ if((hw->device_id == IXGB_DEVICE_ID_82597EX)
+ ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
+ ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+ hw->mac_type = ixgb_82597;
else {
/* should never have loaded on this device */
printk(KERN_ERR "ixgb: unsupported device id\n");
@@ -540,31 +585,32 @@ static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter)
* and the stack is notified that the interface is ready.
**/
-static int ixgb_open(struct net_device *netdev)
+static int
+ixgb_open(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
int err;
/* allocate transmit descriptors */
- if ((err = ixgb_setup_tx_resources(adapter)))
+ if((err = ixgb_setup_tx_resources(adapter)))
goto err_setup_tx;
/* allocate receive descriptors */
- if ((err = ixgb_setup_rx_resources(adapter)))
+ if((err = ixgb_setup_rx_resources(adapter)))
goto err_setup_rx;
- if ((err = ixgb_up(adapter)))
+ if((err = ixgb_up(adapter)))
goto err_up;
return 0;
- err_up:
+err_up:
ixgb_free_rx_resources(adapter);
- err_setup_rx:
+err_setup_rx:
ixgb_free_tx_resources(adapter);
- err_setup_tx:
+err_setup_tx:
ixgb_reset(adapter);
return err;
@@ -582,7 +628,8 @@ static int ixgb_open(struct net_device *netdev)
* hardware, and all transmit and receive resources are freed.
**/
-static int ixgb_close(struct net_device *netdev)
+static int
+ixgb_close(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
@@ -601,15 +648,16 @@ static int ixgb_close(struct net_device *netdev)
* Return 0 on success, negative on failure
**/
-static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+int
+ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
size = sizeof(struct ixgb_buffer) * txdr->count;
- txdr->buffer_info = kmalloc(size, GFP_KERNEL);
- if (!txdr->buffer_info) {
+ txdr->buffer_info = vmalloc(size);
+ if(!txdr->buffer_info) {
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
@@ -620,8 +668,8 @@ static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
IXGB_ROUNDUP(txdr->size, 4096);
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if (!txdr->desc) {
- kfree(txdr->buffer_info);
+ if(!txdr->desc) {
+ vfree(txdr->buffer_info);
return -ENOMEM;
}
memset(txdr->desc, 0, txdr->size);
@@ -639,7 +687,8 @@ static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
* Configure the Tx unit of the MAC after a reset.
**/
-static void ixgb_configure_tx(struct ixgb_adapter *adapter)
+static void
+ixgb_configure_tx(struct ixgb_adapter *adapter)
{
uint64_t tdba = adapter->tx_ring.dma;
uint32_t tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
@@ -679,8 +728,8 @@ static void ixgb_configure_tx(struct ixgb_adapter *adapter)
/* Setup Transmit Descriptor Settings for this adapter */
adapter->tx_cmd_type =
- IXGB_TX_DESC_TYPE
- | (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
+ IXGB_TX_DESC_TYPE
+ | (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
}
/**
@@ -690,15 +739,16 @@ static void ixgb_configure_tx(struct ixgb_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+int
+ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
size = sizeof(struct ixgb_buffer) * rxdr->count;
- rxdr->buffer_info = kmalloc(size, GFP_KERNEL);
- if (!rxdr->buffer_info) {
+ rxdr->buffer_info = vmalloc(size);
+ if(!rxdr->buffer_info) {
return -ENOMEM;
}
memset(rxdr->buffer_info, 0, size);
@@ -710,8 +760,8 @@ static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if (!rxdr->desc) {
- kfree(rxdr->buffer_info);
+ if(!rxdr->desc) {
+ vfree(rxdr->buffer_info);
return -ENOMEM;
}
memset(rxdr->desc, 0, rxdr->size);
@@ -727,7 +777,8 @@ static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
* @adapter: Board private structure
**/
-static void ixgb_setup_rctl(struct ixgb_adapter *adapter)
+static void
+ixgb_setup_rctl(struct ixgb_adapter *adapter)
{
uint32_t rctl;
@@ -736,9 +787,9 @@ static void ixgb_setup_rctl(struct ixgb_adapter *adapter)
rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
rctl |=
- IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
- IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
- (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
+ IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
+ IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
+ (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
rctl |= IXGB_RCTL_SECRC;
@@ -768,7 +819,8 @@ static void ixgb_setup_rctl(struct ixgb_adapter *adapter)
* Configure the Rx unit of the MAC after a reset.
**/
-static void ixgb_configure_rx(struct ixgb_adapter *adapter)
+static void
+ixgb_configure_rx(struct ixgb_adapter *adapter)
{
uint64_t rdba = adapter->rx_ring.dma;
uint32_t rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
@@ -797,51 +849,14 @@ static void ixgb_configure_rx(struct ixgb_adapter *adapter)
IXGB_WRITE_REG(hw, RDH, 0);
IXGB_WRITE_REG(hw, RDT, 0);
- /* burst 16 or burst when RXT0 */
- rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
- | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
- | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
+ /* burst 16 or burst when RXT0*/
+ rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
+ | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
+ | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
- if (adapter->raidc) {
- uint32_t raidc;
- uint8_t poll_threshold;
-
- /* Poll every rx_int_delay period, if RBD exists
- * Receive Backlog Detection is set to <threshold>
- * Rx Descriptors
- * max is 0x3F == set to poll when 504 RxDesc left
- * min is 0 */
-
- /* polling times are 1 == 0.8192us
- 2 == 1.6384us
- 3 == 3.2768us etc
- ...
- 511 == 418 us
- */
-#define IXGB_RAIDC_POLL_DEFAULT 122 /* set to poll every ~100 us under load
- also known as 10000 interrupts / sec */
-
- /* divide this by 2^3 (8) to get a register size count */
- poll_threshold = ((adapter->rx_ring.count - 1) >> 3);
- /* poll at half of that size */
- poll_threshold >>= 1;
- /* make sure its not bigger than our max */
- poll_threshold &= 0x3F;
-
- raidc = IXGB_RAIDC_EN | /* turn on raidc style moderation */
- IXGB_RAIDC_RXT_GATE | /* don't interrupt with rxt0 while
- in RBD mode (polling) */
- (IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
- /* this sets the regular "min interrupt delay" */
- (adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
- poll_threshold;
-
- IXGB_WRITE_REG(hw, RAIDC, raidc);
- }
-
/* Enable Receive Checksum Offload for TCP and UDP */
- if (adapter->rx_csum == TRUE) {
+ if(adapter->rx_csum == TRUE) {
rxcsum = IXGB_READ_REG(hw, RXCSUM);
rxcsum |= IXGB_RXCSUM_TUOFL;
IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
@@ -859,13 +874,14 @@ static void ixgb_configure_rx(struct ixgb_adapter *adapter)
* Free all transmit software resources
**/
-static void ixgb_free_tx_resources(struct ixgb_adapter *adapter)
+void
+ixgb_free_tx_resources(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
ixgb_clean_tx_ring(adapter);
- kfree(adapter->tx_ring.buffer_info);
+ vfree(adapter->tx_ring.buffer_info);
adapter->tx_ring.buffer_info = NULL;
pci_free_consistent(pdev, adapter->tx_ring.size,
@@ -874,33 +890,42 @@ static void ixgb_free_tx_resources(struct ixgb_adapter *adapter)
adapter->tx_ring.desc = NULL;
}
+static inline void
+ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
+ struct ixgb_buffer *buffer_info)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ if(buffer_info->dma) {
+ pci_unmap_page(pdev,
+ buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+ if(buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+}
+
/**
* ixgb_clean_tx_ring - Free Tx Buffers
* @adapter: board private structure
**/
-static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
+static void
+ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct ixgb_buffer *buffer_info;
- struct pci_dev *pdev = adapter->pdev;
unsigned long size;
unsigned int i;
/* Free all the Tx ring sk_buffs */
- for (i = 0; i < tx_ring->count; i++) {
+ for(i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
- if (buffer_info->skb) {
-
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length, PCI_DMA_TODEVICE);
-
- dev_kfree_skb(buffer_info->skb);
-
- buffer_info->skb = NULL;
- }
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
}
size = sizeof(struct ixgb_buffer) * tx_ring->count;
@@ -924,14 +949,15 @@ static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
* Free all receive software resources
**/
-static void ixgb_free_rx_resources(struct ixgb_adapter *adapter)
+void
+ixgb_free_rx_resources(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
ixgb_clean_rx_ring(adapter);
- kfree(rx_ring->buffer_info);
+ vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
@@ -944,7 +970,8 @@ static void ixgb_free_rx_resources(struct ixgb_adapter *adapter)
* @adapter: board private structure
**/
-static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
+static void
+ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct ixgb_buffer *buffer_info;
@@ -954,9 +981,9 @@ static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
/* Free all the Rx ring sk_buffs */
- for (i = 0; i < rx_ring->count; i++) {
+ for(i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if (buffer_info->skb) {
+ if(buffer_info->skb) {
pci_unmap_single(pdev,
buffer_info->dma,
@@ -991,12 +1018,13 @@ static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int ixgb_set_mac(struct net_device *netdev, void *p)
+static int
+ixgb_set_mac(struct net_device *netdev, void *p)
{
struct ixgb_adapter *adapter = netdev->priv;
struct sockaddr *addr = p;
- if (!is_valid_ether_addr(addr->sa_data))
+ if(!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -1016,7 +1044,8 @@ static int ixgb_set_mac(struct net_device *netdev, void *p)
* promiscuous mode, and all-multi behavior.
**/
-static void ixgb_set_multi(struct net_device *netdev)
+static void
+ixgb_set_multi(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
@@ -1028,16 +1057,16 @@ static void ixgb_set_multi(struct net_device *netdev)
rctl = IXGB_READ_REG(hw, RCTL);
- if (netdev->flags & IFF_PROMISC) {
+ if(netdev->flags & IFF_PROMISC) {
rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
- } else if (netdev->flags & IFF_ALLMULTI) {
+ } else if(netdev->flags & IFF_ALLMULTI) {
rctl |= IXGB_RCTL_MPE;
rctl &= ~IXGB_RCTL_UPE;
} else {
rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
}
- if (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
+ if(netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
rctl |= IXGB_RCTL_MPE;
IXGB_WRITE_REG(hw, RCTL, rctl);
} else {
@@ -1045,10 +1074,10 @@ static void ixgb_set_multi(struct net_device *netdev)
IXGB_WRITE_REG(hw, RCTL, rctl);
- for (i = 0, mc_ptr = netdev->mc_list; mc_ptr;
- i++, mc_ptr = mc_ptr->next)
+ for(i = 0, mc_ptr = netdev->mc_list; mc_ptr;
+ i++, mc_ptr = mc_ptr->next)
memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],
- mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
+ mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0);
}
@@ -1059,7 +1088,8 @@ static void ixgb_set_multi(struct net_device *netdev)
* @data: pointer to netdev cast into an unsigned long
**/
-static void ixgb_watchdog(unsigned long data)
+static void
+ixgb_watchdog(unsigned long data)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
struct net_device *netdev = adapter->netdev;
@@ -1073,21 +1103,22 @@ static void ixgb_watchdog(unsigned long data)
netif_stop_queue(netdev);
}
- if (adapter->hw.link_up) {
- if (!netif_carrier_ok(netdev)) {
+ if(adapter->hw.link_up) {
+ if(!netif_carrier_ok(netdev)) {
printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
- netdev->name, 10000, "Full Duplex");
+ netdev->name, 10000, "Full Duplex");
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
} else {
- if (netif_carrier_ok(netdev)) {
+ if(netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
printk(KERN_INFO
- "ixgb: %s NIC Link is Down\n", netdev->name);
+ "ixgb: %s NIC Link is Down\n",
+ netdev->name);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -1096,8 +1127,8 @@ static void ixgb_watchdog(unsigned long data)
ixgb_update_stats(adapter);
- if (!netif_carrier_ok(netdev)) {
- if (IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {
+ if(!netif_carrier_ok(netdev)) {
+ if(IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
@@ -1108,9 +1139,9 @@ static void ixgb_watchdog(unsigned long data)
/* Early detection of hung controller */
i = txdr->next_to_clean;
- if (txdr->buffer_info[i].dma &&
- time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
- !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
+ if(txdr->buffer_info[i].dma &&
+ time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
+ !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
netif_stop_queue(netdev);
/* generate an interrupt to force clean up of any stragglers */
@@ -1133,7 +1164,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
uint16_t ipcse, tucse, mss;
- if (likely(skb_shinfo(skb)->tso_size)) {
+ if(likely(skb_shinfo(skb)->tso_size)) {
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
skb->nh.iph->tot_len = 0;
@@ -1160,22 +1191,16 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
context_desc->mss = cpu_to_le16(mss);
context_desc->hdr_len = hdr_len;
context_desc->status = 0;
- context_desc->cmd_type_len = cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
- |
- IXGB_CONTEXT_DESC_CMD_TSE
- |
- IXGB_CONTEXT_DESC_CMD_IP
- |
- IXGB_CONTEXT_DESC_CMD_TCP
- |
- IXGB_CONTEXT_DESC_CMD_RS
- |
- IXGB_CONTEXT_DESC_CMD_IDE
- | (skb->len -
- (hdr_len)));
-
- if (++i == adapter->tx_ring.count)
- i = 0;
+ context_desc->cmd_type_len = cpu_to_le32(
+ IXGB_CONTEXT_DESC_TYPE
+ | IXGB_CONTEXT_DESC_CMD_TSE
+ | IXGB_CONTEXT_DESC_CMD_IP
+ | IXGB_CONTEXT_DESC_CMD_TCP
+ | IXGB_CONTEXT_DESC_CMD_RS
+ | IXGB_CONTEXT_DESC_CMD_IDE
+ | (skb->len - (hdr_len)));
+
+ if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
return TRUE;
@@ -1192,7 +1217,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
unsigned int i;
uint8_t css, cso;
- if (likely(skb->ip_summed == CHECKSUM_HW)) {
+ if(likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
cso = (skb->h.raw + skb->csum) - skb->data;
@@ -1203,16 +1228,16 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
context_desc->tucso = cso;
context_desc->tucse = 0;
/* zero out any previously existing data in one instruction */
- *(uint32_t *) & (context_desc->ipcss) = 0;
+ *(uint32_t *)&(context_desc->ipcss) = 0;
context_desc->status = 0;
context_desc->hdr_len = 0;
context_desc->mss = 0;
context_desc->cmd_type_len =
- cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
- | IXGB_TX_DESC_CMD_RS | IXGB_TX_DESC_CMD_IDE);
+ cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
+ | IXGB_TX_DESC_CMD_RS
+ | IXGB_TX_DESC_CMD_IDE);
- if (++i == adapter->tx_ring.count)
- i = 0;
+ if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
return TRUE;
@@ -1239,45 +1264,46 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
i = tx_ring->next_to_use;
- while (len) {
+ while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
buffer_info->length = size;
buffer_info->dma =
- pci_map_single(adapter->pdev,
- skb->data + offset, size, PCI_DMA_TODEVICE);
+ pci_map_single(adapter->pdev,
+ skb->data + offset,
+ size,
+ PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
len -= size;
offset += size;
count++;
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
- for (f = 0; f < nr_frags; f++) {
+ for(f = 0; f < nr_frags; f++) {
struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = 0;
- while (len) {
+ while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
buffer_info->length = size;
buffer_info->dma =
- pci_map_page(adapter->pdev,
- frag->page,
- frag->page_offset + offset,
- size, PCI_DMA_TODEVICE);
+ pci_map_page(adapter->pdev,
+ frag->page,
+ frag->page_offset + offset,
+ size,
+ PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
len -= size;
offset += size;
count++;
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
}
i = (i == 0) ? tx_ring->count - 1 : i - 1;
@@ -1288,8 +1314,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
}
static inline void
-ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
- int tx_flags)
+ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct ixgb_tx_desc *tx_desc = NULL;
@@ -1299,36 +1324,35 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
uint8_t popts = 0;
unsigned int i;
- if (tx_flags & IXGB_TX_FLAGS_TSO) {
+ if(tx_flags & IXGB_TX_FLAGS_TSO) {
cmd_type_len |= IXGB_TX_DESC_CMD_TSE;
popts |= (IXGB_TX_DESC_POPTS_IXSM | IXGB_TX_DESC_POPTS_TXSM);
}
- if (tx_flags & IXGB_TX_FLAGS_CSUM)
+ if(tx_flags & IXGB_TX_FLAGS_CSUM)
popts |= IXGB_TX_DESC_POPTS_TXSM;
- if (tx_flags & IXGB_TX_FLAGS_VLAN) {
+ if(tx_flags & IXGB_TX_FLAGS_VLAN) {
cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
}
i = tx_ring->next_to_use;
- while (count--) {
+ while(count--) {
buffer_info = &tx_ring->buffer_info[i];
tx_desc = IXGB_TX_DESC(*tx_ring, i);
tx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
tx_desc->cmd_type_len =
- cpu_to_le32(cmd_type_len | buffer_info->length);
+ cpu_to_le32(cmd_type_len | buffer_info->length);
tx_desc->status = status;
tx_desc->popts = popts;
tx_desc->vlan = cpu_to_le16(vlan_id);
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
- tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP
- | IXGB_TX_DESC_CMD_RS);
+ tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP
+ | IXGB_TX_DESC_CMD_RS );
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
@@ -1346,7 +1370,8 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
-static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static int
+ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
unsigned int first;
@@ -1354,33 +1379,33 @@ static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned long flags;
int vlan_id = 0;
- if (skb->len <= 0) {
+ if(skb->len <= 0) {
dev_kfree_skb_any(skb);
return 0;
}
spin_lock_irqsave(&adapter->tx_lock, flags);
- if (unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+ if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return 1;
}
spin_unlock_irqrestore(&adapter->tx_lock, flags);
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
tx_flags |= IXGB_TX_FLAGS_VLAN;
vlan_id = vlan_tx_tag_get(skb);
}
first = adapter->tx_ring.next_to_use;
-
- if (ixgb_tso(adapter, skb))
+
+ if(ixgb_tso(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_TSO;
- else if (ixgb_tx_csum(adapter, skb))
+ else if(ixgb_tx_csum(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_CSUM;
ixgb_tx_queue(adapter, ixgb_tx_map(adapter, skb, first), vlan_id,
- tx_flags);
+ tx_flags);
netdev->trans_start = jiffies;
@@ -1392,7 +1417,8 @@ static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* @netdev: network interface device structure
**/
-static void ixgb_tx_timeout(struct net_device *netdev)
+static void
+ixgb_tx_timeout(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
@@ -1400,14 +1426,13 @@ static void ixgb_tx_timeout(struct net_device *netdev)
schedule_work(&adapter->tx_timeout_task);
}
-static void ixgb_tx_timeout_task(struct net_device *netdev)
+static void
+ixgb_tx_timeout_task(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
- netif_device_detach(netdev);
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
- netif_device_attach(netdev);
}
/**
@@ -1418,7 +1443,8 @@ static void ixgb_tx_timeout_task(struct net_device *netdev)
* The statistics are actually updated from the timer callback.
**/
-static struct net_device_stats *ixgb_get_stats(struct net_device *netdev)
+static struct net_device_stats *
+ixgb_get_stats(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
@@ -1433,27 +1459,28 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev)
* Returns 0 on success, negative on failure
**/
-static int ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+static int
+ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgb_adapter *adapter = netdev->priv;
- uint32_t old_mtu = adapter->rx_buffer_len;
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+ int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+
- if ((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
- || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
+ if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+ || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
IXGB_ERR("Invalid MTU setting\n");
return -EINVAL;
}
- if ((max_frame <=
- IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
- || (max_frame <= IXGB_RXBUFFER_2048)) {
+ if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+ || (max_frame <= IXGB_RXBUFFER_2048)) {
adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
- } else if (max_frame <= IXGB_RXBUFFER_4096) {
+ } else if(max_frame <= IXGB_RXBUFFER_4096) {
adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
- } else if (max_frame <= IXGB_RXBUFFER_8192) {
+ } else if(max_frame <= IXGB_RXBUFFER_8192) {
adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
} else {
@@ -1462,7 +1489,7 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- if (old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
+ if(old_max_frame != max_frame && netif_running(netdev)) {
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
@@ -1476,7 +1503,8 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu)
* @adapter: board private structure
**/
-static void ixgb_update_stats(struct ixgb_adapter *adapter)
+void
+ixgb_update_stats(struct ixgb_adapter *adapter)
{
adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
@@ -1585,31 +1613,33 @@ static void ixgb_update_stats(struct ixgb_adapter *adapter)
* @pt_regs: CPU registers structure
**/
-static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t
+ixgb_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = data;
struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
- uint32_t icr = IXGB_READ_REG(&adapter->hw, ICR);
+ uint32_t icr = IXGB_READ_REG(hw, ICR);
#ifndef CONFIG_IXGB_NAPI
unsigned int i;
#endif
- if (unlikely(!icr))
- return IRQ_NONE; /* Not our interrupt */
+ if(unlikely(!icr))
+ return IRQ_NONE; /* Not our interrupt */
- if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
+ if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
mod_timer(&adapter->watchdog_timer, jiffies);
}
+
#ifdef CONFIG_IXGB_NAPI
- if (netif_rx_schedule_prep(netdev)) {
+ if(netif_rx_schedule_prep(netdev)) {
/* Disable interrupts and register for poll. The flush
- of the posted write is intentionally left out.
- */
+ of the posted write is intentionally left out.
+ */
atomic_inc(&adapter->irq_sem);
- IXGB_WRITE_REG(hw, IMC, ~0);
+ IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
__netif_rx_schedule(netdev);
}
#else
@@ -1621,16 +1651,7 @@ static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs)
if(!ixgb_clean_rx_irq(adapter) &
!ixgb_clean_tx_irq(adapter))
break;
- /* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to
- * set IMS:RXDMT0 to 1 to restart the RBD timer (POLL)
- */
- if ((icr & IXGB_INT_RXDMT0) && adapter->raidc) {
- /* ready the timer by writing the clear reg */
- IXGB_WRITE_REG(hw, IMC, IXGB_INT_RXDMT0);
- /* now restart it, h/w will decide if its necessary */
- IXGB_WRITE_REG(hw, IMS, IXGB_INT_RXDMT0);
- }
-#endif
+#endif
return IRQ_HANDLED;
}
@@ -1640,25 +1661,32 @@ static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs)
* @adapter: board private structure
**/
-static int ixgb_clean(struct net_device *netdev, int *budget)
+static int
+ixgb_clean(struct net_device *netdev, int *budget)
{
struct ixgb_adapter *adapter = netdev->priv;
int work_to_do = min(*budget, netdev->quota);
+ int tx_cleaned;
int work_done = 0;
+
+ if (!netif_carrier_ok(netdev))
+ goto quit_polling;
- ixgb_clean_tx_irq(adapter);
+ tx_cleaned = ixgb_clean_tx_irq(adapter);
ixgb_clean_rx_irq(adapter, &work_done, work_to_do);
*budget -= work_done;
netdev->quota -= work_done;
-
- if (work_done < work_to_do || !netif_running(netdev)) {
- netif_rx_complete(netdev);
- /* RAIDC will be automatically restarted by irq_enable */
+
+ /* if no Tx cleanup and not enough Rx work done, exit the polling mode */
+ if((!tx_cleaned && (work_done < work_to_do)) ||
+ !netif_running(netdev)) {
+quit_polling: netif_rx_complete(netdev);
ixgb_irq_enable(adapter);
+ return 0;
}
- return (work_done >= work_to_do);
+ return 1;
}
#endif
@@ -1667,11 +1695,11 @@ static int ixgb_clean(struct net_device *netdev, int *budget)
* @adapter: board private structure
**/
-static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+static boolean_t
+ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
struct ixgb_tx_desc *tx_desc, *eop_desc;
struct ixgb_buffer *buffer_info;
unsigned int i, eop;
@@ -1681,9 +1709,9 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = IXGB_TX_DESC(*tx_ring, eop);
- while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
+ while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
- for (cleaned = FALSE; !cleaned;) {
+ for(cleaned = FALSE; !cleaned; ) {
tx_desc = IXGB_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
@@ -1692,28 +1720,12 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
IXGB_TX_DESC_POPTS_IXSM))
adapter->hw_csum_tx_good++;
- if (buffer_info->dma) {
-
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_TODEVICE);
-
- buffer_info->dma = 0;
- }
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
- if (buffer_info->skb) {
-
- dev_kfree_skb_any(buffer_info->skb);
-
- buffer_info->skb = NULL;
- }
-
- *(uint32_t *) & (tx_desc->status) = 0;
+ *(uint32_t *)&(tx_desc->status) = 0;
cleaned = (i == eop);
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
eop = tx_ring->buffer_info[i].next_to_watch;
@@ -1723,8 +1735,8 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
tx_ring->next_to_clean = i;
spin_lock(&adapter->tx_lock);
- if (cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev)
- && (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
+ if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+ (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
netif_wake_queue(netdev);
}
@@ -1742,20 +1754,21 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
static inline void
ixgb_rx_checksum(struct ixgb_adapter *adapter,
- struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
+ struct ixgb_rx_desc *rx_desc,
+ struct sk_buff *skb)
{
/* Ignore Checksum bit is set OR
* TCP Checksum has not been calculated
*/
- if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
- (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
+ if((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
+ (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
skb->ip_summed = CHECKSUM_NONE;
return;
}
/* At this point we know the hardware did the TCP checksum */
/* now look at the TCP checksum error bit */
- if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
+ if(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
/* let the stack verify checksum errors */
skb->ip_summed = CHECKSUM_NONE;
adapter->hw_csum_rx_error++;
@@ -1792,18 +1805,22 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
rx_desc = IXGB_RX_DESC(*rx_ring, i);
buffer_info = &rx_ring->buffer_info[i];
- while (rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+ while(rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+
+#ifdef CONFIG_IXGB_NAPI
+ if(*work_done >= work_to_do)
+ break;
+ (*work_done)++;
+#endif
skb = buffer_info->skb;
prefetch(skb->data);
- if (++i == rx_ring->count)
- i = 0;
+ if(++i == rx_ring->count) i = 0;
next_rxd = IXGB_RX_DESC(*rx_ring, i);
prefetch(next_rxd);
- if ((j = i + 1) == rx_ring->count)
- j = 0;
+ if((j = i + 1) == rx_ring->count) j = 0;
next2_buffer = &rx_ring->buffer_info[j];
prefetch(next2_buffer);
@@ -1811,27 +1828,22 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
next_skb = next_buffer->skb;
prefetch(next_skb);
-#ifdef CONFIG_IXGB_NAPI
- if (*work_done >= work_to_do)
- break;
-
- (*work_done)++;
-#endif
cleaned = TRUE;
pci_unmap_single(pdev,
buffer_info->dma,
- buffer_info->length, PCI_DMA_FROMDEVICE);
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
length = le16_to_cpu(rx_desc->length);
- if (unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
+ if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
/* All receives must fit into a single buffer */
IXGB_DBG("Receive packet consumed multiple buffers "
- "length<%x>\n", length);
+ "length<%x>\n", length);
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
@@ -1864,26 +1876,22 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_IXGB_NAPI
- if (adapter->vlgrp
- && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+ if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->
- special &
- IXGB_RX_DESC_SPECIAL_VLAN_MASK));
+ le16_to_cpu(rx_desc->special) &
+ IXGB_RX_DESC_SPECIAL_VLAN_MASK);
} else {
netif_receive_skb(skb);
}
-#else /* CONFIG_IXGB_NAPI */
- if (adapter->vlgrp
- && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+#else /* CONFIG_IXGB_NAPI */
+ if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->
- special &
- IXGB_RX_DESC_SPECIAL_VLAN_MASK));
+ le16_to_cpu(rx_desc->special) &
+ IXGB_RX_DESC_SPECIAL_VLAN_MASK);
} else {
netif_rx(skb);
}
-#endif /* CONFIG_IXGB_NAPI */
+#endif /* CONFIG_IXGB_NAPI */
netdev->last_rx = jiffies;
rx_desc->status = 0;
@@ -1905,7 +1913,8 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
* @adapter: address of board private structure
**/
-static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
+static void
+ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
@@ -1921,19 +1930,15 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
buffer_info = &rx_ring->buffer_info[i];
cleancount = IXGB_DESC_UNUSED(rx_ring);
- /* lessen this to 4 if we're
- * in the midst of raidc and rbd is occuring
- * because we don't want to delay returning buffers when low
- */
- num_group_tail_writes = adapter->raidc ? 4 : IXGB_RX_BUFFER_WRITE;
+ num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
/* leave one descriptor unused */
- while (--cleancount > 0) {
+ while(--cleancount > 0) {
rx_desc = IXGB_RX_DESC(*rx_ring, i);
skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
- if (unlikely(!skb)) {
+ if(unlikely(!skb)) {
/* Better luck next round */
break;
}
@@ -1949,13 +1954,14 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
buffer_info->dma =
- pci_map_single(pdev,
+ pci_map_single(pdev,
skb->data,
- adapter->rx_buffer_len, PCI_DMA_FROMDEVICE);
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
- if ((i & ~(num_group_tail_writes - 1)) == i) {
+ if((i & ~(num_group_tail_writes- 1)) == i) {
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
@@ -1965,8 +1971,7 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
IXGB_WRITE_REG(&adapter->hw, RDT, i);
}
- if (++i == rx_ring->count)
- i = 0;
+ if(++i == rx_ring->count) i = 0;
buffer_info = &rx_ring->buffer_info[i];
}
@@ -1988,7 +1993,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
ixgb_irq_disable(adapter);
adapter->vlgrp = grp;
- if (grp) {
+ if(grp) {
/* enable VLAN tag insert/strip */
ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
ctrl |= IXGB_CTRL0_VME;
@@ -2017,7 +2022,8 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
ixgb_irq_enable(adapter);
}
-static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+static void
+ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t vfta, index;
@@ -2030,19 +2036,20 @@ static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
ixgb_write_vfta(&adapter->hw, index, vfta);
}
-static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
+static void
+ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t vfta, index;
ixgb_irq_disable(adapter);
- if (adapter->vlgrp)
+ if(adapter->vlgrp)
adapter->vlgrp->vlan_devices[vid] = NULL;
ixgb_irq_enable(adapter);
- /* remove VID from filter table */
+ /* remove VID from filter table*/
index = (vid >> 5) & 0x7F;
vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -2050,14 +2057,15 @@ static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
ixgb_write_vfta(&adapter->hw, index, vfta);
}
-static void ixgb_restore_vlan(struct ixgb_adapter *adapter)
+static void
+ixgb_restore_vlan(struct ixgb_adapter *adapter)
{
ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
- if (adapter->vlgrp) {
+ if(adapter->vlgrp) {
uint16_t vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if (!adapter->vlgrp->vlan_devices[vid])
+ for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if(!adapter->vlgrp->vlan_devices[vid])
continue;
ixgb_vlan_rx_add_vid(adapter->netdev, vid);
}
@@ -2075,7 +2083,7 @@ ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
struct pci_dev *pdev = NULL;
- switch (event) {
+ switch(event) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
@@ -2092,14 +2100,15 @@ ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
* @param pdev pci driver structure used for passing to
* @param state power state to enter
**/
-static int ixgb_suspend(struct pci_dev *pdev, uint32_t state)
+static int
+ixgb_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv;
netif_device_detach(netdev);
- if (netif_running(netdev))
+ if(netif_running(netdev))
ixgb_down(adapter, TRUE);
pci_save_state(pdev);
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index 892f86caeabab5..5d254b30b93a7f 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -78,19 +78,19 @@ typedef enum {
#define DEBUGOUT7 DEBUGOUT3
#define IXGB_WRITE_REG(a, reg, value) ( \
- writel((value), ((a)->hw_addr + IXGB_##reg)))
+ writel((value), ((a)->hw_addr + IXGB_##reg)))
#define IXGB_READ_REG(a, reg) ( \
- readl((a)->hw_addr + IXGB_##reg))
+ readl((a)->hw_addr + IXGB_##reg))
#define IXGB_WRITE_REG_ARRAY(a, reg, offset, value) ( \
- writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
+ writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
#define IXGB_READ_REG_ARRAY(a, reg, offset) ( \
- readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
+ readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
#define IXGB_WRITE_FLUSH(a) IXGB_READ_REG(a, STATUS)
#define IXGB_MEMCPY memcpy
-#endif /* _IXGB_OSDEP_H_ */
+#endif /* _IXGB_OSDEP_H_ */
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
index 0cb1027fc2954d..23379279ea1a5c 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -34,31 +34,21 @@
#define IXGB_MAX_NIC 8
-#define OPTION_UNSET -1
+#define OPTION_UNSET -1
#define OPTION_DISABLED 0
#define OPTION_ENABLED 1
-/* Module Parameters are always initialized to -1, so that the driver
- * can tell the difference between no user specified value or the
- * user asking for the default value.
- * The true default values are loaded in when ixgb_check_options is called.
- *
- * This is a GCC extension to ANSI C.
- * See the item "Labeled Elements in Initializers" in the section
- * "Extensions to the C Language Family" of the GCC documentation.
- */
-
-#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
-
/* All parameters are treated the same, as an integer array of values.
* This macro just reduces the need to repeat the same declaration code
* over and over (plus this helps to avoid typo bugs).
*/
-#define IXGB_PARAM(X, S) \
-static int __devinitdata X[IXGB_MAX_NIC + 1] = IXGB_PARAM_INIT; \
-module_param_array(X, int, NULL, 0); \
-MODULE_PARM_DESC(X, S);
+#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
+#define IXGB_PARAM(X, desc) \
+ static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \
+ static int num_##X = 0; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
+ MODULE_PARM_DESC(X, desc);
/* Transmit Descriptor Count
*
@@ -121,15 +111,6 @@ IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay");
IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay");
-/* Receive Interrupt Moderation enable (uses RxIntDelay too)
- *
- * Valid Range: 0,1
- *
- * Default Value: 1
- */
-
-IXGB_PARAM(RAIDC, "Disable or enable Receive Interrupt Moderation");
-
/* Receive Flow control high threshold (when we send a pause frame)
* (FCRTH)
*
@@ -173,13 +154,6 @@ IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
-#define DEFAULT_TXD 256
-#define MAX_TXD 4096
-#define MIN_TXD 64
-
-#define DEFAULT_RXD 1024
-#define MAX_RXD 4096
-#define MIN_RXD 64
#define DEFAULT_TIDV 32
#define MAX_TIDV 0xFFFF
@@ -224,9 +198,10 @@ struct ixgb_option {
} arg;
};
-static int __devinit ixgb_validate_option(int *value, struct ixgb_option *opt)
+static int __devinit
+ixgb_validate_option(int *value, struct ixgb_option *opt)
{
- if (*value == OPTION_UNSET) {
+ if(*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
@@ -243,32 +218,31 @@ static int __devinit ixgb_validate_option(int *value, struct ixgb_option *opt)
}
break;
case range_option:
- if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
printk(KERN_INFO "%s set to %i\n", opt->name, *value);
return 0;
}
break;
- case list_option:{
- int i;
- struct ixgb_opt_list *ent;
-
- for (i = 0; i < opt->arg.l.nr; i++) {
- ent = &opt->arg.l.p[i];
- if (*value == ent->i) {
- if (ent->str[0] != '\0')
- printk(KERN_INFO "%s\n",
- ent->str);
- return 0;
- }
+ case list_option: {
+ int i;
+ struct ixgb_opt_list *ent;
+
+ for(i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if(*value == ent->i) {
+ if(ent->str[0] != '\0')
+ printk(KERN_INFO "%s\n", ent->str);
+ return 0;
}
}
+ }
break;
default:
BUG();
}
printk(KERN_INFO "Invalid %s specified (%i) %s\n",
- opt->name, *value, opt->err);
+ opt->name, *value, opt->err);
*value = opt->def;
return -1;
}
@@ -285,198 +259,218 @@ static int __devinit ixgb_validate_option(int *value, struct ixgb_option *opt)
* in a variable in the adapter structure.
**/
-void __devinit ixgb_check_options(struct ixgb_adapter *adapter)
+void __devinit
+ixgb_check_options(struct ixgb_adapter *adapter)
{
int bd = adapter->bd_number;
- if (bd >= IXGB_MAX_NIC) {
+ if(bd >= IXGB_MAX_NIC) {
printk(KERN_NOTICE
- "Warning: no configuration for board #%i\n", bd);
+ "Warning: no configuration for board #%i\n", bd);
printk(KERN_NOTICE "Using defaults for all values\n");
- bd = IXGB_MAX_NIC;
}
- { /* Transmit Descriptor Count */
+ { /* Transmit Descriptor Count */
struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Descriptors",
- .err = "using default of " __MODULE_STRING(DEFAULT_TXD),
- .def = DEFAULT_TXD,
- .arg = {.r = {.min = MIN_TXD,
- .max = MAX_TXD}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_TXD),
+ .def = DEFAULT_TXD,
+ .arg = { .r = { .min = MIN_TXD,
+ .max = MAX_TXD}}
};
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
- tx_ring->count = TxDescriptors[bd];
- ixgb_validate_option(&tx_ring->count, &opt);
+ if(num_TxDescriptors > bd) {
+ tx_ring->count = TxDescriptors[bd];
+ ixgb_validate_option(&tx_ring->count, &opt);
+ } else {
+ tx_ring->count = opt.def;
+ }
IXGB_ROUNDUP(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
}
- { /* Receive Descriptor Count */
+ { /* Receive Descriptor Count */
struct ixgb_option opt = {
.type = range_option,
.name = "Receive Descriptors",
- .err = "using default of " __MODULE_STRING(DEFAULT_RXD),
- .def = DEFAULT_RXD,
- .arg = {.r = {.min = MIN_RXD,
- .max = MAX_RXD}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_RXD),
+ .def = DEFAULT_RXD,
+ .arg = { .r = { .min = MIN_RXD,
+ .max = MAX_RXD}}
};
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
- rx_ring->count = RxDescriptors[bd];
- ixgb_validate_option(&rx_ring->count, &opt);
+ if(num_RxDescriptors > bd) {
+ rx_ring->count = RxDescriptors[bd];
+ ixgb_validate_option(&rx_ring->count, &opt);
+ } else {
+ rx_ring->count = opt.def;
+ }
IXGB_ROUNDUP(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
}
- { /* Receive Checksum Offload Enable */
+ { /* Receive Checksum Offload Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Receive Checksum Offload",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
};
- int rx_csum = XsumRX[bd];
- ixgb_validate_option(&rx_csum, &opt);
- adapter->rx_csum = rx_csum;
+ if(num_XsumRX > bd) {
+ int rx_csum = XsumRX[bd];
+ ixgb_validate_option(&rx_csum, &opt);
+ adapter->rx_csum = rx_csum;
+ } else {
+ adapter->rx_csum = opt.def;
+ }
}
- { /* Flow Control */
+ { /* Flow Control */
struct ixgb_opt_list fc_list[] =
- { {ixgb_fc_none, "Flow Control Disabled"},
- {ixgb_fc_rx_pause, "Flow Control Receive Only"},
- {ixgb_fc_tx_pause, "Flow Control Transmit Only"},
- {ixgb_fc_full, "Flow Control Enabled"},
- {ixgb_fc_default, "Flow Control Hardware Default"}
- };
+ {{ ixgb_fc_none, "Flow Control Disabled" },
+ { ixgb_fc_rx_pause,"Flow Control Receive Only" },
+ { ixgb_fc_tx_pause,"Flow Control Transmit Only" },
+ { ixgb_fc_full, "Flow Control Enabled" },
+ { ixgb_fc_default, "Flow Control Hardware Default" }};
struct ixgb_option opt = {
.type = list_option,
.name = "Flow Control",
- .err = "reading default settings from EEPROM",
- .def = ixgb_fc_full,
- .arg = {.l = {.nr = LIST_LEN(fc_list),
- .p = fc_list}}
+ .err = "reading default settings from EEPROM",
+ .def = ixgb_fc_full,
+ .arg = { .l = { .nr = LIST_LEN(fc_list),
+ .p = fc_list }}
};
- int fc = FlowControl[bd];
- ixgb_validate_option(&fc, &opt);
- adapter->hw.fc.type = fc;
+ if(num_FlowControl > bd) {
+ int fc = FlowControl[bd];
+ ixgb_validate_option(&fc, &opt);
+ adapter->hw.fc.type = fc;
+ } else {
+ adapter->hw.fc.type = opt.def;
+ }
}
- { /* Receive Flow Control High Threshold */
+ { /* Receive Flow Control High Threshold */
struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control High Threshold",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_FCRTH),
- .def = DEFAULT_FCRTH,
- .arg = {.r = {.min = MIN_FCRTH,
- .max = MAX_FCRTH}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
+ .def = DEFAULT_FCRTH,
+ .arg = { .r = { .min = MIN_FCRTH,
+ .max = MAX_FCRTH}}
};
- adapter->hw.fc.high_water = RxFCHighThresh[bd];
- ixgb_validate_option(&adapter->hw.fc.high_water, &opt);
- if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
- printk(KERN_INFO
- "Ignoring RxFCHighThresh when no RxFC\n");
+ if(num_RxFCHighThresh > bd) {
+ adapter->hw.fc.high_water = RxFCHighThresh[bd];
+ ixgb_validate_option(&adapter->hw.fc.high_water, &opt);
+ } else {
+ adapter->hw.fc.high_water = opt.def;
+ }
+ if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+ printk (KERN_INFO
+ "Ignoring RxFCHighThresh when no RxFC\n");
}
- { /* Receive Flow Control Low Threshold */
+ { /* Receive Flow Control Low Threshold */
struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control Low Threshold",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_FCRTL),
- .def = DEFAULT_FCRTL,
- .arg = {.r = {.min = MIN_FCRTL,
- .max = MAX_FCRTL}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
+ .def = DEFAULT_FCRTL,
+ .arg = { .r = { .min = MIN_FCRTL,
+ .max = MAX_FCRTL}}
};
- adapter->hw.fc.low_water = RxFCLowThresh[bd];
- ixgb_validate_option(&adapter->hw.fc.low_water, &opt);
- if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
- printk(KERN_INFO
- "Ignoring RxFCLowThresh when no RxFC\n");
+ if(num_RxFCLowThresh > bd) {
+ adapter->hw.fc.low_water = RxFCLowThresh[bd];
+ ixgb_validate_option(&adapter->hw.fc.low_water, &opt);
+ } else {
+ adapter->hw.fc.low_water = opt.def;
+ }
+ if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+ printk (KERN_INFO
+ "Ignoring RxFCLowThresh when no RxFC\n");
}
- { /* Flow Control Pause Time Request */
+ { /* Flow Control Pause Time Request*/
struct ixgb_option opt = {
.type = range_option,
.name = "Flow Control Pause Time Request",
- .err =
- "using default of "
- __MODULE_STRING(DEFAULT_FCPAUSE),
- .def = DEFAULT_FCPAUSE,
- .arg = {.r = {.min = MIN_FCPAUSE,
- .max = MAX_FCPAUSE}}
+ .err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
+ .def = DEFAULT_FCPAUSE,
+ .arg = { .r = { .min = MIN_FCPAUSE,
+ .max = MAX_FCPAUSE}}
};
- int pause_time = FCReqTimeout[bd];
-
- ixgb_validate_option(&pause_time, &opt);
- if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
- printk(KERN_INFO
- "Ignoring FCReqTimeout when no RxFC\n");
- adapter->hw.fc.pause_time = pause_time;
+ if(num_FCReqTimeout > bd) {
+ int pause_time = FCReqTimeout[bd];
+ ixgb_validate_option(&pause_time, &opt);
+ adapter->hw.fc.pause_time = pause_time;
+ } else {
+ adapter->hw.fc.pause_time = opt.def;
+ }
+ if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+ printk (KERN_INFO
+ "Ignoring FCReqTimeout when no RxFC\n");
}
/* high low and spacing check for rx flow control thresholds */
if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
/* high must be greater than low */
if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
/* set defaults */
- printk(KERN_INFO
- "RxFCHighThresh must be >= (RxFCLowThresh + 8), "
- "Using Defaults\n");
+ printk (KERN_INFO
+ "RxFCHighThresh must be >= (RxFCLowThresh + 8), "
+ "Using Defaults\n");
adapter->hw.fc.high_water = DEFAULT_FCRTH;
- adapter->hw.fc.low_water = DEFAULT_FCRTL;
+ adapter->hw.fc.low_water = DEFAULT_FCRTL;
}
}
- { /* Receive Interrupt Delay */
+ { /* Receive Interrupt Delay */
struct ixgb_option opt = {
.type = range_option,
.name = "Receive Interrupt Delay",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_RDTR),
- .def = DEFAULT_RDTR,
- .arg = {.r = {.min = MIN_RDTR,
- .max = MAX_RDTR}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
+ .def = DEFAULT_RDTR,
+ .arg = { .r = { .min = MIN_RDTR,
+ .max = MAX_RDTR}}
};
- adapter->rx_int_delay = RxIntDelay[bd];
- ixgb_validate_option(&adapter->rx_int_delay, &opt);
- }
- { /* Receive Interrupt Moderation */
- struct ixgb_option opt = {
- .type = enable_option,
- .name = "Advanced Receive Interrupt Moderation",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
- };
- int raidc = RAIDC[bd];
-
- ixgb_validate_option(&raidc, &opt);
- adapter->raidc = raidc;
+ if(num_RxIntDelay > bd) {
+ adapter->rx_int_delay = RxIntDelay[bd];
+ ixgb_validate_option(&adapter->rx_int_delay, &opt);
+ } else {
+ adapter->rx_int_delay = opt.def;
+ }
}
- { /* Transmit Interrupt Delay */
+ { /* Transmit Interrupt Delay */
struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Interrupt Delay",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_TIDV),
- .def = DEFAULT_TIDV,
- .arg = {.r = {.min = MIN_TIDV,
- .max = MAX_TIDV}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
+ .def = DEFAULT_TIDV,
+ .arg = { .r = { .min = MIN_TIDV,
+ .max = MAX_TIDV}}
};
- adapter->tx_int_delay = TxIntDelay[bd];
- ixgb_validate_option(&adapter->tx_int_delay, &opt);
+ if(num_TxIntDelay > bd) {
+ adapter->tx_int_delay = TxIntDelay[bd];
+ ixgb_validate_option(&adapter->tx_int_delay, &opt);
+ } else {
+ adapter->tx_int_delay = opt.def;
+ }
}
- { /* Transmit Interrupt Delay Enable */
+ { /* Transmit Interrupt Delay Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Tx Interrupt Delay Enable",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
};
- int ide = IntDelayEnable[bd];
- ixgb_validate_option(&ide, &opt);
- adapter->tx_int_delay_enable = ide;
+ if(num_IntDelayEnable > bd) {
+ int ide = IntDelayEnable[bd];
+ ixgb_validate_option(&ide, &opt);
+ adapter->tx_int_delay_enable = ide;
+ } else {
+ adapter->tx_int_delay_enable = opt.def;
+ }
}
}
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 08ffa1bcb68c89..3e05fd77412853 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -322,7 +322,6 @@ static dev_link_t *tc574_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -519,6 +518,7 @@ static void tc574_config(dev_link_t *link)
link->state &= ~DEV_CONFIG_PENDING;
link->dev = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
@@ -1308,8 +1308,7 @@ static int __init init_tc574(void)
static void __exit exit_tc574(void)
{
pcmcia_unregister_driver(&tc574_driver);
- while (dev_list != NULL)
- tc574_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_tc574);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 06ace14a6ba2a6..00c82eafb21b0d 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -236,7 +236,6 @@ static dev_link_t *tc589_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -391,6 +390,7 @@ static void tc589_config(dev_link_t *link)
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
@@ -1083,8 +1083,7 @@ static int __init init_tc589(void)
static void __exit exit_tc589(void)
{
pcmcia_unregister_driver(&tc589_driver);
- while (dev_list != NULL)
- tc589_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_tc589);
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 957bd2e8ab89e1..c61fba0ea8985e 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -191,7 +191,6 @@ static dev_link_t *axnet_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -458,6 +457,7 @@ static void axnet_config(dev_link_t *link)
info->phy_id = (i < 32) ? i : -1;
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
@@ -877,8 +877,7 @@ static int __init init_axnet_cs(void)
static void __exit exit_axnet_cs(void)
{
pcmcia_unregister_driver(&axnet_cs_driver);
- while (dev_list != NULL)
- axnet_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_axnet_cs);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index fbdc0b7a53d763..211fdac0a6eb88 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -211,7 +211,6 @@ static dev_link_t *com20020_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -394,6 +393,7 @@ static void com20020_config(dev_link_t *link)
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = com20020_found(dev, 0); /* calls register_netdev */
@@ -513,8 +513,7 @@ static int __init init_com20020_cs(void)
static void __exit exit_com20020_cs(void)
{
pcmcia_unregister_driver(&com20020_cs_driver);
- while (dev_list != NULL)
- com20020_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_com20020_cs);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index d676aba69dc151..850f1d94c5d677 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -299,7 +299,6 @@ static dev_link_t *fmvj18x_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -591,6 +590,7 @@ static void fmvj18x_config(dev_link_t *link)
lp->cardtype = cardtype;
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
@@ -792,8 +792,7 @@ static int __init init_fmvj18x_cs(void)
static void __exit exit_fmvj18x_cs(void)
{
pcmcia_unregister_driver(&fmvj18x_cs_driver);
- while (dev_list != NULL)
- fmvj18x_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_fmvj18x_cs);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index dbdcbc6cec052a..c3ca9fb6591205 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -204,7 +204,6 @@ static dev_link_t *ibmtr_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -366,6 +365,7 @@ static void ibmtr_config(dev_link_t *link)
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = ibmtr_probe_card(dev);
if (i != 0) {
@@ -538,8 +538,7 @@ static int __init init_ibmtr_cs(void)
static void __exit exit_ibmtr_cs(void)
{
pcmcia_unregister_driver(&ibmtr_cs_driver);
- while (dev_list != NULL)
- ibmtr_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_ibmtr_cs);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index f97ce65d76b0c4..35e66f0f9e4278 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -512,7 +512,6 @@ static dev_link_t *nmclan_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -775,6 +774,7 @@ static void nmclan_config(dev_link_t *link)
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = register_netdev(dev);
if (i != 0) {
@@ -1702,8 +1702,7 @@ static int __init init_nmclan_cs(void)
static void __exit exit_nmclan_cs(void)
{
pcmcia_unregister_driver(&nmclan_cs_driver);
- while (dev_list != NULL)
- nmclan_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_nmclan_cs);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b17b3fb8629697..ddaf72136c2d89 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -286,7 +286,6 @@ static dev_link_t *pcnet_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -722,6 +721,7 @@ static void pcnet_config(dev_link_t *link)
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ei_poll;
@@ -1662,8 +1662,7 @@ static void __exit exit_pcnet_cs(void)
{
DEBUG(0, "pcnet_cs: unloading\n");
pcmcia_unregister_driver(&pcnet_driver);
- while (dev_list != NULL)
- pcnet_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_pcnet_cs);
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 284375f2026c48..78f84e1f9fc897 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -374,7 +374,6 @@ static dev_link_t *smc91c92_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
@@ -1024,6 +1023,7 @@ static void smc91c92_config(dev_link_t *link)
link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
@@ -2263,8 +2263,7 @@ static int __init init_smc91c92_cs(void)
static void __exit exit_smc91c92_cs(void)
{
pcmcia_unregister_driver(&smc91c92_cs_driver);
- while (dev_list != NULL)
- smc91c92_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_smc91c92_cs);
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 6f4eeaf7f5de26..aadbb787982ca2 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -627,7 +627,6 @@ xirc2ps_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -1121,6 +1120,7 @@ xirc2ps_config(dev_link_t * link)
link->dev = &local->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
@@ -2016,9 +2016,7 @@ static void __exit
exit_xirc2ps_cs(void)
{
pcmcia_unregister_driver(&xirc2ps_cs_driver);
-
- while (dev_list)
- xirc2ps_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_xirc2ps_cs);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index eca5b66cdb4fd8..0393ee5ecd8582 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -560,21 +560,35 @@ static void free_shared_mem(struct s2io_nic *nic)
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
+ if (!nic->ba[i])
+ goto end_free;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
- if (!nic->ba[i][j])
- continue;
+ if (!nic->ba[i][j]) {
+ kfree(nic->ba[i]);
+ goto end_free;
+ }
while (k != MAX_RXDS_PER_BLOCK) {
buffAdd_t *ba = &nic->ba[i][j][k];
+ if (!ba || !ba->ba_0_org || !ba->ba_1_org)
+ {
+ kfree(nic->ba[i]);
+ kfree(nic->ba[i][j]);
+ if(ba->ba_0_org)
+ kfree(ba->ba_0_org);
+ if(ba->ba_1_org)
+ kfree(ba->ba_1_org);
+ goto end_free;
+ }
kfree(ba->ba_0_org);
kfree(ba->ba_1_org);
k++;
}
kfree(nic->ba[i][j]);
}
- if (nic->ba[i])
- kfree(nic->ba[i]);
+ kfree(nic->ba[i]);
}
+end_free:
#endif
if (mac_control->stats_mem) {
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index d2deaaf5d98bab..b4cc65dbf2a795 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -740,8 +740,8 @@ static inline u64 readq(void *addr)
{
u64 ret = 0;
ret = readl(addr + 4);
- (u64) ret <<= 32;
- (u64) ret |= readl(addr);
+ ret <<= 32;
+ ret |= readl(addr);
return ret;
}
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 695278c97afeca..a29ac209692317 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -156,8 +156,6 @@ static int __init do_ultra_probe(struct net_device *dev)
/* Look for any installed ISAPnP cards */
if (isapnp_present() && (ultra_probe_isapnp(dev) == 0))
return 0;
-
- printk(KERN_NOTICE "smc-ultra.c: No ISAPnP cards found, trying standard ones...\n");
#endif
for (i = 0; ultra_portlist[i]; i++) {
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 9b75be8b971eab..fb9935b670ac29 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1333,6 +1333,19 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void smc_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ smc_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
/* Our watchdog timed out. Called by the networking layer */
static void smc_timeout(struct net_device *dev)
{
@@ -1912,6 +1925,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
dev->get_stats = smc_query_statistics;
dev->set_multicast_list = smc_set_multicast_list;
dev->ethtool_ops = &smc_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = smc_poll_controller;
+#endif
tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
INIT_WORK(&lp->phy_configure, smc_phy_configure, dev);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index aee87bb3438422..2152403888fcac 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -2697,7 +2697,8 @@ int reset_card( struct net_device *dev , int lock) {
}
struct net_device *_init_airo_card( unsigned short irq, int port,
- int is_pcmcia, struct pci_dev *pci )
+ int is_pcmcia, struct pci_dev *pci,
+ struct device *dmdev )
{
struct net_device *dev;
struct airo_info *ai;
@@ -2759,10 +2760,8 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
dev->irq = irq;
dev->base_addr = port;
- /* what is with PCMCIA ??? */
- if (pci) {
- SET_NETDEV_DEV(dev, &pci->dev);
- }
+ SET_NETDEV_DEV(dev, dmdev);
+
if (test_bit(FLAG_MPI,&ai->flags))
reset_card (dev, 1);
@@ -2844,9 +2843,10 @@ err_out_free:
return NULL;
}
-struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
+struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia,
+ struct device *dmdev)
{
- return _init_airo_card ( irq, port, is_pcmcia, NULL);
+ return _init_airo_card ( irq, port, is_pcmcia, NULL, dmdev);
}
EXPORT_SYMBOL(init_airo_card);
@@ -5455,9 +5455,9 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
if (pdev->device == 0x5000 || pdev->device == 0xa504)
- dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev);
+ dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
else
- dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev);
+ dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
if (!dev)
return -ENODEV;
@@ -5559,7 +5559,7 @@ static int __init airo_init_module( void )
printk( KERN_INFO
"airo: Trying to configure ISA adapter at irq=%d io=0x%x\n",
irq[i], io[i] );
- if (init_airo_card( irq[i], io[i], 0 ))
+ if (init_airo_card( irq[i], io[i], 0, NULL ))
have_isa_dev = 1;
}
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 939783ff112037..16a97314109126 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -89,7 +89,7 @@ module_param_array(irq_list, int, NULL, 0);
event handler.
*/
-struct net_device *init_airo_card( int, int, int );
+struct net_device *init_airo_card( int, int, int, struct device * );
void stop_airo_card( struct net_device *, int );
int reset_airo_card( struct net_device * );
@@ -225,7 +225,6 @@ static dev_link_t *airo_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -450,7 +449,7 @@ static void airo_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
((local_info_t*)link->priv)->eth_dev =
init_airo_card( link->irq.AssignedIRQ,
- link->io.BasePort1, 1 );
+ link->io.BasePort1, 1, &handle_to_dev(handle) );
if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
/*
@@ -592,13 +591,7 @@ static int airo_cs_init(void)
static void airo_cs_cleanup(void)
{
pcmcia_unregister_driver(&airo_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- airo_release(dev_list);
- airo_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
/*
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 8337121c9ed97a..3fe780d128d948 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -237,7 +237,6 @@ static dev_link_t *atmel_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -347,18 +346,6 @@ static struct {
{ 0, 0, "11WAVE/11WP611AL-E", "atmel_at76c502e%s.bin", "11WAVE WaveBuddy" }
};
-/* This is strictly temporary, until PCMCIA devices get integrated into the device model. */
-static struct device *atmel_device(void)
-{
- static struct device dev = {
- .bus_id = "pcmcia",
- };
- kobject_set_name(&dev.kobj, "atmel_cs");
- kobject_init(&dev.kobj);
-
- return &dev;
-}
-
static void atmel_config(dev_link_t *link)
{
client_handle_t handle;
@@ -549,7 +536,7 @@ static void atmel_config(dev_link_t *link)
init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1,
card_index == -1 ? NULL : card_table[card_index].firmware,
- atmel_device(),
+ &handle_to_dev(handle),
card_present,
link);
if (!((local_info_t*)link->priv)->eth_dev)
@@ -693,13 +680,7 @@ static int atmel_cs_init(void)
static void atmel_cs_cleanup(void)
{
pcmcia_unregister_driver(&atmel_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- atmel_release(dev_list);
- atmel_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
/*
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 4936d7e3469d11..e2685634c2d5f6 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -503,7 +503,6 @@ static dev_link_t *netwave_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -1073,6 +1072,8 @@ static void netwave_pcmcia_config(dev_link_t *link) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+
if (register_netdev(dev) != 0) {
printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
goto failed;
@@ -1696,9 +1697,7 @@ static int __init init_netwave_cs(void)
static void __exit exit_netwave_cs(void)
{
pcmcia_unregister_driver(&netwave_driver);
-
- if (dev_list != NULL) /* Critical situation */
- printk("netwave_cs: devices remaining when removing module\n");
+ BUG_ON(dev_list != NULL);
}
module_init(init_netwave_cs);
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 823fa82e6b9a4b..8f746051af82da 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -617,9 +617,8 @@ static int orinoco_open(struct net_device *dev)
unsigned long flags;
int err;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = __orinoco_up(dev);
@@ -671,10 +670,9 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
return NULL; /* FIXME: Can we do better than this? */
}
- err = orinoco_lock(priv, &flags);
- if (err)
- return NULL; /* FIXME: Erg, we've been signalled, how
- * do we propagate this back up? */
+ if (orinoco_lock(priv, &flags) != 0)
+ return NULL; /* FIXME: Erg, we've been signalled, how
+ * do we propagate this back up? */
if (priv->iw_mode == IW_MODE_ADHOC) {
memset(&wstats->qual, 0, sizeof(wstats->qual));
@@ -1819,10 +1817,8 @@ static int orinoco_reconfigure(struct net_device *dev)
return 0;
}
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
-
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_disable_port(hw, 0);
if (err) {
@@ -1864,11 +1860,10 @@ static void orinoco_reset(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
struct hermes *hw = &priv->hw;
- int err;
+ int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
+ if (orinoco_lock(priv, &flags) != 0)
/* When the hardware becomes available again, whatever
* detects that is responsible for re-initializing
* it. So no need for anything further */
@@ -2411,9 +2406,8 @@ static int orinoco_hw_get_bssid(struct orinoco_private *priv,
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, buf);
@@ -2433,9 +2427,8 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
int len;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (strlen(priv->desired_essid) > 0) {
/* We read the desired SSID from the hardware rather
@@ -2486,9 +2479,8 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
long freq = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
if (err)
@@ -2528,9 +2520,8 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int i;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
sizeof(list), NULL, &list);
@@ -2568,9 +2559,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
rrq->length = sizeof(range);
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
mode = priv->iw_mode;
orinoco_unlock(priv, &flags);
@@ -2639,9 +2629,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
range.min_frag = 256;
range.max_frag = 2346;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (priv->has_wep) {
range.max_encoding_tokens = ORINOCO_MAX_KEYS;
@@ -2706,10 +2695,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
if (copy_from_user(keybuf, erq->pointer, erq->length))
return -EFAULT;
}
-
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (erq->pointer) {
if (erq->length > ORINOCO_MAX_KEY_SIZE) {
@@ -2788,12 +2776,10 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
u16 xlen = 0;
char keybuf[ORINOCO_MAX_KEY_SIZE];
- int err;
unsigned long flags;
-
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
index = priv->tx_key;
@@ -2833,7 +2819,6 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
{
struct orinoco_private *priv = netdev_priv(dev);
char essidbuf[IW_ESSID_MAX_SIZE+1];
- int err;
unsigned long flags;
/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
@@ -2851,9 +2836,8 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
essidbuf[erq->length] = '\0';
}
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid));
@@ -2877,9 +2861,8 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
if (err)
return err;
} else {
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf));
orinoco_unlock(priv, &flags);
}
@@ -2899,7 +2882,6 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
{
struct orinoco_private *priv = netdev_priv(dev);
char nickbuf[IW_ESSID_MAX_SIZE+1];
- int err;
unsigned long flags;
if (nrq->length > IW_ESSID_MAX_SIZE)
@@ -2912,9 +2894,8 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
nickbuf[nrq->length] = '\0';
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(priv->nick, nickbuf, sizeof(priv->nick));
@@ -2927,12 +2908,10 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
{
struct orinoco_private *priv = netdev_priv(dev);
char nickbuf[IW_ESSID_MAX_SIZE+1];
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
orinoco_unlock(priv, &flags);
@@ -2949,7 +2928,6 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
{
struct orinoco_private *priv = netdev_priv(dev);
int chan = -1;
- int err;
unsigned long flags;
/* We can only use this in Ad-Hoc demo mode to set the operating
@@ -2978,9 +2956,8 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
! (priv->channel_mask & (1 << (chan-1)) ) )
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->channel = chan;
orinoco_unlock(priv, &flags);
@@ -2998,9 +2975,8 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
if (!priv->has_sensitivity)
return -EOPNOTSUPP;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP,
HERMES_RID_CNFSYSTEMSCALE, &val);
orinoco_unlock(priv, &flags);
@@ -3018,7 +2994,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = srq->value;
- int err;
unsigned long flags;
if (!priv->has_sensitivity)
@@ -3027,9 +3002,8 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
if ((val < 1) || (val > 3))
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->ap_density = val;
orinoco_unlock(priv, &flags);
@@ -3040,7 +3014,6 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = rrq->value;
- int err;
unsigned long flags;
if (rrq->disabled)
@@ -3049,9 +3022,8 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
if ( (val < 0) || (val > 2347) )
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->rts_thresh = val;
orinoco_unlock(priv, &flags);
@@ -3065,9 +3037,8 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (priv->has_mwo) {
if (frq->disabled)
@@ -3102,9 +3073,8 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
u16 val;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (priv->has_mwo) {
err = hermes_read_wordrec(hw, USER_BAP,
@@ -3166,9 +3136,8 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
if (ratemode == -1)
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->bitratemode = ratemode;
orinoco_unlock(priv, &flags);
@@ -3185,9 +3154,8 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
u16 val;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
ratemode = priv->bitratemode;
@@ -3247,9 +3215,8 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (prq->disabled) {
priv->pm_on = 0;
@@ -3302,9 +3269,8 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
u16 enable, period, timeout, mcast;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
if (err)
@@ -3351,9 +3317,8 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
u16 short_limit, long_limit, lifetime;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
&short_limit);
@@ -3399,12 +3364,10 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = *( (int *) wrq->u.name );
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->ibss_port = val ;
@@ -3419,12 +3382,10 @@ static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int *val = (int *)wrq->u.name;
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->ibss_port;
orinoco_unlock(priv, &flags);
@@ -3439,9 +3400,8 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
switch (val) {
case 0: /* Try to do IEEE ad-hoc mode */
@@ -3478,12 +3438,10 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int *val = (int *)wrq->u.name;
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->prefer_port3;
orinoco_unlock(priv, &flags);
@@ -3513,9 +3471,8 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
}
/* Make sure nobody mess with the structure while we do */
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
/* orinoco_lock() doesn't disable interrupts, so make sure the
* interrupt rx path don't get confused while we copy */
@@ -3546,12 +3503,10 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
struct iw_quality spy_stat[IW_MAX_SPY];
int number;
int i;
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
number = priv->spy_number;
if ((number > 0) && (srq->pointer)) {
@@ -3621,9 +3576,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SIOCSIWMODE:
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
switch (wrq->u.mode) {
case IW_MODE_ADHOC:
if (! (priv->has_ibss || priv->has_port3) )
@@ -3648,9 +3602,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SIOCGIWMODE:
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
wrq->u.mode = priv->iw_mode;
orinoco_unlock(priv, &flags);
break;
@@ -3865,9 +3818,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if(priv->has_preamble) {
int val = *( (int *) wrq->u.name );
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (val)
priv->preamble = 1;
else
@@ -3882,9 +3834,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if(priv->has_preamble) {
int *val = (int *)wrq->u.name;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->preamble;
orinoco_unlock(priv, &flags);
} else
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d7085037eb9bca..2c8618098602d8 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -197,7 +197,6 @@ orinoco_cs_attach(void)
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -454,6 +453,7 @@ orinoco_cs_config(dev_link_t *link)
/* register_netdev will give us an ethX name */
dev->name[0] = '\0';
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -653,14 +653,7 @@ static void __exit
exit_orinoco_cs(void)
{
pcmcia_unregister_driver(&orinoco_driver);
-
- if (dev_list)
- DEBUG(0, PFX "Removing leftover devices.\n");
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- orinoco_cs_release(dev_list);
- orinoco_cs_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_orinoco_cs);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7ba64e3c87571c..e220781b03ae57 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -398,7 +398,6 @@ static dev_link_t *ray_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -564,6 +563,7 @@ static void ray_config(dev_link_t *link)
return;
}
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = register_netdev(dev);
if (i != 0) {
printk("ray_config register_netdev() failed\n");
@@ -2952,8 +2952,7 @@ static void __exit exit_ray_cs(void)
#endif
pcmcia_unregister_driver(&ray_driver);
- while (dev_list != NULL)
- ray_detach(dev_list);
+ BUG_ON(dev_list != NULL);
} /* exit_ray_cs */
module_init(init_ray_cs);
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 17fcd84c1a14a8..a2b95854f4fcc1 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4068,6 +4068,7 @@ wv_pcmcia_config(dev_link_t * link)
lp->mem, dev->irq, (u_int) dev->base_addr);
#endif
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = register_netdev(dev);
if(i != 0)
{
@@ -4688,7 +4689,6 @@ wavelan_attach(void)
/* Register with Card Services */
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_REGISTRATION_COMPLETE |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 58b101389ffa50..ba05d01de58a98 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -100,7 +100,7 @@ module_param(pc_debug, int, 0);
/* Parameters that can be set with 'insmod' */
/* Bit map of interrupts to choose from */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
-static unsigned long wl3501_irq_mask = 0xdeb8;
+static unsigned int wl3501_irq_mask = 0xdeb8;
static int wl3501_irq_list[4] = { -1 };
/*
@@ -2015,7 +2015,6 @@ static dev_link_t *wl3501_attach(void)
link->next = wl3501_dev_list;
wl3501_dev_list = link;
client_reg.dev_info = &wl3501_dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask = CS_EVENT_CARD_INSERTION |
CS_EVENT_RESET_PHYSICAL |
CS_EVENT_CARD_RESET |
@@ -2105,6 +2104,7 @@ static void wl3501_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev)) {
printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
goto failed;
@@ -2267,19 +2267,13 @@ static void __exit wl3501_exit_module(void)
{
dprintk(0, ": unloading");
pcmcia_unregister_driver(&wl3501_driver);
- while (wl3501_dev_list) {
- /* Mark the device as non-existing to minimize calls to card */
- wl3501_dev_list->state &= ~DEV_PRESENT;
- if (wl3501_dev_list->state & DEV_CONFIG)
- wl3501_release(wl3501_dev_list);
- wl3501_detach(wl3501_dev_list);
- }
+ BUG_ON(wl3501_dev_list != NULL);
}
module_init(wl3501_init_module);
module_exit(wl3501_exit_module);
-module_param(wl3501_irq_mask, int, 0);
+module_param(wl3501_irq_mask, uint, 0);
module_param_array(wl3501_irq_list, int, NULL, 0);
MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, "
"Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 58706683b886d9..d497877ef11c21 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -143,7 +143,6 @@ static dev_link_t *parport_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -401,10 +400,7 @@ static int __init init_parport_cs(void)
static void __exit exit_parport_cs(void)
{
pcmcia_unregister_driver(&parport_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- parport_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_parport_cs);
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 37b643d24825d3..ca14e721502dda 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -39,18 +39,6 @@ config PCMCIA_DEBUG
In all the above examples, N is the debugging verbosity
level.
-config PCMCIA_OBSOLETE
- bool "Enable obsolete PCCARD code"
- depends on PCCARD != n
- help
- Say Y here to enable some code found in the PCCARD subsystem
- which has no in-kernel usage, but might be needed for certain
- external PCMCIA drivers. If you do need to say Y here so that
- one such driver compiles and/or works correctly, please report
- this to linux-pcmcia <at> lists.infradead.org
-
- If unsure, say N
-
config PCMCIA
tristate "16-bit PCMCIA support"
depends on PCCARD
@@ -92,6 +80,7 @@ config YENTA
depends on PCCARD && PCI
#fixme: remove dependendcy on CARDBUS
depends on CARDBUS
+ select PCCARD_NONSTATIC
---help---
This option enables support for CardBus host bridges. Virtually
all modern PCMCIA bridges are CardBus compatible. A "bridge" is
@@ -106,6 +95,7 @@ config YENTA
config PD6729
tristate "Cirrus PD6729 compatible bridge support"
depends on PCMCIA && PCI
+ select PCCARD_NONSTATIC
help
This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
device, found in some older laptops and PCMCIA card readers.
@@ -113,6 +103,7 @@ config PD6729
config I82092
tristate "i82092 compatible bridge support"
depends on PCMCIA && PCI
+ select PCCARD_NONSTATIC
help
This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
found in some older laptops and more commonly in evaluation boards for the
@@ -121,6 +112,7 @@ config I82092
config I82365
tristate "i82365 compatible bridge support"
depends on PCMCIA && ISA
+ select PCCARD_NONSTATIC
help
Say Y here to include support for ISA-bus PCMCIA host bridges that
are register compatible with the Intel i82365. These are found on
@@ -131,6 +123,7 @@ config I82365
config TCIC
tristate "Databook TCIC host bridge support"
depends on PCMCIA
+ select PCCARD_NONSTATIC
help
Say Y here to include support for the Databook TCIC family of PCMCIA
host bridges. These are only found on a handful of old systems.
@@ -190,4 +183,8 @@ config M32R_CFC_NUM
help
Set the number of M32R CF slots.
+config PCCARD_NONSTATIC
+ tristate
+ depends on PCCARD
+
endmenu
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index dff3caa0dc396d..3d5eb4984a7fbb 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -10,9 +10,11 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
-pcmcia-y += ds.o bulkmem.o pcmcia_compat.o
+pcmcia-y += ds.o pcmcia_compat.o
obj-$(CONFIG_PCMCIA) += pcmcia.o
+obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o
+
# socket drivers
diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
deleted file mode 100644
index 855c1f76c5dd27..00000000000000
--- a/drivers/pcmcia/bulkmem.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*======================================================================
-
- PCMCIA Bulk Memory Services
-
- bulkmem.c 1.38 2000/09/25 19:29:51
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-
-#define IN_CARD_SERVICES
-#include <pcmcia/cs_types.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-
-#ifdef DEBUG
-extern int ds_pc_debug;
-#define cs_socket_name(skt) ((skt)->dev.class_id)
-
-#define ds_dbg(skt, lvl, fmt, arg...) do { \
- if (ds_pc_debug >= lvl) \
- printk(KERN_DEBUG "ds: %s: " fmt, \
- cs_socket_name(skt) , ## arg); \
-} while (0)
-#else
-#define ds_dbg(lvl, fmt, arg...) do { } while (0)
-#endif
-
-/*======================================================================
-
- This stuff is used by Card Services to initialize the table of
- region info used for subsequent calls to GetFirstRegion and
- GetNextRegion.
-
-======================================================================*/
-
-static void setup_regions(struct pcmcia_socket *s, unsigned int function,
- int attr, memory_handle_t *list)
-{
- int i, code, has_jedec, has_geo;
- u_int offset;
- cistpl_device_t device;
- cistpl_jedec_t jedec;
- cistpl_device_geo_t geo;
- memory_handle_t r;
-
- ds_dbg(s, 1, "setup_regions(0x%d, %d, 0x%p)\n",
- function, attr, list);
-
- code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE;
- if (pccard_read_tuple(s, function, code, &device) != CS_SUCCESS)
- return;
- code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C;
- has_jedec = (pccard_read_tuple(s, function, code, &jedec) == CS_SUCCESS);
- if (has_jedec && (device.ndev != jedec.nid)) {
- ds_dbg(s, 0, "Device info does not match JEDEC info.\n");
- has_jedec = 0;
- }
- code = (attr) ? CISTPL_DEVICE_GEO_A : CISTPL_DEVICE_GEO;
- has_geo = (pccard_read_tuple(s, function, code, &geo) == CS_SUCCESS);
- if (has_geo && (device.ndev != geo.ngeo)) {
- ds_dbg(s, 0, "Device info does not match geometry tuple.\n");
- has_geo = 0;
- }
-
- offset = 0;
- for (i = 0; i < device.ndev; i++) {
- if ((device.dev[i].type != CISTPL_DTYPE_NULL) &&
- (device.dev[i].size != 0)) {
- r = kmalloc(sizeof(*r), GFP_KERNEL);
- if (!r) {
- printk(KERN_NOTICE "cs: setup_regions: kmalloc failed!\n");
- return;
- }
- r->region_magic = REGION_MAGIC;
- r->state = 0;
- r->dev_info[0] = '\0';
- r->mtd = NULL;
- r->info.Attributes = (attr) ? REGION_TYPE_AM : 0;
- r->info.CardOffset = offset;
- r->info.RegionSize = device.dev[i].size;
- r->info.AccessSpeed = device.dev[i].speed;
- if (has_jedec) {
- r->info.JedecMfr = jedec.id[i].mfr;
- r->info.JedecInfo = jedec.id[i].info;
- } else
- r->info.JedecMfr = r->info.JedecInfo = 0;
- if (has_geo) {
- r->info.BlockSize = geo.geo[i].buswidth *
- geo.geo[i].erase_block * geo.geo[i].interleave;
- r->info.PartMultiple =
- r->info.BlockSize * geo.geo[i].partition;
- } else
- r->info.BlockSize = r->info.PartMultiple = 1;
- r->info.next = *list; *list = r;
- }
- offset += device.dev[i].size;
- }
-} /* setup_regions */
-
-/*======================================================================
-
- This is tricky. When get_first_region() is called by Driver
- Services, we initialize the region info table in the socket
- structure. When it is called by an MTD, we can just scan the
- table for matching entries.
-
-======================================================================*/
-
-static int pccard_match_region(memory_handle_t list, region_info_t *match)
-{
- if (list) {
- *match = list->info;
- return CS_SUCCESS;
- }
- return CS_NO_MORE_ITEMS;
-} /* match_region */
-
-int pccard_get_first_region(struct pcmcia_socket *s, region_info_t *rgn)
-{
- if (!(s->state & SOCKET_REGION_INFO)) {
- setup_regions(s, BIND_FN_ALL, 0, &s->c_region);
- setup_regions(s, BIND_FN_ALL, 1, &s->a_region);
- s->state |= SOCKET_REGION_INFO;
- }
-
- if (rgn->Attributes & REGION_TYPE_AM)
- return pccard_match_region(s->a_region, rgn);
- else
- return pccard_match_region(s->c_region, rgn);
-} /* get_first_region */
-
-int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn)
-{
- return pccard_match_region(rgn->next, rgn);
-} /* get_next_region */
-
-
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-static int match_region(client_handle_t handle, memory_handle_t list,
- region_info_t *match)
-{
- while (list != NULL) {
- if (!(handle->Attributes & INFO_MTD_CLIENT) ||
- (strcmp(handle->dev_info, list->dev_info) == 0)) {
- *match = list->info;
- return CS_SUCCESS;
- }
- list = list->info.next;
- }
- return CS_NO_MORE_ITEMS;
-} /* match_region */
-
-int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn)
-{
- struct pcmcia_socket *s = SOCKET(handle);
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-
- if ((handle->Attributes & INFO_MASTER_CLIENT) &&
- (!(s->state & SOCKET_REGION_INFO))) {
- setup_regions(s, handle->Function, 0, &s->c_region);
- setup_regions(s, handle->Function, 1, &s->a_region);
- s->state |= SOCKET_REGION_INFO;
- }
-
- if (rgn->Attributes & REGION_TYPE_AM)
- return match_region(handle, s->a_region, rgn);
- else
- return match_region(handle, s->c_region, rgn);
-} /* get_first_region */
-EXPORT_SYMBOL(pcmcia_get_first_region);
-
-int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn)
-{
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- return match_region(handle, rgn->next, rgn);
-} /* get_next_region */
-EXPORT_SYMBOL(pcmcia_get_next_region);
-
-#endif
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 1b86c6d3a572f4..3ccb5247ec504d 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- Cardbus device configuration
-
- cardbus.c 1.87 2002/10/24 06:11:41
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
+/*
+ * cardbus.c -- 16-bit PCMCIA core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
/*
* Cardbus handling has been re-written to be more of a PCI bridge thing,
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 8cf0623397f757..e29a6ddf2fd7e1 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- PCMCIA Card Information Structure parser
-
- cistpl.c 1.99 2002/10/24 06:11:48
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in
- which case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
+/*
+ * cistpl.c -- 16-bit PCMCIA Card Information Structure parser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -97,6 +78,7 @@ void release_cis_mem(struct pcmcia_socket *s)
s->cis_virt = NULL;
}
}
+EXPORT_SYMBOL(release_cis_mem);
/*
* Map the card memory at "card_offset" into virtual space.
@@ -108,8 +90,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
{
pccard_mem_map *mem = &s->cis_mem;
if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) {
- mem->res = find_mem_region(0, s->map_size, s->map_size, 0,
- "card services", s);
+ mem->res = find_mem_region(0, s->map_size, s->map_size, 0, s);
if (mem->res == NULL) {
printk(KERN_NOTICE "cs: unable to map card memory!\n");
return NULL;
@@ -340,6 +321,7 @@ void destroy_cis_cache(struct pcmcia_socket *s)
s->fake_cis = NULL;
}
}
+EXPORT_SYMBOL(destroy_cis_cache);
/*======================================================================
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 4e4c964f7e01bf..edfc17a306875e 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- Kernel Card Services -- core services
-
- cs.c 1.271 2000/10/02 20:27:49
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
+/*
+ * cs.c -- Kernel Card Services - core services
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -60,6 +41,7 @@
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
#include "cs_internal.h"
#ifdef CONFIG_PCI
@@ -92,7 +74,7 @@ static const char *options = "options: " OPTIONS;
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Linux Kernel Card Services\noptions:" OPTIONS);
-MODULE_LICENSE("Dual MPL/GPL");
+MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
@@ -132,6 +114,8 @@ socket_state_t dead_socket = {
/* List of all sockets, protected by a rwsem */
LIST_HEAD(pcmcia_socket_list);
DECLARE_RWSEM(pcmcia_socket_list_rwsem);
+EXPORT_SYMBOL(pcmcia_socket_list);
+EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
/*====================================================================
@@ -189,16 +173,32 @@ int pcmcia_socket_dev_resume(struct device *dev)
EXPORT_SYMBOL(pcmcia_socket_dev_resume);
+struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt)
+{
+ struct class_device *cl_dev = class_device_get(&skt->dev);
+ if (!cl_dev)
+ return NULL;
+ skt = class_get_devdata(cl_dev);
+ if (!try_module_get(skt->owner)) {
+ class_device_put(&skt->dev);
+ return NULL;
+ }
+ return (skt);
+}
+EXPORT_SYMBOL(pcmcia_get_socket);
+
+
+void pcmcia_put_socket(struct pcmcia_socket *skt)
+{
+ module_put(skt->owner);
+ class_device_put(&skt->dev);
+}
+EXPORT_SYMBOL(pcmcia_put_socket);
+
+
static void pcmcia_release_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
- client_t *client;
-
- while (socket->clients) {
- client = socket->clients;
- socket->clients = socket->clients->next;
- kfree(client);
- }
complete(&socket->socket_released);
}
@@ -212,11 +212,17 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
{
int ret;
- if (!socket || !socket->ops || !socket->dev.dev)
+ if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops)
return -EINVAL;
cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
+ if (socket->resource_ops->init) {
+ ret = socket->resource_ops->init(socket);
+ if (ret)
+ return (ret);
+ }
+
/* try to obtain a socket number [yes, it gets ugly if we
* register more than 2^sizeof(unsigned int) pcmcia
* sockets... but the socket number is deprecated
@@ -305,6 +311,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
up_write(&pcmcia_socket_list_rwsem);
/* wait for sysfs to drop all references */
+ release_resource_db(socket);
wait_for_completion(&socket->socket_released);
} /* pcmcia_unregister_socket */
EXPORT_SYMBOL(pcmcia_unregister_socket);
@@ -349,12 +356,8 @@ static void free_regions(memory_handle_t *list)
}
}
-static int send_event(struct pcmcia_socket *s, event_t event, int priority);
-
static void shutdown_socket(struct pcmcia_socket *s)
{
- client_t **c;
-
cs_dbg(s, 1, "shutdown_socket\n");
/* Blank out the socket state */
@@ -372,15 +375,6 @@ static void shutdown_socket(struct pcmcia_socket *s)
kfree(s->config);
s->config = NULL;
}
- for (c = &s->clients; *c; ) {
- if ((*c)->state & CLIENT_UNBOUND) {
- client_t *d = *c;
- *c = (*c)->next;
- kfree(d);
- } else {
- c = &((*c)->next);
- }
- }
free_regions(&s->a_region);
free_regions(&s->c_region);
@@ -395,45 +389,44 @@ static void shutdown_socket(struct pcmcia_socket *s)
/*======================================================================
- The central event handler. Send_event() sends an event to all
- valid clients. Parse_events() interprets the event bits from
+ The central event handler. Send_event() sends an event to the
+ 16-bit subsystem, which then calls the relevant device drivers.
+ Parse_events() interprets the event bits from
a card status change report. Do_shutdown() handles the high
priority stuff associated with a card removal.
======================================================================*/
+
+/* NOTE: send_event needs to be called with skt->sem held. */
+
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
- client_t *client = s->clients;
- int ret;
- cs_dbg(s, 1, "send_event(event %d, pri %d)\n",
- event, priority);
- ret = 0;
- if (s->state & SOCKET_CARDBUS)
- return 0;
- for (; client; client = client->next) {
- if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
- continue;
- if (client->EventMask & event) {
- ret = EVENT(client, event, priority);
- if (ret != 0)
- return ret;
- }
- }
- return ret;
-} /* send_event */
+ int ret;
+
+ if (s->state & SOCKET_CARDBUS)
+ return 0;
+
+ cs_dbg(s, 1, "send_event(event %d, pri %d, callback 0x%p)\n",
+ event, priority, s->callback);
+
+ if (!s->callback)
+ return 0;
+ if (!try_module_get(s->callback->owner))
+ return 0;
+
+ ret = s->callback->event(s, event, priority);
+
+ module_put(s->callback->owner);
+
+ return ret;
+}
static void socket_remove_drivers(struct pcmcia_socket *skt)
{
- client_t *client;
-
cs_dbg(skt, 4, "remove_drivers\n");
send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
-
- for (client = skt->clients; client; client = client->next)
- if (!(client->Attributes & INFO_MASTER_CLIENT))
- client->state |= CLIENT_STALE;
}
static void socket_shutdown(struct pcmcia_socket *skt)
@@ -756,7 +749,7 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
======================================================================*/
static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
- ioaddr_t num, u_int lines, char *name)
+ ioaddr_t num, u_int lines)
{
int i;
ioaddr_t try, align;
@@ -788,7 +781,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
return 1;
for (i = 0; i < MAX_IO_WIN; i++) {
if (s->io[i].NumPorts == 0) {
- s->io[i].res = find_io_region(*base, num, align, name, s);
+ s->io[i].res = find_io_region(*base, num, align, s);
if (s->io[i].res) {
s->io[i].Attributes = attr;
s->io[i].BasePort = *base = s->io[i].res->start;
@@ -888,49 +881,6 @@ int pccard_access_configuration_register(struct pcmcia_socket *s,
} /* access_configuration_register */
EXPORT_SYMBOL(pccard_access_configuration_register);
-/*====================================================================*/
-
-int pcmcia_deregister_client(client_handle_t handle)
-{
- client_t **client;
- struct pcmcia_socket *s;
- u_long flags;
- int i;
-
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-
- s = SOCKET(handle);
- cs_dbg(s, 1, "deregister_client(%p)\n", handle);
-
- if (handle->state &
- (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
- return CS_IN_USE;
- for (i = 0; i < MAX_WIN; i++)
- if (handle->state & CLIENT_WIN_REQ(i))
- return CS_IN_USE;
-
- if ((handle->state & CLIENT_STALE) ||
- (handle->Attributes & INFO_MASTER_CLIENT)) {
- spin_lock_irqsave(&s->lock, flags);
- client = &s->clients;
- while ((*client) && ((*client) != handle))
- client = &(*client)->next;
- if (*client == NULL) {
- spin_unlock_irqrestore(&s->lock, flags);
- return CS_BAD_HANDLE;
- }
- *client = handle->next;
- handle->client_magic = 0;
- kfree(handle);
- spin_unlock_irqrestore(&s->lock, flags);
- } else {
- handle->state = CLIENT_UNBOUND;
- handle->event_handler = NULL;
- }
-
- return CS_SUCCESS;
-} /* deregister_client */
/*====================================================================*/
@@ -1014,53 +964,6 @@ int pcmcia_get_card_services_info(servinfo_t *info)
return CS_SUCCESS;
} /* get_card_services_info */
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-/*======================================================================
-
- Note that get_first_client() *does* recognize the Socket field
- in the request structure.
-
-======================================================================*/
-
-int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
-{
- socket_t s;
- struct pcmcia_socket *socket;
- if (req->Attributes & CLIENT_THIS_SOCKET)
- s = req->Socket;
- else
- s = 0;
- socket = pcmcia_get_socket_by_nr(s);
- if (!socket)
- return CS_BAD_SOCKET;
- if (socket->clients == NULL)
- return CS_NO_MORE_ITEMS;
- *handle = socket->clients;
- return CS_SUCCESS;
-} /* get_first_client */
-EXPORT_SYMBOL(pcmcia_get_first_client);
-
-/*====================================================================*/
-
-int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req)
-{
- struct pcmcia_socket *s;
- if ((handle == NULL) || CHECK_HANDLE(*handle))
- return CS_BAD_HANDLE;
- if ((*handle)->next == NULL) {
- if (req->Attributes & CLIENT_THIS_SOCKET)
- return CS_NO_MORE_ITEMS;
- s = (*handle)->Socket;
- if (s->clients == NULL)
- return CS_NO_MORE_ITEMS;
- *handle = s->clients;
- } else
- *handle = (*handle)->next;
- return CS_SUCCESS;
-} /* get_next_client */
-EXPORT_SYMBOL(pcmcia_get_next_client);
-#endif /* CONFIG_PCMCIA_OBSOLETE */
/*====================================================================*/
@@ -1251,117 +1154,33 @@ int pcmcia_modify_configuration(client_handle_t handle,
return CS_SUCCESS;
} /* modify_configuration */
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-/*======================================================================
-
- Modify the attributes of a window returned by RequestWindow.
-
-======================================================================*/
-
-int pcmcia_modify_window(window_handle_t win, modwin_t *req)
+/* register pcmcia_callback */
+int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
{
- if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
-
- win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE);
- if (req->Attributes & WIN_MEMORY_TYPE)
- win->ctl.flags |= MAP_ATTRIB;
- if (req->Attributes & WIN_ENABLE)
- win->ctl.flags |= MAP_ACTIVE;
- if (req->Attributes & WIN_DATA_WIDTH_16)
- win->ctl.flags |= MAP_16BIT;
- if (req->Attributes & WIN_USE_WAIT)
- win->ctl.flags |= MAP_USE_WAIT;
- win->ctl.speed = req->AccessSpeed;
- win->sock->ops->set_mem_map(win->sock, &win->ctl);
-
- return CS_SUCCESS;
-} /* modify_window */
-EXPORT_SYMBOL(pcmcia_modify_window);
-
-#endif /* CONFIG_PCMCIA_OBSOLETE */
-
+ int ret = 0;
-/*======================================================================
+ /* s->skt_sem also protects s->callback */
+ down(&s->skt_sem);
- Register_client() uses the dev_info_t handle to match the
- caller with a socket. The driver must have already been bound
- to a socket with bind_device() -- in fact, bind_device()
- allocates the client structure that will be used.
-
-======================================================================*/
-
-int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
-{
- client_t *client = NULL;
- struct pcmcia_socket *s;
-
- /* Look for unbound client with matching dev_info */
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
- client = s->clients;
- while (client != NULL) {
- if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
- && (client->state & CLIENT_UNBOUND)) break;
- client = client->next;
- }
- if (client != NULL) break;
- }
- up_read(&pcmcia_socket_list_rwsem);
- if (client == NULL)
- return CS_OUT_OF_RESOURCE;
+ if (c) {
+ /* registration */
+ if (s->callback) {
+ ret = -EBUSY;
+ goto err;
+ }
- /*
- * Prevent this racing with a card insertion.
- */
- down(&s->skt_sem);
- *handle = client;
- client->state &= ~CLIENT_UNBOUND;
- client->Socket = s;
- client->Attributes = req->Attributes;
- client->EventMask = req->EventMask;
- client->event_handler = req->event_handler;
- client->event_callback_args = req->event_callback_args;
- client->event_callback_args.client_handle = client;
-
- if (s->state & SOCKET_CARDBUS)
- client->state |= CLIENT_CARDBUS;
-
- if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
- (client->Function != BIND_FN_ALL)) {
- cistpl_longlink_mfc_t mfc;
- if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc)
- == CS_SUCCESS)
- s->functions = mfc.nfn;
- else
- s->functions = 1;
- s->config = kmalloc(sizeof(config_t) * s->functions,
- GFP_KERNEL);
- if (!s->config)
- goto out_no_resource;
- memset(s->config, 0, sizeof(config_t) * s->functions);
- }
-
- cs_dbg(s, 1, "register_client(): client 0x%p, dev %s\n",
- client, client->dev_info);
- if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
- EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
-
- if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
- if (client->EventMask & CS_EVENT_CARD_INSERTION)
- EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
- else
- client->PendingEvents |= CS_EVENT_CARD_INSERTION;
- }
+ s->callback = c;
- up(&s->skt_sem);
- return CS_SUCCESS;
+ if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT)
+ send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ } else
+ s->callback = NULL;
+ err:
+ up(&s->skt_sem);
- out_no_resource:
- up(&s->skt_sem);
- return CS_OUT_OF_RESOURCE;
-} /* register_client */
+ return ret;
+}
+EXPORT_SYMBOL(pccard_register_pcmcia);
/*====================================================================*/
@@ -1685,14 +1504,12 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req)
return CS_BAD_ATTRIBUTE;
if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
- req->NumPorts1, req->IOAddrLines,
- handle->dev_info))
+ req->NumPorts1, req->IOAddrLines))
return CS_IN_USE;
if (req->NumPorts2) {
if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
- req->NumPorts2, req->IOAddrLines,
- handle->dev_info)) {
+ req->NumPorts2, req->IOAddrLines)) {
release_io_space(s, req->BasePort1, req->NumPorts1);
return CS_IN_USE;
}
@@ -1720,6 +1537,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
struct pcmcia_socket *s;
config_t *c;
int ret = CS_IN_USE, irq = 0;
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
@@ -1769,7 +1587,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
- handle->dev_info, req->Instance))
+ p_dev->dev.bus_id, req->Instance))
return CS_IN_USE;
}
@@ -1832,8 +1650,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
if (!(s->features & SS_CAP_STATIC_MAP)) {
win->ctl.res = find_mem_region(req->Base, req->Size, align,
- (req->Attributes & WIN_MAP_BELOW_1MB),
- (*handle)->dev_info, s);
+ (req->Attributes & WIN_MAP_BELOW_1MB), s);
if (!win->ctl.res)
return CS_IN_USE;
}
@@ -2022,47 +1839,16 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
/*======================================================================
- Maybe this should send a CS_EVENT_CARD_INSERTION event if we
- haven't sent one to this client yet?
-
-======================================================================*/
-
-#ifdef CONFIG_PCMCIA_OBSOLETE
-int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
-{
- u_int events, bit;
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- if (handle->Attributes & CONF_EVENT_MASK_VALID)
- return CS_BAD_SOCKET;
- handle->EventMask = mask->EventMask;
- events = handle->PendingEvents & handle->EventMask;
- handle->PendingEvents -= events;
- while (events != 0) {
- bit = ((events ^ (events-1)) + 1) >> 1;
- EVENT(handle, bit, CS_EVENT_PRI_LOW);
- events -= bit;
- }
- return CS_SUCCESS;
-} /* set_event_mask */
-EXPORT_SYMBOL(pcmcia_set_event_mask);
-
-#endif /* CONFIG_PCMCIA_OBSOLETE */
-
-/*======================================================================
-
OS-specific module glue goes here
======================================================================*/
/* in alpha order */
-EXPORT_SYMBOL(pcmcia_deregister_client);
EXPORT_SYMBOL(pcmcia_eject_card);
EXPORT_SYMBOL(pcmcia_get_card_services_info);
EXPORT_SYMBOL(pcmcia_get_mem_page);
EXPORT_SYMBOL(pcmcia_insert_card);
EXPORT_SYMBOL(pcmcia_map_mem_page);
EXPORT_SYMBOL(pcmcia_modify_configuration);
-EXPORT_SYMBOL(pcmcia_register_client);
EXPORT_SYMBOL(pcmcia_release_configuration);
EXPORT_SYMBOL(pcmcia_release_io);
EXPORT_SYMBOL(pcmcia_release_irq);
@@ -2100,7 +1886,6 @@ static int __init init_pcmcia_cs(void)
static void __exit exit_pcmcia_cs(void)
{
printk(KERN_INFO "unloading Kernel Card Services\n");
- release_resource_db();
class_interface_unregister(&pccard_sysfs_interface);
class_unregister(&pcmcia_socket_class);
}
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index fbce6b67988b22..f64ca5663f3cc4 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -1,19 +1,15 @@
/*
- * cs_internal.h 1.57 2002/10/24 06:11:43
+ * cs_internal.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CS_INTERNAL_H
@@ -22,19 +18,7 @@
#include <linux/config.h>
#define CLIENT_MAGIC 0x51E6
-typedef struct client_t {
- u_short client_magic;
- struct pcmcia_socket *Socket;
- u_char Function;
- dev_info_t dev_info;
- u_int Attributes;
- u_int state;
- event_t EventMask, PendingEvents;
- int (*event_handler)(event_t event, int priority,
- event_callback_args_t *);
- event_callback_args_t event_callback_args;
- struct client_t *next;
-} client_t;
+typedef struct client_t client_t;
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
@@ -151,15 +135,15 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
/* In rsrc_mgr */
void pcmcia_validate_mem(struct pcmcia_socket *s);
struct resource *find_io_region(unsigned long base, int num, unsigned long align,
- char *name, struct pcmcia_socket *s);
+ struct pcmcia_socket *s);
int adjust_io_region(struct resource *res, unsigned long r_start,
unsigned long r_end, struct pcmcia_socket *s);
struct resource *find_mem_region(u_long base, u_long num, u_long align,
- int low, char *name, struct pcmcia_socket *s);
+ int low, struct pcmcia_socket *s);
int try_irq(u_int Attributes, int irq, int specific);
void undo_irq(u_int Attributes, int irq);
int adjust_resource_info(client_handle_t handle, adjust_t *adj);
-void release_resource_db(void);
+void release_resource_db(struct pcmcia_socket *s);
/* In socket_sysfs.c */
extern struct class_interface pccard_sysfs_interface;
@@ -173,6 +157,14 @@ int pccard_reset_card(struct pcmcia_socket *skt);
int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status);
int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg);
+
+struct pcmcia_callback{
+ struct module *owner;
+ int (*event) (struct pcmcia_socket *s, event_t event, int priority);
+};
+
+int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
+
#define cs_socket_name(skt) ((skt)->dev.class_id)
#ifdef DEBUG
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 639c5acf22f159..6d40401abe930f 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1,35 +1,17 @@
-/*======================================================================
-
- PC Card Driver Services
-
- ds.c 1.112 2001/10/13 00:08:28
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in
- which case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
+/*
+ * ds.c -- 16-bit PCMCIA core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ * (C) 2003 - 2004 Dominik Brodowski
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -51,6 +33,7 @@
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/delay.h>
+#include <linux/kref.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
@@ -72,7 +55,7 @@
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA Driver Services");
-MODULE_LICENSE("Dual MPL/GPL");
+MODULE_LICENSE("GPL");
#ifdef DEBUG
int ds_pc_debug;
@@ -89,13 +72,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644);
/*====================================================================*/
-typedef struct socket_bind_t {
- struct pcmcia_driver *driver;
- u_char function;
- dev_link_t *instance;
- struct socket_bind_t *next;
-} socket_bind_t;
-
/* Device user information */
#define MAX_EVENTS 32
#define USER_MAGIC 0x7ea4
@@ -111,16 +87,22 @@ typedef struct user_info_t {
/* Socket state information */
struct pcmcia_bus_socket {
- atomic_t refcount;
- client_handle_t handle;
+ struct kref refcount;
+ struct pcmcia_callback callback;
int state;
user_info_t *user;
int req_pending, req_result;
wait_queue_head_t queue, request;
- struct work_struct removal;
- socket_bind_t *bind;
struct pcmcia_socket *parent;
+
+ /* the PCMCIA devices connected to this socket (normally one, more
+ * for multifunction devices: */
+ struct list_head devices_list;
+ u8 device_count; /* the number of devices, used
+ * only internally and subject
+ * to incorrectness and change */
};
+static spinlock_t pcmcia_dev_list_lock;
#define DS_SOCKET_PRESENT 0x01
#define DS_SOCKET_BUSY 0x02
@@ -129,89 +111,14 @@ struct pcmcia_bus_socket {
/*====================================================================*/
-/* Device driver ID passed to Card Services */
-static dev_info_t dev_info = "Driver Services";
-
static int major_dev = -1;
+static int unbind_request(struct pcmcia_bus_socket *s);
+
/*====================================================================*/
/* code which was in cs.c before */
-/*======================================================================
-
- Bind_device() associates a device driver with a particular socket.
- It is normally called by Driver Services after it has identified
- a newly inserted card. An instance of that driver will then be
- eligible to register as a client of this socket.
-
-======================================================================*/
-
-static int pcmcia_bind_device(bind_req_t *req)
-{
- client_t *client;
- struct pcmcia_socket *s;
-
- s = req->Socket;
- if (!s)
- return CS_BAD_SOCKET;
-
- client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL);
- if (!client)
- return CS_OUT_OF_RESOURCE;
- memset(client, '\0', sizeof(client_t));
- client->client_magic = CLIENT_MAGIC;
- strlcpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
- client->Socket = s;
- client->Function = req->Function;
- client->state = CLIENT_UNBOUND;
- client->next = s->clients;
- s->clients = client;
- ds_dbg(1, "%s: bind_device(): client 0x%p, dev %s\n",
- cs_socket_name(client->Socket), client, client->dev_info);
- return CS_SUCCESS;
-} /* bind_device */
-
-
-/*======================================================================
-
- Bind_mtd() associates a device driver with a particular memory
- region. It is normally called by Driver Services after it has
- identified a memory device type. An instance of the corresponding
- driver will then be able to register to control this region.
-
-======================================================================*/
-
-static int pcmcia_bind_mtd(mtd_bind_t *req)
-{
- struct pcmcia_socket *s;
- memory_handle_t region;
-
- s = req->Socket;
- if (!s)
- return CS_BAD_SOCKET;
-
- if (req->Attributes & REGION_TYPE_AM)
- region = s->a_region;
- else
- region = s->c_region;
-
- while (region) {
- if (region->info.CardOffset == req->CardOffset)
- break;
- region = region->info.next;
- }
- if (!region || (region->mtd != NULL))
- return CS_BAD_OFFSET;
- strlcpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
-
- ds_dbg(1, "%s: bind_mtd: attr 0x%x, offset 0x%x, dev %s\n",
- cs_socket_name(s), req->Attributes, req->CardOffset,
- (char *)req->dev_info);
- return CS_SUCCESS;
-} /* bind_mtd */
-
-
/* String tables for error messages */
typedef struct lookup_t {
@@ -314,8 +221,10 @@ int pcmcia_report_error(client_handle_t handle, error_info_t *err)
if (CHECK_HANDLE(handle))
printk(KERN_NOTICE);
- else
- printk(KERN_NOTICE "%s: ", handle->dev_info);
+ else {
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
+ printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
+ }
for (i = 0; i < ARRAY_SIZE(service_table); i++)
if (service_table[i].key == err->func)
@@ -353,22 +262,22 @@ EXPORT_SYMBOL(cs_error);
static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info);
static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr);
-static void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s)
+static void pcmcia_release_bus_socket(struct kref *refcount)
{
- if (atomic_dec_and_test(&s->refcount))
- kfree(s);
+ struct pcmcia_bus_socket *s = container_of(refcount, struct pcmcia_bus_socket, refcount);
+ pcmcia_put_socket(s->parent);
+ kfree(s);
}
-static struct pcmcia_bus_socket *pcmcia_get_bus_socket(int nr)
+static void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s)
{
- struct pcmcia_bus_socket *s;
+ kref_put(&s->refcount, pcmcia_release_bus_socket);
+}
- s = get_socket_info_by_nr(nr);
- if (s) {
- WARN_ON(atomic_read(&s->refcount) == 0);
- atomic_inc(&s->refcount);
- }
- return s;
+static struct pcmcia_bus_socket *pcmcia_get_bus_socket(struct pcmcia_bus_socket *s)
+{
+ kref_get(&s->refcount);
+ return (s);
}
/**
@@ -381,8 +290,8 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
if (!driver)
return -EINVAL;
- driver->use_count = 0;
driver->drv.bus = &pcmcia_bus_type;
+ driver->drv.owner = driver->owner;
return driver_register(&driver->drv);
}
@@ -403,10 +312,16 @@ static struct proc_dir_entry *proc_pccard = NULL;
static int proc_read_drivers_callback(struct device_driver *driver, void *d)
{
char **p = d;
- struct pcmcia_driver *p_dev = container_of(driver,
+ struct pcmcia_driver *p_drv = container_of(driver,
struct pcmcia_driver, drv);
- *p += sprintf(*p, "%-24.24s 1 %d\n", driver->name, p_dev->use_count);
+ *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name,
+#ifdef CONFIG_MODULE_UNLOAD
+ (p_drv->owner) ? module_refcount(p_drv->owner) : 1
+#else
+ 1
+#endif
+ );
d = (void *) p;
return 0;
@@ -424,6 +339,31 @@ static int proc_read_drivers(char *buf, char **start, off_t pos,
}
#endif
+/* pcmcia_device handling */
+
+static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev)
+{
+ struct device *tmp_dev;
+ tmp_dev = get_device(&p_dev->dev);
+ if (!tmp_dev)
+ return NULL;
+ return to_pcmcia_dev(tmp_dev);
+}
+
+static void pcmcia_put_dev(struct pcmcia_device *p_dev)
+{
+ put_device(&p_dev->dev);
+}
+
+static void pcmcia_release_dev(struct device *dev)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ ds_dbg(1, "releasing dev %p\n", p_dev);
+ pcmcia_put_bus_socket(p_dev->socket->pcmcia);
+ kfree(p_dev);
+}
+
+
/*======================================================================
These manage a ring buffer of events pending for one user process
@@ -471,255 +411,494 @@ static int handle_request(struct pcmcia_bus_socket *s, event_t event)
return CS_SUCCESS;
}
-static void handle_removal(void *data)
-{
- struct pcmcia_bus_socket *s = data;
- handle_event(s, CS_EVENT_CARD_REMOVAL);
- s->state &= ~DS_SOCKET_REMOVAL_PENDING;
-}
-
/*======================================================================
The card status event handler.
======================================================================*/
-static int ds_event(event_t event, int priority,
- event_callback_args_t *args)
+struct send_event_data {
+ struct pcmcia_socket *skt;
+ event_t event;
+ int priority;
+};
+
+static int send_event_callback(struct device *dev, void * _data)
{
- struct pcmcia_bus_socket *s;
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ struct send_event_data *data = _data;
- ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, args->client_handle);
- s = args->client_data;
-
- switch (event) {
-
- case CS_EVENT_CARD_REMOVAL:
- s->state &= ~DS_SOCKET_PRESENT;
- if (!(s->state & DS_SOCKET_REMOVAL_PENDING)) {
- s->state |= DS_SOCKET_REMOVAL_PENDING;
- schedule_delayed_work(&s->removal, HZ/10);
- }
- break;
-
- case CS_EVENT_CARD_INSERTION:
- s->state |= DS_SOCKET_PRESENT;
- handle_event(s, event);
- break;
+ /* we get called for all sockets, but may only pass the event
+ * for drivers _on the affected socket_ */
+ if (p_dev->socket != data->skt)
+ return 0;
- case CS_EVENT_EJECTION_REQUEST:
- return handle_request(s, event);
- break;
-
- default:
- handle_event(s, event);
- break;
- }
+ if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE))
+ return 0;
- return 0;
-} /* ds_event */
+ if (p_dev->client.EventMask & data->event)
+ return EVENT(&p_dev->client, data->event, data->priority);
-/*======================================================================
+ return 0;
+}
- bind_mtd() connects a memory region with an MTD client.
-
-======================================================================*/
+static int send_event(struct pcmcia_socket *s, event_t event, int priority)
+{
+ int ret = 0;
+ struct send_event_data private;
+ struct pcmcia_bus_socket *skt = pcmcia_get_bus_socket(s->pcmcia);
+
+ if (!skt)
+ return 0;
+
+ private.skt = s;
+ private.event = event;
+ private.priority = priority;
-static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info)
+ ret = bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback);
+
+ pcmcia_put_bus_socket(skt);
+ return ret;
+} /* send_event */
+
+
+/* Normally, the event is passed to individual drivers after
+ * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
+ * is inversed to maintain historic compatibility.
+ */
+
+static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{
- mtd_bind_t bind_req;
- int ret;
+ struct pcmcia_bus_socket *s = skt->pcmcia;
+ int ret = 0;
- bind_req.dev_info = &mtd_info->dev_info;
- bind_req.Attributes = mtd_info->Attributes;
- bind_req.Socket = bus_sock->parent;
- bind_req.CardOffset = mtd_info->CardOffset;
- ret = pcmcia_bind_mtd(&bind_req);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindMTD, ret);
- printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
- " offset 0x%x\n",
- (char *)bind_req.dev_info, bus_sock->parent->sock, bind_req.CardOffset);
- return -ENODEV;
+ ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
+ event, priority, s);
+
+ switch (event) {
+
+ case CS_EVENT_CARD_REMOVAL:
+ s->state &= ~DS_SOCKET_PRESENT;
+ send_event(skt, event, priority);
+ unbind_request(s);
+ handle_event(s, event);
+ break;
+
+ case CS_EVENT_CARD_INSERTION:
+ s->state |= DS_SOCKET_PRESENT;
+ handle_event(s, event);
+ send_event(skt, event, priority);
+ break;
+
+ case CS_EVENT_EJECTION_REQUEST:
+ ret = handle_request(s, event);
+ if (ret)
+ break;
+ ret = send_event(skt, event, priority);
+ break;
+
+ default:
+ handle_event(s, event);
+ send_event(skt, event, priority);
+ break;
}
+
return 0;
-} /* bind_mtd */
+} /* ds_event */
+
/*======================================================================
+ bind_request() and bind_device() are merged by now. Register_client()
+ is called right at the end of bind_request(), during the driver's
+ ->attach() call. Individual descriptions:
+
bind_request() connects a socket to a particular client driver.
It looks up the specified device ID in the list of registered
drivers, binds it to the socket, and tries to create an instance
of the device. unbind_request() deletes a driver instance.
+ Bind_device() associates a device driver with a particular socket.
+ It is normally called by Driver Services after it has identified
+ a newly inserted card. An instance of that driver will then be
+ eligible to register as a client of this socket.
+
+ Register_client() uses the dev_info_t handle to match the
+ caller with a socket. The driver must have already been bound
+ to a socket with bind_device() -- in fact, bind_device()
+ allocates the client structure that will be used.
+
======================================================================*/
static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
- struct pcmcia_driver *driver;
- socket_bind_t *b;
- bind_req_t bind_req;
- int ret;
+ struct pcmcia_driver *p_drv;
+ struct pcmcia_device *p_dev, *tmp_dev;
+ unsigned long flags;
+ int ret = 0;
- if (!s)
- return -EINVAL;
-
- ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock,
- (char *)bind_info->dev_info);
- driver = get_pcmcia_driver(&bind_info->dev_info);
- if (!driver)
- return -EINVAL;
-
- for (b = s->bind; b; b = b->next)
- if ((driver == b->driver) &&
- (bind_info->function == b->function))
- break;
- if (b != NULL) {
- bind_info->instance = b->instance;
- return -EBUSY;
- }
+ s = pcmcia_get_bus_socket(s);
+ if (!s)
+ return -EINVAL;
- if (!try_module_get(driver->owner))
- return -EINVAL;
-
- bind_req.Socket = s->parent;
- bind_req.Function = bind_info->function;
- bind_req.dev_info = (dev_info_t *) driver->drv.name;
- ret = pcmcia_bind_device(&bind_req);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindDevice, ret);
- printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
- (char *)dev_info, s->parent->sock);
- module_put(driver->owner);
- return -ENODEV;
- }
+ ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock,
+ (char *)bind_info->dev_info);
- /* Add binding to list for this socket */
- driver->use_count++;
- b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
- if (!b)
- {
- driver->use_count--;
- module_put(driver->owner);
- return -ENOMEM;
- }
- b->driver = driver;
- b->function = bind_info->function;
- b->instance = NULL;
- b->next = s->bind;
- s->bind = b;
-
- if (driver->attach) {
- b->instance = driver->attach();
- if (b->instance == NULL) {
- printk(KERN_NOTICE "ds: unable to create instance "
- "of '%s'!\n", (char *)bind_info->dev_info);
- module_put(driver->owner);
- return -ENODEV;
+ p_drv = get_pcmcia_driver(&bind_info->dev_info);
+ if (!p_drv) {
+ ret = -EINVAL;
+ goto err_put;
}
- }
-
- return 0;
+
+ if (!try_module_get(p_drv->owner)) {
+ ret = -EINVAL;
+ goto err_put_driver;
+ }
+
+ /* Currently, the userspace pcmcia cardmgr detects pcmcia devices.
+ * Here this information is translated into a kernel
+ * struct pcmcia_device.
+ */
+
+ p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
+ if (!p_dev) {
+ ret = -ENOMEM;
+ goto err_put_module;
+ }
+ memset(p_dev, 0, sizeof(struct pcmcia_device));
+
+ p_dev->socket = s->parent;
+ p_dev->device_no = (s->device_count++);
+ p_dev->func = bind_info->function;
+
+ p_dev->dev.bus = &pcmcia_bus_type;
+ p_dev->dev.parent = s->parent->dev.dev;
+ p_dev->dev.release = pcmcia_release_dev;
+ sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ p_dev->dev.driver = &p_drv->drv;
+
+ /* compat */
+ p_dev->client.client_magic = CLIENT_MAGIC;
+ p_dev->client.Socket = s->parent;
+ p_dev->client.Function = bind_info->function;
+ p_dev->client.state = CLIENT_UNBOUND;
+
+ ret = device_register(&p_dev->dev);
+ if (ret) {
+ kfree(p_dev);
+ goto err_put_module;
+ }
+
+ /* Add to the list in pcmcia_bus_socket, but only if no device
+ * with the same func _and_ driver exists */
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) {
+ if ((tmp_dev->func == bind_info->function) &&
+ (tmp_dev->dev.driver == p_dev->dev.driver)){
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ bind_info->instance = tmp_dev->instance;
+ ret = -EBUSY;
+ goto err_unregister;
+ }
+ }
+ list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ if (p_drv->attach) {
+ p_dev->instance = p_drv->attach();
+ if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
+ printk(KERN_NOTICE "ds: unable to create instance "
+ "of '%s'!\n", (char *)bind_info->dev_info);
+ ret = -ENODEV;
+ goto err_unregister;
+ }
+ }
+
+ put_driver(&p_drv->drv);
+
+ return 0;
+
+ err_unregister:
+ device_unregister(&p_dev->dev);
+ module_put(p_drv->owner);
+ put_driver(&p_drv->drv);
+ return (ret);
+
+ err_put_module:
+ module_put(p_drv->owner);
+ err_put_driver:
+ put_driver(&p_drv->drv);
+ err_put:
+ pcmcia_put_bus_socket(s);
+ return (ret);
} /* bind_request */
+int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
+{
+ client_t *client = NULL;
+ struct pcmcia_socket *s;
+ struct pcmcia_bus_socket *skt = NULL;
+ struct pcmcia_device *p_dev = NULL;
+
+ /* Look for unbound client with matching dev_info */
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+ unsigned long flags;
+
+ if (s->state & SOCKET_CARDBUS)
+ continue;
+
+ skt = s->pcmcia;
+ if (!skt)
+ continue;
+ skt = pcmcia_get_bus_socket(skt);
+ if (!skt)
+ continue;
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) {
+ struct pcmcia_driver *p_drv;
+ p_dev = pcmcia_get_dev(p_dev);
+ if (!p_dev)
+ continue;
+ if ((!p_dev->client.state & CLIENT_UNBOUND) ||
+ (!p_dev->dev.driver)) {
+ pcmcia_put_dev(p_dev);
+ continue;
+ }
+ p_drv = to_pcmcia_drv(p_dev->dev.driver);
+ if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
+ client = &p_dev->client;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ goto found;
+ }
+ pcmcia_put_dev(p_dev);
+ }
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ pcmcia_put_bus_socket(skt);
+ }
+ found:
+ up_read(&pcmcia_socket_list_rwsem);
+ if (!p_dev || !client)
+ return -ENODEV;
+
+ pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */
+
+ /*
+ * Prevent this racing with a card insertion.
+ */
+ down(&s->skt_sem);
+ *handle = client;
+ client->state &= ~CLIENT_UNBOUND;
+ client->Socket = s;
+ client->EventMask = req->EventMask;
+ client->event_handler = req->event_handler;
+ client->event_callback_args = req->event_callback_args;
+ client->event_callback_args.client_handle = client;
+
+ if (s->state & SOCKET_CARDBUS)
+ client->state |= CLIENT_CARDBUS;
+
+ if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
+ (client->Function != BIND_FN_ALL)) {
+ cistpl_longlink_mfc_t mfc;
+ if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc)
+ == CS_SUCCESS)
+ s->functions = mfc.nfn;
+ else
+ s->functions = 1;
+ s->config = kmalloc(sizeof(config_t) * s->functions,
+ GFP_KERNEL);
+ if (!s->config)
+ goto out_no_resource;
+ memset(s->config, 0, sizeof(config_t) * s->functions);
+ }
+
+ ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
+ client, p_dev->dev.bus_id);
+ if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
+ EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
+
+ if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
+ if (client->EventMask & CS_EVENT_CARD_INSERTION)
+ EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ }
+
+ up(&s->skt_sem);
+ return CS_SUCCESS;
+
+ out_no_resource:
+ up(&s->skt_sem);
+ pcmcia_put_dev(p_dev);
+ return CS_OUT_OF_RESOURCE;
+} /* register_client */
+EXPORT_SYMBOL(pcmcia_register_client);
+
+
/*====================================================================*/
extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s);
static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first)
{
- socket_bind_t *b;
- dev_node_t *node;
+ dev_node_t *node;
+ struct pcmcia_device *p_dev;
+ unsigned long flags;
+ int ret = 0;
#ifdef CONFIG_CARDBUS
- /*
- * Some unbelievably ugly code to associate the PCI cardbus
- * device and its driver with the PCMCIA "bind" information.
- */
- {
- struct pci_bus *bus;
-
- bus = pcmcia_lookup_bus(s->parent);
- if (bus) {
- struct list_head *list;
- struct pci_dev *dev = NULL;
-
- list = bus->devices.next;
- while (list != &bus->devices) {
- struct pci_dev *pdev = pci_dev_b(list);
- list = list->next;
-
- if (first) {
- dev = pdev;
- break;
- }
+ /*
+ * Some unbelievably ugly code to associate the PCI cardbus
+ * device and its driver with the PCMCIA "bind" information.
+ */
+ {
+ struct pci_bus *bus;
- /* Try to handle "next" here some way? */
- }
- if (dev && dev->driver) {
- strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
- bind_info->major = 0;
- bind_info->minor = 0;
- bind_info->next = NULL;
- return 0;
+ bus = pcmcia_lookup_bus(s->parent);
+ if (bus) {
+ struct list_head *list;
+ struct pci_dev *dev = NULL;
+
+ list = bus->devices.next;
+ while (list != &bus->devices) {
+ struct pci_dev *pdev = pci_dev_b(list);
+ list = list->next;
+
+ if (first) {
+ dev = pdev;
+ break;
+ }
+
+ /* Try to handle "next" here some way? */
+ }
+ if (dev && dev->driver) {
+ strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
+ bind_info->major = 0;
+ bind_info->minor = 0;
+ bind_info->next = NULL;
+ return 0;
+ }
}
}
- }
#endif
- for (b = s->bind; b; b = b->next)
- if ((strcmp((char *)b->driver->drv.name,
- (char *)bind_info->dev_info) == 0) &&
- (b->function == bind_info->function))
- break;
- if (b == NULL) return -ENODEV;
- if ((b->instance == NULL) ||
- (b->instance->state & DEV_CONFIG_PENDING))
- return -EAGAIN;
- if (first)
- node = b->instance->dev;
- else
- for (node = b->instance->dev; node; node = node->next)
- if (node == bind_info->next) break;
- if (node == NULL) return -ENODEV;
-
- strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
- bind_info->major = node->major;
- bind_info->minor = node->minor;
- bind_info->next = node->next;
-
- return 0;
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+ if (p_dev->func == bind_info->function) {
+ p_dev = pcmcia_get_dev(p_dev);
+ if (!p_dev)
+ continue;
+ goto found;
+ }
+ }
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return -ENODEV;
+
+ found:
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ if ((!p_dev->instance) ||
+ (p_dev->instance->state & DEV_CONFIG_PENDING)) {
+ ret = -EAGAIN;
+ goto err_put;
+ }
+
+ if (first)
+ node = p_dev->instance->dev;
+ else
+ for (node = p_dev->instance->dev; node; node = node->next)
+ if (node == bind_info->next)
+ break;
+ if (!node) {
+ ret = -ENODEV;
+ goto err_put;
+ }
+
+ strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
+ bind_info->major = node->major;
+ bind_info->minor = node->minor;
+ bind_info->next = node->next;
+
+ err_put:
+ pcmcia_put_dev(p_dev);
+ return (ret);
} /* get_device_info */
/*====================================================================*/
-static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
+/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
+ * drivers have been called with EVENT_CARD_REMOVAL before.
+ */
+static int unbind_request(struct pcmcia_bus_socket *s)
{
- socket_bind_t **b, *c;
-
- ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock,
- (char *)bind_info->dev_info);
- for (b = &s->bind; *b; b = &(*b)->next)
- if ((strcmp((char *)(*b)->driver->drv.name,
- (char *)bind_info->dev_info) == 0) &&
- ((*b)->function == bind_info->function))
- break;
- if (*b == NULL)
- return -ENODEV;
-
- c = *b;
- c->driver->use_count--;
- if (c->driver->detach) {
- if (c->instance)
- c->driver->detach(c->instance);
- }
- module_put(c->driver->owner);
- *b = c->next;
- kfree(c);
- return 0;
+ struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
+ unsigned long flags;
+
+ ds_dbg(2, "unbind_request(%d)\n", s->parent->sock);
+
+ s->device_count = 0;
+
+ for (;;) {
+ /* unregister all pcmcia_devices registered with this socket*/
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ if (list_empty(&s->devices_list)) {
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return 0;
+ }
+ p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
+ list_del(&p_dev->socket_device_list);
+ p_dev->client.state |= CLIENT_STALE;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ /* detach the "instance" */
+ p_drv = to_pcmcia_drv(p_dev->dev.driver);
+ if (p_drv) {
+ if ((p_drv->detach) && (p_dev->instance))
+ p_drv->detach(p_dev->instance);
+ module_put(p_drv->owner);
+ }
+
+ device_unregister(&p_dev->dev);
+ }
+
+ return 0;
} /* unbind_request */
+int pcmcia_deregister_client(client_handle_t handle)
+{
+ struct pcmcia_socket *s;
+ int i;
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+
+ s = SOCKET(handle);
+ ds_dbg(1, "deregister_client(%p)\n", handle);
+
+ if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+ goto warn_out;
+ for (i = 0; i < MAX_WIN; i++)
+ if (handle->state & CLIENT_WIN_REQ(i))
+ goto warn_out;
+
+ if (handle->state & CLIENT_STALE) {
+ handle->client_magic = 0;
+ handle->state &= ~CLIENT_STALE;
+ pcmcia_put_dev(p_dev);
+ } else {
+ handle->state = CLIENT_UNBOUND;
+ handle->event_handler = NULL;
+ }
+
+ return CS_SUCCESS;
+ warn_out:
+ printk(KERN_WARNING "ds: deregister_client was called too early.\n");
+ return CS_IN_USE;
+} /* deregister_client */
+EXPORT_SYMBOL(pcmcia_deregister_client);
+
+
/*======================================================================
The user-mode PC Card device interface
@@ -734,19 +913,27 @@ static int ds_open(struct inode *inode, struct file *file)
ds_dbg(0, "ds_open(socket %d)\n", i);
- s = pcmcia_get_bus_socket(i);
+ s = get_socket_info_by_nr(i);
+ if (!s)
+ return -ENODEV;
+ s = pcmcia_get_bus_socket(s);
if (!s)
return -ENODEV;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
- if (s->state & DS_SOCKET_BUSY)
- return -EBUSY;
+ if (s->state & DS_SOCKET_BUSY) {
+ pcmcia_put_bus_socket(s);
+ return -EBUSY;
+ }
else
s->state |= DS_SOCKET_BUSY;
}
user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
- if (!user) return -ENOMEM;
+ if (!user) {
+ pcmcia_put_bus_socket(s);
+ return -ENOMEM;
+ }
user->event_tail = user->event_head = 0;
user->next = s->user;
user->user_magic = USER_MAGIC;
@@ -883,8 +1070,6 @@ static u_int ds_poll(struct file *file, poll_table *wait)
/*====================================================================*/
extern int pcmcia_adjust_resource_info(adjust_t *adj);
-extern int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn);
-extern int pccard_get_first_region(struct pcmcia_socket *s, region_info_t *rgn);
static int ds_ioctl(struct inode * inode, struct file * file,
u_int cmd, u_long arg)
@@ -893,7 +1078,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
void __user *uarg = (char __user *)arg;
u_int size;
int ret, err;
- ds_ioctl_arg_t buf;
+ ds_ioctl_arg_t *buf;
user_info_t *user;
ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
@@ -927,54 +1112,58 @@ static int ds_ioctl(struct inode * inode, struct file * file,
return err;
}
}
+ buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
err = ret = 0;
- if (cmd & IOC_IN) __copy_from_user((char *)&buf, uarg, size);
+ if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size);
switch (cmd) {
case DS_ADJUST_RESOURCE_INFO:
- ret = pcmcia_adjust_resource_info(&buf.adjust);
+ ret = pcmcia_adjust_resource_info(&buf->adjust);
break;
case DS_GET_CARD_SERVICES_INFO:
- ret = pcmcia_get_card_services_info(&buf.servinfo);
+ ret = pcmcia_get_card_services_info(&buf->servinfo);
break;
case DS_GET_CONFIGURATION_INFO:
- if (buf.config.Function &&
- (buf.config.Function >= s->parent->functions))
+ if (buf->config.Function &&
+ (buf->config.Function >= s->parent->functions))
ret = CS_BAD_ARGS;
else
- ret = pccard_get_configuration_info(s->parent, buf.config.Function, &buf.config);
+ ret = pccard_get_configuration_info(s->parent,
+ buf->config.Function, &buf->config);
break;
case DS_GET_FIRST_TUPLE:
pcmcia_validate_mem(s->parent);
- ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf.tuple);
+ ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_NEXT_TUPLE:
- ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf.tuple);
+ ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_TUPLE_DATA:
- buf.tuple.TupleData = buf.tuple_parse.data;
- buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
- ret = pccard_get_tuple_data(s->parent, &buf.tuple);
+ buf->tuple.TupleData = buf->tuple_parse.data;
+ buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data);
+ ret = pccard_get_tuple_data(s->parent, &buf->tuple);
break;
case DS_PARSE_TUPLE:
- buf.tuple.TupleData = buf.tuple_parse.data;
- ret = pccard_parse_tuple(&buf.tuple, &buf.tuple_parse.parse);
+ buf->tuple.TupleData = buf->tuple_parse.data;
+ ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
break;
case DS_RESET_CARD:
ret = pccard_reset_card(s->parent);
break;
case DS_GET_STATUS:
- if (buf.status.Function &&
- (buf.status.Function >= s->parent->functions))
+ if (buf->status.Function &&
+ (buf->status.Function >= s->parent->functions))
ret = CS_BAD_ARGS;
else
- ret = pccard_get_status(s->parent, buf.status.Function, &buf.status);
+ ret = pccard_get_status(s->parent, buf->status.Function, &buf->status);
break;
case DS_VALIDATE_CIS:
pcmcia_validate_mem(s->parent);
- ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf.cisinfo);
+ ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf->cisinfo);
break;
case DS_SUSPEND_CARD:
ret = pcmcia_suspend_card(s->parent);
@@ -989,49 +1178,64 @@ static int ds_ioctl(struct inode * inode, struct file * file,
err = pcmcia_insert_card(s->parent);
break;
case DS_ACCESS_CONFIGURATION_REGISTER:
- if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (buf.conf_reg.Function &&
- (buf.conf_reg.Function >= s->parent->functions))
+ if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto free_out;
+ }
+ if (buf->conf_reg.Function &&
+ (buf->conf_reg.Function >= s->parent->functions))
ret = CS_BAD_ARGS;
else
- ret = pccard_access_configuration_register(s->parent, buf.conf_reg.Function, &buf.conf_reg);
+ ret = pccard_access_configuration_register(s->parent,
+ buf->conf_reg.Function, &buf->conf_reg);
break;
case DS_GET_FIRST_REGION:
- ret = pccard_get_first_region(s->parent, &buf.region);
- break;
case DS_GET_NEXT_REGION:
- ret = pccard_get_next_region(s->parent, &buf.region);
+ case DS_BIND_MTD:
+ if (!capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto free_out;
+ } else {
+ static int printed = 0;
+ if (!printed) {
+ printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n");
+ printk(KERN_WARNING "MTD handling any more.\n");
+ printed++;
+ }
+ }
+ ret = -EINVAL;
+ goto free_out;
break;
case DS_GET_FIRST_WINDOW:
- ret = pcmcia_get_window(s->parent, &buf.win_info.handle, 0, &buf.win_info.window);
+ ret = pcmcia_get_window(s->parent, &buf->win_info.handle, 0,
+ &buf->win_info.window);
break;
case DS_GET_NEXT_WINDOW:
- ret = pcmcia_get_window(s->parent, &buf.win_info.handle, buf.win_info.handle->index + 1, &buf.win_info.window);
+ ret = pcmcia_get_window(s->parent, &buf->win_info.handle,
+ buf->win_info.handle->index + 1, &buf->win_info.window);
break;
case DS_GET_MEM_PAGE:
- ret = pcmcia_get_mem_page(buf.win_info.handle,
- &buf.win_info.map);
+ ret = pcmcia_get_mem_page(buf->win_info.handle,
+ &buf->win_info.map);
break;
case DS_REPLACE_CIS:
- ret = pcmcia_replace_cis(s->parent, &buf.cisdump);
+ ret = pcmcia_replace_cis(s->parent, &buf->cisdump);
break;
case DS_BIND_REQUEST:
- if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- err = bind_request(s, &buf.bind_info);
+ if (!capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto free_out;
+ }
+ err = bind_request(s, &buf->bind_info);
break;
case DS_GET_DEVICE_INFO:
- err = get_device_info(s, &buf.bind_info, 1);
+ err = get_device_info(s, &buf->bind_info, 1);
break;
case DS_GET_NEXT_DEVICE:
- err = get_device_info(s, &buf.bind_info, 0);
+ err = get_device_info(s, &buf->bind_info, 0);
break;
case DS_UNBIND_REQUEST:
- err = unbind_request(s, &buf.bind_info);
- break;
- case DS_BIND_MTD:
- if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- err = bind_mtd(s, &buf.mtd_info);
+ err = 0;
break;
default:
err = -EINVAL;
@@ -1059,11 +1263,12 @@ static int ds_ioctl(struct inode * inode, struct file * file,
}
if (cmd & IOC_OUT) {
- if (__copy_to_user(uarg, (char *)&buf, size))
+ if (__copy_to_user(uarg, (char *)buf, size))
err = -EFAULT;
}
-
+free_out:
+ kfree(buf);
return err;
} /* ds_ioctl */
@@ -1081,9 +1286,7 @@ static struct file_operations ds_fops = {
static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
{
- struct pcmcia_socket *socket = class_dev->class_data;
- client_reg_t client_reg;
- bind_req_t bind;
+ struct pcmcia_socket *socket = class_get_devdata(class_dev);
struct pcmcia_bus_socket *s;
int ret;
@@ -1091,7 +1294,16 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
if(!s)
return -ENOMEM;
memset(s, 0, sizeof(struct pcmcia_bus_socket));
- atomic_set(&s->refcount, 1);
+
+ /* get reference to parent socket */
+ s->parent = pcmcia_get_socket(socket);
+ if (!s->parent) {
+ printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket);
+ kfree (s);
+ return -ENODEV;
+ }
+
+ kref_init(&s->refcount);
/*
* Ugly. But we want to wait for the socket threads to have started up.
@@ -1101,55 +1313,33 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
init_waitqueue_head(&s->queue);
init_waitqueue_head(&s->request);
-
- /* initialize data */
- INIT_WORK(&s->removal, handle_removal, s);
- s->parent = socket;
+ INIT_LIST_HEAD(&s->devices_list);
/* Set up hotline to Card Services */
- client_reg.dev_info = bind.dev_info = &dev_info;
-
- bind.Socket = socket;
- bind.Function = BIND_FN_ALL;
- ret = pcmcia_bind_device(&bind);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindDevice, ret);
- kfree(s);
- return -EINVAL;
- }
+ s->callback.owner = THIS_MODULE;
+ s->callback.event = &ds_event;
+ socket->pcmcia = s;
- client_reg.Attributes = INFO_MASTER_CLIENT;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.event_handler = &ds_event;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = s;
- ret = pcmcia_register_client(&s->handle, &client_reg);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, RegisterClient, ret);
- kfree(s);
- return -EINVAL;
+ ret = pccard_register_pcmcia(socket, &s->callback);
+ if (ret) {
+ printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
+ pcmcia_put_bus_socket(s);
+ socket->pcmcia = NULL;
+ return (ret);
}
- socket->pcmcia = s;
-
return 0;
}
static void pcmcia_bus_remove_socket(struct class_device *class_dev)
{
- struct pcmcia_socket *socket = class_dev->class_data;
+ struct pcmcia_socket *socket = class_get_devdata(class_dev);
if (!socket || !socket->pcmcia)
return;
- flush_scheduled_work();
-
- pcmcia_deregister_client(socket->pcmcia->handle);
+ pccard_register_pcmcia(socket, NULL);
socket->pcmcia->state |= DS_SOCKET_DEAD;
pcmcia_put_bus_socket(socket->pcmcia);
@@ -1177,6 +1367,8 @@ static int __init init_pcmcia_bus(void)
{
int i;
+ spin_lock_init(&pcmcia_dev_list_lock);
+
bus_register(&pcmcia_bus_type);
class_interface_register(&pcmcia_bus_interface);
@@ -1232,33 +1424,18 @@ static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr)
/* backwards-compatible accessing of driver --- by name! */
-struct cmp_data {
- void *dev_info;
- struct pcmcia_driver *drv;
-};
-
-static int cmp_drv_callback(struct device_driver *drv, void *data)
-{
- struct cmp_data *cmp = data;
- if (strncmp((char *)cmp->dev_info, (char *)drv->name,
- DEV_NAME_LEN) == 0) {
- cmp->drv = container_of(drv, struct pcmcia_driver, drv);
- return -EINVAL;
- }
- return 0;
-}
-
static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
{
- int ret;
- struct cmp_data cmp = {
- .dev_info = dev_info,
- };
-
- ret = bus_for_each_drv(&pcmcia_bus_type, NULL, &cmp, cmp_drv_callback);
- if (ret)
- return cmp.drv;
- return NULL;
+ struct device_driver *drv;
+ struct pcmcia_driver *p_drv;
+
+ drv = driver_find((char *) dev_info, &pcmcia_bus_type);
+ if (!drv)
+ return NULL;
+
+ p_drv = container_of(drv, struct pcmcia_driver, drv);
+
+ return (p_drv);
}
MODULE_ALIAS("ds");
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 875c9cfaea3f15..36d85f04e276cb 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -922,6 +922,7 @@ static int __init init_hs(void)
hs_set_voltages(&hs_sockets[i], 0, 0);
hs_sockets[i].socket.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP; /* mappings are fixed in host memory */
+ hs_sockets[i].socket.resource_ops = &pccard_static_ops;
hs_sockets[i].socket.irq_mask = 0xffde;/*0xffff*/ /* IRQs mapped in s/w so can do any, really */
hs_sockets[i].socket.map_size = HD64465_PCC_WINDOW; /* 16MB fixed window size */
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index eb255238aef8d5..aa8ed192d21a50 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -162,6 +162,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de
for (i = 0; i<socket_count; i++) {
sockets[i].socket.dev.dev = &dev->dev;
sockets[i].socket.ops = &i82092aa_operations;
+ sockets[i].socket.resource_ops = &pccard_nonstatic_ops;
ret = pcmcia_register_socket(&sockets[i].socket);
if (ret) {
goto err_out_free_sockets;
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 56ced25d993c62..0d9bb1505c2e15 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1400,6 +1400,7 @@ static int __init init_i82365(void)
for (i = 0; i < sockets; i++) {
socket[i].socket.dev.dev = &i82365_device.dev;
socket[i].socket.ops = &pcic_operations;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 836058dfa2c01b..023013d3e26358 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -831,6 +831,7 @@ static int __init init_m32r_pcc(void)
for (i = 0 ; i < pcc_sockets ; i++) {
socket[i].socket.dev.dev = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
+ socket[i].socket.resource_ops = &pccard_static_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index aae7a16a1815af..8c881ae7328789 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -768,6 +768,7 @@ static int __init init_m32r_pcc(void)
for (i = 0 ; i < pcc_sockets ; i++) {
socket[i].socket.dev.dev = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
+ socket[i].socket.resource_ops = &pccard_static_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c
index 673d34576d3bef..68b80084f83f28 100644
--- a/drivers/pcmcia/pcmcia_compat.c
+++ b/drivers/pcmcia/pcmcia_compat.c
@@ -123,23 +123,3 @@ int pcmcia_access_configuration_register(client_handle_t handle,
}
EXPORT_SYMBOL(pcmcia_access_configuration_register);
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-int pcmcia_get_first_window(window_handle_t *win, win_req_t *req)
-{
- if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
-
- return pcmcia_get_window(((client_handle_t)*win)->Socket, win, 0, req);
-}
-EXPORT_SYMBOL(pcmcia_get_first_window);
-
-int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
-{
- if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
- return pcmcia_get_window((*win)->sock, win, (*win)->index+1, req);
-}
-EXPORT_SYMBOL(pcmcia_get_next_window);
-
-#endif
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 4f00c9dda0754b..1347f94260c712 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -29,7 +29,7 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver for the Cirrus PD6729 PCI-PCMCIA bridge");
-MODULE_AUTHOR("Jun Komuro <komurojun@mbn.nifty.com>");
+MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>");
#define MAX_SOCKETS 2
@@ -39,11 +39,40 @@ MODULE_AUTHOR("Jun Komuro <komurojun@mbn.nifty.com>");
*/
#define to_cycles(ns) ((ns)/120)
+#ifndef NO_IRQ
+#define NO_IRQ ((unsigned int)(0))
+#endif
+
+/*
+ * PARAMETERS
+ * irq_mode=n
+ * Specifies the interrupt delivery mode. The default (1) is to use PCI
+ * interrupts; a value of 0 selects ISA interrupts. This must be set for
+ * correct operation of PCI card readers.
+ *
+ * irq_list=i,j,...
+ * This list limits the set of interrupts that can be used by PCMCIA
+ * cards.
+ * The default list is 3,4,5,7,9,10,11.
+ * (irq_list parameter is not used, if irq_mode = 1)
+ */
+
+static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */
+static int irq_list[16];
+static int irq_list_count = 0;
+
+module_param(irq_mode, int, 0444);
+module_param_array(irq_list, int, &irq_list_count, 0444);
+MODULE_PARM_DESC(irq_mode,
+ "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1");
+MODULE_PARM_DESC(irq_list, "interrupts that can be used by PCMCIA cards");
+
static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
/* basic value read/write functions */
-static unsigned char indirect_read(struct pd6729_socket *socket, unsigned short reg)
+static unsigned char indirect_read(struct pd6729_socket *socket,
+ unsigned short reg)
{
unsigned long port;
unsigned char val;
@@ -59,7 +88,8 @@ static unsigned char indirect_read(struct pd6729_socket *socket, unsigned short
return val;
}
-static unsigned short indirect_read16(struct pd6729_socket *socket, unsigned short reg)
+static unsigned short indirect_read16(struct pd6729_socket *socket,
+ unsigned short reg)
{
unsigned long port;
unsigned short tmp;
@@ -78,7 +108,8 @@ static unsigned short indirect_read16(struct pd6729_socket *socket, unsigned sho
return tmp;
}
-static void indirect_write(struct pd6729_socket *socket, unsigned short reg, unsigned char value)
+static void indirect_write(struct pd6729_socket *socket, unsigned short reg,
+ unsigned char value)
{
unsigned long port;
unsigned long flags;
@@ -91,7 +122,8 @@ static void indirect_write(struct pd6729_socket *socket, unsigned short reg, uns
spin_unlock_irqrestore(&port_lock, flags);
}
-static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, unsigned char mask)
+static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg,
+ unsigned char mask)
{
unsigned long port;
unsigned char val;
@@ -108,7 +140,8 @@ static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, un
spin_unlock_irqrestore(&port_lock, flags);
}
-static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg, unsigned char mask)
+static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg,
+ unsigned char mask)
{
unsigned long port;
unsigned char val;
@@ -125,7 +158,8 @@ static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg,
spin_unlock_irqrestore(&port_lock, flags);
}
-static void indirect_write16(struct pd6729_socket *socket, unsigned short reg, unsigned short value)
+static void indirect_write16(struct pd6729_socket *socket, unsigned short reg,
+ unsigned short value)
{
unsigned long port;
unsigned char val;
@@ -160,7 +194,8 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
while (1) {
loopcount++;
if (loopcount > 20) {
- printk(KERN_ERR "pd6729: infinite eventloop in interrupt\n");
+ printk(KERN_ERR "pd6729: infinite eventloop "
+ "in interrupt\n");
break;
}
@@ -182,14 +217,19 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
dprintk("Card detected in socket %i!\n", i);
}
- if (indirect_read(&socket[i], I365_INTCTL) & I365_PC_IOCARD) {
+ if (indirect_read(&socket[i], I365_INTCTL)
+ & I365_PC_IOCARD) {
/* For IO/CARDS, bit 0 means "read the card" */
- events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+ events |= (csc & I365_CSC_STSCHG)
+ ? SS_STSCHG : 0;
} else {
/* Check for battery/ready events */
- events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
- events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
- events |= (csc & I365_CSC_READY) ? SS_READY : 0;
+ events |= (csc & I365_CSC_BVD1)
+ ? SS_BATDEAD : 0;
+ events |= (csc & I365_CSC_BVD2)
+ ? SS_BATWARN : 0;
+ events |= (csc & I365_CSC_READY)
+ ? SS_READY : 0;
}
if (events) {
@@ -206,17 +246,18 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
/* socket functions */
-static void set_bridge_state(struct pd6729_socket *socket)
+static void pd6729_interrupt_wrapper(unsigned long data)
{
- indirect_write(socket, I365_GBLCTL, 0x00);
- indirect_write(socket, I365_GENCTL, 0x00);
+ struct pd6729_socket *socket = (struct pd6729_socket *) data;
- indirect_setbit(socket, I365_INTCTL, 0x08);
+ pd6729_interrupt(0, (void *)socket, NULL);
+ mod_timer(&socket->poll_timer, jiffies + HZ);
}
static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned int status;
unsigned int data;
struct pd6729_socket *t;
@@ -265,7 +306,8 @@ static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned char reg, vcc, vpp;
state->flags = 0;
@@ -274,10 +316,7 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
state->io_irq = 0;
state->csc_mask = 0;
- /*
- * First the power status of the socket
- * PCTRL - Power Control Register
- */
+ /* First the power status of the socket */
reg = indirect_read(socket, I365_POWER);
if (reg & I365_PWR_AUTO)
@@ -302,10 +341,7 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
state->Vpp = 120;
}
- /*
- * Now the IO card, RESET flags and IO interrupt
- * IGENC, Interrupt and General Control
- */
+ /* Now the IO card, RESET flags and IO interrupt */
reg = indirect_read(socket, I365_INTCTL);
if ((reg & I365_PC_RESET) == 0)
@@ -314,12 +350,9 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
state->flags |= SS_IOCARD; /* This is an IO card */
/* Set the IRQ number */
- state->io_irq = socket->socket.pci_irq;
+ state->io_irq = socket->card_irq;
- /*
- * Card status change
- * CSCICR, Card Status Change Interrupt Configuration
- */
+ /* Card status change */
reg = indirect_read(socket, I365_CSCINT);
if (reg & I365_CSC_DETECT)
@@ -342,21 +375,23 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
- unsigned char reg;
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
+ unsigned char reg, data;
/* First, set the global controller options */
-
- set_bridge_state(socket);
+ indirect_write(socket, I365_GBLCTL, 0x00);
+ indirect_write(socket, I365_GENCTL, 0x00);
/* Values for the IGENC register */
+ socket->card_irq = state->io_irq;
reg = 0;
/* The reset bit has "inverse" logic */
if (!(state->flags & SS_RESET))
- reg = reg | I365_PC_RESET;
+ reg |= I365_PC_RESET;
if (state->flags & SS_IOCARD)
- reg = reg | I365_PC_IOCARD;
+ reg |= I365_PC_IOCARD;
/* IGENC, Interrupt and General Control Register */
indirect_write(socket, I365_INTCTL, reg);
@@ -390,7 +425,8 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
break;
default:
- dprintk("pd6729: pd6729_set_socket called with invalid VCC power value: %i\n",
+ dprintk("pd6729: pd6729_set_socket called with "
+ "invalid VCC power value: %i\n",
state->Vcc);
return -EINVAL;
}
@@ -418,9 +454,14 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (reg != indirect_read(socket, I365_POWER))
indirect_write(socket, I365_POWER, reg);
- /* Now, specifiy that all interrupts are to be done as PCI interrupts */
+ if (irq_mode == 1) {
+ /* all interrupts are to be done as PCI interrupts */
+ data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
+ } else
+ data = 0;
+
indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1);
- indirect_write(socket, PD67_EXT_DATA, PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ);
+ indirect_write(socket, PD67_EXT_DATA, data);
/* Enable specific interrupt events */
@@ -439,11 +480,15 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (state->csc_mask & SS_READY)
reg |= I365_CSC_READY;
}
- reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */
+ if (irq_mode == 1)
+ reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */
indirect_write(socket, I365_CSCINT, reg);
reg = indirect_read(socket, I365_INTCTL);
- reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */
+ if (irq_mode == 1)
+ reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */
+ else
+ reg |= socket->card_irq;
indirect_write(socket, I365_INTCTL, reg);
/* now clear the (probably bogus) pending stuff by doing a dummy read */
@@ -452,9 +497,11 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
return 0;
}
-static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
+static int pd6729_set_io_map(struct pcmcia_socket *sock,
+ struct pccard_io_map *io)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned char map, ioctl;
map = io->map;
@@ -469,7 +516,8 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *i
if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map))
indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map));
-/* dprintk("set_io_map: Setting range to %x - %x\n", io->start, io->stop);*/
+ /* dprintk("set_io_map: Setting range to %x - %x\n",
+ io->start, io->stop);*/
/* write the new values */
indirect_write16(socket, I365_IO(map)+I365_W_START, io->start);
@@ -490,9 +538,11 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *i
return 0;
}
-static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+static int pd6729_set_mem_map(struct pcmcia_socket *sock,
+ struct pccard_mem_map *mem)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned short base, i;
unsigned char map;
@@ -504,8 +554,6 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
printk("pd6729_set_mem_map: invalid address / speed");
- /* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n",
- sock, mem->res->start, mem->res->end, mem->card_start); */
return -EINVAL;
}
@@ -551,11 +599,11 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
if (mem->flags & MAP_WRPROT)
i |= I365_MEM_WRPROT;
if (mem->flags & MAP_ATTRIB) {
-/* dprintk("requesting attribute memory for socket %i\n",
+ /* dprintk("requesting attribute memory for socket %i\n",
socket->number);*/
i |= I365_MEM_REG;
} else {
-/* dprintk("requesting normal memory for socket %i\n",
+ /* dprintk("requesting normal memory for socket %i\n",
socket->number);*/
}
indirect_write16(socket, base + I365_W_OFF, i);
@@ -604,13 +652,66 @@ static struct pccard_operations pd6729_operations = {
.set_mem_map = pd6729_set_mem_map,
};
-static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static irqreturn_t pd6729_test(int irq, void *dev, struct pt_regs *regs)
+{
+ dprintk("-> hit on irq %d\n", irq);
+ return IRQ_HANDLED;
+}
+
+static int pd6729_check_irq(int irq, int flags)
+{
+ if (request_irq(irq, pd6729_test, flags, "x", pd6729_test) != 0)
+ return -1;
+ free_irq(irq, pd6729_test);
+ return 0;
+}
+
+static u_int __init pd6729_isa_scan(void)
+{
+ u_int mask0, mask = 0;
+ int i;
+
+ if (irq_mode == 1) {
+ printk(KERN_INFO "pd6729: PCI card interrupts, "
+ "PCI status changes\n");
+ return 0;
+ }
+
+ if (irq_list_count == 0)
+ mask0 = 0xffff;
+ else
+ for (i = mask0 = 0; i < irq_list_count; i++)
+ mask0 |= (1<<irq_list[i]);
+
+ mask0 &= PD67_MASK;
+
+ /* just find interrupts that aren't in use */
+ for (i = 0; i < 16; i++)
+ if ((mask0 & (1 << i)) && (pd6729_check_irq(i, 0) == 0))
+ mask |= (1 << i);
+
+ printk(KERN_INFO "pd6729: ISA irqs = ");
+ for (i = 0; i < 16; i++)
+ if (mask & (1<<i))
+ printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i);
+
+ if (mask == 0) printk("none!");
+
+ printk(" polling status changes.\n");
+
+ return mask;
+}
+
+static int __devinit pd6729_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
int i, j, ret;
+ u_int mask;
char configbyte;
struct pd6729_socket *socket;
- socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, GFP_KERNEL);
+ socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
+ GFP_KERNEL);
if (!socket)
return -ENOMEM;
@@ -619,13 +720,11 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_devi
if ((ret = pci_enable_device(dev)))
goto err_out_free_mem;
- printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge at 0x%lx on irq %d\n",
- pci_resource_start(dev, 0), dev->irq);
- printk(KERN_INFO "pd6729: configured as a %d socket device.\n", MAX_SOCKETS);
+ printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge "
+ "at 0x%lx on irq %d\n", pci_resource_start(dev, 0), dev->irq);
/*
- * Since we have no memory BARs some firmware we may not
- * have had PCI_COMMAND_MEM enabled, yet the device needs
- * it.
+ * Since we have no memory BARs some firmware may not
+ * have had PCI_COMMAND_MEMORY enabled, yet the device needs it.
*/
pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
if (!(configbyte & PCI_COMMAND_MEMORY)) {
@@ -640,33 +739,54 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_devi
goto err_out_disable;
}
+ if (dev->irq == NO_IRQ)
+ irq_mode = 0; /* fall back to ISA interrupt mode */
+
+ mask = pd6729_isa_scan();
+ if (irq_mode == 0 && mask == 0) {
+ printk(KERN_INFO "pd6729: no ISA interrupt is available.\n");
+ goto err_out_free_res;
+ }
+
for (i = 0; i < MAX_SOCKETS; i++) {
socket[i].io_base = pci_resource_start(dev, 0);
socket[i].socket.features |= SS_CAP_PCCARD;
socket[i].socket.map_size = 0x1000;
- socket[i].socket.irq_mask = 0;
+ socket[i].socket.irq_mask = mask;
socket[i].socket.pci_irq = dev->irq;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
socket[i].socket.ops = &pd6729_operations;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.dev.dev = &dev->dev;
socket[i].socket.driver_data = &socket[i];
}
pci_set_drvdata(dev, socket);
-
- /* Register the interrupt handler */
- if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ, "pd6729", socket))) {
- printk(KERN_ERR "pd6729: Failed to register irq %d, aborting\n", dev->irq);
- goto err_out_free_res;
+ if (irq_mode == 1) {
+ /* Register the interrupt handler */
+ if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ,
+ "pd6729", socket))) {
+ printk(KERN_ERR "pd6729: Failed to register irq %d, "
+ "aborting\n", dev->irq);
+ goto err_out_free_res;
+ }
+ } else {
+ /* poll Card status change */
+ init_timer(&socket->poll_timer);
+ socket->poll_timer.function = pd6729_interrupt_wrapper;
+ socket->poll_timer.data = (unsigned long)socket;
+ socket->poll_timer.expires = jiffies + HZ;
+ add_timer(&socket->poll_timer);
}
for (i = 0; i < MAX_SOCKETS; i++) {
ret = pcmcia_register_socket(&socket[i].socket);
if (ret) {
- printk(KERN_INFO "pd6729: pcmcia_register_socket failed.\n");
+ printk(KERN_INFO "pd6729: pcmcia_register_socket "
+ "failed.\n");
for (j = 0; j < i ; j++)
pcmcia_unregister_socket(&socket[j].socket);
goto err_out_free_res2;
@@ -676,7 +796,10 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_devi
return 0;
err_out_free_res2:
- free_irq(dev->irq, socket);
+ if (irq_mode == 1)
+ free_irq(dev->irq, socket);
+ else
+ del_timer_sync(&socket->poll_timer);
err_out_free_res:
pci_release_regions(dev);
err_out_disable:
@@ -692,10 +815,18 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
int i;
struct pd6729_socket *socket = pci_get_drvdata(dev);
- for (i = 0; i < MAX_SOCKETS; i++)
+ for (i = 0; i < MAX_SOCKETS; i++) {
+ /* Turn off all interrupt sources */
+ indirect_write(&socket[i], I365_CSCINT, 0);
+ indirect_write(&socket[i], I365_INTCTL, 0);
+
pcmcia_unregister_socket(&socket[i].socket);
+ }
- free_irq(dev->irq, socket);
+ if (irq_mode == 1)
+ free_irq(dev->irq, socket);
+ else
+ del_timer_sync(&socket->poll_timer);
pci_release_regions(dev);
pci_disable_device(dev);
diff --git a/drivers/pcmcia/pd6729.h b/drivers/pcmcia/pd6729.h
index 9e90520ef6cc13..f392e458cdfd7f 100644
--- a/drivers/pcmcia/pd6729.h
+++ b/drivers/pcmcia/pd6729.h
@@ -16,13 +16,15 @@
#define PD67_EXD_VS1(s) (0x01 << ((s) << 1))
#define PD67_EXD_VS2(s) (0x02 << ((s) << 1))
-
-
+/* Default ISA interrupt mask */
+#define PD67_MASK 0x0eb8 /* irq 11,10,9,7,5,4,3 */
struct pd6729_socket {
int number;
+ int card_irq;
unsigned long io_base; /* base io address of the socket */
struct pcmcia_socket socket;
+ struct timer_list poll_timer;
};
#endif
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 4e0ca166dade40..b3f1fe0b02caa6 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- Resource management routines
-
- rsrc_mgr.c 1.79 2000/08/30 20:23:58
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
-
-======================================================================*/
+/*
+ * rsrc_mgr.c -- Resource management routines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -53,44 +34,7 @@
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
-
-INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
-#ifdef CONFIG_PCMCIA_PROBE
-INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
-INT_MODULE_PARM(mem_limit, 0x10000);
-#endif
-
-/*======================================================================
-
- The resource_map_t structures are used to track what resources are
- available for allocation for PC Card devices.
-
-======================================================================*/
-
-typedef struct resource_map_t {
- u_long base, num;
- struct resource_map_t *next;
-} resource_map_t;
-
-/* Memory resource database */
-static resource_map_t mem_db = {
- .next = &mem_db,
-};
-
-/* IO port resource database */
-static resource_map_t io_db = {
- .next = &io_db,
-};
-
static DECLARE_MUTEX(rsrc_sem);
-static unsigned int rsrc_mem_probe;
-#define MEM_PROBE_LOW (1 << 0)
-#define MEM_PROBE_HIGH (1 << 1)
#ifdef CONFIG_PCMCIA_PROBE
@@ -105,617 +49,6 @@ static irq_info_t irq_table[NR_IRQS];
#endif
-/*======================================================================
-
- Linux resource management extensions
-
-======================================================================*/
-
-static struct resource *
-make_resource(unsigned long b, unsigned long n, int flags, char *name)
-{
- struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
-
- if (res) {
- memset(res, 0, sizeof(*res));
- res->name = name;
- res->start = b;
- res->end = b + n - 1;
- res->flags = flags;
- }
- return res;
-}
-
-static struct resource *
-claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
- int type, char *name)
-{
- struct resource *res, *parent;
-
- parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
- res = make_resource(base, size, type | IORESOURCE_BUSY, name);
-
- if (res) {
-#ifdef CONFIG_PCI
- if (s && s->cb_dev)
- parent = pci_find_parent_resource(s->cb_dev, res);
-#endif
- if (!parent || request_resource(parent, res)) {
- kfree(res);
- res = NULL;
- }
- }
- return res;
-}
-
-static void free_region(struct resource *res)
-{
- if (res) {
- release_resource(res);
- kfree(res);
- }
-}
-
-/*======================================================================
-
- These manage the internal databases of available resources.
-
-======================================================================*/
-
-static int add_interval(resource_map_t *map, u_long base, u_long num)
-{
- resource_map_t *p, *q;
-
- for (p = map; ; p = p->next) {
- if ((p != map) && (p->base+p->num-1 >= base))
- return -1;
- if ((p->next == map) || (p->next->base > base+num-1))
- break;
- }
- q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
- if (!q) return CS_OUT_OF_RESOURCE;
- q->base = base; q->num = num;
- q->next = p->next; p->next = q;
- return CS_SUCCESS;
-}
-
-/*====================================================================*/
-
-static int sub_interval(resource_map_t *map, u_long base, u_long num)
-{
- resource_map_t *p, *q;
-
- for (p = map; ; p = q) {
- q = p->next;
- if (q == map)
- break;
- if ((q->base+q->num > base) && (base+num > q->base)) {
- if (q->base >= base) {
- if (q->base+q->num <= base+num) {
- /* Delete whole block */
- p->next = q->next;
- kfree(q);
- /* don't advance the pointer yet */
- q = p;
- } else {
- /* Cut off bit from the front */
- q->num = q->base + q->num - base - num;
- q->base = base + num;
- }
- } else if (q->base+q->num <= base+num) {
- /* Cut off bit from the end */
- q->num = base - q->base;
- } else {
- /* Split the block into two pieces */
- p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
- if (!p) return CS_OUT_OF_RESOURCE;
- p->base = base+num;
- p->num = q->base+q->num - p->base;
- q->num = base - q->base;
- p->next = q->next ; q->next = p;
- }
- }
- }
- return CS_SUCCESS;
-}
-
-/*======================================================================
-
- These routines examine a region of IO or memory addresses to
- determine what ranges might be genuinely available.
-
-======================================================================*/
-
-#ifdef CONFIG_PCMCIA_PROBE
-static void do_io_probe(ioaddr_t base, ioaddr_t num)
-{
- struct resource *res;
- ioaddr_t i, j, bad, any;
- u_char *b, hole, most;
-
- printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
- base, base+num-1);
-
- /* First, what does a floating port look like? */
- b = kmalloc(256, GFP_KERNEL);
- if (!b) {
- printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
- return;
- }
- memset(b, 0, 256);
- for (i = base, most = 0; i < base+num; i += 8) {
- res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
- if (!res)
- continue;
- hole = inb(i);
- for (j = 1; j < 8; j++)
- if (inb(i+j) != hole) break;
- free_region(res);
- if ((j == 8) && (++b[hole] > b[most]))
- most = hole;
- if (b[most] == 127) break;
- }
- kfree(b);
-
- bad = any = 0;
- for (i = base; i < base+num; i += 8) {
- res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
- if (!res)
- continue;
- for (j = 0; j < 8; j++)
- if (inb(i+j) != most) break;
- free_region(res);
- if (j < 8) {
- if (!any)
- printk(" excluding");
- if (!bad)
- bad = any = i;
- } else {
- if (bad) {
- sub_interval(&io_db, bad, i-bad);
- printk(" %#04x-%#04x", bad, i-1);
- bad = 0;
- }
- }
- }
- if (bad) {
- if ((num > 16) && (bad == base) && (i == base+num)) {
- printk(" nothing: probe failed.\n");
- return;
- } else {
- sub_interval(&io_db, bad, i-bad);
- printk(" %#04x-%#04x", bad, i-1);
- }
- }
-
- printk(any ? "\n" : " clean.\n");
-}
-#endif
-
-/*======================================================================
-
- This is tricky... when we set up CIS memory, we try to validate
- the memory window space allocations.
-
-======================================================================*/
-
-/* Validation function for cards with a valid CIS */
-static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
-{
- int ret = -1;
-
- s->cis_mem.res = res;
- s->cis_virt = ioremap(res->start, s->map_size);
- if (s->cis_virt) {
- ret = pccard_validate_cis(s, BIND_FN_ALL, info);
- /* invalidate mapping and CIS cache */
- iounmap(s->cis_virt);
- s->cis_virt = NULL;
- destroy_cis_cache(s);
- }
- s->cis_mem.res = NULL;
- if ((ret != 0) || (info->Chains == 0))
- return 0;
- return 1;
-}
-
-/* Validation function for simple memory cards */
-static int checksum(struct pcmcia_socket *s, struct resource *res)
-{
- pccard_mem_map map;
- int i, a = 0, b = -1, d;
- void __iomem *virt;
-
- virt = ioremap(res->start, s->map_size);
- if (virt) {
- map.map = 0;
- map.flags = MAP_ACTIVE;
- map.speed = 0;
- map.res = res;
- map.card_start = 0;
- s->ops->set_mem_map(s, &map);
-
- /* Don't bother checking every word... */
- for (i = 0; i < s->map_size; i += 44) {
- d = readl(virt+i);
- a += d;
- b &= d;
- }
-
- map.flags = 0;
- s->ops->set_mem_map(s, &map);
-
- iounmap(virt);
- }
-
- return (b == -1) ? -1 : (a>>1);
-}
-
-static int
-cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
-{
- struct resource *res1, *res2;
- cisinfo_t info1, info2;
- int ret = 0;
-
- res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
- res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
-
- if (res1 && res2) {
- ret = readable(s, res1, &info1);
- ret += readable(s, res2, &info2);
- }
-
- free_region(res2);
- free_region(res1);
-
- return (ret == 2) && (info1.Chains == info2.Chains);
-}
-
-static int
-checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
-{
- struct resource *res1, *res2;
- int a = -1, b = -1;
-
- res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
- res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
-
- if (res1 && res2) {
- a = checksum(s, res1);
- b = checksum(s, res2);
- }
-
- free_region(res2);
- free_region(res1);
-
- return (a == b) && (a >= 0);
-}
-
-/*======================================================================
-
- The memory probe. If the memory list includes a 64K-aligned block
- below 1MB, we probe in 64K chunks, and as soon as we accumulate at
- least mem_limit free space, we quit.
-
-======================================================================*/
-
-static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
-{
- u_long i, j, bad, fail, step;
-
- printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
- base, base+num-1);
- bad = fail = 0;
- step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
- /* cis_readable wants to map 2x map_size */
- if (step < 2 * s->map_size)
- step = 2 * s->map_size;
- for (i = j = base; i < base+num; i = j + step) {
- if (!fail) {
- for (j = i; j < base+num; j += step) {
- if (cis_readable(s, j, step))
- break;
- }
- fail = ((i == base) && (j == base+num));
- }
- if (fail) {
- for (j = i; j < base+num; j += 2*step)
- if (checksum_match(s, j, step) &&
- checksum_match(s, j + step, step))
- break;
- }
- if (i != j) {
- if (!bad) printk(" excluding");
- printk(" %#05lx-%#05lx", i, j-1);
- sub_interval(&mem_db, i, j-i);
- bad += j-i;
- }
- }
- printk(bad ? "\n" : " clean.\n");
- return (num - bad);
-}
-
-#ifdef CONFIG_PCMCIA_PROBE
-
-static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
-{
- u_long ok;
- if (m == &mem_db)
- return 0;
- ok = inv_probe(m->next, s);
- if (ok) {
- if (m->base >= 0x100000)
- sub_interval(&mem_db, m->base, m->num);
- return ok;
- }
- if (m->base < 0x100000)
- return 0;
- return do_mem_probe(m->base, m->num, s);
-}
-
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
-{
- resource_map_t *m, mm;
- static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- u_long b, i, ok = 0;
-
- /* We do up to four passes through the list */
- if (probe_mask & MEM_PROBE_HIGH) {
- if (inv_probe(mem_db.next, s) > 0)
- return;
- printk(KERN_NOTICE "cs: warning: no high memory space "
- "available!\n");
- }
- if ((probe_mask & MEM_PROBE_LOW) == 0)
- return;
- for (m = mem_db.next; m != &mem_db; m = mm.next) {
- mm = *m;
- /* Only probe < 1 MB */
- if (mm.base >= 0x100000) continue;
- if ((mm.base | mm.num) & 0xffff) {
- ok += do_mem_probe(mm.base, mm.num, s);
- continue;
- }
- /* Special probe for 64K-aligned block */
- for (i = 0; i < 4; i++) {
- b = order[i] << 12;
- if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
- if (ok >= mem_limit)
- sub_interval(&mem_db, b, 0x10000);
- else
- ok += do_mem_probe(b, 0x10000, s);
- }
- }
- }
-}
-
-#else /* CONFIG_PCMCIA_PROBE */
-
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
-{
- resource_map_t *m, mm;
-
- for (m = mem_db.next; m != &mem_db; m = mm.next) {
- mm = *m;
- if (do_mem_probe(mm.base, mm.num, s))
- break;
- }
-}
-
-#endif /* CONFIG_PCMCIA_PROBE */
-
-/*
- * Locking note: this is the only place where we take
- * both rsrc_sem and skt_sem.
- */
-void pcmcia_validate_mem(struct pcmcia_socket *s)
-{
- if (probe_mem) {
- unsigned int probe_mask;
-
- down(&rsrc_sem);
-
- probe_mask = MEM_PROBE_LOW;
- if (s->features & SS_CAP_PAGE_REGS)
- probe_mask = MEM_PROBE_HIGH;
-
- if (probe_mask & ~rsrc_mem_probe) {
- rsrc_mem_probe |= probe_mask;
-
- down(&s->skt_sem);
-
- if (s->state & SOCKET_PRESENT)
- validate_mem(s, probe_mask);
-
- up(&s->skt_sem);
- }
-
- up(&rsrc_sem);
- }
-}
-
-EXPORT_SYMBOL(pcmcia_validate_mem);
-
-struct pcmcia_align_data {
- unsigned long mask;
- unsigned long offset;
- resource_map_t *map;
-};
-
-static void
-pcmcia_common_align(void *align_data, struct resource *res,
- unsigned long size, unsigned long align)
-{
- struct pcmcia_align_data *data = align_data;
- unsigned long start;
- /*
- * Ensure that we have the correct start address
- */
- start = (res->start & ~data->mask) + data->offset;
- if (start < res->start)
- start += data->mask + 1;
- res->start = start;
-}
-
-static void
-pcmcia_align(void *align_data, struct resource *res,
- unsigned long size, unsigned long align)
-{
- struct pcmcia_align_data *data = align_data;
- resource_map_t *m;
-
- pcmcia_common_align(data, res, size, align);
-
- for (m = data->map->next; m != data->map; m = m->next) {
- unsigned long start = m->base;
- unsigned long end = m->base + m->num - 1;
-
- /*
- * If the lower resources are not available, try aligning
- * to this entry of the resource database to see if it'll
- * fit here.
- */
- if (res->start < start) {
- res->start = start;
- pcmcia_common_align(data, res, size, align);
- }
-
- /*
- * If we're above the area which was passed in, there's
- * no point proceeding.
- */
- if (res->start >= res->end)
- break;
-
- if ((res->start + size - 1) <= end)
- break;
- }
-
- /*
- * If we failed to find something suitable, ensure we fail.
- */
- if (m == data->map)
- res->start = res->end;
-}
-
-/*
- * Adjust an existing IO region allocation, but making sure that we don't
- * encroach outside the resources which the user supplied.
- */
-int adjust_io_region(struct resource *res, unsigned long r_start,
- unsigned long r_end, struct pcmcia_socket *s)
-{
- resource_map_t *m;
- int ret = -ENOMEM;
-
- down(&rsrc_sem);
- for (m = io_db.next; m != &io_db; m = m->next) {
- unsigned long start = m->base;
- unsigned long end = m->base + m->num - 1;
-
- if (start > r_start || r_end > end)
- continue;
-
- ret = adjust_resource(res, r_start, r_end - r_start + 1);
- break;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
-/*======================================================================
-
- These find ranges of I/O ports or memory addresses that are not
- currently allocated by other devices.
-
- The 'align' field should reflect the number of bits of address
- that need to be preserved from the initial value of *base. It
- should be a power of two, greater than or equal to 'num'. A value
- of 0 means that all bits of *base are significant. *base should
- also be strictly less than 'align'.
-
-======================================================================*/
-
-struct resource *find_io_region(unsigned long base, int num,
- unsigned long align, char *name, struct pcmcia_socket *s)
-{
- struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
- struct pcmcia_align_data data;
- unsigned long min = base;
- int ret;
-
- if (align == 0)
- align = 0x10000;
-
- data.mask = align - 1;
- data.offset = base & data.mask;
- data.map = &io_db;
-
- down(&rsrc_sem);
-#ifdef CONFIG_PCI
- if (s->cb_dev) {
- ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
- min, 0, pcmcia_align, &data);
- } else
-#endif
- ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
- 1, pcmcia_align, &data);
- up(&rsrc_sem);
-
- if (ret != 0) {
- kfree(res);
- res = NULL;
- }
- return res;
-}
-
-struct resource *find_mem_region(u_long base, u_long num, u_long align,
- int low, char *name, struct pcmcia_socket *s)
-{
- struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
- struct pcmcia_align_data data;
- unsigned long min, max;
- int ret, i;
-
- low = low || !(s->features & SS_CAP_PAGE_REGS);
-
- data.mask = align - 1;
- data.offset = base & data.mask;
- data.map = &mem_db;
-
- for (i = 0; i < 2; i++) {
- if (low) {
- max = 0x100000UL;
- min = base < max ? base : 0;
- } else {
- max = ~0UL;
- min = 0x100000UL + base;
- }
-
- down(&rsrc_sem);
-#ifdef CONFIG_PCI
- if (s->cb_dev) {
- ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
- 1, min, 0,
- pcmcia_align, &data);
- } else
-#endif
- ret = allocate_resource(&iomem_resource, res, num, min,
- max, 1, pcmcia_align, &data);
- up(&rsrc_sem);
- if (ret == 0 || low)
- break;
- low = 1;
- }
-
- if (ret != 0) {
- kfree(res);
- res = NULL;
- }
- return res;
-}
/*======================================================================
@@ -842,85 +175,6 @@ void undo_irq(u_int Attributes, int irq)
#endif
-/*======================================================================
-
- The various adjust_* calls form the external interface to the
- resource database.
-
-======================================================================*/
-
-static int adjust_memory(adjust_t *adj)
-{
- u_long base, num;
- int ret;
-
- base = adj->resource.memory.Base;
- num = adj->resource.memory.Size;
- if ((num == 0) || (base+num-1 < base))
- return CS_BAD_SIZE;
-
- ret = CS_SUCCESS;
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- ret = add_interval(&mem_db, base, num);
- break;
- case REMOVE_MANAGED_RESOURCE:
- ret = sub_interval(&mem_db, base, num);
- if (ret == CS_SUCCESS) {
- struct pcmcia_socket *socket;
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
- release_cis_mem(socket);
- up_read(&pcmcia_socket_list_rwsem);
- }
- break;
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
-/*====================================================================*/
-
-static int adjust_io(adjust_t *adj)
-{
- int base, num, ret = CS_SUCCESS;
-
- base = adj->resource.io.BasePort;
- num = adj->resource.io.NumPorts;
- if ((base < 0) || (base > 0xffff))
- return CS_BAD_BASE;
- if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
- return CS_BAD_SIZE;
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0) {
- ret = CS_IN_USE;
- break;
- }
-#ifdef CONFIG_PCMCIA_PROBE
- if (probe_io)
- do_io_probe(base, num);
-#endif
- break;
- case REMOVE_MANAGED_RESOURCE:
- sub_interval(&io_db, base, num);
- break;
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- break;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
/*====================================================================*/
static int adjust_irq(adjust_t *adj)
@@ -971,37 +225,69 @@ static int adjust_irq(adjust_t *adj)
return ret;
}
-/*====================================================================*/
-
int pcmcia_adjust_resource_info(adjust_t *adj)
{
- switch (adj->Resource) {
- case RES_MEMORY_RANGE:
- return adjust_memory(adj);
- break;
- case RES_IO_RANGE:
- return adjust_io(adj);
- break;
- case RES_IRQ:
- return adjust_irq(adj);
- break;
- }
- return CS_UNSUPPORTED_FUNCTION;
+ struct pcmcia_socket *s;
+ int ret = CS_UNSUPPORTED_FUNCTION;
+
+ if (adj->Resource == RES_IRQ)
+ return adjust_irq(adj);
+
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+ if (s->resource_ops->adjust_resource)
+ ret = s->resource_ops->adjust_resource(s, adj);
+ }
+ up_read(&pcmcia_socket_list_rwsem);
+
+ return (ret);
}
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
-/*====================================================================*/
+void pcmcia_validate_mem(struct pcmcia_socket *s)
+{
+ if (s->resource_ops->validate_mem)
+ s->resource_ops->validate_mem(s);
+}
+EXPORT_SYMBOL(pcmcia_validate_mem);
+
+int adjust_io_region(struct resource *res, unsigned long r_start,
+ unsigned long r_end, struct pcmcia_socket *s)
+{
+ if (s->resource_ops->adjust_io_region)
+ return s->resource_ops->adjust_io_region(res, r_start, r_end, s);
+ return -ENOMEM;
+}
-void release_resource_db(void)
+struct resource *find_io_region(unsigned long base, int num,
+ unsigned long align, struct pcmcia_socket *s)
{
- resource_map_t *p, *q;
-
- for (p = mem_db.next; p != &mem_db; p = q) {
- q = p->next;
- kfree(p);
- }
- for (p = io_db.next; p != &io_db; p = q) {
- q = p->next;
- kfree(p);
- }
+ if (s->resource_ops->find_io)
+ return s->resource_ops->find_io(base, num, align, s);
+ return NULL;
+}
+
+struct resource *find_mem_region(u_long base, u_long num, u_long align,
+ int low, struct pcmcia_socket *s)
+{
+ if (s->resource_ops->find_mem)
+ return s->resource_ops->find_mem(base, num, align, low, s);
+ return NULL;
}
+
+void release_resource_db(struct pcmcia_socket *s)
+{
+ if (s->resource_ops->exit)
+ s->resource_ops->exit(s);
+}
+
+
+struct pccard_resource_ops pccard_static_ops = {
+ .validate_mem = NULL,
+ .adjust_io_region = NULL,
+ .find_io = NULL,
+ .find_mem = NULL,
+ .adjust_resource = NULL,
+ .exit = NULL,
+};
+EXPORT_SYMBOL(pccard_static_ops);
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
new file mode 100644
index 00000000000000..cbc3440d161c78
--- /dev/null
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -0,0 +1,816 @@
+/*
+ * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
+MODULE_LICENSE("GPL");
+
+/* Parameters that can be set with 'insmod' */
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
+
+INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
+#ifdef CONFIG_PCMCIA_PROBE
+INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
+INT_MODULE_PARM(mem_limit, 0x10000);
+#endif
+
+/* for io_db and mem_db */
+struct resource_map {
+ u_long base, num;
+ struct resource_map *next;
+};
+
+struct socket_data {
+ struct resource_map mem_db;
+ struct resource_map io_db;
+ unsigned int rsrc_mem_probe;
+};
+
+static DECLARE_MUTEX(rsrc_sem);
+#define MEM_PROBE_LOW (1 << 0)
+#define MEM_PROBE_HIGH (1 << 1)
+
+
+/*======================================================================
+
+ Linux resource management extensions
+
+======================================================================*/
+
+static struct resource *
+make_resource(unsigned long b, unsigned long n, int flags, char *name)
+{
+ struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+
+ if (res) {
+ memset(res, 0, sizeof(*res));
+ res->name = name;
+ res->start = b;
+ res->end = b + n - 1;
+ res->flags = flags;
+ }
+ return res;
+}
+
+static struct resource *
+claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
+ int type, char *name)
+{
+ struct resource *res, *parent;
+
+ parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
+ res = make_resource(base, size, type | IORESOURCE_BUSY, name);
+
+ if (res) {
+#ifdef CONFIG_PCI
+ if (s && s->cb_dev)
+ parent = pci_find_parent_resource(s->cb_dev, res);
+#endif
+ if (!parent || request_resource(parent, res)) {
+ kfree(res);
+ res = NULL;
+ }
+ }
+ return res;
+}
+
+static void free_region(struct resource *res)
+{
+ if (res) {
+ release_resource(res);
+ kfree(res);
+ }
+}
+
+/*======================================================================
+
+ These manage the internal databases of available resources.
+
+======================================================================*/
+
+static int add_interval(struct resource_map *map, u_long base, u_long num)
+{
+ struct resource_map *p, *q;
+
+ for (p = map; ; p = p->next) {
+ if ((p != map) && (p->base+p->num-1 >= base))
+ return -1;
+ if ((p->next == map) || (p->next->base > base+num-1))
+ break;
+ }
+ q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+ if (!q) return CS_OUT_OF_RESOURCE;
+ q->base = base; q->num = num;
+ q->next = p->next; p->next = q;
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int sub_interval(struct resource_map *map, u_long base, u_long num)
+{
+ struct resource_map *p, *q;
+
+ for (p = map; ; p = q) {
+ q = p->next;
+ if (q == map)
+ break;
+ if ((q->base+q->num > base) && (base+num > q->base)) {
+ if (q->base >= base) {
+ if (q->base+q->num <= base+num) {
+ /* Delete whole block */
+ p->next = q->next;
+ kfree(q);
+ /* don't advance the pointer yet */
+ q = p;
+ } else {
+ /* Cut off bit from the front */
+ q->num = q->base + q->num - base - num;
+ q->base = base + num;
+ }
+ } else if (q->base+q->num <= base+num) {
+ /* Cut off bit from the end */
+ q->num = base - q->base;
+ } else {
+ /* Split the block into two pieces */
+ p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+ if (!p) return CS_OUT_OF_RESOURCE;
+ p->base = base+num;
+ p->num = q->base+q->num - p->base;
+ q->num = base - q->base;
+ p->next = q->next ; q->next = p;
+ }
+ }
+ }
+ return CS_SUCCESS;
+}
+
+/*======================================================================
+
+ These routines examine a region of IO or memory addresses to
+ determine what ranges might be genuinely available.
+
+======================================================================*/
+
+#ifdef CONFIG_PCMCIA_PROBE
+static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num)
+{
+ struct resource *res;
+ struct socket_data *s_data = s->resource_data;
+ ioaddr_t i, j, bad, any;
+ u_char *b, hole, most;
+
+ printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
+ base, base+num-1);
+
+ /* First, what does a floating port look like? */
+ b = kmalloc(256, GFP_KERNEL);
+ if (!b) {
+ printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
+ return;
+ }
+ memset(b, 0, 256);
+ for (i = base, most = 0; i < base+num; i += 8) {
+ res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
+ if (!res)
+ continue;
+ hole = inb(i);
+ for (j = 1; j < 8; j++)
+ if (inb(i+j) != hole) break;
+ free_region(res);
+ if ((j == 8) && (++b[hole] > b[most]))
+ most = hole;
+ if (b[most] == 127) break;
+ }
+ kfree(b);
+
+ bad = any = 0;
+ for (i = base; i < base+num; i += 8) {
+ res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
+ if (!res)
+ continue;
+ for (j = 0; j < 8; j++)
+ if (inb(i+j) != most) break;
+ free_region(res);
+ if (j < 8) {
+ if (!any)
+ printk(" excluding");
+ if (!bad)
+ bad = any = i;
+ } else {
+ if (bad) {
+ sub_interval(&s_data->io_db, bad, i-bad);
+ printk(" %#04x-%#04x", bad, i-1);
+ bad = 0;
+ }
+ }
+ }
+ if (bad) {
+ if ((num > 16) && (bad == base) && (i == base+num)) {
+ printk(" nothing: probe failed.\n");
+ return;
+ } else {
+ sub_interval(&s_data->io_db, bad, i-bad);
+ printk(" %#04x-%#04x", bad, i-1);
+ }
+ }
+
+ printk(any ? "\n" : " clean.\n");
+}
+#endif
+
+/*======================================================================
+
+ This is tricky... when we set up CIS memory, we try to validate
+ the memory window space allocations.
+
+======================================================================*/
+
+/* Validation function for cards with a valid CIS */
+static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
+{
+ int ret = -1;
+
+ s->cis_mem.res = res;
+ s->cis_virt = ioremap(res->start, s->map_size);
+ if (s->cis_virt) {
+ ret = pccard_validate_cis(s, BIND_FN_ALL, info);
+ /* invalidate mapping and CIS cache */
+ iounmap(s->cis_virt);
+ s->cis_virt = NULL;
+ destroy_cis_cache(s);
+ }
+ s->cis_mem.res = NULL;
+ if ((ret != 0) || (info->Chains == 0))
+ return 0;
+ return 1;
+}
+
+/* Validation function for simple memory cards */
+static int checksum(struct pcmcia_socket *s, struct resource *res)
+{
+ pccard_mem_map map;
+ int i, a = 0, b = -1, d;
+ void __iomem *virt;
+
+ virt = ioremap(res->start, s->map_size);
+ if (virt) {
+ map.map = 0;
+ map.flags = MAP_ACTIVE;
+ map.speed = 0;
+ map.res = res;
+ map.card_start = 0;
+ s->ops->set_mem_map(s, &map);
+
+ /* Don't bother checking every word... */
+ for (i = 0; i < s->map_size; i += 44) {
+ d = readl(virt+i);
+ a += d;
+ b &= d;
+ }
+
+ map.flags = 0;
+ s->ops->set_mem_map(s, &map);
+
+ iounmap(virt);
+ }
+
+ return (b == -1) ? -1 : (a>>1);
+}
+
+static int
+cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
+{
+ struct resource *res1, *res2;
+ cisinfo_t info1, info2;
+ int ret = 0;
+
+ res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
+ res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
+
+ if (res1 && res2) {
+ ret = readable(s, res1, &info1);
+ ret += readable(s, res2, &info2);
+ }
+
+ free_region(res2);
+ free_region(res1);
+
+ return (ret == 2) && (info1.Chains == info2.Chains);
+}
+
+static int
+checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
+{
+ struct resource *res1, *res2;
+ int a = -1, b = -1;
+
+ res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
+ res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
+
+ if (res1 && res2) {
+ a = checksum(s, res1);
+ b = checksum(s, res2);
+ }
+
+ free_region(res2);
+ free_region(res1);
+
+ return (a == b) && (a >= 0);
+}
+
+/*======================================================================
+
+ The memory probe. If the memory list includes a 64K-aligned block
+ below 1MB, we probe in 64K chunks, and as soon as we accumulate at
+ least mem_limit free space, we quit.
+
+======================================================================*/
+
+static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
+{
+ struct socket_data *s_data = s->resource_data;
+ u_long i, j, bad, fail, step;
+
+ printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
+ base, base+num-1);
+ bad = fail = 0;
+ step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
+ /* cis_readable wants to map 2x map_size */
+ if (step < 2 * s->map_size)
+ step = 2 * s->map_size;
+ for (i = j = base; i < base+num; i = j + step) {
+ if (!fail) {
+ for (j = i; j < base+num; j += step) {
+ if (cis_readable(s, j, step))
+ break;
+ }
+ fail = ((i == base) && (j == base+num));
+ }
+ if (fail) {
+ for (j = i; j < base+num; j += 2*step)
+ if (checksum_match(s, j, step) &&
+ checksum_match(s, j + step, step))
+ break;
+ }
+ if (i != j) {
+ if (!bad) printk(" excluding");
+ printk(" %#05lx-%#05lx", i, j-1);
+ sub_interval(&s_data->mem_db, i, j-i);
+ bad += j-i;
+ }
+ }
+ printk(bad ? "\n" : " clean.\n");
+ return (num - bad);
+}
+
+#ifdef CONFIG_PCMCIA_PROBE
+
+static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
+{
+ struct socket_data *s_data = s->resource_data;
+ u_long ok;
+ if (m == &s_data->mem_db)
+ return 0;
+ ok = inv_probe(m->next, s);
+ if (ok) {
+ if (m->base >= 0x100000)
+ sub_interval(&s_data->mem_db, m->base, m->num);
+ return ok;
+ }
+ if (m->base < 0x100000)
+ return 0;
+ return do_mem_probe(m->base, m->num, s);
+}
+
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+{
+ struct resource_map *m, mm;
+ static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+ u_long b, i, ok = 0;
+ struct socket_data *s_data = s->resource_data;
+
+ /* We do up to four passes through the list */
+ if (probe_mask & MEM_PROBE_HIGH) {
+ if (inv_probe(s_data->mem_db.next, s) > 0)
+ return;
+ printk(KERN_NOTICE "cs: warning: no high memory space "
+ "available!\n");
+ }
+ if ((probe_mask & MEM_PROBE_LOW) == 0)
+ return;
+ for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+ mm = *m;
+ /* Only probe < 1 MB */
+ if (mm.base >= 0x100000) continue;
+ if ((mm.base | mm.num) & 0xffff) {
+ ok += do_mem_probe(mm.base, mm.num, s);
+ continue;
+ }
+ /* Special probe for 64K-aligned block */
+ for (i = 0; i < 4; i++) {
+ b = order[i] << 12;
+ if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+ if (ok >= mem_limit)
+ sub_interval(&s_data->mem_db, b, 0x10000);
+ else
+ ok += do_mem_probe(b, 0x10000, s);
+ }
+ }
+ }
+}
+
+#else /* CONFIG_PCMCIA_PROBE */
+
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+{
+ struct resource_map *m, mm;
+ struct socket_data *s_data = s->resource_data;
+
+ for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+ mm = *m;
+ if (do_mem_probe(mm.base, mm.num, s))
+ break;
+ }
+}
+
+#endif /* CONFIG_PCMCIA_PROBE */
+
+
+/*
+ * Locking note: this is the only place where we take
+ * both rsrc_sem and skt_sem.
+ */
+static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+{
+ struct socket_data *s_data = s->resource_data;
+ if (probe_mem) {
+ unsigned int probe_mask;
+
+ down(&rsrc_sem);
+
+ probe_mask = MEM_PROBE_LOW;
+ if (s->features & SS_CAP_PAGE_REGS)
+ probe_mask = MEM_PROBE_HIGH;
+
+ if (probe_mask & ~s_data->rsrc_mem_probe) {
+ s_data->rsrc_mem_probe |= probe_mask;
+
+ down(&s->skt_sem);
+
+ if (s->state & SOCKET_PRESENT)
+ validate_mem(s, probe_mask);
+
+ up(&s->skt_sem);
+ }
+
+ up(&rsrc_sem);
+ }
+}
+
+struct pcmcia_align_data {
+ unsigned long mask;
+ unsigned long offset;
+ struct resource_map *map;
+};
+
+static void
+pcmcia_common_align(void *align_data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pcmcia_align_data *data = align_data;
+ unsigned long start;
+ /*
+ * Ensure that we have the correct start address
+ */
+ start = (res->start & ~data->mask) + data->offset;
+ if (start < res->start)
+ start += data->mask + 1;
+ res->start = start;
+}
+
+static void
+pcmcia_align(void *align_data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pcmcia_align_data *data = align_data;
+ struct resource_map *m;
+
+ pcmcia_common_align(data, res, size, align);
+
+ for (m = data->map->next; m != data->map; m = m->next) {
+ unsigned long start = m->base;
+ unsigned long end = m->base + m->num - 1;
+
+ /*
+ * If the lower resources are not available, try aligning
+ * to this entry of the resource database to see if it'll
+ * fit here.
+ */
+ if (res->start < start) {
+ res->start = start;
+ pcmcia_common_align(data, res, size, align);
+ }
+
+ /*
+ * If we're above the area which was passed in, there's
+ * no point proceeding.
+ */
+ if (res->start >= res->end)
+ break;
+
+ if ((res->start + size - 1) <= end)
+ break;
+ }
+
+ /*
+ * If we failed to find something suitable, ensure we fail.
+ */
+ if (m == data->map)
+ res->start = res->end;
+}
+
+/*
+ * Adjust an existing IO region allocation, but making sure that we don't
+ * encroach outside the resources which the user supplied.
+ */
+static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
+ unsigned long r_end, struct pcmcia_socket *s)
+{
+ struct resource_map *m;
+ struct socket_data *s_data = s->resource_data;
+ int ret = -ENOMEM;
+
+ down(&rsrc_sem);
+ for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
+ unsigned long start = m->base;
+ unsigned long end = m->base + m->num - 1;
+
+ if (start > r_start || r_end > end)
+ continue;
+
+ ret = adjust_resource(res, r_start, r_end - r_start + 1);
+ break;
+ }
+ up(&rsrc_sem);
+
+ return ret;
+}
+
+/*======================================================================
+
+ These find ranges of I/O ports or memory addresses that are not
+ currently allocated by other devices.
+
+ The 'align' field should reflect the number of bits of address
+ that need to be preserved from the initial value of *base. It
+ should be a power of two, greater than or equal to 'num'. A value
+ of 0 means that all bits of *base are significant. *base should
+ also be strictly less than 'align'.
+
+======================================================================*/
+
+struct resource *nonstatic_find_io_region(unsigned long base, int num,
+ unsigned long align, struct pcmcia_socket *s)
+{
+ struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
+ struct socket_data *s_data = s->resource_data;
+ struct pcmcia_align_data data;
+ unsigned long min = base;
+ int ret;
+
+ if (align == 0)
+ align = 0x10000;
+
+ data.mask = align - 1;
+ data.offset = base & data.mask;
+ data.map = &s_data->io_db;
+
+ down(&rsrc_sem);
+#ifdef CONFIG_PCI
+ if (s->cb_dev) {
+ ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
+ min, 0, pcmcia_align, &data);
+ } else
+#endif
+ ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
+ 1, pcmcia_align, &data);
+ up(&rsrc_sem);
+
+ if (ret != 0) {
+ kfree(res);
+ res = NULL;
+ }
+ return res;
+}
+
+struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align,
+ int low, struct pcmcia_socket *s)
+{
+ struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
+ struct socket_data *s_data = s->resource_data;
+ struct pcmcia_align_data data;
+ unsigned long min, max;
+ int ret, i;
+
+ low = low || !(s->features & SS_CAP_PAGE_REGS);
+
+ data.mask = align - 1;
+ data.offset = base & data.mask;
+ data.map = &s_data->mem_db;
+
+ for (i = 0; i < 2; i++) {
+ if (low) {
+ max = 0x100000UL;
+ min = base < max ? base : 0;
+ } else {
+ max = ~0UL;
+ min = 0x100000UL + base;
+ }
+
+ down(&rsrc_sem);
+#ifdef CONFIG_PCI
+ if (s->cb_dev) {
+ ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
+ 1, min, 0,
+ pcmcia_align, &data);
+ } else
+#endif
+ ret = allocate_resource(&iomem_resource, res, num, min,
+ max, 1, pcmcia_align, &data);
+ up(&rsrc_sem);
+ if (ret == 0 || low)
+ break;
+ low = 1;
+ }
+
+ if (ret != 0) {
+ kfree(res);
+ res = NULL;
+ }
+ return res;
+}
+
+
+static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
+{
+ u_long base, num;
+ struct socket_data *data = s->resource_data;
+ int ret;
+
+ base = adj->resource.memory.Base;
+ num = adj->resource.memory.Size;
+ if ((num == 0) || (base+num-1 < base))
+ return CS_BAD_SIZE;
+
+ ret = CS_SUCCESS;
+
+ down(&rsrc_sem);
+ switch (adj->Action) {
+ case ADD_MANAGED_RESOURCE:
+ ret = add_interval(&data->mem_db, base, num);
+ break;
+ case REMOVE_MANAGED_RESOURCE:
+ ret = sub_interval(&data->mem_db, base, num);
+ if (ret == CS_SUCCESS) {
+ struct pcmcia_socket *socket;
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
+ release_cis_mem(socket);
+ up_read(&pcmcia_socket_list_rwsem);
+ }
+ break;
+ default:
+ ret = CS_UNSUPPORTED_FUNCTION;
+ }
+ up(&rsrc_sem);
+
+ return ret;
+}
+
+
+static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
+{
+ struct socket_data *data = s->resource_data;
+ int base, num, ret = CS_SUCCESS;
+
+ base = adj->resource.io.BasePort;
+ num = adj->resource.io.NumPorts;
+ if ((base < 0) || (base > 0xffff))
+ return CS_BAD_BASE;
+ if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
+ return CS_BAD_SIZE;
+
+ down(&rsrc_sem);
+ switch (adj->Action) {
+ case ADD_MANAGED_RESOURCE:
+ if (add_interval(&data->io_db, base, num) != 0) {
+ ret = CS_IN_USE;
+ break;
+ }
+#ifdef CONFIG_PCMCIA_PROBE
+ if (probe_io)
+ do_io_probe(s, base, num);
+#endif
+ break;
+ case REMOVE_MANAGED_RESOURCE:
+ sub_interval(&data->io_db, base, num);
+ break;
+ default:
+ ret = CS_UNSUPPORTED_FUNCTION;
+ break;
+ }
+ up(&rsrc_sem);
+
+ return ret;
+}
+
+
+static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj)
+{
+ switch (adj->Resource) {
+ case RES_MEMORY_RANGE:
+ return adjust_memory(s, adj);
+ case RES_IO_RANGE:
+ return adjust_io(s, adj);
+ }
+ return CS_UNSUPPORTED_FUNCTION;
+}
+
+static int nonstatic_init(struct pcmcia_socket *s)
+{
+ struct socket_data *data;
+
+ data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->mem_db.next = &data->mem_db;
+ data->io_db.next = &data->io_db;
+
+ s->resource_data = (void *) data;
+
+ return 0;
+}
+
+static void nonstatic_release_resource_db(struct pcmcia_socket *s)
+{
+ struct socket_data *data = s->resource_data;
+ struct resource_map *p, *q;
+
+ down(&rsrc_sem);
+ for (p = data->mem_db.next; p != &data->mem_db; p = q) {
+ q = p->next;
+ kfree(p);
+ }
+ for (p = data->io_db.next; p != &data->io_db; p = q) {
+ q = p->next;
+ kfree(p);
+ }
+ up(&rsrc_sem);
+}
+
+
+struct pccard_resource_ops pccard_nonstatic_ops = {
+ .validate_mem = pcmcia_nonstatic_validate_mem,
+ .adjust_io_region = nonstatic_adjust_io_region,
+ .find_io = nonstatic_find_io_region,
+ .find_mem = nonstatic_find_mem_region,
+ .adjust_resource = nonstatic_adjust_resource_info,
+ .init = nonstatic_init,
+ .exit = nonstatic_release_resource_db,
+};
+EXPORT_SYMBOL(pccard_nonstatic_ops);
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index a45fee3f43550f..20dd66b245bc98 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -758,6 +758,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
goto out_err_6;
skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
+ skt->socket.resource_ops = &pccard_static_ops;
skt->socket.irq_mask = 0;
skt->socket.map_size = PAGE_SIZE;
skt->socket.pci_irq = skt->irq;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index a651309eb84fb8..e20438a7408f41 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -531,8 +531,9 @@ static int __init init_tcic(void)
for (i = 0; i < sockets; i++) {
socket_table[i].socket.ops = &tcic_operations;
+ socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
socket_table[i].socket.dev.dev = &tcic_device.dev;
- ret = pcmcia_register_socket(&socket_table[i].socket);
+ ret = pcmcia_register_socket(&socket_table[i].socket);
if (ret && i)
pcmcia_unregister_socket(&socket_table[0].socket);
}
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 315f634fd7f103..b9f3e3f21ad6c5 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -592,15 +592,20 @@ out:
static int ti12xx_override(struct yenta_socket *socket)
{
- u32 val;
+ u32 val, val_orig;
/* make sure that memory burst is active */
- val = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ val_orig = val = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ if (disable_clkrun && PCI_FUNC(socket->dev->devfn) == 0) {
+ printk(KERN_INFO "Yenta: Disabling CLKRUN feature\n");
+ val |= TI113X_SCR_KEEPCLK;
+ }
if (!(val & TI122X_SCR_MRBURSTUP)) {
printk(KERN_INFO "Yenta: Enabling burst memory read transactions\n");
val |= TI122X_SCR_MRBURSTUP;
- config_writel(socket, TI113X_SYSTEM_CONTROL, val);
}
+ if (val_orig != val)
+ config_writel(socket, TI113X_SYSTEM_CONTROL, val);
/*
* for EnE bridges only: clear testbit TLTEnable. this makes the
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 4b8b822bcca37a..9fae06ac2761c1 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -28,6 +28,9 @@
#include "yenta_socket.h"
#include "i82365.h"
+static int disable_clkrun;
+module_param(disable_clkrun, bool, 0444);
+MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
#if 0
#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
@@ -42,6 +45,10 @@
static int yenta_probe_cb_irq(struct yenta_socket *socket);
+static unsigned int override_bios;
+module_param(override_bios, uint, 0000);
+MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation");
+
/*
* Generate easy-to-use ways of reading a cardbus sockets
* regular memory space ("cb_xxx"), configuration space
@@ -551,7 +558,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
start = config_readl(socket, offset) & mask;
end = config_readl(socket, offset+4) | ~mask;
- if (start && end > start) {
+ if (start && end > start && !override_bios) {
res->start = start;
res->end = end;
if (request_resource(root, res) == 0)
@@ -914,6 +921,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* prepare pcmcia_socket */
socket->socket.ops = &yenta_socket_operations;
+ socket->socket.resource_ops = &pccard_nonstatic_ops;
socket->socket.dev.dev = &dev->dev;
socket->socket.driver_data = socket;
socket->socket.owner = THIS_MODULE;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index f53956f77f283e..a379bc9a1276b7 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -768,28 +768,6 @@ void aac_printf(struct aac_dev *dev, u32 val)
memset(cp, 0, 256);
}
-
-/**
- * aac_handle_aif - Handle a message from the firmware
- * @dev: Which adapter this fib is from
- * @fibptr: Pointer to fibptr from adapter
- *
- * This routine handles a driver notify fib from the adapter and
- * dispatches it to the appropriate routine for handling.
- */
-
-static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
-{
- struct hw_fib * hw_fib = fibptr->hw_fib;
- /*
- * Set the status of this FIB to be Invalid parameter.
- *
- * *(u32 *)fib->data = ST_INVAL;
- */
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fibptr, sizeof(u32));
-}
-
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
@@ -859,7 +837,6 @@ int aac_command_thread(struct aac_dev * dev)
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
- aac_handle_aif(dev, fib);
*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
} else {
@@ -870,10 +847,6 @@ int aac_command_thread(struct aac_dev * dev)
u32 time_now, time_last;
unsigned long flagv;
- /* Sniff events */
- if (aifcmd->command == cpu_to_le32(AifCmdEventNotify))
- aac_handle_aif(dev, fib);
-
time_now = jiffies/HZ;
spin_lock_irqsave(&dev->fib_lock, flagv);
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index d97a8b137fe050..c2b47f2bdffdf4 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -125,14 +125,8 @@ ahc_linux_eisa_init(void)
uint32_t eisa_id;
size_t id_size;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0)
- continue;
- request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx");
-#else
if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0)
continue;
-#endif
eisa_id = 0;
id_size = sizeof(eisa_id);
@@ -207,14 +201,8 @@ aic7770_map_registers(struct ahc_softc *ahc, u_int port)
/*
* Lock out other contenders for our i/o space.
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- if (check_region(port, AHC_EISA_IOSIZE) != 0)
- return (ENOMEM);
- request_region(port, AHC_EISA_IOSIZE, "aic7xxx");
-#else
if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
return (ENOMEM);
-#endif
ahc->tag = BUS_SPACE_PIO;
ahc->bsh.ioport = port;
return (0);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 539ae081f15303..db3bd6321dd4b2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -831,8 +831,6 @@ static inline void ahc_linux_eisa_exit(void) {
/******************************* PCI Routines *********************************/
#ifdef CONFIG_PCI
-void ahc_power_state_change(struct ahc_softc *ahc,
- ahc_power_state new_state);
int ahc_linux_pci_init(void);
void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 49d799ac61e8c4..6f6674aa31ef43 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -42,12 +42,6 @@
#include "aic7xxx_osm.h"
#include "aic7xxx_pci.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-struct pci_device_id
-{
-};
-#endif
-
static int ahc_linux_pci_dev_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
@@ -55,7 +49,6 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
uint8_t __iomem **maddr);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
@@ -169,7 +162,6 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
} else
ahc_list_unlock(&l);
}
-#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -219,7 +211,6 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc = ahc_alloc(NULL, name);
if (ahc == NULL)
return (-ENOMEM);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (pci_enable_device(pdev)) {
ahc_free(ahc);
return (-ENODEV);
@@ -238,14 +229,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK;
}
-#endif
ahc->dev_softc = pci;
error = ahc_pci_config(ahc, entry);
if (error != 0) {
ahc_free(ahc);
return (-error);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_set_drvdata(pdev, ahc);
if (aic7xxx_detect_complete) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -256,39 +245,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return (-ENODEV);
#endif
}
-#endif
return (0);
}
int
ahc_linux_pci_init(void)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Translate error or zero return into zero or one */
return pci_module_init(&aic7xxx_pci_driver) ? 0 : 1;
-#else
- struct pci_dev *pdev;
- u_int class;
- int found;
-
- /* If we don't have a PCI bus, we can't find any adapters. */
- if (pci_present() == 0)
- return (0);
-
- found = 0;
- pdev = NULL;
- class = PCI_CLASS_STORAGE_SCSI << 8;
- while ((pdev = pci_find_class(class, pdev)) != NULL) {
- ahc_dev_softc_t pci;
- int error;
-
- pci = pdev;
- error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL);
- if (error == 0)
- found++;
- }
- return (found);
-#endif
}
void
@@ -303,22 +267,11 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
if (aic7xxx_allow_memio == 0)
return (ENOMEM);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
*base = pci_resource_start(ahc->dev_softc, 0);
-#else
- *base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4);
- *base &= PCI_BASE_ADDRESS_IO_MASK;
-#endif
if (*base == 0)
return (ENOMEM);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- if (check_region(*base, 256) != 0)
- return (ENOMEM);
- request_region(*base, 256, "aic7xxx");
-#else
if (request_region(*base, 256, "aic7xxx") == 0)
return (ENOMEM);
-#endif
return (0);
}
@@ -334,17 +287,13 @@ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
start = pci_resource_start(ahc->dev_softc, 1);
if (start != 0) {
*bus_addr = start;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (request_mem_region(start, 0x1000, "aic7xxx") == 0)
error = ENOMEM;
-#endif
if (error == 0) {
*maddr = ioremap_nocache(start, 256);
if (*maddr == NULL) {
error = ENOMEM;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(start, 0x1000);
-#endif
}
}
} else
@@ -387,10 +336,8 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
ahc_get_pci_slot(ahc->dev_softc),
ahc_get_pci_function(ahc->dev_softc));
iounmap(maddr);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(ahc->platform_data->mem_busaddr,
0x1000);
-#endif
ahc->bsh.maddr = NULL;
maddr = NULL;
} else
@@ -440,41 +387,3 @@ ahc_pci_map_int(struct ahc_softc *ahc)
return (-error);
}
-void
-ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- pci_set_power_state(ahc->dev_softc, new_state);
-#else
- uint32_t cap;
- u_int cap_offset;
-
- /*
- * Traverse the capability list looking for
- * the power management capability.
- */
- cap = 0;
- cap_offset = ahc_pci_read_config(ahc->dev_softc,
- PCIR_CAP_PTR, /*bytes*/1);
- while (cap_offset != 0) {
-
- cap = ahc_pci_read_config(ahc->dev_softc,
- cap_offset, /*bytes*/4);
- if ((cap & 0xFF) == 1
- && ((cap >> 16) & 0x3) > 0) {
- uint32_t pm_control;
-
- pm_control = ahc_pci_read_config(ahc->dev_softc,
- cap_offset + 4,
- /*bytes*/4);
- pm_control &= ~0x3;
- pm_control |= new_state;
- ahc_pci_write_config(ahc->dev_softc,
- cap_offset + 4,
- pm_control, /*bytes*/2);
- break;
- }
- cap_offset = (cap >> 8) & 0xFF;
- }
-#endif
-}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index e3b50fcf62f7a9..7ddcc97fb243f7 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -721,7 +721,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc->chip |= AHC_PCI;
ahc->description = entry->name;
- ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+ pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
error = ahc_pci_map_registers(ahc);
if (error != 0)
@@ -2016,7 +2016,7 @@ static int
ahc_pci_resume(struct ahc_softc *ahc)
{
- ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+ pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
/*
* We assume that the OS has restored our register
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index e710da4d00e1ed..d625fdebe052bd 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1156,17 +1156,14 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
}
/* Print sense information */
-static void
-print_sense_internal(const char *devclass,
- const unsigned char *sense_buffer,
- int sense_len,
- struct request *req)
+void
+__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
+ int sense_len)
{
int k, num, res;
unsigned int info;
const char *error;
const char *sense_txt;
- const char *name = req->rq_disk ? req->rq_disk->disk_name : devclass;
struct scsi_sense_hdr ssh;
res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
@@ -1254,18 +1251,25 @@ print_sense_internal(const char *devclass,
printk("\n");
}
}
+EXPORT_SYMBOL(__scsi_print_sense);
void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
{
- print_sense_internal(devclass, cmd->sense_buffer,
- SCSI_SENSE_BUFFERSIZE, cmd->request);
+ const char *name = devclass;
+
+ if (cmd->request->rq_disk)
+ name = cmd->request->rq_disk->disk_name;
+ __scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_sense);
void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
{
- print_sense_internal(devclass, sreq->sr_sense_buffer,
- SCSI_SENSE_BUFFERSIZE, sreq->sr_request);
+ const char *name = devclass;
+
+ if (sreq->sr_request->rq_disk)
+ name = sreq->sr_request->rq_disk->disk_name;
+ __scsi_print_sense(name, sreq->sr_sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_req_sense);
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 32e0cd59752ca7..770930e2aec336 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -96,7 +96,6 @@
#include "scsi.h"
#include <scsi/scsi_host.h>
-#include "fd_mcs.h"
#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
@@ -104,14 +103,12 @@
#define DEBUG 0 /* Enable debugging output */
#define ENABLE_PARITY 1 /* Enable SCSI Parity */
-#define DO_DETECT 0 /* Do device detection here (see scsi.c) */
/* END OF USER DEFINABLE OPTIONS */
#if DEBUG
#define EVERY_ACCESS 0 /* Write a line on every scsi access */
#define ERRORS_ONLY 1 /* Only write a line if there is an error */
-#define DEBUG_DETECT 1 /* Debug fd_mcs_detect() */
#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
#define DEBUG_ABORT 1 /* Debug abort() routine */
#define DEBUG_RESET 1 /* Debug reset() routine */
@@ -119,7 +116,6 @@
#else
#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
#define ERRORS_ONLY 0
-#define DEBUG_DETECT 0
#define DEBUG_MESSAGES 0
#define DEBUG_ABORT 0
#define DEBUG_RESET 0
@@ -432,6 +428,7 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
+/* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
#ifdef NOT_USED
/* *************************************************** */
/* Try to toggle 32-bit mode. This only
@@ -510,59 +507,6 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);
/* done reset */
-
-#if DO_DETECT
- /* scan devices attached */
- {
- const int buflen = 255;
- int i, j, retcode;
- Scsi_Cmnd SCinit;
- unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
- unsigned char do_request_sense[] = { REQUEST_SENSE,
- 0, 0, 0, buflen, 0
- };
- unsigned char do_read_capacity[] = { READ_CAPACITY,
- 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char buf[buflen];
-
- SCinit.request_buffer = SCinit.buffer = buf;
- SCinit.request_bufflen = SCinit.bufflen = sizeof(buf) - 1;
- SCinit.use_sg = 0;
- SCinit.lun = 0;
- SCinit.host = shpnt;
-
- printk("fd_mcs: detection routine scanning for devices:\n");
- for (i = 0; i < 8; i++) {
- if (i == shpnt->this_id) /* Skip host adapter */
- continue;
- SCinit.target = i;
- memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
- retcode = fd_mcs_command(&SCinit);
- if (!retcode) {
- memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
- retcode = fd_mcs_command(&SCinit);
- if (!retcode) {
- printk(" SCSI ID %d: ", i);
- for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
- printk("%c", buf[j] >= 20 ? buf[j] : ' ');
- memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
- retcode = fd_mcs_command(&SCinit);
- if (!retcode) {
- unsigned long blocks, size, capacity;
-
- blocks = (buf[0] << 24) | (buf[1] << 16)
- | (buf[2] << 8) | buf[3];
- size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
- capacity = +(+(blocks / 1024L) * +(size * 10L)) / 1024L;
-
- printk("%lu MB (%lu byte blocks)\n", ((capacity + 5L) / 10L), size);
- }
- }
- }
- }
- }
-#endif
}
}
diff --git a/drivers/scsi/fd_mcs.h b/drivers/scsi/fd_mcs.h
deleted file mode 100644
index 011a7878a2017a..00000000000000
--- a/drivers/scsi/fd_mcs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* fd_mcs.h -- Header for Future Domain MCS 600/700 (or IBM OEM) driver
- *
- * fd_mcs.h v0.2 03/11/1998 ZP Gu (zpg@castle.net)
- *
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
-
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef _FD_MCS_H
-#define _FD_MCS_H
-
-static int fd_mcs_detect(Scsi_Host_Template *);
-static int fd_mcs_release(struct Scsi_Host *);
-static int fd_mcs_command(Scsi_Cmnd *);
-static int fd_mcs_abort(Scsi_Cmnd *);
-static int fd_mcs_bus_reset(Scsi_Cmnd *);
-static int fd_mcs_device_reset(Scsi_Cmnd *);
-static int fd_mcs_host_reset(Scsi_Cmnd *);
-static int fd_mcs_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-static int fd_mcs_biosparam(struct scsi_device *, struct block_device *,
- sector_t, int *);
-static const char *fd_mcs_info(struct Scsi_Host *);
-
-#endif /* _FD_MCS_H */
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 2442ca46aeb0fb..4a092bec4bb7a9 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -397,11 +397,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#include <linux/spinlock.h>
-#else
-#include <asm/spinlock.h>
-#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include <linux/blkdev.h>
#else
@@ -412,14 +408,11 @@
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "gdth.h"
+#include "gdth_kcompat.h"
static void gdth_delay(int milliseconds);
static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-#else
-static void gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-#endif
static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
static int gdth_async_event(int hanum);
static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
@@ -617,32 +610,6 @@ static unchar gdth_direction_tab[0x100] = {
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
};
-/* __initfunc, __initdata macros */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#define GDTH_INITFUNC(type, func) type __init func
-#include <linux/init.h>
-#else
-#define GDTH_INITFUNC(type, func) __initfunc(type func)
-#include <linux/init.h>
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
-#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
-#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
-
-#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
-#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags)
-
-#else
-#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
-#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
-#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
-
-#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)
-#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)
-#endif
-
/* LILO and modprobe/insmod parameters */
/* IRQ list for GDT3000/3020 EISA controllers */
static int irq[MAXHA] __initdata =
@@ -674,7 +641,6 @@ static int probe_eisa_isa = 0;
/* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */
static int force_dma32 = 0;
-#ifdef MODULE
/* parameters for modprobe/insmod */
module_param(irq, int, 0);
module_param(disable, int, 0);
@@ -689,33 +655,15 @@ module_param(shared_access, int, 0);
module_param(probe_eisa_isa, int, 0);
module_param(force_dma32, int, 0);
MODULE_AUTHOR("Achim Leubner");
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
MODULE_LICENSE("GPL");
-#endif
-#endif
/* ioctl interface */
static struct file_operations gdth_fops = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
.ioctl = gdth_ioctl,
.open = gdth_open,
.release = gdth_close,
-#else
- ioctl:gdth_ioctl,
- open:gdth_open,
- release:gdth_close,
-#endif
};
-/* /proc support */
-#include <linux/stat.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-struct proc_dir_entry proc_scsi_gdth = {
- PROC_SCSI_GDTH, 4, "gdth",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-#endif
-
#include "gdth_proc.h"
#include "gdth_proc.c"
@@ -755,7 +703,7 @@ static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs
/* controller search and initialization functions */
-GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
+static int __init gdth_search_eisa(ushort eisa_adr)
{
ulong32 id;
@@ -773,7 +721,7 @@ GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
}
-GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
+static int __init gdth_search_isa(ulong32 bios_adr)
{
void __iomem *addr;
ulong32 id;
@@ -789,7 +737,7 @@ GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
}
-GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
+static int __init gdth_search_pci(gdth_pci_str *pcistr)
{
ushort device, cnt;
@@ -812,21 +760,19 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
return cnt;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Vortex only makes RAID controllers.
* We do not really want to specify all 550 ids here, so wildcard match.
*/
-static struct pci_device_id gdthtable[] __devinitdata = {
+static struct pci_device_id gdthtable[] __attribute_used__ = {
{PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID},
{PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID},
{0}
};
MODULE_DEVICE_TABLE(pci,gdthtable);
-#endif
-GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
- ushort vendor, ushort device))
+static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+ ushort vendor, ushort device)
{
ulong base0, base1, base2;
struct pci_dev *pdev;
@@ -834,7 +780,6 @@ GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
*cnt, vendor, device));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pdev = NULL;
while ((pdev = pci_find_device(vendor, device, pdev))
!= NULL) {
@@ -872,52 +817,10 @@ GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
pcistr[*cnt].irq, pcistr[*cnt].dpmem));
(*cnt)++;
}
-#else
- pdev = NULL;
- while ((pdev = pci_find_device(vendor, device, pdev))
- != NULL) {
- if (*cnt >= MAXHA)
- return;
- /* GDT PCI controller found, resources are already in pdev */
- pcistr[*cnt].pdev = pdev;
- pcistr[*cnt].vendor_id = vendor;
- pcistr[*cnt].device_id = device;
- pcistr[*cnt].bus = pdev->bus->number;
- pcistr[*cnt].device_fn = pdev->devfn;
- pcibios_read_config_word(pcistr[*cnt].bus, pcistr[*cnt].device_fn,
- PCI_SUBSYSTEM_ID, &pcistr[*cnt].subdevice_id);
- pcistr[*cnt].irq = pdev->irq;
- base0 = pdev->base_address[0];
- base1 = pdev->base_address[1];
- base2 = pdev->base_address[2];
- if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
- device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
- if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY)
- continue;
- pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
- } else { /* GDT6110, GDT6120, .. */
- if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY ||
- (base2 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY ||
- (base1 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_IO)
- continue;
- pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
- pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
- pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
- }
- TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
- pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
- pcistr[*cnt].irq, pcistr[*cnt].dpmem));
- (*cnt)++;
- }
-#endif
}
-GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
+static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
{
gdth_pci_str temp;
int i, changed;
@@ -955,7 +858,7 @@ GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
}
-GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
+static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
{
ulong32 retries,id;
unchar prot_ver,eisacf,i,irq_found;
@@ -1048,7 +951,7 @@ GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
}
-GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
+static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
{
register gdt2_dpram_str __iomem *dp2_ptr;
int i;
@@ -1148,7 +1051,7 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
}
-GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
+static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
{
register gdt6_dpram_str __iomem *dp6_ptr;
register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -1168,9 +1071,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
ha->stype = (ulong32)pcistr->device_id;
ha->subdevice_id = pcistr->subdevice_id;
ha->irq = pcistr->irq;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
ha->pdev = pcistr->pdev;
-#endif
if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
@@ -1401,7 +1302,6 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
}
/* manipulate config. space to enable DPMEM, start RP controller */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
command |= 6;
pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
@@ -1412,18 +1312,6 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
gdth_delay(1);
pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
pci_resource_start(pcistr->pdev, 8));
-#else
- pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
- command |= 6;
- pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
- if (pcistr->pdev->rom_address == 1UL)
- pcistr->pdev->rom_address = 0UL;
- i = 0xFEFF0001UL;
- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
- gdth_delay(1);
- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
- pcistr->pdev->rom_address);
-#endif
dp6m_ptr = ha->brd;
@@ -1550,7 +1438,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
/* controller protocol functions */
-GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
+static void __init gdth_enable_int(int hanum)
{
gdth_ha_str *ha;
ulong flags;
@@ -1560,7 +1448,7 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
TRACE(("gdth_enable_int() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (ha->type == GDT_EISA) {
outb(0xff, ha->bmic + EDOORREG);
@@ -1585,7 +1473,7 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
&dp6m_ptr->i960r.edoor_en_reg);
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
@@ -1897,7 +1785,7 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
/* search for devices */
-GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
+static int __init gdth_search_drives(int hanum)
{
register gdth_ha_str *ha;
ushort cdev_cnt, i;
@@ -2357,16 +2245,11 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
TRACE(("gdth_putq() priority %d\n",priority));
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
scp->SCp.this_residual = (int)priority;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (priority >= DEFAULT_PRI) {
if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
(b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
@@ -2389,7 +2272,7 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
pscp->SCp.ptr = (char *)scp;
scp->SCp.ptr = (char *)nscp;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
#ifdef GDTH_STATISTICS
flags = 0;
@@ -2415,7 +2298,7 @@ static void gdth_next(int hanum)
TRACE(("gdth_next() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
if (!gdth_polling)
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
this_cmd = firsttime = TRUE;
@@ -2425,15 +2308,9 @@ static void gdth_next(int hanum)
for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
t = nscp->device->id;
l = nscp->device->lun;
-#else
- b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
- t = nscp->target;
- l = nscp->lun;
-#endif
if (nscp->SCp.this_residual >= DEFAULT_PRI) {
if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
(b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
@@ -2444,7 +2321,7 @@ static void gdth_next(int hanum)
if (gdth_test_busy(hanum)) { /* controller busy ? */
TRACE(("gdth_next() controller %d busy !\n",hanum));
if (!gdth_polling) {
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return;
}
while (gdth_test_busy(hanum))
@@ -2513,14 +2390,8 @@ static void gdth_next(int hanum)
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
}
} else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
@@ -2538,14 +2409,8 @@ static void gdth_next(int hanum)
nscp->result = DID_BAD_TARGET << 16;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
} else {
switch (nscp->cmnd[0]) {
case TEST_UNIT_READY:
@@ -2555,9 +2420,7 @@ static void gdth_next(int hanum)
case VERIFY:
case START_STOP:
case MODE_SENSE:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case SERVICE_ACTION_IN:
-#endif
TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
nscp->cmnd[4],nscp->cmnd[5]));
@@ -2572,22 +2435,10 @@ static void gdth_next(int hanum)
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
- } else if (gdth_internal_cache_cmd(hanum,nscp)) {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ } else if (gdth_internal_cache_cmd(hanum,nscp))
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
break;
case ALLOW_MEDIUM_REMOVAL:
@@ -2600,14 +2451,8 @@ static void gdth_next(int hanum)
nscp->sense_buffer[0] = 0;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
} else {
nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
TRACE(("Prevent/allow r. %d rem. drive %d\n",
@@ -2629,10 +2474,8 @@ static void gdth_next(int hanum)
case WRITE_6:
case READ_10:
case WRITE_10:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case READ_16:
case WRITE_16:
-#endif
if (ha->hdr[t].media_changed) {
/* return UNIT_ATTENTION */
TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
@@ -2644,14 +2487,8 @@ static void gdth_next(int hanum)
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
} else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
break;
@@ -2665,14 +2502,8 @@ static void gdth_next(int hanum)
nscp->result = DID_ABORT << 16;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
break;
}
}
@@ -2692,7 +2523,7 @@ static void gdth_next(int hanum)
}
if (!gdth_polling)
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
if (gdth_polling && ha->cmd_cnt > 0) {
if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
@@ -2708,7 +2539,6 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
ushort cpsum,cpnow;
struct scatterlist *sl;
gdth_ha_str *ha;
- int sgcnt;
char *address;
cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
@@ -2716,10 +2546,9 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
- sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
- for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
- cpnow = (ushort)sg_dma_len(sl);
+ for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
+ unsigned long flags;
+ cpnow = (ushort)sl->length;
TRACE(("copy_internal() now %d sum %d count %d %d\n",
cpnow,cpsum,cpcount,(ushort)scp->bufflen));
if (cpsum+cpnow > cpcount)
@@ -2730,30 +2559,16 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
hanum);
return;
}
- address = (char *)(page_address(sl->page) + sl->offset);
- memcpy(address,buffer,cpnow);
- if (cpsum == cpcount)
- break;
- buffer += cpnow;
- }
- pci_unmap_sg(ha->pdev,scp->request_buffer,
- scp->use_sg,PCI_DMA_FROMDEVICE);
-#else
- sgcnt = scp->use_sg;
- for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
- cpnow = (ushort)sl->length;
- TRACE(("copy_internal() now %d sum %d count %d %d\n",
- cpnow,cpsum,cpcount,(ushort)scp->bufflen));
- if (cpsum+cpnow > cpcount)
- cpnow = cpcount - cpsum;
- cpsum += cpnow;
- address = (char *)sl->address;
+ local_irq_save(flags);
+ address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
memcpy(address,buffer,cpnow);
+ flush_dcache_page(sl->page);
+ kunmap_atomic(address, KM_BIO_SRC_IRQ);
+ local_irq_restore(flags);
if (cpsum == cpcount)
break;
buffer += cpnow;
}
-#endif
} else {
TRACE(("copy_internal() count %d\n",cpcount));
memcpy((char*)scp->request_buffer,buffer,cpcount);
@@ -2770,11 +2585,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
gdth_modep_data mpd;
ha = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
t = scp->device->id;
-#else
- t = scp->target;
-#endif
TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
scp->cmnd[0],t));
@@ -2839,7 +2650,6 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case SERVICE_ACTION_IN:
if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 &&
(ha->cache_feat & GDT_64BIT)) {
@@ -2853,7 +2663,6 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
scp->result = DID_ABORT << 16;
}
break;
-#endif
default:
TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
@@ -2877,10 +2686,8 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
ulong64 no, blockno;
dma_addr_t phys_addr;
int i, cmd_index, read_write, sgcnt, mode64;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
struct page *page;
ulong offset;
-#endif
ha = HADATA(gdth_ctr_tab[hanum]);
cmdp = ha->pccb;
@@ -2922,10 +2729,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
else
cmdp->OpCode = GDT_FLUSH;
} else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
- scp->cmnd[0] == WRITE_12
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- || scp->cmnd[0] == WRITE_16
-#endif
+ scp->cmnd[0] == WRITE_12 || scp->cmnd[0] == WRITE_16
) {
read_write = 1;
if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) &&
@@ -2976,7 +2780,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
sgcnt = scp->use_sg;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SG;
scp->SCp.Message = (read_write == 1 ?
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
@@ -3005,23 +2808,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
}
}
-#else
- if (mode64) {
- cmdp->u.cache64.DestAddr= (ulong64)-1;
- cmdp->u.cache64.sg_canz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.cache64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.cache64.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- } else {
- cmdp->u.cache.DestAddr= 0xffffffff;
- cmdp->u.cache.sg_canz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- }
-#endif
#ifdef GDTH_STATISTICS
if (max_sg < (ulong32)sgcnt) {
@@ -3031,7 +2817,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
#endif
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SINGLE;
scp->SCp.Message = (read_write == 1 ?
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
@@ -3040,9 +2825,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
phys_addr = pci_map_page(ha->pdev,page,offset,
scp->request_bufflen,scp->SCp.Message);
scp->SCp.dma_handle = phys_addr;
-#else
- phys_addr = virt_to_bus(scp->request_buffer);
-#endif
if (mode64) {
if (ha->cache_feat & SCATTER_GATHER) {
cmdp->u.cache64.DestAddr = (ulong64)-1;
@@ -3114,19 +2896,12 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
dma_addr_t phys_addr, sense_paddr;
int cmd_index, sgcnt, mode64;
unchar t,l;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
struct page *page;
ulong offset;
-#endif
ha = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
t = scp->device->id;
l = scp->device->lun;
-#else
- t = scp->target;
- l = scp->lun;
-#endif
cmdp = ha->pccb;
TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
scp->cmnd[0],b,t,l));
@@ -3166,7 +2941,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
}
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
page = virt_to_page(scp->sense_buffer);
offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
sense_paddr = pci_map_page(ha->pdev,page,offset,
@@ -3174,9 +2948,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr);
/* high part, if 64bit */
scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32);
-#else
- sense_paddr = virt_to_bus(scp->sense_buffer);
-#endif
cmdp->OpCode = GDT_WRITE; /* always */
cmdp->BoardNode = LOCALBOARD;
if (mode64) {
@@ -3215,7 +2986,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
sgcnt = scp->use_sg;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SG;
scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
@@ -3243,23 +3013,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
}
}
-#else
- if (mode64) {
- cmdp->u.raw64.sdata = (ulong64)-1;
- cmdp->u.raw64.sg_ranz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.raw64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.raw64.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- } else {
- cmdp->u.raw.sdata = 0xffffffff;
- cmdp->u.raw.sg_ranz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- }
-#endif
#ifdef GDTH_STATISTICS
if (max_sg < sgcnt) {
@@ -3269,7 +3022,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
#endif
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SINGLE;
scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
page = virt_to_page(scp->request_buffer);
@@ -3277,9 +3029,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
phys_addr = pci_map_page(ha->pdev,page,offset,
scp->request_bufflen,scp->SCp.Message);
scp->SCp.dma_handle = phys_addr;
-#else
- phys_addr = virt_to_bus(scp->request_buffer);
-#endif
+
if (mode64) {
if (ha->raw_feat & SCATTER_GATHER) {
cmdp->u.raw64.sdata = (ulong64)-1;
@@ -3461,7 +3211,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
ulong flags;
TRACE2(("gdth_read_event() handle %d\n", handle));
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (handle == -1)
eindex = eoldidx;
else
@@ -3469,7 +3219,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
estr->event_source = 0;
if (eindex >= MAX_EVENTS) {
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return eindex;
}
e = &ebuffer[eindex];
@@ -3482,7 +3232,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
}
memcpy(estr, e, sizeof(gdth_evt_str));
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return eindex;
}
@@ -3495,7 +3245,7 @@ static void gdth_readapp_event(gdth_ha_str *ha,
unchar found = FALSE;
TRACE2(("gdth_readapp_event() app. %d\n", application));
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
eindex = eoldidx;
for (;;) {
e = &ebuffer[eindex];
@@ -3515,7 +3265,7 @@ static void gdth_readapp_event(gdth_ha_str *ha,
memcpy(estr, e, sizeof(gdth_evt_str));
else
estr->event_source = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static void gdth_clear_events(void)
@@ -3529,12 +3279,9 @@ static void gdth_clear_events(void)
/* SCSI interface functions */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
-#else
-static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
-#endif
{
+ gdth_ha_str *ha2 = (gdth_ha_str *)dev_id;
register gdth_ha_str *ha;
gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
gdt6_dpram_str __iomem *dp6_ptr;
@@ -3556,28 +3303,20 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
/* if polling and not from gdth_wait() -> return */
if (gdth_polling) {
if (!gdth_from_wait) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
return IRQ_HANDLED;
-#else
- return;
-#endif
}
}
if (!gdth_polling)
- GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags);
+ spin_lock_irqsave(&ha2->smp_lock, flags);
wait_index = 0;
/* search controller */
if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
/* spurious interrupt */
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -3711,12 +3450,8 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
} else {
TRACE2(("gdth_interrupt() unknown controller type\n"));
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
TRACE(("gdth_interrupt() index %d stat %d info %d\n",
@@ -3731,13 +3466,9 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
TRACE2(("gdth_interrupt() async. event\n"));
gdth_async_event(hanum);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
gdth_next(hanum);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
return IRQ_HANDLED;
-#else
- return;
-#endif
}
if (IStatus == SPEZINDEX) {
@@ -3746,12 +3477,8 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
ha->dvr.eu.driver.ionode = hanum;
gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
scp = ha->cmd_tab[IStatus-2].cmnd;
Service = ha->cmd_tab[IStatus-2].service;
@@ -3763,40 +3490,24 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
ha->dvr.eu.driver.index = IStatus;
gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
if (scp == INTERNAL_CMND) {
TRACE(("gdth_interrupt() answer to internal command\n"));
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
TRACE(("gdth_interrupt() sync. status\n"));
rval = gdth_sync_event(hanum,Service,IStatus,scp);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
if (rval == 2) {
gdth_putq(hanum,scp,scp->SCp.this_residual);
} else if (rval == 1) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
- scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
-#else
- GDTH_LOCK_SCSI_DONE(flags);
scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(flags);
-#endif
}
#ifdef INT_COAL
@@ -3825,9 +3536,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
#endif
gdth_next(hanum);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
return IRQ_HANDLED;
-#endif
}
static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
@@ -3911,13 +3620,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
printk("\n");
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
}
@@ -3929,7 +3633,6 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
/* retry */
return 2;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
if (scp->SCp.Status == GDTH_MAP_SG)
pci_unmap_sg(ha->pdev,scp->request_buffer,
scp->use_sg,scp->SCp.Message);
@@ -3943,7 +3646,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32);
pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
}
-#endif
+
if (ha->status == S_OK) {
scp->SCp.Status = S_OK;
scp->SCp.Message = ha->info;
@@ -4340,7 +4043,7 @@ void gdth_timeout(ulong data)
int hanum = 0;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
@@ -4355,11 +4058,11 @@ void gdth_timeout(ulong data)
gdth_timer.expires = jiffies + 30 * HZ;
add_timer(&gdth_timer);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
#endif
-GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
+void __init internal_setup(char *str,int *ints)
{
int i, argc;
char *cur_str, *argv;
@@ -4432,7 +4135,7 @@ GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
}
}
-GDTH_INITFUNC(int, option_setup(char *str))
+int __init option_setup(char *str)
{
int ints[MAXHA];
char *cur = str;
@@ -4450,7 +4153,7 @@ GDTH_INITFUNC(int, option_setup(char *str))
return 1;
}
-GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
+int __init gdth_detect(Scsi_Host_Template *shtp)
{
struct Scsi_Host *shp;
gdth_pci_str pcistr[MAXHA];
@@ -4540,7 +4243,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->pccb = CMDDATA(shp);
ha->ccb_phys = 0L;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
ha->pdev = NULL;
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&scratch_dma_handle);
@@ -4554,21 +4256,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
MAXOFFSETS, &scratch_dma_handle);
ha->coal_stat_phys = scratch_dma_handle;
#endif
-#else
- ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
- if (ha->pscratch)
- ha->scratch_phys = virt_to_bus(ha->pscratch);
- ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
- if (ha->pmsg)
- ha->msg_phys = virt_to_bus(ha->pmsg);
-#ifdef INT_COAL
- ha->coal_stat =
- scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
- GFP_ATOMIC | GFP_DMA);
- if (ha->coal_stat)
- ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
-#endif
-#endif
+
ha->scratch_busy = FALSE;
ha->req_first = NULL;
ha->tid_cnt = MAX_HDRIVES;
@@ -4583,7 +4271,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-ISA: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -4596,17 +4284,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
if (ha->pmsg)
pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
ha->pmsg, ha->msg_phys);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
+
free_irq(ha->irq,ha);
scsi_unregister(shp);
continue;
@@ -4615,14 +4293,13 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
hdr_channel = ha->bus_cnt;
ha->virt_bus = hdr_channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
shp->highmem_io = 0;
#endif
if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
shp->max_cmd_len = 16;
-#endif
+
shp->max_id = ha->tid_cnt;
shp->max_lun = MAXLUN;
shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
@@ -4640,7 +4317,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
}
}
- GDTH_INIT_LOCK_HA(ha);
+ spin_lock_init(&ha->smp_lock);
gdth_enable_int(hanum);
#endif /* !__ia64__ */
}
@@ -4686,7 +4363,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->pccb = CMDDATA(shp);
ha->ccb_phys = 0L;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
ha->pdev = NULL;
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&scratch_dma_handle);
@@ -4703,22 +4380,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->ccb_phys =
pci_map_single(ha->pdev,ha->pccb,
sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-#else
- ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
- if (ha->pscratch)
- ha->scratch_phys = virt_to_bus(ha->pscratch);
- ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
- if (ha->pmsg)
- ha->msg_phys = virt_to_bus(ha->pmsg);
-#ifdef INT_COAL
- ha->coal_stat =
- scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
- GFP_ATOMIC | GFP_DMA);
- if (ha->coal_stat)
- ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
-#endif
- ha->ccb_phys = virt_to_bus(ha->pccb);
-#endif
ha->scratch_busy = FALSE;
ha->req_first = NULL;
ha->tid_cnt = MAX_HDRIVES;
@@ -4733,7 +4394,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-EISA: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -4749,17 +4409,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
if (ha->ccb_phys)
pci_unmap_single(ha->pdev,ha->ccb_phys,
sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
free_irq(ha->irq,ha);
scsi_unregister(shp);
continue;
@@ -4768,14 +4417,13 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
hdr_channel = ha->bus_cnt;
ha->virt_bus = hdr_channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
shp->highmem_io = 0;
#endif
if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
shp->max_cmd_len = 16;
-#endif
+
shp->max_id = ha->tid_cnt;
shp->max_lun = MAXLUN;
shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
@@ -4793,7 +4441,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
}
}
- GDTH_INIT_LOCK_HA(ha);
+ spin_lock_init(&ha->smp_lock);
gdth_enable_int(hanum);
}
}
@@ -4841,7 +4489,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->pccb = CMDDATA(shp);
ha->ccb_phys = 0L;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&scratch_dma_handle);
ha->scratch_phys = scratch_dma_handle;
@@ -4854,21 +4502,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
MAXOFFSETS, &scratch_dma_handle);
ha->coal_stat_phys = scratch_dma_handle;
#endif
-#else
- ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
- if (ha->pscratch)
- ha->scratch_phys = virt_to_bus(ha->pscratch);
- ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
- if (ha->pmsg)
- ha->msg_phys = virt_to_bus(ha->pmsg);
-#ifdef INT_COAL
- ha->coal_stat =
- scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
- GFP_ATOMIC | GFP_DMA);
- if (ha->coal_stat)
- ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
-#endif
-#endif
ha->scratch_busy = FALSE;
ha->req_first = NULL;
ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
@@ -4887,7 +4520,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
hdr_channel = ha->bus_cnt;
ha->virt_bus = hdr_channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_set_device(shp, &pcistr[ctr].pdev->dev);
#else
@@ -4909,14 +4542,12 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
err = TRUE;
}
}
-#endif
}
if (err) {
printk("GDT-PCI %d: Error during device scan\n", hanum);
--gdth_ctr_count;
--gdth_ctr_vcount;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -4929,17 +4560,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
if (ha->pmsg)
pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
ha->pmsg, ha->msg_phys);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
free_irq(ha->irq,ha);
scsi_unregister(shp);
continue;
@@ -4962,8 +4582,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
}
}
-
- GDTH_INIT_LOCK_HA(ha);
+ spin_lock_init(&ha->smp_lock);
gdth_enable_int(hanum);
}
@@ -4994,12 +4613,10 @@ int gdth_release(struct Scsi_Host *shp)
if (NUMDATA(shp)->busnum == 0) {
hanum = NUMDATA(shp)->hanum;
ha = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (ha->sdev) {
scsi_free_host_dev(ha->sdev);
ha->sdev = NULL;
}
-#endif
gdth_flush(hanum);
if (shp->irq) {
@@ -5010,7 +4627,6 @@ int gdth_release(struct Scsi_Host *shp)
free_dma(shp->dma_channel);
}
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -5025,17 +4641,6 @@ int gdth_release(struct Scsi_Host *shp)
if (ha->ccb_phys)
pci_unmap_single(ha->pdev,ha->ccb_phys,
sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
gdth_ctr_released++;
TRACE2(("gdth_release(): HA %d of %d\n",
gdth_ctr_released, gdth_ctr_count));
@@ -5098,21 +4703,6 @@ const char *gdth_info(struct Scsi_Host *shp)
return ((const char *)ha->binfo.type_string);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-/* old error handling */
-int gdth_abort(Scsi_Cmnd *scp)
-{
- TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
- return SCSI_ABORT_SNOOZE;
-}
-
-int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
-{
- TRACE2(("gdth_reset()\n"));
- return SCSI_RESET_PUNT;
-}
-#endif
-
/* new error handling */
int gdth_eh_abort(Scsi_Cmnd *scp)
{
@@ -5135,33 +4725,25 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp)
unchar b;
TRACE2(("gdth_eh_bus_reset()\n"));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
hanum = NUMDATA(scp->device->host)->hanum;
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-#else
- hanum = NUMDATA(scp->host)->hanum;
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
-#endif
ha = HADATA(gdth_ctr_tab[hanum]);
/* clear command tab */
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (i = 0; i < GDTH_MAXCMDS; ++i) {
cmnd = ha->cmd_tab[i].cmnd;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
-#else
- if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
-#endif
ha->cmd_tab[i].cmnd = UNUSED_CMND;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
if (b == ha->virt_bus) {
/* host drives */
for (i = 0; i < MAX_HDRIVES; ++i) {
if (ha->hdr[i].present) {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
gdth_polling = TRUE;
while (gdth_test_busy(hanum))
gdth_delay(0);
@@ -5169,12 +4751,12 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp)
GDT_CLUST_RESET, i, 0, 0))
ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
gdth_polling = FALSE;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
}
} else {
/* raw devices */
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (i = 0; i < MAXID; ++i)
ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
gdth_polling = TRUE;
@@ -5183,7 +4765,7 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp)
gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
BUS_L2P(ha,b), 0, 0);
gdth_polling = FALSE;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
return SUCCESS;
}
@@ -5249,11 +4831,8 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
scp->SCp.sent_command = -1;
scp->SCp.Status = GDTH_MAP_NONE;
scp->SCp.buffer = (struct scatterlist *)NULL;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
hanum = NUMDATA(scp->device->host)->hanum;
-#else
- hanum = NUMDATA(scp->host)->hanum;
-#endif
#ifdef GDTH_STATISTICS
++act_ios;
#endif
@@ -5270,7 +4849,6 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
static int gdth_open(struct inode *inode, struct file *filep)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
gdth_ha_str *ha;
int i;
@@ -5279,7 +4857,6 @@ static int gdth_open(struct inode *inode, struct file *filep)
if (!ha->sdev)
ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]);
}
-#endif
TRACE(("gdth_open()\n"));
return 0;
@@ -5311,10 +4888,10 @@ static int ioc_event(void __user *arg)
evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync);
else
evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
&evt.event.event_data);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
} else if (evt.erase == 0xfe) {
gdth_clear_events();
} else if (evt.erase == 0) {
@@ -5344,15 +4921,15 @@ static int ioc_lockdrv(void __user *arg)
if (j >= MAX_HDRIVES || !ha->hdr[j].present)
continue;
if (ldrv.lock) {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[j].lock = 1;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j);
gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j);
} else {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[j].lock = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j);
gdth_next(ldrv.ionode);
}
@@ -5367,11 +4944,9 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
int hanum;
gdth_ha_str *ha;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
+ Scsi_Request *srp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
@@ -5398,7 +4973,7 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
gdth_do_req(srp, &cmd, cmnd, 30);
res.status = (ushort)srp->sr_command->SCp.Status;
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
@@ -5407,15 +4982,8 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
gdth_do_cmd(scp, &cmd, cmnd, 30);
res.status = (ushort)scp->SCp.Status;
scsi_release_command(scp);
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- res.status = (ushort)scp.SCp.Status;
#endif
+
if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset)))
return -EFAULT;
return 0;
@@ -5430,10 +4998,8 @@ static int ioc_general(void __user *arg, char *cmnd)
gdth_ha_str *ha;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) ||
@@ -5536,7 +5102,7 @@ static int ioc_general(void __user *arg, char *cmnd)
gen.status = srp->sr_command->SCp.Status;
gen.info = srp->sr_command->SCp.Message;
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
@@ -5546,15 +5112,6 @@ static int ioc_general(void __user *arg, char *cmnd)
gen.status = scp->SCp.Status;
gen.info = scp->SCp.Message;
scsi_release_command(scp);
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
- gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout);
- gen.status = scp.SCp.Status;
- gen.info = scp.SCp.Message;
#endif
if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf,
@@ -5573,185 +5130,183 @@ static int ioc_general(void __user *arg, char *cmnd)
static int ioc_hdrlist(void __user *arg, char *cmnd)
{
- gdth_ioctl_rescan rsc;
- gdth_cmd_str cmd;
+ gdth_ioctl_rescan *rsc;
+ gdth_cmd_str *cmd;
gdth_ha_str *ha;
unchar i;
- int hanum;
+ int hanum, rc = -ENOMEM;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
- if (copy_from_user(&rsc, arg, sizeof(gdth_ioctl_rescan)) ||
- rsc.ionode >= gdth_ctr_count)
- return -EFAULT;
- hanum = rsc.ionode;
+ rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
+ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!rsc || !cmd)
+ goto free_fail;
+
+ if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
+ rsc->ionode >= gdth_ctr_count) {
+ rc = -EFAULT;
+ goto free_fail;
+ }
+ hanum = rsc->ionode;
ha = HADATA(gdth_ctr_tab[hanum]);
- memset(&cmd, 0, sizeof(gdth_cmd_str));
+ memset(cmd, 0, sizeof(gdth_cmd_str));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
if (!srp)
- return -ENOMEM;
+ goto free_fail;
srp->sr_cmd_len = 12;
srp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
#endif
for (i = 0; i < MAX_HDRIVES; ++i) {
if (!ha->hdr[i].present) {
- rsc.hdr_list[i].bus = 0xff;
+ rsc->hdr_list[i].bus = 0xff;
continue;
}
- rsc.hdr_list[i].bus = ha->virt_bus;
- rsc.hdr_list[i].target = i;
- rsc.hdr_list[i].lun = 0;
- rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+ rsc->hdr_list[i].bus = ha->virt_bus;
+ rsc->hdr_list[i].target = i;
+ rsc->hdr_list[i].lun = 0;
+ rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_CLUST_INFO;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_CLUST_INFO;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
if (srp->sr_command->SCp.Status == S_OK)
- rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
- rsc.hdr_list[i].cluster_type = scp->SCp.Message;
+ rsc->hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
- rsc.hdr_list[i].cluster_type = scp.SCp.Message;
+ gdth_do_cmd(scp, cmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
+ rsc->hdr_list[i].cluster_type = scp->SCp.Message;
#endif
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
#endif
- if (copy_to_user(arg, &rsc, sizeof(gdth_ioctl_rescan)))
- return -EFAULT;
- return 0;
+ if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
+ rc = -EFAULT;
+ else
+ rc = 0;
+
+free_fail:
+ kfree(rsc);
+ kfree(cmd);
+ return rc;
}
static int ioc_rescan(void __user *arg, char *cmnd)
{
- gdth_ioctl_rescan rsc;
- gdth_cmd_str cmd;
+ gdth_ioctl_rescan *rsc;
+ gdth_cmd_str *cmd;
ushort i, status, hdr_cnt;
ulong32 info;
int hanum, cyls, hds, secs;
+ int rc = -ENOMEM;
ulong flags;
gdth_ha_str *ha;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
-
- if (copy_from_user(&rsc, arg, sizeof(gdth_ioctl_rescan)) ||
- rsc.ionode >= gdth_ctr_count)
- return -EFAULT;
- hanum = rsc.ionode;
+
+ rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
+ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd || !rsc)
+ goto free_fail;
+
+ if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
+ rsc->ionode >= gdth_ctr_count) {
+ rc = -EFAULT;
+ goto free_fail;
+ }
+ hanum = rsc->ionode;
ha = HADATA(gdth_ctr_tab[hanum]);
- memset(&cmd, 0, sizeof(gdth_cmd_str));
+ memset(cmd, 0, sizeof(gdth_cmd_str));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
if (!srp)
- return -ENOMEM;
+ goto free_fail;
srp->sr_cmd_len = 12;
srp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
#endif
- if (rsc.flag == 0) {
+ if (rsc->flag == 0) {
/* old method: re-init. cache service */
- cmd.Service = CACHESERVICE;
+ cmd->Service = CACHESERVICE;
if (ha->cache_feat & GDT_64BIT) {
- cmd.OpCode = GDT_X_INIT_HOST;
- cmd.u.cache64.DeviceNo = LINUX_OS;
+ cmd->OpCode = GDT_X_INIT_HOST;
+ cmd->u.cache64.DeviceNo = LINUX_OS;
} else {
- cmd.OpCode = GDT_INIT;
- cmd.u.cache.DeviceNo = LINUX_OS;
+ cmd->OpCode = GDT_INIT;
+ cmd->u.cache.DeviceNo = LINUX_OS;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
+ gdth_do_cmd(&scp, cmd, cmnd, 30);
status = (ushort)scp.SCp.Status;
info = (ulong32)scp.SCp.Message;
#endif
i = 0;
hdr_cnt = (status == S_OK ? (ushort)info : 0);
} else {
- i = rsc.hdr_no;
+ i = rsc->hdr_no;
hdr_cnt = i + 1;
}
+
for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_INFO;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_INFO;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
- rsc.hdr_list[i].bus = ha->virt_bus;
- rsc.hdr_list[i].target = i;
- rsc.hdr_list[i].lun = 0;
+ spin_lock_irqsave(&ha->smp_lock, flags);
+ rsc->hdr_list[i].bus = ha->virt_bus;
+ rsc->hdr_list[i].target = i;
+ rsc->hdr_list[i].lun = 0;
if (status != S_OK) {
ha->hdr[i].present = FALSE;
} else {
@@ -5765,7 +5320,7 @@ static int ioc_rescan(void __user *arg, char *cmnd)
/* round size */
ha->hdr[i].size = cyls * hds * secs;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
if (status != S_OK)
continue;
@@ -5773,99 +5328,87 @@ static int ioc_rescan(void __user *arg, char *cmnd)
/* but we need ha->info2, not yet stored in scp->SCp */
/* devtype, cluster info, R/W attribs */
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_DEVTYPE;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_DEVTYPE;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_CLUST_INFO;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_CLUST_INFO;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[i].cluster_type =
((status == S_OK && !shared_access) ? (ushort)info : 0);
- GDTH_UNLOCK_HA(ha, flags);
- rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
+ rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_RW_ATTRIBS;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_RW_ATTRIBS;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
#endif
- if (copy_to_user(arg, &rsc, sizeof(gdth_ioctl_rescan)))
- return -EFAULT;
- return 0;
+ if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
+ rc = -EFAULT;
+ else
+ rc = 0;
+
+free_fail:
+ kfree(rsc);
+ kfree(cmd);
+ return rc;
}
static int gdth_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg)
{
gdth_ha_str *ha;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Cmnd *scp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
-#else
- Scsi_Cmnd scp;
-#endif
ulong flags;
char cmnd[MAX_COMMAND_SIZE];
void __user *argp = (void __user *)arg;
@@ -5956,17 +5499,17 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
i = lchn.channel;
if (i < ha->bus_cnt) {
if (lchn.lock) {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 1;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
gdth_wait_completion(lchn.ionode, i, j);
gdth_stop_timeout(lchn.ionode, i, j);
}
} else {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
gdth_start_timeout(lchn.ionode, i, j);
gdth_next(lchn.ionode);
@@ -6004,7 +5547,7 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
rval = gdth_eh_bus_reset(scp);
res.status = (rval == SUCCESS ? S_OK : S_GENERR);
scsi_put_command(scp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
@@ -6014,15 +5557,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
rval = gdth_eh_bus_reset(scp);
res.status = (rval == SUCCESS ? S_OK : S_GENERR);
scsi_release_command(scp);
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
- scp.channel = virt_ctr ? 0 : res.number;
- rval = gdth_eh_bus_reset(&scp);
- res.status = (rval == SUCCESS ? S_OK : S_GENERR);
#endif
if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset)))
return -EFAULT;
@@ -6047,14 +5581,10 @@ static void gdth_flush(int hanum)
gdth_cmd_str gdtcmd;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
- Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
- Scsi_Device *sdev;
#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
+ Scsi_Cmnd *scp;
#endif
+ Scsi_Device *sdev;
char cmnd[MAX_COMMAND_SIZE];
memset(cmnd, 0xff, MAX_COMMAND_SIZE);
@@ -6068,19 +5598,13 @@ static void gdth_flush(int hanum)
return;
srp->sr_cmd_len = 12;
srp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp)
return;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- sdev.host = scp.host = gdth_ctr_tab[hanum];
- sdev.id = scp.target = sdev.host->this_id;
- scp.device = &sdev;
#endif
for (i = 0; i < MAX_HDRIVES; ++i) {
@@ -6100,17 +5624,15 @@ static void gdth_flush(int hanum)
TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
gdth_do_req(srp, &gdtcmd, cmnd, 30);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+ gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#endif
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(srp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
@@ -6125,12 +5647,9 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
Scsi_Cmnd *scp;
Scsi_Device *sdev;
-#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
#endif
char cmnd[MAX_COMMAND_SIZE];
#endif
@@ -6162,7 +5681,7 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
gdth_do_req(srp, &gdtcmd, cmnd, 10);
scsi_release_request(srp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp) {
@@ -6174,13 +5693,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
scsi_release_command(scp);
scsi_free_host_dev(sdev);
-#else
- memset(&sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- sdev.host = scp.host = gdth_ctr_tab[hanum];
- sdev.id = scp.target = sdev.host->this_id;
- scp.device = &sdev;
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
#endif
#endif
}
@@ -6193,19 +5705,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
return NOTIFY_OK;
}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) && !defined(MODULE)
-
-GDTH_INITFUNC(void, gdth_setup(char *str,int *ints))
-{
- TRACE2(("gdth_setup() str %s ints[0] %d\n",
- str ? str:"NULL", ints ? ints[0]:0));
- internal_setup(str, ints);
-}
-
-#else
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
static Scsi_Host_Template driver_template = {
.proc_name = "gdth",
.proc_info = gdth_proc_info,
@@ -6232,13 +5731,8 @@ static Scsi_Host_Template driver_template = {
#endif
#endif
};
-#else
-static Scsi_Host_Template driver_template = GDTH;
-#endif
#include "scsi_module.c"
#ifndef MODULE
__setup("gdth=", option_setup);
#endif
-
-#endif
diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h
new file mode 100644
index 00000000000000..e6cf0edfa0caef
--- /dev/null
+++ b/drivers/scsi/gdth_kcompat.h
@@ -0,0 +1,21 @@
+
+
+#ifndef IRQ_HANDLED
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(x)
+#endif
+
+#ifndef SERVICE_ACTION_IN
+#define SERVICE_ACTION_IN 0x9e
+#endif
+#ifndef READ_16
+#define READ_16 0x88
+#endif
+#ifndef WRITE_16
+#define WRITE_16 0x8a
+#endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index e37faaaeb0e541..1bd02f8d1e6a21 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -2,9 +2,7 @@
* $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
#include <linux/completion.h>
-#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,
@@ -57,12 +55,9 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *scp;
Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
Scsi_Cmnd *scp;
Scsi_Device *sdev;
-#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
#endif
TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
@@ -73,19 +68,13 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
return -ENOMEM;
scp->sr_cmd_len = 12;
scp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
sdev = scsi_get_host_dev(host);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- sdev.host = scp.host = host;
- sdev.id = scp.target = sdev.host->this_id;
- scp.device = &sdev;
#endif
if (length >= 4) {
@@ -98,7 +87,7 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(scp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
@@ -107,10 +96,8 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
#else
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
#endif
{
int orig_length, drive, wb_mode;
@@ -161,10 +148,8 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
gdth_do_req(scp, &gdtcmd, cmnd, 30);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+ gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#endif
}
}
@@ -219,10 +204,8 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
pcpar->write_back = wb_mode==1 ? 0:1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
gdth_do_req(scp, &gdtcmd, cmnd, 30);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+ gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#endif
gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
printk("Done.\n");
@@ -243,18 +226,16 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
int no_mdrv = 0, drv_no, is_mirr;
ulong32 cnt;
ulong64 paddr;
+ int rc = -ENOMEM;
- gdth_cmd_str gdtcmd;
- gdth_evt_str estr;
+ gdth_cmd_str *gdtcmd;
+ gdth_evt_str *estr;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *scp;
Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
Scsi_Cmnd *scp;
Scsi_Device *sdev;
-#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
#endif
char hrec[161];
struct timeval tv;
@@ -266,10 +247,15 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
gdth_defcnt_str *pdef;
gdth_cdrinfo_str *pcdi;
gdth_hget_str *phg;
-
char cmnd[MAX_COMMAND_SIZE];
+
+ gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL);
+ estr = kmalloc(sizeof(*estr), GFP_KERNEL);
+ if (!gdtcmd || !estr)
+ goto free_fail;
+
memset(cmnd, 0xff, 12);
- memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
+ memset(gdtcmd, 0, sizeof(gdth_cmd_str));
TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -278,14 +264,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
sdev = scsi_get_host_dev(host);
scp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->sr_cmd_len = 12;
scp->sr_use_sg = 0;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
sdev = scsi_get_host_dev(host);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->cmd_len = 12;
scp->use_sg = 0;
#else
@@ -387,12 +373,12 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 2.a statistics (and retries/reassigns) */
TRACE2(("pdr_statistics() chn %d\n",i));
pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
- gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
- gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
+ gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4;
+ gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
pds->bid = ha->raw[i].local_no;
pds->first = 0;
pds->entries = ha->raw[i].pdev_cnt;
@@ -401,14 +387,11 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
if (pds->entries > cnt)
pds->entries = cnt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status != S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status != S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status != S_OK)
#endif
{
pds->count = 0;
@@ -420,22 +403,19 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
TRACE2(("scsi_drv_info() chn %d dev %d\n",
i, ha->raw[i].id_list[j]));
pdi = (gdth_diskinfo_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
- gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel =
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str);
+ gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel =
ha->raw[i].address | ha->raw[i].id_list[j];
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
#endif
{
strncpy(hrec,pdi->vendor,8);
@@ -478,23 +458,20 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
i, ha->raw[i].id_list[j]));
pdef = (gdth_defcnt_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
- gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel =
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str);
+ gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel =
ha->raw[i].address | ha->raw[i].id_list[j];
pdef->sddc_type = 0x08;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
#endif
{
size = sprintf(buffer+len,
@@ -536,21 +513,18 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 3.a log. drive info */
TRACE2(("cache_drv_info() drive no %d\n",drv_no));
pcdi = (gdth_cdrinfo_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
- gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
- gdtcmd.u.ioctl.channel = drv_no;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
+ gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO;
+ gdtcmd->u.ioctl.channel = drv_no;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status != S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status != S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status != S_OK)
#endif
{
break;
@@ -649,21 +623,18 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 4.a array drive info */
TRACE2(("array_info() drive no %d\n",i));
pai = (gdth_arrayinf_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
- gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel = i;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str);
+ gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
#endif
{
if (pai->ai_state == 0)
@@ -731,23 +702,20 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 5.a get host drive list */
TRACE2(("host_get() drv_no %d\n",i));
phg = (gdth_hget_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
- gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel = i;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str);
+ gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel = i;
phg->entries = MAX_HDRIVES;
phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status != S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status != S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status != S_OK)
#endif
{
ha->hdr[i].ldr_no = i;
@@ -799,14 +767,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
len += size; pos = begin + len;
for (id = -1;;) {
- id = gdth_read_event(ha, id, &estr);
- if (estr.event_source == 0)
+ id = gdth_read_event(ha, id, estr);
+ if (estr->event_source == 0)
break;
- if (estr.event_data.eu.driver.ionode == hanum &&
- estr.event_source == ES_ASYNC) {
- gdth_log_event(&estr.event_data, hrec);
+ if (estr->event_data.eu.driver.ionode == hanum &&
+ estr->event_source == ES_ASYNC) {
+ gdth_log_event(&estr->event_data, hrec);
do_gettimeofday(&tv);
- sec = (int)(tv.tv_sec - estr.first_stamp);
+ sec = (int)(tv.tv_sec - estr->first_stamp);
if (sec < 0) sec = 0;
size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
sec/3600, sec%3600/60, sec%60, hrec);
@@ -826,7 +794,7 @@ stop_output:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(scp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
@@ -836,7 +804,12 @@ stop_output:
len = length;
TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
len,(int)pos,(int)begin,(int)offset,length,size));
- return(len);
+ rc = len;
+
+free_fail:
+ kfree(gdtcmd);
+ kfree(estr);
+ return rc;
}
@@ -864,13 +837,7 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
char *cmnd, int timeout)
{
unsigned bufflen;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
DECLARE_COMPLETION(wait);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- DECLARE_MUTEX_LOCKED(sem);
-#else
- struct semaphore sem = MUTEX_LOCKED;
-#endif
TRACE2(("gdth_do_cmd()\n"));
if (gdtcmd != NULL) {
@@ -880,22 +847,11 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
scp->SCp.this_residual = DEFAULT_PRI;
bufflen = 0;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+
scp->request.rq_status = RQ_SCSI_BUSY;
scp->request.waiting = &wait;
scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
wait_for_completion(&wait);
-#else
- scp->request.sem = &sem;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
-#else
- spin_lock_irq(&io_request_lock);
- scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
- spin_unlock_irq(&io_request_lock);
-#endif
- down(&sem);
-#endif
}
#endif
@@ -907,14 +863,10 @@ void gdth_scsi_done(Scsi_Cmnd *scp)
scp->request->rq_status = RQ_SCSI_DONE;
if (scp->request->waiting != NULL)
complete(scp->request->waiting);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+#else
scp->request.rq_status = RQ_SCSI_DONE;
if (scp->request.waiting != NULL)
complete(scp->request.waiting);
-#else
- scp->request.rq_status = RQ_SCSI_DONE;
- if (scp->request.sem != NULL)
- up(scp->request.sem);
#endif
}
@@ -929,7 +881,7 @@ static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
return NULL;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
ha->scratch_busy = TRUE;
@@ -938,19 +890,13 @@ static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
} else if (scratch) {
ret_val = NULL;
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
dma_addr_t dma_addr;
ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr);
*paddr = dma_addr;
-#else
- ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA);
- if (ret_val)
- *paddr = virt_to_bus(ret_val);
-#endif
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return ret_val;
}
@@ -960,19 +906,15 @@ static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr)
ulong flags;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (buf == ha->pscratch) {
ha->scratch_busy = FALSE;
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_free_consistent(ha->pdev, size, buf, paddr);
-#else
- scsi_init_free((void *)buf, size);
-#endif
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
#ifdef GDTH_IOCTL_PROC
@@ -983,14 +925,14 @@ static int gdth_ioctl_check_bin(int hanum, ushort size)
int ret_val;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ret_val = FALSE;
if (ha->scratch_busy) {
if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size)
ret_val = TRUE;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return ret_val;
}
#endif
@@ -1004,36 +946,23 @@ static void gdth_wait_completion(int hanum, int busnum, int id)
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (i = 0; i < GDTH_MAXCMDS; ++i) {
scp = ha->cmd_tab[i].cmnd;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (!SPECIAL_SCP(scp) && t == (unchar)id &&
b == (unchar)busnum) {
scp->SCp.have_data_in = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
while (!scp->SCp.have_data_in)
barrier();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
- scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
-#else
- GDTH_LOCK_SCSI_DONE(flags);
- scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(flags);
-#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
}
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static void gdth_stop_timeout(int hanum, int busnum, int id)
@@ -1044,22 +973,17 @@ static void gdth_stop_timeout(int hanum, int busnum, int id)
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (t == (unchar)id && b == (unchar)busnum) {
TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
}
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static void gdth_start_timeout(int hanum, int busnum, int id)
@@ -1070,22 +994,17 @@ static void gdth_start_timeout(int hanum, int busnum, int id)
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (t == (unchar)id && b == (unchar)busnum) {
TRACE2(("gdth_start_timeout(): update_timeout()\n"));
gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
}
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index 5fb191625c3339..295e825e2c6006 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -14,14 +14,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
-#else
-static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
- char *cmnd, int timeout);
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
#endif
static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index f8721d9f558fb4..e89f76e5dd531f 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
-#define IBMVSCSI_VERSION "1.5.1"
+#define IBMVSCSI_VERSION "1.5.5"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
@@ -256,6 +256,7 @@ static void init_event_struct(struct srp_event_struct *evt_struct,
{
evt_struct->cmnd = NULL;
evt_struct->cmnd_done = NULL;
+ evt_struct->sync_srp = NULL;
evt_struct->crq.format = format;
evt_struct->crq.timeout = timeout;
evt_struct->done = done;
@@ -467,7 +468,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
struct ibmvscsi_host_data *hostdata)
{
- struct scsi_cmnd *cmnd = evt_struct->cmnd;
+ struct scsi_cmnd *cmnd;
u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
int rc;
@@ -479,22 +480,15 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
(atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
/* See if the adapter is disabled */
- if (atomic_read(&hostdata->request_limit) < 0) {
- if (cmnd)
- cmnd->result = DID_ERROR << 16;
- if (evt_struct->cmnd_done)
- evt_struct->cmnd_done(cmnd);
- unmap_cmd_data(&evt_struct->iu.srp.cmd,
- hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- return 0;
- } else {
- printk("ibmvscsi: Warning, request_limit exceeded\n");
- unmap_cmd_data(&evt_struct->iu.srp.cmd,
- hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
+ if (atomic_read(&hostdata->request_limit) < 0)
+ goto send_error;
+
+ printk(KERN_WARNING
+ "ibmvscsi: Warning, request_limit exceeded\n");
+ unmap_cmd_data(&evt_struct->iu.srp.cmd,
+ hostdata->dev);
+ free_event_struct(&hostdata->pool, evt_struct);
+ return SCSI_MLQUEUE_HOST_BUSY;
}
/* Copy the IU into the transfer area */
@@ -511,18 +505,24 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
list_del(&evt_struct->list);
- cmnd = evt_struct->cmnd;
printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
rc);
- unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- if (cmnd)
- cmnd->result = DID_ERROR << 16;
- if (evt_struct->cmnd_done)
- evt_struct->cmnd_done(cmnd);
+ goto send_error;
}
return 0;
+
+ send_error:
+ unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+
+ if ((cmnd = evt_struct->cmnd) != NULL) {
+ cmnd->result = DID_ERROR << 16;
+ evt_struct->cmnd_done(cmnd);
+ } else if (evt_struct->done)
+ evt_struct->done(evt_struct);
+
+ free_event_struct(&hostdata->pool, evt_struct);
+ return 0;
}
/**
@@ -537,6 +537,13 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
struct scsi_cmnd *cmnd = evt_struct->cmnd;
+ if (unlikely(rsp->type != SRP_RSP_TYPE)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: bad SRP RSP type %d\n",
+ rsp->type);
+ }
+
if (cmnd) {
cmnd->result = rsp->status;
if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
@@ -641,11 +648,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
evt_struct->xfer_iu->mad.adapter_info.common.status);
} else {
printk("ibmvscsi: host srp version: %s, "
- "host partition %s (%d), OS %d\n",
+ "host partition %s (%d), OS %d, max io %u\n",
hostdata->madapter_info.srp_version,
hostdata->madapter_info.partition_name,
hostdata->madapter_info.partition_number,
- hostdata->madapter_info.os_type);
+ hostdata->madapter_info.os_type,
+ hostdata->madapter_info.port_max_txu[0]);
+
+ if (hostdata->madapter_info.port_max_txu[0])
+ hostdata->host->max_sectors =
+ hostdata->madapter_info.port_max_txu[0] >> 9;
}
}
@@ -796,6 +808,10 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
*/
static void sync_completion(struct srp_event_struct *evt_struct)
{
+ /* copy the response back */
+ if (evt_struct->sync_srp)
+ *evt_struct->sync_srp = *evt_struct->xfer_iu;
+
complete(&evt_struct->comp);
}
@@ -810,6 +826,8 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
struct srp_tsk_mgmt *tsk_mgmt;
struct srp_event_struct *evt;
struct srp_event_struct *tmp_evt, *found_evt;
+ union viosrp_iu srp_rsp;
+ int rsp_rc;
u16 lun = lun_from_dev(cmd->device);
/* First, find this command in our sent list so we can figure
@@ -849,6 +867,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+ evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
@@ -859,6 +878,29 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
spin_lock_irq(hostdata->host->host_lock);
+ /* make sure we got a good response */
+ if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: abort bad SRP RSP type %d\n",
+ srp_rsp.srp.generic.type);
+ return FAILED;
+ }
+
+ if (srp_rsp.srp.rsp.rspvalid)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ else
+ rsp_rc = srp_rsp.srp.rsp.status;
+
+ if (rsp_rc) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: abort code %d for task tag 0x%lx\n",
+ rsp_rc,
+ tsk_mgmt->managed_task_tag);
+ return FAILED;
+ }
+
/* Because we dropped the spinlock above, it's possible
* The event is no longer in our list. Make sure it didn't
* complete while we were aborting
@@ -871,13 +913,17 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
}
+ if (found_evt == NULL) {
+ printk(KERN_INFO
+ "ibmvscsi: aborted task tag 0x%lx completed\n",
+ tsk_mgmt->managed_task_tag);
+ return SUCCESS;
+ }
+
printk(KERN_INFO
"ibmvscsi: successfully aborted task tag 0x%lx\n",
tsk_mgmt->managed_task_tag);
- if (found_evt == NULL)
- return SUCCESS;
-
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
@@ -899,6 +945,8 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
struct srp_tsk_mgmt *tsk_mgmt;
struct srp_event_struct *evt;
struct srp_event_struct *tmp_evt, *pos;
+ union viosrp_iu srp_rsp;
+ int rsp_rc;
u16 lun = lun_from_dev(cmd->device);
evt = get_event_struct(&hostdata->pool);
@@ -923,6 +971,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
tsk_mgmt->lun);
+ evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
@@ -933,6 +982,29 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
spin_lock_irq(hostdata->host->host_lock);
+ /* make sure we got a good response */
+ if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: reset bad SRP RSP type %d\n",
+ srp_rsp.srp.generic.type);
+ return FAILED;
+ }
+
+ if (srp_rsp.srp.rsp.rspvalid)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ else
+ rsp_rc = srp_rsp.srp.rsp.status;
+
+ if (rsp_rc) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: reset code %d for task tag 0x%lx\n",
+ rsp_rc,
+ tsk_mgmt->managed_task_tag);
+ return FAILED;
+ }
+
/* We need to find all commands for this LUN that have not yet been
* responded to, and fail them with DID_RESET
*/
@@ -1048,6 +1120,13 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
return;
}
+ if (atomic_read(&evt_struct->free)) {
+ printk(KERN_ERR
+ "ibmvscsi: received duplicate correlation_token 0x%p!\n",
+ (void *)crq->IU_data_ptr);
+ return;
+ }
+
if (crq->format == VIOSRP_SRP_FORMAT)
atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
&hostdata->request_limit);
@@ -1295,6 +1374,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
hostdata->host = host;
hostdata->dev = dev;
atomic_set(&hostdata->request_limit, -1);
+ hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
max_requests) != 0) {
@@ -1326,7 +1406,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
*/
for (wait_switch = jiffies + (init_timeout * HZ);
time_before(jiffies, wait_switch) &&
- atomic_read(&hostdata->request_limit) < 0;) {
+ atomic_read(&hostdata->request_limit) < 2;) {
msleep(10);
}
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index dbe1735e593422..1030b703c30e93 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -67,6 +67,7 @@ struct srp_event_struct {
union viosrp_iu iu;
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
+ union viosrp_iu *sync_srp;
};
/* a pool of event structs for use */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index ad8a86184dea54..f0059b1f7a01af 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2610,23 +2610,19 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
#endif
/**
- * ipr_store_queue_depth - Change the device's queue depth
- * @dev: device struct
- * @buf: buffer
+ * ipr_change_queue_depth - Change the device's queue depth
+ * @sdev: scsi device struct
+ * @qdepth: depth to set
*
* Return value:
- * number of bytes printed to buffer
+ * actual depth set
**/
-static ssize_t ipr_store_queue_depth(struct device *dev,
- const char *buf, size_t count)
+static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- struct scsi_device *sdev = to_scsi_device(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
struct ipr_resource_entry *res;
- int qdepth = simple_strtoul(buf, NULL, 10);
int tagged = 0;
unsigned long lock_flags = 0;
- ssize_t len = -ENXIO;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
res = (struct ipr_resource_entry *)sdev->hostdata;
@@ -2635,23 +2631,13 @@ static ssize_t ipr_store_queue_depth(struct device *dev,
if (ipr_is_gscsi(res) && res->tcq_active)
tagged = MSG_ORDERED_TAG;
-
- len = strlen(buf);
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_adjust_queue_depth(sdev, tagged, qdepth);
- return len;
+ return qdepth;
}
-static struct device_attribute ipr_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = ipr_store_queue_depth
-};
-
/**
* ipr_show_tcq_enable - Show if the device is enabled for tcqing
* @dev: device struct
@@ -2760,7 +2746,6 @@ static struct device_attribute ipr_adapter_handle_attr = {
};
static struct device_attribute *ipr_dev_attrs[] = {
- &ipr_queue_depth_attr,
&ipr_tcqing_attr,
&ipr_adapter_handle_attr,
NULL,
@@ -3961,6 +3946,7 @@ static struct scsi_host_template driver_template = {
.slave_alloc = ipr_slave_alloc,
.slave_configure = ipr_slave_configure,
.slave_destroy = ipr_slave_destroy,
+ .change_queue_depth = ipr_change_queue_depth,
.bios_param = ipr_biosparam,
.can_queue = IPR_MAX_COMMANDS,
.this_id = -1,
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 35110f4d13c514..25729f3f81648b 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -54,13 +54,33 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
-#include "lasi700.h"
#include "53c700.h"
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("lasi700 SCSI Driver");
MODULE_LICENSE("GPL");
+#define LASI_700_SVERSION 0x00071
+#define LASI_710_SVERSION 0x00082
+
+#define LASI700_ID_TABLE { \
+ .hw_type = HPHW_FIO, \
+ .sversion = LASI_700_SVERSION, \
+ .hversion = HVERSION_ANY_ID, \
+ .hversion_rev = HVERSION_REV_ANY_ID, \
+}
+
+#define LASI710_ID_TABLE { \
+ .hw_type = HPHW_FIO, \
+ .sversion = LASI_710_SVERSION, \
+ .hversion = HVERSION_ANY_ID, \
+ .hversion_rev = HVERSION_REV_ANY_ID, \
+}
+
+#define LASI700_CLOCK 25
+#define LASI710_CLOCK 40
+#define LASI_SCSI_CORE_OFFSET 0x100
+
static struct parisc_device_id lasi700_ids[] = {
LASI700_ID_TABLE,
LASI710_ID_TABLE,
diff --git a/drivers/scsi/lasi700.h b/drivers/scsi/lasi700.h
deleted file mode 100644
index 244a648824ee36..00000000000000
--- a/drivers/scsi/lasi700.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* PARISC LASI driver for the 53c700 chip
- *
- * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com
-**-----------------------------------------------------------------------------
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**-----------------------------------------------------------------------------
- */
-
-#ifndef _LASI700_H
-#define _LASI700_H
-
-#define LASI_710_SVERSION 0x082
-#define LASI_700_SVERSION 0x071
-
-#define LASI700_ID_TABLE { \
- .hw_type = HPHW_FIO, \
- .sversion = LASI_700_SVERSION, \
- .hversion = HVERSION_ANY_ID, \
- .hversion_rev = HVERSION_REV_ANY_ID, \
-}
-
-#define LASI710_ID_TABLE { \
- .hw_type = HPHW_FIO, \
- .sversion = LASI_710_SVERSION, \
- .hversion = HVERSION_ANY_ID, \
- .hversion_rev = HVERSION_REV_ANY_ID, \
-}
-
-#define LASI700_CLOCK 25
-#define LASI710_CLOCK 40
-#define LASI_SCSI_CORE_OFFSET 0x100
-
-#endif
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 8b81553a3ab6c4..4aff0d68298d20 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -13,18 +13,18 @@
order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
- Copyright 1992 - 2002 Kai Makisara / Willem Riede
- email Kai.Makisara@metla.fi / osst@riede.org
+ Copyright 1992 - 2002 Kai Makisara / 2000 - 2004 Willem Riede
+ email osst@riede.org
- $Header: /cvsroot/osst/Driver/osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $
+ $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
Microscopic alterations - Rik Ling, 2000/12/21
Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
Some small formal changes - aeb, 950809
*/
-static const char * cvsid = "$Id: osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $";
-const char * osst_version = "0.99.1";
+static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
+const char * osst_version = "0.99.3";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
@@ -36,6 +36,7 @@ const char * osst_version = "0.99.1";
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
@@ -46,6 +47,7 @@ const char * osst_version = "0.99.1";
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
+#include <linux/moduleparam.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
@@ -82,13 +84,13 @@ MODULE_AUTHOR("Willem Riede");
MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
MODULE_LICENSE("GPL");
-module_param(max_dev, int, 0);
+module_param(max_dev, int, 0444);
MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
-module_param(write_threshold_kbs, int, 0);
+module_param(write_threshold_kbs, int, 0644);
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
-module_param(max_sg_segs, int, 0);
+module_param(max_sg_segs, int, 0644);
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
#else
static struct osst_dev_parm {
@@ -119,10 +121,10 @@ static int debugging = 1;
// #define OSST_INJECT_ERRORS 1
#endif
-#define MAX_RETRIES 2
-#define MAX_READ_RETRIES 0
-#define MAX_WRITE_RETRIES 0
-#define MAX_READY_RETRIES 0
+/* Do not retry! The drive firmware already retries when appropriate,
+ and when it tries to tell us something, we had better listen... */
+#define MAX_RETRIES 0
+
#define NO_TAPE NOT_READY
#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
@@ -147,19 +149,19 @@ static int osst_max_sg_segs = OSST_MAX_SG;
static int osst_max_dev = OSST_MAX_TAPES;
static int osst_nr_dev;
-static OS_Scsi_Tape **os_scsi_tapes = NULL;
-static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
+static struct osst_tape **os_scsi_tapes = NULL;
+static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
static int modes_defined = FALSE;
-static OSST_buffer *new_tape_buffer(int, int, int);
-static int enlarge_buffer(OSST_buffer *, int);
-static void normalize_buffer(OSST_buffer *);
-static int append_to_buffer(const char __user *, OSST_buffer *, int);
-static int from_buffer(OSST_buffer *, char __user *, int);
-static int osst_zero_buffer_tail(OSST_buffer *);
-static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
-static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
+static struct osst_buffer *new_tape_buffer(int, int, int);
+static int enlarge_buffer(struct osst_buffer *, int);
+static void normalize_buffer(struct osst_buffer *);
+static int append_to_buffer(const char __user *, struct osst_buffer *, int);
+static int from_buffer(struct osst_buffer *, char __user *, int);
+static int osst_zero_buffer_tail(struct osst_buffer *);
+static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
+static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
static int osst_probe(struct device *);
static int osst_remove(struct device *);
@@ -173,17 +175,18 @@ struct scsi_driver osst_template = {
}
};
-static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
+static int osst_int_ioctl(struct osst_tape *STp, struct scsi_request ** aSRpnt,
+ unsigned int cmd_in, unsigned long arg);
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
+static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int frame, int skip);
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt);
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt);
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
+static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending);
-static inline char *tape_name(OS_Scsi_Tape *tape)
+static inline char *tape_name(struct osst_tape *tape)
{
return tape->drive->disk_name;
}
@@ -191,7 +194,7 @@ static inline char *tape_name(OS_Scsi_Tape *tape)
/* Routines that handle the interaction with mid-layer SCSI routines */
/* Convert the result to success code */
-static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
+static int osst_chk_result(struct osst_tape * STp, struct scsi_request * SRpnt)
{
char *name = tape_name(STp);
int result = SRpnt->sr_result;
@@ -222,7 +225,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
if (driver_byte(result) & DRIVER_SENSE)
print_req_sense("osst ", SRpnt);
}
-// else
+ else
#endif
if (!(driver_byte(result) & DRIVER_SENSE) ||
((sense[0] & 0x70) == 0x70 &&
@@ -234,7 +237,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
SRpnt->sr_cmnd[0] != MODE_SENSE &&
SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
if (driver_byte(result) & DRIVER_SENSE) {
- printk(KERN_WARNING "%s:W: Command with sense data: ", name);
+ printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
print_req_sense("osst:", SRpnt);
}
else {
@@ -281,7 +284,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
/* Wakeup from interrupt */
static void osst_sleep_done (Scsi_Cmnd * SCpnt)
{
- OS_Scsi_Tape * STp = container_of(SCpnt->request->rq_disk->private_data, OS_Scsi_Tape, driver);
+ struct osst_tape * STp = container_of(SCpnt->request->rq_disk->private_data, struct osst_tape, driver);
if ((STp->buffer)->writing &&
(SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
@@ -307,7 +310,7 @@ static void osst_sleep_done (Scsi_Cmnd * SCpnt)
/* Do the scsi command. Waits until command performed if do_wait is true.
Otherwise osst_write_behind_check() is used to check that the command
has finished. */
-static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
+static struct scsi_request * osst_do_scsi(struct scsi_request *SRpnt, struct osst_tape *STp,
unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
{
unsigned char *bp;
@@ -366,9 +369,9 @@ static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
/* Handle the write-behind checking (downs the semaphore) */
-static void osst_write_behind_check(OS_Scsi_Tape *STp)
+static void osst_write_behind_check(struct osst_tape *STp)
{
- OSST_buffer * STbuffer;
+ struct osst_buffer * STbuffer;
STbuffer = STp->buffer;
@@ -406,7 +409,7 @@ static void osst_write_behind_check(OS_Scsi_Tape *STp)
/*
* Initialize the OnStream AUX
*/
-static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
+static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
int logical_blk_num, int blk_sz, int blk_cnt)
{
os_aux_t *aux = STp->buffer->aux;
@@ -468,13 +471,13 @@ static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_numb
/*
* Verify that we have the correct tape frame
*/
-static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
+static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
{
- char * name = tape_name(STp);
- os_aux_t * aux = STp->buffer->aux;
- os_partition_t * par = &(aux->partition);
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- int blk_cnt, blk_sz, i;
+ char * name = tape_name(STp);
+ os_aux_t * aux = STp->buffer->aux;
+ os_partition_t * par = &(aux->partition);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ int blk_cnt, blk_sz, i;
if (STp->raw) {
if (STp->buffer->syscall_result) {
@@ -602,14 +605,15 @@ err_out:
/*
* Wait for the unit to become Ready
*/
-static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
+static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ unsigned timeout, int initial_delay)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
- char * name = tape_name(STp);
+ int dbg = debugging;
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
#endif
@@ -620,7 +624,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
@@ -641,7 +645,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
}
*aSRpnt = SRpnt;
#if DEBUG
@@ -666,14 +670,14 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
/*
* Wait for a tape to be inserted in the unit
*/
-static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
+static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** aSRpnt, unsigned timeout)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
- char * name = tape_name(STp);
+ int dbg = debugging;
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
#endif
@@ -681,7 +685,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
@@ -700,7 +704,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
}
*aSRpnt = SRpnt;
#if DEBUG
@@ -722,7 +726,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
return 1;
}
-static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
+static int osst_position_tape_and_confirm(struct osst_tape * STp, struct scsi_request ** aSRpnt, int frame)
{
int retval;
@@ -736,15 +740,14 @@ static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aS
/*
* Wait for write(s) to complete
*/
-static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_flush_drive_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
-
- int result = 0;
- int delay = OSST_WAIT_WRITE_COMPLETE;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int result = 0;
+ int delay = OSST_WAIT_WRITE_COMPLETE;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
#endif
@@ -753,7 +756,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
cmd[0] = WRITE_FILEMARKS;
cmd[1] = 1;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
if (STp->buffer->syscall_result) {
@@ -771,12 +774,12 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
}
#define OSST_POLL_PER_SEC 10
-static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
+static int osst_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int curr, int minlast, int to)
{
- unsigned long startwait = jiffies;
- char * name = tape_name(STp);
+ unsigned long startwait = jiffies;
+ char * name = tape_name(STp);
#if DEBUG
- char notyetprinted = 1;
+ char notyetprinted = 1;
#endif
if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
@@ -784,7 +787,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr,
while (time_before (jiffies, startwait + to*HZ))
{
int result;
- result = osst_get_frame_position (STp, aSRpnt);
+ result = osst_get_frame_position(STp, aSRpnt);
if (result == -EIO)
if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
return 0; /* successful recovery leaves drive ready for frame */
@@ -826,23 +829,79 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr,
return -EBUSY;
}
+static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int writing)
+{
+ struct scsi_request * SRpnt;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned long startwait = jiffies;
+ int retval = 1;
+ char * name = tape_name(STp);
+
+ if (writing) {
+ char mybuf[24];
+ char * olddata = STp->buffer->b_data;
+ int oldsize = STp->buffer->buffer_size;
+
+ /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
+
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = WRITE_FILEMARKS;
+ cmd[1] = 1;
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
+ MAX_RETRIES, TRUE);
+
+ while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
+
+ if (STp->buffer->syscall_result && (SRpnt->sr_sense_buffer[2] & 0x0f) != 2) {
+
+ /* some failure - not just not-ready */
+ retval = osst_write_error_recovery(STp, aSRpnt, 0);
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout (HZ / OSST_POLL_PER_SEC);
+
+ STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = READ_POSITION;
+
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, SCSI_DATA_READ, STp->timeout,
+ MAX_RETRIES, TRUE);
+
+ retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
+ STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
+ }
+ if (retval)
+ printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
+ } else
+ /* TODO - figure out which error conditions can be handled */
+ if (STp->buffer->syscall_result)
+ printk(KERN_WARNING
+ "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
+ (*aSRpnt)->sr_sense_buffer[ 2] & 0x0f,
+ (*aSRpnt)->sr_sense_buffer[12],
+ (*aSRpnt)->sr_sense_buffer[13]);
+
+ return retval;
+}
+
/*
* Read the next OnStream tape frame at the current location
*/
-static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
+static int osst_read_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int timeout)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int retval = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int retval = 0;
#if DEBUG
- os_aux_t * aux = STp->buffer->aux;
- char * name = tape_name(STp);
+ os_aux_t * aux = STp->buffer->aux;
+ char * name = tape_name(STp);
#endif
- /* TODO: Error handling */
if (STp->poll)
- retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
-
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
+ retval = osst_recover_wait_frame(STp, aSRpnt, 0);
+
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = READ_6;
cmd[1] = 1;
@@ -850,13 +909,13 @@ static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeo
#if DEBUG
if (debugging)
- printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
+ printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_READ_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt)
- return (-EBUSY);
+ return (-EBUSY);
if ((STp->buffer)->syscall_result) {
retval = 1;
@@ -900,15 +959,13 @@ static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeo
return (retval);
}
-static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_initiate_read(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- Scsi_Request * SRpnt ;
- unsigned char cmd[MAX_COMMAND_SIZE];
- int retval = 0;
-#if DEBUG
- char * name = tape_name(STp);
-#endif
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ struct scsi_request * SRpnt ;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ int retval = 0;
+ char * name = tape_name(STp);
if (STps->rw != ST_READING) { /* Initialize read operation */
if (STps->rw == ST_WRITING || STp->dirty) {
@@ -930,23 +987,25 @@ static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
- retval = STp->buffer->syscall_result;
+ if ((retval = STp->buffer->syscall_result))
+ printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
}
return retval;
}
-static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
+static int osst_get_logical_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ int frame_seq_number, int quiet)
{
struct st_partstat * STps = &(STp->ps[STp->partition]);
- char * name = tape_name(STp);
- int cnt = 0,
- bad = 0,
- past = 0,
- x,
- position;
+ char * name = tape_name(STp);
+ int cnt = 0,
+ bad = 0,
+ past = 0,
+ x,
+ position;
/*
* If we want just any frame (-1) and there is a frame in the buffer, return it
@@ -971,6 +1030,7 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
name, STp->read_error_frame);
#endif
STp->read_error_frame = 0;
+ STp->abort_count++;
}
return (-EIO);
}
@@ -988,10 +1048,11 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
position = 0xbb8;
else if (position > STp->eod_frame_ppos || ++bad == 10) {
position = STp->read_error_frame - 1;
+ bad = 0;
}
else {
- position += 39;
- cnt += 20;
+ position += 29;
+ cnt += 19;
}
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
@@ -1064,10 +1125,10 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
return (STps->eof);
}
-static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
+static int osst_seek_logical_blk(struct osst_tape * STp, struct scsi_request ** aSRpnt, int logical_blk_num)
{
struct st_partstat * STps = &(STp->ps[STp->partition]);
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
int retries = 0;
int frame_seq_estimate, ppos_estimate, move;
@@ -1173,7 +1234,7 @@ error:
#define OSST_SECTOR_SHIFT 9
#define OSST_SECTOR_MASK 0x03F
-static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_get_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int sector;
#if DEBUG
@@ -1203,12 +1264,12 @@ static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return sector;
}
-static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
+static int osst_seek_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt, int sector)
{
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- int frame = sector >> OSST_FRAME_SHIFT,
- offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
- r;
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ int frame = sector >> OSST_FRAME_SHIFT,
+ offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
+ r;
#if DEBUG
char * name = tape_name(STp);
@@ -1266,23 +1327,23 @@ static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sect
* Precondition for this function to work: all frames in the
* drive's buffer must be of one type (DATA, MARK or EOD)!
*/
-static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
- unsigned int frame, unsigned int skip, int pending)
+static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ unsigned int frame, unsigned int skip, int pending)
{
- Scsi_Request * SRpnt = * aSRpnt;
- unsigned char * buffer, * p;
- unsigned char cmd[MAX_COMMAND_SIZE];
- int flag, new_frame, i;
- int nframes = STp->cur_frames;
- int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
- int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
+ struct scsi_request * SRpnt = * aSRpnt;
+ unsigned char * buffer, * p;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ int flag, new_frame, i;
+ int nframes = STp->cur_frames;
+ int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+ int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
- (nframes + pending - 1);
- int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
+ int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
- (nframes + pending - 1) * blks_per_frame;
- char * name = tape_name(STp);
- unsigned long startwait = jiffies;
+ char * name = tape_name(STp);
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
+ int dbg = debugging;
#endif
if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
@@ -1308,7 +1369,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
cmd[8] = 32768 & 0xff;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_READ_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if ((STp->buffer)->syscall_result || !SRpnt) {
printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
@@ -1357,8 +1418,8 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
vfree((void *)buffer);
return (-EIO);
}
- flag = 0;
if ( i >= nframes + pending ) break;
+ flag = 0;
}
osst_copy_to_buffer(STp->buffer, p);
/*
@@ -1380,7 +1441,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
p[0], p[1], p[2], p[3]);
#endif
SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if (STp->buffer->syscall_result)
flag = 1;
@@ -1396,7 +1457,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
cmd[0] = WRITE_FILEMARKS;
cmd[1] = 1;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
#if DEBUG
if (debugging) {
printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
@@ -1411,7 +1472,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
cmd[0] = TEST_UNIT_READY;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
- MAX_READY_RETRIES, TRUE);
+ MAX_RETRIES, TRUE);
if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
(SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
@@ -1448,29 +1509,34 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
#endif
osst_get_frame_position(STp, aSRpnt);
#if DEBUG
- printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
- name, STp->first_frame_position, STp->last_frame_position);
+ printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
+ name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
#endif
}
- }
+ }
+ if (flag) {
+ /* error recovery did not successfully complete */
+ printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
+ STp->write_type == OS_WRITE_HEADER?"header":"body");
+ }
if (!pending)
osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
vfree((void *)buffer);
return 0;
}
-static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request ** aSRpnt,
unsigned int frame, unsigned int skip, int pending)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- char * name = tape_name(STp);
- int expected = 0;
- int attempts = 1000 / skip;
- int flag = 1;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ char * name = tape_name(STp);
+ int expected = 0;
+ int attempts = 1000 / skip;
+ int flag = 1;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
+ int dbg = debugging;
#endif
while (attempts && time_before(jiffies, startwait + 60*HZ)) {
@@ -1512,7 +1578,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
name, STp->frame_seq_number-1, STp->first_frame_position);
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (STp->buffer->syscall_result) { /* additional write error */
@@ -1550,6 +1616,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
debugging = 0;
}
#endif
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 10);
}
printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
@@ -1563,14 +1630,14 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
* Error recovery algorithm for the OnStream tape.
*/
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
+static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending)
{
- Scsi_Request * SRpnt = * aSRpnt;
+ struct scsi_request * SRpnt = * aSRpnt;
struct st_partstat * STps = & STp->ps[STp->partition];
- char * name = tape_name(STp);
- int retval = 0;
- int rw_state;
- unsigned int frame, skip;
+ char * name = tape_name(STp);
+ int retval = 0;
+ int rw_state;
+ unsigned int frame, skip;
rw_state = STps->rw;
@@ -1635,12 +1702,14 @@ static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
if (retval == 0) {
STp->recover_count++;
STp->recover_erreg++;
- }
+ } else
+ STp->abort_count++;
+
STps->rw = rw_state;
return retval;
}
-static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct scsi_request ** aSRpnt,
int mt_op, int mt_count)
{
char * name = tape_name(STp);
@@ -1739,7 +1808,7 @@ found:
*
* Just scans for the filemark sequentially.
*/
-static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct scsi_request ** aSRpnt,
int mt_op, int mt_count)
{
int cnt = 0;
@@ -1793,7 +1862,7 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Reque
/*
* Fast linux specific version of OnStream FSF
*/
-static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct scsi_request ** aSRpnt,
int mt_op, int mt_count)
{
char * name = tape_name(STp);
@@ -1944,11 +2013,11 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque
* to test the error recovery mechanism.
*/
#if DEBUG
-static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
+static void osst_set_retries(struct osst_tape * STp, struct scsi_request ** aSRpnt, int retries)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = * aSRpnt;
- char * name = tape_name(STp);
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = * aSRpnt;
+ char * name = tape_name(STp);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SELECT;
@@ -1976,7 +2045,7 @@ static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ret
#endif
-static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_filemark(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int result;
int this_mark_ppos = STp->first_frame_position;
@@ -2004,7 +2073,7 @@ static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return result;
}
-static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_eod(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int result;
#if DEBUG
@@ -2027,7 +2096,7 @@ static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return result;
}
-static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int osst_write_filler(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count)
{
char * name = tape_name(STp);
@@ -2052,7 +2121,7 @@ static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int whe
return osst_flush_drive_buffer(STp, aSRpnt);
}
-static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int __osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count)
{
char * name = tape_name(STp);
int result;
@@ -2079,7 +2148,7 @@ static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int w
return result;
}
-static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
+static int osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int locate_eod)
{
os_header_t * header;
int result;
@@ -2153,7 +2222,7 @@ static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int loc
return result;
}
-static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_reset_header(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
if (STp->header_cache != NULL)
memset(STp->header_cache, 0, sizeof(os_header_t));
@@ -2166,7 +2235,7 @@ static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return osst_write_header(STp, aSRpnt, 1);
}
-static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
+static int __osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt, int ppos)
{
char * name = tape_name(STp);
os_header_t * header;
@@ -2343,7 +2412,7 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
return 1;
}
-static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int position, ppos;
int first, last;
@@ -2398,7 +2467,7 @@ static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return 1;
}
-static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_verify_position(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int frame_position = STp->first_frame_position;
int frame_seq_numbr = STp->frame_seq_number;
@@ -2474,11 +2543,11 @@ static unsigned int osst_parse_firmware_rev (const char * str)
/*
* Configure the OnStream SCII tape drive for default operation
*/
-static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_configure_onstream(struct osst_tape *STp, struct scsi_request ** aSRpnt)
{
unsigned char cmd[MAX_COMMAND_SIZE];
char * name = tape_name(STp);
- Scsi_Request * SRpnt = * aSRpnt;
+ struct scsi_request * SRpnt = * aSRpnt;
osst_mode_parameter_header_t * header;
osst_block_size_page_t * bs;
osst_capabilities_page_t * cp;
@@ -2645,7 +2714,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
/* Step over EOF if it has been inadvertently crossed (ioctl not used because
it messes up the block number). */
-static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
+static int cross_eof(struct osst_tape *STp, struct scsi_request ** aSRpnt, int forward)
{
int result;
char * name = tape_name(STp);
@@ -2674,18 +2743,18 @@ static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
/* Get the tape position. */
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt)
{
- unsigned char scmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int result = 0;
+ unsigned char scmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int result = 0;
+ char * name = tape_name(STp);
/* KG: We want to be able to use it for checking Write Buffer availability
* and thus don't want to risk to overwrite anything. Exchange buffers ... */
char mybuf[24];
char * olddata = STp->buffer->b_data;
int oldsize = STp->buffer->buffer_size;
- char * name = tape_name(STp);
if (STp->ready != ST_READY) return (-EIO);
@@ -2702,13 +2771,12 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
*aSRpnt = SRpnt;
if (STp->buffer->syscall_result)
- result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
+ result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
if (result == -EINVAL)
printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
else {
-
- if (result == -EIO) { /* re-read position */
+ if (result == -EIO) { /* re-read position - this needs to preserve media errors */
unsigned char mysense[16];
memcpy (mysense, SRpnt->sr_sense_buffer, 16);
memset (scmd, 0, MAX_COMMAND_SIZE);
@@ -2716,8 +2784,15 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
STp->timeout, MAX_RETRIES, TRUE);
+#if DEBUG
+ printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
+ name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
+ SRpnt->sr_sense_buffer[2],SRpnt->sr_sense_buffer[12],SRpnt->sr_sense_buffer[13]);
+#endif
if (!STp->buffer->syscall_result)
memcpy (SRpnt->sr_sense_buffer, mysense, 16);
+ else
+ printk(KERN_WARNING "%s:W: Double error in get position\n", name);
}
STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
+ ((STp->buffer)->b_data[5] << 16)
@@ -2739,7 +2814,7 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
#endif
if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
#if DEBUG
- printk(KERN_WARNING "%s:D: Correcting read position %d, %d, %d\n", name,
+ printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
#endif
STp->first_frame_position = STp->last_frame_position;
@@ -2752,14 +2827,14 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
/* Set the tape block */
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
+static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int ppos, int skip)
{
- unsigned char scmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- struct st_partstat * STps;
- int result = 0;
- int pp = (ppos == 3000 && !skip)? 0 : ppos;
- char * name = tape_name(STp);
+ unsigned char scmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ struct st_partstat * STps;
+ int result = 0;
+ int pp = (ppos == 3000 && !skip)? 0 : ppos;
+ char * name = tape_name(STp);
if (STp->ready != ST_READY) return (-EIO);
@@ -2810,7 +2885,7 @@ static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, in
return result;
}
-static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT)
+static int osst_write_trailer(struct osst_tape *STp, struct scsi_request ** aSRpnt, int leave_at_EOT)
{
struct st_partstat * STps = &(STp->ps[STp->partition]);
int result = 0;
@@ -2837,26 +2912,26 @@ out:
/* osst versions of st functions - augmented and stripped to suit OnStream only */
/* Flush the write buffer (never need to write if variable blocksize). */
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt)
{
- int offset, transfer, blks = 0;
- int result = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = *aSRpnt;
- struct st_partstat * STps;
- char * name = tape_name(STp);
+ int offset, transfer, blks = 0;
+ int result = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = *aSRpnt;
+ struct st_partstat * STps;
+ char * name = tape_name(STp);
if ((STp->buffer)->writing) {
if (SRpnt == (STp->buffer)->last_SRpnt)
#if DEBUG
{ printk(OSST_DEB_MSG
- "%s:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", name);
+ "%s:D: aSRpnt points to scsi_request that write_behind_check will release -- cleared\n", name);
#endif
*aSRpnt = SRpnt = NULL;
#if DEBUG
} else if (SRpnt)
printk(OSST_DEB_MSG
- "%s:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", name);
+ "%s:D: aSRpnt does not point to scsi_request that write_behind_check will release -- strange\n", name);
#endif
osst_write_behind_check(STp);
if ((STp->buffer)->syscall_result) {
@@ -2884,9 +2959,9 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
if (offset < OS_DATA_SIZE)
osst_zero_buffer_tail(STp->buffer);
- /* TODO: Error handling! */
if (STp->poll)
- result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
+ result = osst_recover_wait_frame(STp, aSRpnt, 1);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = WRITE_6;
@@ -2925,7 +3000,7 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt)
return (-EBUSY);
@@ -2967,12 +3042,12 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
/* Flush the tape buffer. The tape will be positioned correctly unless
seek_next is true. */
-static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
+static int osst_flush_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt, int seek_next)
{
struct st_partstat * STps;
- int backspace = 0, result = 0;
+ int backspace = 0, result = 0;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
#endif
/*
@@ -3029,13 +3104,13 @@ static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int see
return result;
}
-static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
+static int osst_write_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int synchronous)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int blks;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int blks;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
#endif
if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
@@ -3055,8 +3130,9 @@ static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sync
}
if (STp->poll)
- osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
- /* TODO: Check for an error ! */
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
+ if (osst_recover_wait_frame(STp, aSRpnt, 1))
+ return (-EIO);
// osst_build_stats(STp, &SRpnt);
@@ -3081,7 +3157,7 @@ static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sync
STp->write_pending = 1;
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
- MAX_WRITE_RETRIES, synchronous);
+ MAX_RETRIES, synchronous);
if (!SRpnt)
return (-EBUSY);
*aSRpnt = SRpnt;
@@ -3111,8 +3187,8 @@ static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sync
return 0;
}
-/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */
-static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
+/* Lock or unlock the drive door. Don't use when struct scsi_request allocated. */
+static int do_door_lock(struct osst_tape * STp, int do_lock)
{
int retval, cmd;
@@ -3131,7 +3207,7 @@ static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
}
/* Set the internal state after reset */
-static void reset_state(OS_Scsi_Tape *STp)
+static void reset_state(struct osst_tape *STp)
{
int i;
struct st_partstat *STps;
@@ -3154,16 +3230,16 @@ static void reset_state(OS_Scsi_Tape *STp)
/* Write command */
static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
{
- ssize_t total, retval = 0;
- ssize_t i, do_count, blks, transfer;
- int write_threshold;
- int doing_write = 0;
+ ssize_t total, retval = 0;
+ ssize_t i, do_count, blks, transfer;
+ int write_threshold;
+ int doing_write = 0;
const char __user * b_point;
- Scsi_Request * SRpnt = NULL;
+ struct scsi_request * SRpnt = NULL;
struct st_modedef * STm;
struct st_partstat * STps;
- OS_Scsi_Tape * STp = filp->private_data;
- char * name = tape_name(STp);
+ struct osst_tape * STp = filp->private_data;
+ char * name = tape_name(STp);
if (down_interruptible(&STp->lock))
@@ -3477,14 +3553,14 @@ out:
/* Read command */
static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
{
- ssize_t total, retval = 0;
- ssize_t i, transfer;
- int special;
- struct st_modedef * STm;
+ ssize_t total, retval = 0;
+ ssize_t i, transfer;
+ int special;
+ struct st_modedef * STm;
struct st_partstat * STps;
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp = filp->private_data;
- char * name = tape_name(STp);
+ struct scsi_request * SRpnt = NULL;
+ struct osst_tape * STp = filp->private_data;
+ char * name = tape_name(STp);
if (down_interruptible(&STp->lock))
@@ -3660,8 +3736,7 @@ out:
/* Set the driver options */
-static void osst_log_options(OS_Scsi_Tape *STp, struct st_modedef *STm,
- char *name)
+static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
{
printk(KERN_INFO
"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
@@ -3684,12 +3759,12 @@ static void osst_log_options(OS_Scsi_Tape *STp, struct st_modedef *STm,
}
-static int osst_set_options(OS_Scsi_Tape *STp, long options)
+static int osst_set_options(struct osst_tape *STp, long options)
{
- int value;
- long code;
+ int value;
+ long code;
struct st_modedef * STm;
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
STm = &(STp->modes[STp->current_mode]);
if (!STm->defined) {
@@ -3840,18 +3915,19 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options)
/* Internal ioctl function */
-static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
+static int osst_int_ioctl(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ unsigned int cmd_in, unsigned long arg)
{
- int timeout;
- long ltmp;
- int i, ioctl_result;
- int chg_eof = TRUE;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = * aSRpnt;
- struct st_partstat * STps;
- int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
- int datalen = 0, direction = SCSI_DATA_NONE;
- char * name = tape_name(STp);
+ int timeout;
+ long ltmp;
+ int i, ioctl_result;
+ int chg_eof = TRUE;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = * aSRpnt;
+ struct st_partstat * STps;
+ int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
+ int datalen = 0, direction = SCSI_DATA_NONE;
+ char * name = tape_name(STp);
if (STp->ready != ST_READY && cmd_in != MTLOAD) {
if (STp->ready == ST_NO_TAPE)
@@ -4227,16 +4303,16 @@ os_bypass:
/* Open the device */
static int os_scsi_tape_open(struct inode * inode, struct file * filp)
{
- unsigned short flags;
- int i, b_size, new_session = FALSE, retval = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp;
- struct st_modedef * STm;
+ unsigned short flags;
+ int i, b_size, new_session = FALSE, retval = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = NULL;
+ struct osst_tape * STp;
+ struct st_modedef * STm;
struct st_partstat * STps;
- char * name;
- int dev = TAPE_NR(inode);
- int mode = TAPE_MODE(inode);
+ char * name;
+ int dev = TAPE_NR(inode);
+ int mode = TAPE_MODE(inode);
nonseekable_open(inode, filp);
write_lock(&os_scsi_tapes_lock);
@@ -4327,9 +4403,9 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
memset (cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
if (!SRpnt) {
- retval = (STp->buffer)->syscall_result;
+ retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
goto err_out;
}
if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
@@ -4348,7 +4424,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
cmd[1] = 1;
cmd[4] = 1;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
}
osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
}
@@ -4365,7 +4441,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
cmd[0] = TEST_UNIT_READY;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
(SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
break;
@@ -4386,6 +4462,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
}
new_session = TRUE;
STp->recover_count = 0;
+ STp->abort_count = 0;
}
/*
* if we have valid headers from before, and the drive/tape seem untouched,
@@ -4473,7 +4550,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
cmd[0] = TEST_UNIT_READY;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
(SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
break;
@@ -4588,12 +4665,12 @@ err_out:
/* Flush the tape buffer before close */
static int os_scsi_tape_flush(struct file * filp)
{
- int result = 0, result2;
- OS_Scsi_Tape * STp = filp->private_data;
- struct st_modedef * STm = &(STp->modes[STp->current_mode]);
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- Scsi_Request * SRpnt = NULL;
- char * name = tape_name(STp);
+ int result = 0, result2;
+ struct osst_tape * STp = filp->private_data;
+ struct st_modedef * STm = &(STp->modes[STp->current_mode]);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ struct scsi_request * SRpnt = NULL;
+ char * name = tape_name(STp);
if (file_count(filp) > 1)
return 0;
@@ -4657,14 +4734,19 @@ out:
}
if (SRpnt) scsi_release_request(SRpnt);
- if (STp->recover_count) {
- printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
+ if (STp->abort_count || STp->recover_count) {
+ printk(KERN_INFO "%s:I:", name);
+ if (STp->abort_count)
+ printk(" %d unrecovered errors", STp->abort_count);
+ if (STp->recover_count)
+ printk(" %d recovered errors", STp->recover_count);
if (STp->write_count)
- printk(" %d frames written", STp->write_count);
+ printk(" in %d frames written", STp->write_count);
if (STp->read_count)
- printk(" %d frames read", STp->read_count);
+ printk(" in %d frames read", STp->read_count);
printk("\n");
STp->recover_count = 0;
+ STp->abort_count = 0;
}
STp->write_count = 0;
STp->read_count = 0;
@@ -4676,9 +4758,9 @@ out:
/* Close the device and release it */
static int os_scsi_tape_close(struct inode * inode, struct file * filp)
{
- int result = 0;
- OS_Scsi_Tape * STp = filp->private_data;
- Scsi_Request * SRpnt = NULL;
+ int result = 0;
+ struct osst_tape * STp = filp->private_data;
+ struct scsi_request * SRpnt = NULL;
if (SRpnt) scsi_release_request(SRpnt);
@@ -4703,14 +4785,14 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp)
static int osst_ioctl(struct inode * inode,struct file * file,
unsigned int cmd_in, unsigned long arg)
{
- int i, cmd_nr, cmd_type, retval = 0;
- unsigned int blk;
- struct st_modedef * STm;
+ int i, cmd_nr, cmd_type, retval = 0;
+ unsigned int blk;
+ struct st_modedef * STm;
struct st_partstat * STps;
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp = file->private_data;
- char * name = tape_name(STp);
- void __user *p = (void __user *)arg;
+ struct scsi_request * SRpnt = NULL;
+ struct osst_tape * STp = file->private_data;
+ char * name = tape_name(STp);
+ void __user * p = (void __user *)arg;
if (down_interruptible(&STp->lock))
return -ERESTARTSYS;
@@ -5039,18 +5121,18 @@ out:
/* Memory handling routines */
/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
-static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
+static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
{
int i, priority;
- OSST_buffer *tb;
+ struct osst_buffer *tb;
if (from_initialization)
priority = GFP_ATOMIC;
else
priority = GFP_KERNEL;
- i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
- tb = (OSST_buffer *)kmalloc(i, priority);
+ i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
+ tb = (struct osst_buffer *)kmalloc(i, priority);
if (!tb) {
printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
return NULL;
@@ -5071,7 +5153,7 @@ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int
}
/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
-static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
+static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
{
int segs, nbr, max_segs, b_size, priority, order, got;
@@ -5087,12 +5169,10 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
if (nbr <= 2)
return FALSE;
- priority = GFP_KERNEL;
+ priority = GFP_KERNEL /* | __GFP_NOWARN */;
if (need_dma)
priority |= GFP_DMA;
- priority |= __GFP_NOWARN;
-
/* Try to allocate the first segment up to OS_DATA_SIZE and the others
big enough to reach the goal (code assumes no segments in place) */
for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
@@ -5150,7 +5230,7 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
/* Release the segments */
-static void normalize_buffer(OSST_buffer *STbuffer)
+static void normalize_buffer(struct osst_buffer *STbuffer)
{
int i, order, b_size;
@@ -5174,7 +5254,7 @@ static void normalize_buffer(OSST_buffer *STbuffer)
/* Move data from the user buffer to the tape buffer. Returns zero (success) or
negative error code. */
-static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_count)
+static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
{
int i, cnt, res, offset;
@@ -5207,7 +5287,7 @@ static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_c
/* Move data from the tape buffer to the user buffer. Returns zero (success) or
negative error code. */
-static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
+static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
{
int i, cnt, res, offset;
@@ -5239,7 +5319,7 @@ static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
/* Sets the tail of the buffer after fill point to zero.
Returns zero (success) or negative error code. */
-static int osst_zero_buffer_tail(OSST_buffer *st_bp)
+static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
{
int i, offset, do_count, cnt;
@@ -5267,7 +5347,7 @@ static int osst_zero_buffer_tail(OSST_buffer *st_bp)
/* Copy a osst 32K chunk of memory into the buffer.
Returns zero (success) or negative error code. */
-static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
{
int i, cnt, do_count = OS_DATA_SIZE;
@@ -5288,7 +5368,7 @@ static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
/* Copy a osst 32K chunk of memory from the buffer.
Returns zero (success) or negative error code. */
-static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
{
int i, cnt, do_count = OS_DATA_SIZE;
@@ -5406,18 +5486,163 @@ static struct osst_support_data support_list[] = {
}
/*
+ * sysfs support for osst driver parameter information
+ */
+
+static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
+
+static void osst_create_driverfs_files(struct device_driver *driverfs)
+{
+ driver_create_file(driverfs, &driver_attr_version);
+}
+
+static void osst_remove_driverfs_files(struct device_driver *driverfs)
+{
+ driver_remove_file(driverfs, &driver_attr_version);
+}
+
+/*
+ * sysfs support for accessing ADR header information
+ */
+
+static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+
+static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
+
+static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
+
+static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
+
+static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
+
+static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+
+static struct class_simple * osst_sysfs_class;
+
+static int osst_sysfs_valid = 0;
+
+static void osst_sysfs_init(void)
+{
+ osst_sysfs_class = class_simple_create(THIS_MODULE, "onstream_tape");
+ if ( IS_ERR(osst_sysfs_class) )
+ printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
+ else
+ osst_sysfs_valid = TRUE;
+}
+
+static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+{
+ struct class_device *osst_class_member;
+
+ if (!osst_sysfs_valid) return;
+
+ osst_class_member = class_simple_device_add(osst_sysfs_class, dev, device, "%s", name);
+ if (IS_ERR(osst_class_member)) {
+ printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+ return;
+ }
+ class_set_devdata(osst_class_member, STp);
+ class_device_create_file(osst_class_member, &class_device_attr_ADR_rev);
+ class_device_create_file(osst_class_member, &class_device_attr_media_version);
+ class_device_create_file(osst_class_member, &class_device_attr_capacity);
+ class_device_create_file(osst_class_member, &class_device_attr_BOT_frame);
+ class_device_create_file(osst_class_member, &class_device_attr_EOD_frame);
+ class_device_create_file(osst_class_member, &class_device_attr_file_count);
+}
+
+static void osst_sysfs_destroy(dev_t dev)
+{
+ if (!osst_sysfs_valid) return;
+
+ class_simple_device_remove(dev);
+}
+
+static void osst_sysfs_cleanup(void)
+{
+ if (osst_sysfs_valid) {
+ class_simple_destroy(osst_sysfs_class);
+ osst_sysfs_valid = 0;
+ }
+}
+
+/*
* osst startup / cleanup code
*/
static int osst_probe(struct device *dev)
{
- Scsi_Device * SDp = to_scsi_device(dev);
- OS_Scsi_Tape * tpnt;
- struct st_modedef * STm;
- struct st_partstat * STps;
- OSST_buffer * buffer;
- struct gendisk * drive;
- int i, mode, dev_num;
+ Scsi_Device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ struct osst_buffer * buffer;
+ struct gendisk * drive;
+ int i, mode, dev_num;
if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
return -ENODEV;
@@ -5432,7 +5657,7 @@ static int osst_probe(struct device *dev)
write_lock(&os_scsi_tapes_lock);
if (os_scsi_tapes == NULL) {
os_scsi_tapes =
- (OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
+ (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
GFP_ATOMIC);
if (os_scsi_tapes == NULL) {
write_unlock(&os_scsi_tapes_lock);
@@ -5453,14 +5678,14 @@ static int osst_probe(struct device *dev)
if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
dev_num = i;
- /* allocate a OS_Scsi_Tape for this device */
- tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
+ /* allocate a struct osst_tape for this device */
+ tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
goto out_put_disk;
}
- memset(tpnt, 0, sizeof(OS_Scsi_Tape));
+ memset(tpnt, 0, sizeof(struct osst_tape));
/* allocate a buffer for this device */
i = SDp->host->sg_tablesize;
@@ -5545,7 +5770,14 @@ static int osst_probe(struct device *dev)
init_MUTEX(&tpnt->lock);
osst_nr_dev++;
write_unlock(&os_scsi_tapes_lock);
-
+ {
+ char name[8];
+ /* Rewind entry */
+ osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
+ /* No-rewind entry */
+ snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
+ osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+ }
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
/* Rewind entry */
devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
@@ -5572,8 +5804,8 @@ out_put_disk:
static int osst_remove(struct device *dev)
{
- Scsi_Device * SDp = to_scsi_device(dev);
- OS_Scsi_Tape * tpnt;
+ Scsi_Device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
int i, mode;
if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
@@ -5582,6 +5814,8 @@ static int osst_remove(struct device *dev)
write_lock(&os_scsi_tapes_lock);
for(i=0; i < osst_max_dev; i++) {
if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
tpnt->device = NULL;
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
@@ -5610,11 +5844,14 @@ static int __init init_osst(void)
printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
validate_options();
-
+ osst_sysfs_init();
+
if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
+ osst_sysfs_cleanup();
return 1;
}
+ osst_create_driverfs_files(&osst_template.gendrv);
return 0;
}
@@ -5622,10 +5859,12 @@ static int __init init_osst(void)
static void __exit exit_osst (void)
{
int i;
- OS_Scsi_Tape * STp;
+ struct osst_tape * STp;
+ osst_remove_driverfs_files(&osst_template.gendrv);
scsi_unregister_driver(&osst_template.gendrv);
unregister_chrdev(OSST_MAJOR, "osst");
+ osst_sysfs_cleanup();
if (os_scsi_tapes) {
for (i=0; i < osst_max_dev; ++i) {
diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h
index 84bbc591a8ce3c..1561d4ded72bc9 100644
--- a/drivers/scsi/osst.h
+++ b/drivers/scsi/osst.h
@@ -1,5 +1,5 @@
/*
- * $Header: /cvsroot/osst/Driver/osst.h,v 1.14 2003/12/14 14:34:38 wriede Exp $
+ * $Header: /cvsroot/osst/Driver/osst.h,v 1.16 2005/01/01 21:13:35 wriede Exp $
*/
#include <asm/byteorder.h>
@@ -70,7 +70,7 @@ typedef struct {
#define BLOCK_SIZE_PAGE_LENGTH 4
#define BUFFER_FILLING_PAGE 0x33
-#define BUFFER_FILLING_PAGE_LENGTH
+#define BUFFER_FILLING_PAGE_LENGTH 4
#define VENDOR_IDENT_PAGE 0x36
#define VENDOR_IDENT_PAGE_LENGTH 8
@@ -508,7 +508,7 @@ typedef struct os_header_s {
//#define OSST_MAX_SG 2
/* The OnStream tape buffer descriptor. */
-typedef struct {
+struct osst_buffer {
unsigned char in_use;
unsigned char dma; /* DMA-able buffer */
int buffer_size;
@@ -525,16 +525,16 @@ typedef struct {
unsigned short sg_segs; /* number of segments in s/g list */
unsigned short orig_sg_segs; /* number of segments allocated at first try */
struct scatterlist sg[1]; /* MUST BE last item */
-} OSST_buffer;
+} ;
/* The OnStream tape drive descriptor */
-typedef struct {
+struct osst_tape {
struct scsi_driver *driver;
unsigned capacity;
Scsi_Device* device;
struct semaphore lock; /* for serialization */
struct completion wait; /* for SCSI commands */
- OSST_buffer * buffer;
+ struct osst_buffer * buffer;
/* Drive characteristics */
unsigned char omit_blklims;
@@ -577,6 +577,7 @@ typedef struct {
int min_block;
int max_block;
int recover_count; /* from tape opening */
+ int abort_count;
int write_count;
int read_count;
int recover_erreg; /* from last status call */
@@ -623,7 +624,7 @@ typedef struct {
unsigned char last_sense[16];
#endif
struct gendisk *drive;
-} OS_Scsi_Tape;
+} ;
/* Values of write_type */
#define OS_WRITE_DATA 0
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index c0b9e1cc20cac7..97d69da43825d1 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -145,7 +145,6 @@ static dev_link_t *aha152x_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &aha152x_event;
client_reg.EventMask =
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
@@ -347,10 +346,7 @@ static int __init init_aha152x_cs(void)
static void __exit exit_aha152x_cs(void)
{
pcmcia_unregister_driver(&aha152x_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- aha152x_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_aha152x_cs);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index c841137e73a976..343b67578706dc 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -131,7 +131,6 @@ static dev_link_t *fdomain_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &fdomain_event;
client_reg.EventMask =
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
@@ -328,10 +327,7 @@ static int __init init_fdomain_cs(void)
static void __exit exit_fdomain_cs(void)
{
pcmcia_unregister_driver(&fdomain_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- fdomain_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_fdomain_cs);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 0d0bbd26a5f254..8aae1ae9fa9b8c 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1672,7 +1672,6 @@ static dev_link_t *nsp_cs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -2194,10 +2193,9 @@ static void __exit nsp_cs_exit(void)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver);
+ BUG_ON(dev_list != NULL);
#else
unregister_pcmcia_driver(&dev_info);
-#endif
-
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG) {
@@ -2205,6 +2203,7 @@ static void __exit nsp_cs_exit(void)
}
nsp_cs_detach(dev_list);
}
+#endif
}
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 584b5131404152..4b66969ace4af0 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -212,7 +212,6 @@ static dev_link_t *qlogic_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &qlogic_event;
client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.Version = 0x0210;
@@ -432,10 +431,7 @@ static int __init init_qlogic_cs(void)
static void __exit exit_qlogic_cs(void)
{
pcmcia_unregister_driver(&qlogic_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- qlogic_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 84d06345614ede..be3d3369cae69c 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -995,7 +995,6 @@ SYM53C500_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &SYM53C500_event;
client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index f1eb31b955796f..df89d2b7c30fea 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -3400,7 +3400,8 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
+ /* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
+ mmiowb();
out:
if (status)
@@ -3668,7 +3669,8 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
+ /* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
+ mmiowb();
out:
if (status)
@@ -3778,9 +3780,21 @@ qla1280_isp_cmd(struct scsi_qla_host *ha)
} else
ha->request_ring_ptr++;
- /* Set chip new ring index. */
+ /*
+ * Update request index to mailbox4 (Request Queue In).
+ * The mmiowb() ensures that this write is ordered with writes by other
+ * CPUs. Without the mmiowb(), it is possible for the following:
+ * CPUA posts write of index 5 to mailbox4
+ * CPUA releases host lock
+ * CPUB acquires host lock
+ * CPUB posts write of index 6 to mailbox4
+ * On PCI bus, order reverses and write of 6 posts, then index 5,
+ * causing chip to issue full queue of stale commands
+ * The mmiowb() prevents future writes from crossing the barrier.
+ * See Documentation/DocBook/deviceiobook.tmpl for more information.
+ */
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
+ mmiowb();
LEAVE("qla1280_isp_cmd");
}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 80e75bd5a43902..2952d9e159fb7c 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -71,6 +71,8 @@ static struct pci_device_id sil_pci_tbl[] = {
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
+ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ } /* terminate list */
};
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 82c7b0ab404739..63e5224eee0a0c 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1083,6 +1083,28 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost,
EXPORT_SYMBOL(__scsi_iterate_devices);
/**
+ * starget_for_each_device - helper to walk all devices of a target
+ * @starget: target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost. The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+ void (*fn)(struct scsi_device *, void *))
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, shost) {
+ if ((sdev->channel == starget->channel) &&
+ (sdev->id == starget->id))
+ fn(sdev, data);
+ }
+}
+EXPORT_SYMBOL(starget_for_each_device);
+
+/**
* scsi_device_lookup - find a device given the host (UNLOCKED)
* @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 73660628b520a2..38f165070c9434 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1782,31 +1782,29 @@ scsi_device_resume(struct scsi_device *sdev)
}
EXPORT_SYMBOL(scsi_device_resume);
-static int
-device_quiesce_fn(struct device *dev, void *data)
+static void
+device_quiesce_fn(struct scsi_device *sdev, void *data)
{
- scsi_device_quiesce(to_scsi_device(dev));
- return 0;
+ scsi_device_quiesce(sdev);
}
void
scsi_target_quiesce(struct scsi_target *starget)
{
- device_for_each_child(&starget->dev, NULL, device_quiesce_fn);
+ starget_for_each_device(starget, NULL, device_quiesce_fn);
}
EXPORT_SYMBOL(scsi_target_quiesce);
-static int
-device_resume_fn(struct device *dev, void *data)
+static void
+device_resume_fn(struct scsi_device *sdev, void *data)
{
- scsi_device_resume(to_scsi_device(dev));
- return 0;
+ scsi_device_resume(sdev);
}
void
scsi_target_resume(struct scsi_target *starget)
{
- device_for_each_child(&starget->dev, NULL, device_resume_fn);
+ starget_for_each_device(starget, NULL, device_resume_fn);
}
EXPORT_SYMBOL(scsi_target_resume);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 926cec15e5f2d8..1aca210eabd1a3 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -270,6 +270,16 @@ static int fc_setup_host_transport_attrs(struct Scsi_Host *shost)
sizeof(fc_host_symbolic_name(shost)));
fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
fc_host_maxframe_size(shost) = -1;
+ memset(fc_host_hardware_version(shost), 0,
+ sizeof(fc_host_hardware_version(shost)));
+ memset(fc_host_firmware_version(shost), 0,
+ sizeof(fc_host_firmware_version(shost)));
+ memset(fc_host_serial_number(shost), 0,
+ sizeof(fc_host_serial_number(shost)));
+ memset(fc_host_opt_rom_version(shost), 0,
+ sizeof(fc_host_opt_rom_version(shost)));
+ memset(fc_host_driver_version(shost), 0,
+ sizeof(fc_host_driver_version(shost)));
fc_host_port_id(shost) = -1;
fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
@@ -536,6 +546,11 @@ fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
+fc_private_host_rd_attr(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
+fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
+fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
+fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
/* Dynamic Host Attributes */
@@ -772,6 +787,11 @@ fc_attach_transport(struct fc_function_template *ft)
SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
+ SETUP_HOST_ATTRIBUTE_RD(hardware_version);
+ SETUP_HOST_ATTRIBUTE_RD(firmware_version);
+ SETUP_HOST_ATTRIBUTE_RD(serial_number);
+ SETUP_HOST_ATTRIBUTE_RD(opt_rom_version);
+ SETUP_HOST_ATTRIBUTE_RD(driver_version);
SETUP_HOST_ATTRIBUTE_RD(port_id);
SETUP_HOST_ATTRIBUTE_RD(port_type);
@@ -808,10 +828,9 @@ EXPORT_SYMBOL(fc_release_transport);
* @dev: scsi device
* @data: unused
**/
-static int fc_device_block(struct device *dev, void *data)
+static void fc_device_block(struct scsi_device *sdev, void *data)
{
- scsi_internal_device_block(to_scsi_device(dev));
- return 0;
+ scsi_internal_device_block(sdev);
}
/**
@@ -819,10 +838,9 @@ static int fc_device_block(struct device *dev, void *data)
* @dev: scsi device
* @data: unused
**/
-static int fc_device_unblock(struct device *dev, void *data)
+static void fc_device_unblock(struct scsi_device *sdev, void *data)
{
- scsi_internal_device_unblock(to_scsi_device(dev));
- return 0;
+ scsi_internal_device_unblock(sdev);
}
/**
@@ -842,7 +860,7 @@ static void fc_timeout_blocked_tgt(void *data)
* unblock this device, then IO errors will probably
* result if the host still isn't ready.
*/
- device_for_each_child(&starget->dev, NULL, fc_device_unblock);
+ starget_for_each_device(starget, NULL, fc_device_unblock);
}
/**
@@ -870,7 +888,7 @@ fc_target_block(struct scsi_target *starget)
if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
return -EINVAL;
- device_for_each_child(&starget->dev, NULL, fc_device_block);
+ starget_for_each_device(starget, NULL, fc_device_block);
/* The scsi lld blocks this target for the timeout period only. */
schedule_delayed_work(work, timeout * HZ);
@@ -901,7 +919,7 @@ fc_target_unblock(struct scsi_target *starget)
if (cancel_delayed_work(&fc_starget_dev_loss_work(starget)))
flush_scheduled_work();
- device_for_each_child(&starget->dev, NULL, fc_device_unblock);
+ starget_for_each_device(starget, NULL, fc_device_unblock);
}
EXPORT_SYMBOL(fc_target_unblock);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index f01133b4c580bf..d8bdde36fe448c 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -31,6 +31,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_request.h>
+#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
@@ -378,10 +379,16 @@ static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR,
#define DV_RETRIES 3 /* should only need at most
* two cc/ua clears */
+enum spi_compare_returns {
+ SPI_COMPARE_SUCCESS,
+ SPI_COMPARE_FAILURE,
+ SPI_COMPARE_SKIP_TEST,
+};
+
/* This is for read/write Domain Validation: If the device supports
* an echo buffer, we do read/write tests to it */
-static int
+static enum spi_compare_returns
spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
u8 *ptr, const int retries)
{
@@ -438,9 +445,23 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
scsi_wait_req(sreq, spi_write_buffer, buffer, len,
DV_TIMEOUT, DV_RETRIES);
if(sreq->sr_result || !scsi_device_online(sdev)) {
+ struct scsi_sense_hdr sshdr;
+
scsi_device_set_state(sdev, SDEV_QUIESCE);
+ if (scsi_request_normalize_sense(sreq, &sshdr)
+ && sshdr.sense_key == ILLEGAL_REQUEST
+ /* INVALID FIELD IN CDB */
+ && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
+ /* This would mean that the drive lied
+ * to us about supporting an echo
+ * buffer (unfortunately some Western
+ * Digital drives do precisely this)
+ */
+ return SPI_COMPARE_SKIP_TEST;
+
+
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
- return 0;
+ return SPI_COMPARE_FAILURE;
}
memset(ptr, 0, len);
@@ -451,14 +472,14 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
scsi_device_set_state(sdev, SDEV_QUIESCE);
if (memcmp(buffer, ptr, len) != 0)
- return 0;
+ return SPI_COMPARE_FAILURE;
}
- return 1;
+ return SPI_COMPARE_SUCCESS;
}
/* This is for the simplest form of Domain Validation: a read test
* on the inquiry data from the device */
-static int
+static enum spi_compare_returns
spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
u8 *ptr, const int retries)
{
@@ -480,7 +501,7 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
if(sreq->sr_result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
- return 0;
+ return SPI_COMPARE_FAILURE;
}
/* If we don't have the inquiry data already, the
@@ -493,24 +514,28 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
if (memcmp(buffer, ptr, len) != 0)
/* failure */
- return 0;
+ return SPI_COMPARE_FAILURE;
}
- return 1;
+ return SPI_COMPARE_SUCCESS;
}
-static int
+static enum spi_compare_returns
spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
- int (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
+ enum spi_compare_returns
+ (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
{
struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
struct scsi_device *sdev = sreq->sr_device;
int period = 0, prevperiod = 0;
+ enum spi_compare_returns retval;
for (;;) {
int newperiod;
- if (compare_fn(sreq, buffer, ptr, DV_LOOPS))
- /* Successful DV */
+ retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
+
+ if (retval == SPI_COMPARE_SUCCESS
+ || retval == SPI_COMPARE_SKIP_TEST)
break;
/* OK, retrain, fallback */
@@ -527,13 +552,13 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
/* Total failure; set to async and return */
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
DV_SET(offset, 0);
- return 0;
+ return SPI_COMPARE_FAILURE;
}
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
DV_SET(period, period);
prevperiod = period;
}
- return 1;
+ return retval;
}
static int
@@ -599,7 +624,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
DV_SET(offset, 0);
DV_SET(width, 0);
- if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) {
+ if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
+ != SPI_COMPARE_SUCCESS) {
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
return;
@@ -609,9 +635,10 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if (i->f->set_width && sdev->wdtr) {
i->f->set_width(sdev->sdev_target, 1);
- if (!spi_dv_device_compare_inquiry(sreq, buffer,
+ if (spi_dv_device_compare_inquiry(sreq, buffer,
buffer + len,
- DV_LOOPS)) {
+ DV_LOOPS)
+ != SPI_COMPARE_SUCCESS) {
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
i->f->set_width(sdev->sdev_target, 0);
}
@@ -624,31 +651,39 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if(!sdev->ppr && !sdev->sdtr)
return;
- /* now set up to the maximum */
- DV_SET(offset, 255);
- DV_SET(period, 1);
- if (!spi_dv_retrain(sreq, buffer, buffer + len,
- spi_dv_device_compare_inquiry))
- return;
-
- /* OK, now we have our initial speed set by the read only inquiry
- * test, now try an echo buffer test (if the device allows it) */
+ /* see if the device has an echo buffer. If it does we can
+ * do the SPI pattern write tests */
len = 0;
if (sdev->ppr)
len = spi_dv_device_get_echo_buffer(sreq, buffer);
+ retry:
+
+ /* now set up to the maximum */
+ DV_SET(offset, 255);
+ DV_SET(period, 1);
+
if (len == 0) {
SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
+ spi_dv_retrain(sreq, buffer, buffer + len,
+ spi_dv_device_compare_inquiry);
return;
}
+
if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
- spi_dv_retrain(sreq, buffer, buffer + len,
- spi_dv_device_echo_buffer);
+ if (spi_dv_retrain(sreq, buffer, buffer + len,
+ spi_dv_device_echo_buffer)
+ == SPI_COMPARE_SKIP_TEST) {
+ /* OK, the stupid drive can't do a write echo buffer
+ * test after all, fall back to the read tests */
+ len = 0;
+ goto retry;
+ }
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0d10f106701d67..86ee1e14358032 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1082,9 +1082,12 @@ repeat:
" READ CAPACITY(16).\n", diskname);
longrc = 1;
goto repeat;
- } else {
- printk(KERN_ERR "%s: too big for kernel. Assuming maximum 2Tb\n", diskname);
}
+ printk(KERN_ERR "%s: too big for this kernel. Use a "
+ "kernel compiled with support for large block "
+ "devices.\n", diskname);
+ sdkp->capacity = 0;
+ goto got_data;
}
sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
(buffer[1] << 16) |
diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h
index b0f58e72570b40..30bb92c90fc614 100644
--- a/drivers/scsi/sym53c8xx_2/sym_conf.h
+++ b/drivers/scsi/sym53c8xx_2/sym_conf.h
@@ -79,14 +79,6 @@
/* #define SYM_CONF_IARB_SUPPORT */
/*
- * Number of lists for the optimization of the IO timeout handling.
- * Not used under FreeBSD and Linux.
- */
-#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
-#define SYM_CONF_TIMEOUT_ORDER_MAX (8)
-#endif
-
-/*
* Only relevant if IARB support configured.
* - Max number of successive settings of IARB hints.
* - Set IARB on arbitration lost.
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 2e1d89f5de3575..d27071dcb28bb2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,30 +40,10 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.1.18m"
+#define SYM_VERSION "2.1.18n"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
- * PCI device identifier of SYMBIOS chips.
- */
-#define PCI_ID_SYM53C810 PCI_DEVICE_ID_NCR_53C810
-#define PCI_ID_SYM53C810AP PCI_DEVICE_ID_LSI_53C810AP
-#define PCI_ID_SYM53C815 PCI_DEVICE_ID_NCR_53C815
-#define PCI_ID_SYM53C820 PCI_DEVICE_ID_NCR_53C820
-#define PCI_ID_SYM53C825 PCI_DEVICE_ID_NCR_53C825
-#define PCI_ID_SYM53C860 PCI_DEVICE_ID_NCR_53C860
-#define PCI_ID_SYM53C875 PCI_DEVICE_ID_NCR_53C875
-#define PCI_ID_SYM53C875_2 PCI_DEVICE_ID_NCR_53C875J
-#define PCI_ID_SYM53C885 PCI_DEVICE_ID_NCR_53C885
-#define PCI_ID_SYM53C895 PCI_DEVICE_ID_NCR_53C895
-#define PCI_ID_SYM53C896 PCI_DEVICE_ID_NCR_53C896
-#define PCI_ID_SYM53C895A PCI_DEVICE_ID_LSI_53C895A
-#define PCI_ID_SYM53C875A PCI_DEVICE_ID_LSI_53C875A
-#define PCI_ID_LSI53C1010_33 PCI_DEVICE_ID_LSI_53C1010_33
-#define PCI_ID_LSI53C1010_66 PCI_DEVICE_ID_LSI_53C1010_66
-#define PCI_ID_LSI53C1510D PCI_DEVICE_ID_LSI_53C1510
-
-/*
* SYM53C8XX device features descriptor.
*/
struct sym_pci_chip {
@@ -764,27 +744,27 @@ struct sym_tblsel {
#define M_RESTORE_DP RESTORE_POINTERS
#define M_DISCONNECT DISCONNECT
#define M_ID_ERROR INITIATOR_ERROR
-#define M_ABORT ABORT
+#define M_ABORT ABORT_TASK_SET
#define M_REJECT MESSAGE_REJECT
#define M_NOOP NOP
#define M_PARITY MSG_PARITY_ERROR
#define M_LCOMPLETE LINKED_CMD_COMPLETE
#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
-#define M_RESET BUS_DEVICE_RESET
-#define M_ABORT_TAG (0x0d)
-#define M_CLEAR_QUEUE (0x0e)
+#define M_RESET TARGET_RESET
+#define M_ABORT_TAG ABORT_TASK
+#define M_CLEAR_QUEUE CLEAR_TASK_SET
#define M_INIT_REC INITIATE_RECOVERY
#define M_REL_REC RELEASE_RECOVERY
#define M_TERMINATE (0x11)
#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
#define M_ORDERED_TAG ORDERED_QUEUE_TAG
-#define M_IGN_RESIDUE (0x23)
+#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
#define M_X_SYNC_REQ EXTENDED_SDTR
#define M_X_WIDE_REQ EXTENDED_WDTR
-#define M_X_PPR_REQ (0x04)
+#define M_X_PPR_REQ EXTENDED_PPR
/*
* PPR protocol options
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index c30d5cd65e97e1..1c6d0d182d2c0c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -223,13 +223,13 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
- if (!(np->device_id == PCI_ID_LSI53C1010_66 &&
+ if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
np->revision_id < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
- if (!(np->device_id == PCI_ID_LSI53C1010_33 &&
+ if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
/* np->revision_id < 0xff */ 1)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 4c64761be9c60c..c389e55c320454 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -55,6 +55,15 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
+/* SPARC just has to be different ... */
+#ifdef __sparc__
+#define IRQ_FMT "%s"
+#define IRQ_PRM(x) __irq_itoa(x)
+#else
+#define IRQ_FMT "%d"
+#define IRQ_PRM(x) (x)
+#endif
+
struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
unsigned int sym_debug_flags = 0;
@@ -147,7 +156,7 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
}
/* This lock protects only the memory allocation/free. */
-spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
static struct scsi_transport_template *sym2_transport_template = NULL;
@@ -285,7 +294,7 @@ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
ccb->scsi_done(ccb);
}
-void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
+static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
{
sym_set_cam_status(ccb, cam_status);
sym_xpt_done(np, ccb);
@@ -379,7 +388,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
/*
* Bounce back the sense data to user.
*/
- bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
+ memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
memcpy(csio->sense_buffer, cp->sns_bbuf,
min(sizeof(csio->sense_buffer),
(size_t)SYM_SNS_BBUF_LEN));
@@ -513,7 +522,7 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
}
/*
- * Retreive the target descriptor.
+ * Retrieve the target descriptor.
*/
tp = &np->target[ccb->device->id];
@@ -1277,7 +1286,7 @@ static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
int arg_len;
u_long target;
- bzero(uc, sizeof(*uc));
+ memset(uc, 0, sizeof(*uc));
if (len > 0 && ptr[len-1] == '\n')
--len;
@@ -1467,18 +1476,8 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
"revision id 0x%x\n",
np->s.chip_name, np->device_id, np->revision_id);
- copy_info(&info, "At PCI address %s, "
-#ifdef __sparc__
- "IRQ %s\n",
-#else
- "IRQ %d\n",
-#endif
- pci_name(np->s.device),
-#ifdef __sparc__
- __irq_itoa(np->s.irq));
-#else
- (int) np->s.irq);
-#endif
+ copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
+ pci_name(np->s.device), IRQ_PRM(np->s.irq));
copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
(int) (np->minsync_dt ? np->minsync_dt : np->minsync),
np->maxwide ? "Wide" : "Narrow",
@@ -1558,32 +1557,23 @@ static void sym_free_resources(struct sym_hcb *np)
*/
static int sym_setup_bus_dma_mask(struct sym_hcb *np)
{
-#if SYM_CONF_DMA_ADDRESSING_MODE == 0
- if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
- goto out_err32;
-#else
+#if SYM_CONF_DMA_ADDRESSING_MODE > 0
#if SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define PciDmaMask 0xffffffffffULL
+#define DMA_DAC_MASK 0x000000ffffffffffULL /* 40-bit */
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-#define PciDmaMask 0xffffffffffffffffULL
+#define DMA_DAC_MASK DMA_64BIT_MASK
#endif
- if (np->features & FE_DAC) {
- if (!pci_set_dma_mask(np->s.device, PciDmaMask)) {
- np->use_dac = 1;
- printf_info("%s: using 64 bit DMA addressing\n",
- sym_name(np));
- } else {
- if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
- goto out_err32;
- }
+ if ((np->features & FE_DAC) &&
+ !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
+ np->use_dac = 1;
+ return 0;
}
-#undef PciDmaMask
#endif
- return 0;
-out_err32:
- printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n",
- sym_name(np));
+ if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
+ return 0;
+
+ printf_warning("%s: No suitable DMA available\n", sym_name(np));
return -1;
}
@@ -1606,19 +1596,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
struct sym_fw *fw;
printk(KERN_INFO
- "sym%d: <%s> rev 0x%x at pci %s "
-#ifdef __sparc__
- "irq %s\n",
-#else
- "irq %d\n",
-#endif
+ "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
unit, dev->chip.name, dev->chip.revision_id,
- pci_name(dev->pdev),
-#ifdef __sparc__
- __irq_itoa(dev->s.irq));
-#else
- dev->s.irq);
-#endif
+ pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
/*
* Get the firmware for this chip.
@@ -1672,9 +1652,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
- /*
- * Ask/tell the system about DMA addressing.
- */
if (sym_setup_bus_dma_mask(np))
goto attach_failed;
@@ -2010,7 +1987,7 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device)
* the preset SCSI ID (which may be zero) must be read in from
* a special configuration space register of the 875.
*/
-void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
+static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
{
int slot;
u8 tmp;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index df1b9af12d877c..7cfb1b21b69ae5 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -58,13 +58,6 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
-#ifndef bzero
-#define bzero(d, n) memset((d), 0, (n))
-#endif
-
-/*
- * General driver includes.
- */
#include "sym_conf.h"
#include "sym_defs.h"
#include "sym_misc.h"
@@ -123,14 +116,6 @@
typedef struct sym_tcb *tcb_p;
typedef struct sym_lcb *lcb_p;
typedef struct sym_ccb *ccb_p;
-typedef struct sym_hcb *hcb_p;
-
-/*
- * Define a reference to the O/S dependent IO request.
- */
-typedef struct scsi_cmnd *cam_ccb_p; /* Generic */
-typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
-
/*
* IO functions definition for big/little endian CPU support.
@@ -525,7 +510,7 @@ sym_get_cam_status(struct scsi_cmnd *ccb)
/*
* Async handler for negotiations.
*/
-void sym_xpt_async_nego_wide(hcb_p np, int target);
+void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
#define sym_xpt_async_nego_sync(np, target) \
sym_announce_transfer_rate(np, target)
#define sym_xpt_async_nego_ppr(np, target) \
@@ -534,14 +519,14 @@ void sym_xpt_async_nego_wide(hcb_p np, int target);
/*
* Build CAM result for a successful IO and for a failed IO.
*/
-static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
+static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
{
struct scsi_cmnd *cmd = cp->cam_ccb;
cmd->resid = resid;
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
}
-void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
+void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
/*
* Other O/S specific methods.
@@ -549,13 +534,12 @@ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
#define sym_cam_target_id(ccb) (ccb)->target
#define sym_cam_target_lun(ccb) (ccb)->lun
#define sym_freeze_cam_ccb(ccb) do { ; } while (0)
-void sym_xpt_done(hcb_p np, cam_ccb_p ccb);
-void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
+void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
void sym_print_addr (ccb_p cp);
-void sym_xpt_async_bus_reset(hcb_p np);
-void sym_xpt_async_sent_bdr(hcb_p np, int target);
-int sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
-void sym_log_bus_error(hcb_p np);
-void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid);
+void sym_xpt_async_bus_reset(struct sym_hcb *np);
+void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
+int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+void sym_log_bus_error(struct sym_hcb *np);
+void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
#endif /* SYM_GLUE_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 383f48b1014e84..8b7aa921e487aa 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -47,14 +47,14 @@
/*
* Needed function prototypes.
*/
-static void sym_int_ma (hcb_p np);
-static void sym_int_sir (hcb_p np);
-static ccb_p sym_alloc_ccb(hcb_p np);
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa);
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
-static void sym_complete_error (hcb_p np, ccb_p cp);
-static void sym_complete_ok (hcb_p np, ccb_p cp);
-static int sym_compute_residual(hcb_p np, ccb_p cp);
+static void sym_int_ma (struct sym_hcb *np);
+static void sym_int_sir (struct sym_hcb *np);
+static ccb_p sym_alloc_ccb(struct sym_hcb *np);
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
+static void sym_complete_error (struct sym_hcb *np, ccb_p cp);
+static void sym_complete_ok (struct sym_hcb *np, ccb_p cp);
+static int sym_compute_residual(struct sym_hcb *np, ccb_p cp);
/*
* Returns the name of this driver.
@@ -86,12 +86,12 @@ static void sym_printl_hex (char *label, u_char *p, int n)
* Print something which allows to retrieve the controler type,
* unit, target, lun concerned by a kernel message.
*/
-static void sym_print_target (hcb_p np, int target)
+static void sym_print_target (struct sym_hcb *np, int target)
{
printf ("%s:%d:", sym_name(np), target);
}
-static void sym_print_lun(hcb_p np, int target, int lun)
+static void sym_print_lun(struct sym_hcb *np, int target, int lun)
{
printf ("%s:%d:%d:", sym_name(np), target, lun);
}
@@ -126,7 +126,7 @@ static void sym_print_msg (ccb_p cp, char *label, u_char *msg)
printf (".\n");
}
-static void sym_print_nego_msg (hcb_p np, int target, char *label, u_char *msg)
+static void sym_print_nego_msg (struct sym_hcb *np, int target, char *label, u_char *msg)
{
PRINT_TARGET(np, target);
if (label)
@@ -184,7 +184,7 @@ static char *sym_scsi_bus_mode(int mode)
* On the other hand, LVD devices need some delay
* to settle and report actual BUS mode in STEST4.
*/
-static void sym_chip_reset (hcb_p np)
+static void sym_chip_reset (struct sym_hcb *np)
{
OUTB (nc_istat, SRST);
UDELAY (10);
@@ -201,7 +201,7 @@ static void sym_chip_reset (hcb_p np)
* So, we need to abort the current operation prior to
* soft resetting the chip.
*/
-static void sym_soft_reset (hcb_p np)
+static void sym_soft_reset (struct sym_hcb *np)
{
u_char istat = 0;
int i;
@@ -234,12 +234,12 @@ do_chip_reset:
*
* The interrupt handler will reinitialize the chip.
*/
-static void sym_start_reset(hcb_p np)
+static void sym_start_reset(struct sym_hcb *np)
{
(void) sym_reset_scsi_bus(np, 1);
}
-int sym_reset_scsi_bus(hcb_p np, int enab_int)
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
{
u32 term;
int retv = 0;
@@ -293,7 +293,7 @@ out:
/*
* Select SCSI clock frequency
*/
-static void sym_selectclock(hcb_p np, u_char scntl3)
+static void sym_selectclock(struct sym_hcb *np, u_char scntl3)
{
/*
* If multiplier not present or not selected, leave here.
@@ -348,7 +348,7 @@ static void sym_selectclock(hcb_p np, u_char scntl3)
/*
* calculate SCSI clock frequency (in KHz)
*/
-static unsigned getfreq (hcb_p np, int gen)
+static unsigned getfreq (struct sym_hcb *np, int gen)
{
unsigned int ms = 0;
unsigned int f;
@@ -420,7 +420,7 @@ static unsigned getfreq (hcb_p np, int gen)
return f;
}
-static unsigned sym_getfreq (hcb_p np)
+static unsigned sym_getfreq (struct sym_hcb *np)
{
u_int f1, f2;
int gen = 8;
@@ -435,7 +435,7 @@ static unsigned sym_getfreq (hcb_p np)
/*
* Get/probe chip SCSI clock frequency
*/
-static void sym_getclock (hcb_p np, int mult)
+static void sym_getclock (struct sym_hcb *np, int mult)
{
unsigned char scntl3 = np->sv_scntl3;
unsigned char stest1 = np->sv_stest1;
@@ -492,7 +492,7 @@ static void sym_getclock (hcb_p np, int mult)
/*
* Get/probe PCI clock frequency
*/
-static int sym_getpciclock (hcb_p np)
+static int sym_getpciclock (struct sym_hcb *np)
{
int f = 0;
@@ -528,7 +528,7 @@ static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
* synchronous factor period.
*/
static int
-sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
+sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
{
u32 clk = np->clock_khz; /* SCSI clock frequency in kHz */
int div = np->clock_divn; /* Number of divisors supported */
@@ -648,7 +648,7 @@ sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
/*
* Set initial io register bits from burst code.
*/
-static __inline void sym_init_burst(hcb_p np, u_char bc)
+static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
{
np->rv_ctest4 &= ~0x80;
np->rv_dmode &= ~(0x3 << 6);
@@ -668,7 +668,7 @@ static __inline void sym_init_burst(hcb_p np, u_char bc)
/*
* Print out the list of targets that have some flag disabled by user.
*/
-static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
+static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
{
int cnt;
int i;
@@ -696,7 +696,7 @@ static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
* is not safe on paper, but it seems to work quite
* well. :)
*/
-static void sym_save_initial_setting (hcb_p np)
+static void sym_save_initial_setting (struct sym_hcb *np)
{
np->sv_scntl0 = INB(nc_scntl0) & 0x0a;
np->sv_scntl3 = INB(nc_scntl3) & 0x07;
@@ -716,44 +716,11 @@ static void sym_save_initial_setting (hcb_p np)
np->sv_ctest5 = INB(nc_ctest5) & 0x24;
}
-#ifdef CONFIG_PARISC
-static u32 parisc_setup_hcb(hcb_p np, u32 period)
-{
- unsigned long pdc_period;
- char scsi_mode;
- struct hardware_path hwpath;
-
- /* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
- * Many newer machines export one channel of 53c896 chip
- * as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters
- * to set the SCSI Initiator ID.
- */
- get_pci_node_path(np->s.device, &hwpath);
- if (!pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period,
- &np->maxwide, &scsi_mode))
- return period;
-
- if (scsi_mode >= 0) {
- /* C3000 PDC reports period/mode */
- SYM_SETUP_SCSI_DIFF = 0;
- switch(scsi_mode) {
- case 0: np->scsi_mode = SMODE_SE; break;
- case 1: np->scsi_mode = SMODE_HVD; break;
- case 2: np->scsi_mode = SMODE_LVD; break;
- default: break;
- }
- }
-
- return (u32) pdc_period;
-}
-#else
-static inline int parisc_setup_hcb(hcb_p np, u32 period) { return period; }
-#endif
/*
* Prepare io register values used by sym_start_up()
* according to selected and supported features.
*/
-static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
+static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
{
u_char burst_max;
u32 period;
@@ -816,8 +783,6 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
*/
period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
- period = parisc_setup_hcb(np, period);
-
if (period <= 250) np->minsync = 10;
else if (period <= 303) np->minsync = 11;
else if (period <= 500) np->minsync = 12;
@@ -880,7 +845,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* In dual channel mode, contention occurs if internal cycles
* are used. Disable internal cycles.
*/
- if (np->device_id == PCI_ID_LSI53C1010_33 &&
+ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
np->revision_id < 0x1)
np->rv_ccntl0 |= DILS;
@@ -904,9 +869,9 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* this driver. The generic ncr driver that does not use
* LOAD/STORE instructions does not need this work-around.
*/
- if ((np->device_id == PCI_ID_SYM53C810 &&
+ if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 &&
np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
- (np->device_id == PCI_ID_SYM53C860 &&
+ (np->device_id == PCI_DEVICE_ID_NCR_53C860 &&
np->revision_id <= 0x1))
np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
@@ -1000,7 +965,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
if ((SYM_SETUP_SCSI_LED ||
(nvram->type == SYM_SYMBIOS_NVRAM ||
(nvram->type == SYM_TEKRAM_NVRAM &&
- np->device_id == PCI_ID_SYM53C895))) &&
+ np->device_id == PCI_DEVICE_ID_NCR_53C895))) &&
!(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
np->features |= FE_LED0;
@@ -1091,7 +1056,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* Has to be called with interrupts disabled.
*/
#ifndef SYM_CONF_IOMAPPED
-static int sym_regtest (hcb_p np)
+static int sym_regtest (struct sym_hcb *np)
{
register volatile u32 data;
/*
@@ -1115,7 +1080,7 @@ static int sym_regtest (hcb_p np)
}
#endif
-static int sym_snooptest (hcb_p np)
+static int sym_snooptest (struct sym_hcb *np)
{
u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
int i, err=0;
@@ -1241,7 +1206,7 @@ restart_test:
* First 24 register of the chip:
* r0..rf
*/
-static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
+static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
{
u32 dsp;
int script_ofs;
@@ -1299,85 +1264,85 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
}
static struct sym_pci_chip sym_pci_dev_table[] = {
- {PCI_ID_SYM53C810, 0x0f, "810", 4, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, 64,
FE_ERL}
,
#ifdef SYM_DEBUG_GENERIC_SUPPORT
- {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, 1,
FE_BOF}
,
#else
- {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, 1,
FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF}
,
#endif
- {PCI_ID_SYM53C815, 0xff, "815", 4, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4, 8, 4, 64,
FE_BOF|FE_ERL}
,
- {PCI_ID_SYM53C825, 0x0f, "825", 6, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 6, 8, 4, 64,
FE_WIDE|FE_BOF|FE_ERL|FE_DIFF}
,
- {PCI_ID_SYM53C825, 0xff, "825a", 6, 8, 4, 2,
+ {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6, 8, 4, 2,
FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|FE_DIFF}
,
- {PCI_ID_SYM53C860, 0xff, "860", 4, 8, 5, 1,
+ {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, 1,
FE_ULTRA|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN}
,
- {PCI_ID_SYM53C875, 0x01, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
- {PCI_ID_SYM53C875, 0xff, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875, 0xff, "875", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
- {PCI_ID_SYM53C875_2, 0xff, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875J, 0xff, "875J", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
- {PCI_ID_SYM53C885, 0xff, "885", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
#ifdef SYM_DEBUG_GENERIC_SUPPORT
- {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|
FE_RAM|FE_LCKFRQ}
,
#else
- {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_LCKFRQ}
,
#endif
- {PCI_ID_SYM53C896, 0xff, "896", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_SYM53C895A, 0xff, "895a", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C895A, 0xff, "895a", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_SYM53C875A, 0xff, "875a", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C875A, 0xff, "875a", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_LSI53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
FE_C10}
,
- {PCI_ID_LSI53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
FE_C10|FE_U3EN}
,
- {PCI_ID_LSI53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC|
FE_C10|FE_U3EN}
,
- {PCI_ID_LSI53C1510D, 0xff, "1510d", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C1510, 0xff, "1510d", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_IO256|FE_LEDC}
};
@@ -1415,7 +1380,7 @@ sym_lookup_pci_chip_table (u_short device_id, u_char revision)
* This is only used if the direct mapping
* has been unsuccessful.
*/
-int sym_lookup_dmap(hcb_p np, u32 h, int s)
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s)
{
int i;
@@ -1448,7 +1413,7 @@ new:
* Update IO registers scratch C..R so they will be
* in sync. with queued CCB expectations.
*/
-static void sym_update_dmap_regs(hcb_p np)
+static void sym_update_dmap_regs(struct sym_hcb *np)
{
int o, i;
@@ -1463,13 +1428,12 @@ static void sym_update_dmap_regs(hcb_p np)
}
#endif
+/* Enforce all the fiddly SPI rules and the chip limitations */
static void sym_check_goals(struct scsi_device *sdev)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
- /* here we enforce all the fiddly SPI rules */
-
if (!scsi_device_wide(sdev))
st->width = 0;
@@ -1479,7 +1443,7 @@ static void sym_check_goals(struct scsi_device *sdev)
st->offset = 0;
return;
}
-
+
if (scsi_device_dt(sdev)) {
if (scsi_device_dt_only(sdev))
st->options |= PPR_OPT_DT;
@@ -1490,7 +1454,8 @@ static void sym_check_goals(struct scsi_device *sdev)
st->options &= ~PPR_OPT_DT;
}
- if (!(np->features & FE_ULTRA3))
+ /* Some targets fail to properly negotiate DT in SE mode */
+ if ((np->scsi_mode != SMODE_LVD) || !(np->features & FE_U3EN))
st->options &= ~PPR_OPT_DT;
if (st->options & PPR_OPT_DT) {
@@ -1520,38 +1485,31 @@ static void sym_check_goals(struct scsi_device *sdev)
* negotiation and the nego_status field of the CCB.
* Returns the size of the message in bytes.
*/
-static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
+static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
{
tcb_p tp = &np->target[cp->target];
- int msglen = 0;
struct scsi_device *sdev = tp->sdev;
+ struct sym_trans *goal = &tp->tinfo.goal;
+ struct sym_trans *curr = &tp->tinfo.curr;
+ int msglen = 0;
+ int nego;
if (likely(sdev))
sym_check_goals(sdev);
/*
- * Early C1010 chips need a work-around for DT
- * data transfer to work.
+ * Many devices implement PPR in a buggy way, so only use it if we
+ * really want to.
*/
- if (!(np->features & FE_U3EN))
- tp->tinfo.goal.options = 0;
- /*
- * negotiate using PPR ?
- */
- if (scsi_device_dt(sdev)) {
+ if ((goal->options & PPR_OPT_MASK) || (goal->period < 0xa)) {
nego = NS_PPR;
+ } else if (curr->width != goal->width) {
+ nego = NS_WIDE;
+ } else if (curr->period != goal->period ||
+ curr->offset != goal->offset) {
+ nego = NS_SYNC;
} else {
- /*
- * negotiate wide transfers ?
- */
- if (tp->tinfo.curr.width != tp->tinfo.goal.width)
- nego = NS_WIDE;
- /*
- * negotiate synchronous transfers?
- */
- else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
- tp->tinfo.curr.offset != tp->tinfo.goal.offset)
- nego = NS_SYNC;
+ nego = 0;
}
switch (nego) {
@@ -1559,24 +1517,24 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 3;
msgptr[msglen++] = M_X_SYNC_REQ;
- msgptr[msglen++] = tp->tinfo.goal.period;
- msgptr[msglen++] = tp->tinfo.goal.offset;
+ msgptr[msglen++] = goal->period;
+ msgptr[msglen++] = goal->offset;
break;
case NS_WIDE:
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 2;
msgptr[msglen++] = M_X_WIDE_REQ;
- msgptr[msglen++] = tp->tinfo.goal.width;
+ msgptr[msglen++] = goal->width;
break;
case NS_PPR:
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 6;
msgptr[msglen++] = M_X_PPR_REQ;
- msgptr[msglen++] = tp->tinfo.goal.period;
+ msgptr[msglen++] = goal->period;
msgptr[msglen++] = 0;
- msgptr[msglen++] = tp->tinfo.goal.offset;
- msgptr[msglen++] = tp->tinfo.goal.width;
- msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK;
+ msgptr[msglen++] = goal->offset;
+ msgptr[msglen++] = goal->width;
+ msgptr[msglen++] = goal->options & PPR_OPT_MASK;
break;
};
@@ -1598,7 +1556,7 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
/*
* Insert a job into the start queue.
*/
-void sym_put_start_queue(hcb_p np, ccb_p cp)
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp)
{
u_short qidx;
@@ -1630,13 +1588,6 @@ void sym_put_start_queue(hcb_p np, ccb_p cp)
#endif
/*
- * Optionnaly, set the IO timeout condition.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- sym_timeout_ccb(np, cp, sym_cam_timeout(cp->cam_ccb));
-#endif
-
- /*
* Insert first the idle task and then our job.
* The MBs should ensure proper ordering.
*/
@@ -1664,7 +1615,7 @@ void sym_put_start_queue(hcb_p np, ccb_p cp)
/*
* Start next ready-to-start CCBs.
*/
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
{
SYM_QUEHEAD *qp;
ccb_p cp;
@@ -1718,7 +1669,7 @@ void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)
* prevent out of order LOADs by the CPU from having
* prefetched stale data prior to DMA having occurred.
*/
-static int sym_wakeup_done (hcb_p np)
+static int sym_wakeup_done (struct sym_hcb *np)
{
ccb_p cp;
int i, n;
@@ -1752,10 +1703,64 @@ static int sym_wakeup_done (hcb_p np)
}
/*
+ * Complete all CCBs queued to the COMP queue.
+ *
+ * These CCBs are assumed:
+ * - Not to be referenced either by devices or
+ * SCRIPTS-related queues and datas.
+ * - To have to be completed with an error condition
+ * or requeued.
+ *
+ * The device queue freeze count is incremented
+ * for each CCB that does not prevent this.
+ * This function is called when all CCBs involved
+ * in error handling/recovery have been reaped.
+ */
+static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
+{
+ SYM_QUEHEAD *qp;
+ ccb_p cp;
+
+ while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
+ struct scsi_cmnd *ccb;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+ /* Leave quiet CCBs waiting for resources */
+ if (cp->host_status == HS_WAIT)
+ continue;
+ ccb = cp->cam_ccb;
+ if (cam_status)
+ sym_set_cam_status(ccb, cam_status);
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = sym_lp(np, tp, cp->lun);
+ if (lp) {
+ sym_remque(&cp->link2_ccbq);
+ sym_insque_tail(&cp->link2_ccbq,
+ &lp->waiting_ccbq);
+ if (cp->started) {
+ if (cp->tag != NO_TAG)
+ --lp->started_tags;
+ else
+ --lp->started_no_tag;
+ }
+ }
+ cp->started = 0;
+ continue;
+ }
+#endif
+ sym_free_ccb(np, cp);
+ sym_freeze_cam_ccb(ccb);
+ sym_xpt_done(np, ccb);
+ }
+}
+
+/*
* Complete all active CCBs with error.
* Used on CHIP/SCSI RESET.
*/
-static void sym_flush_busy_queue (hcb_p np, int cam_status)
+static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status)
{
/*
* Move all active CCBs to the COMP queue
@@ -1774,7 +1779,7 @@ static void sym_flush_busy_queue (hcb_p np, int cam_status)
* 1: SCSI BUS RESET delivered or received.
* 2: SCSI BUS MODE changed.
*/
-void sym_start_up (hcb_p np, int reason)
+void sym_start_up (struct sym_hcb *np, int reason)
{
int i;
u32 phys;
@@ -1865,7 +1870,7 @@ void sym_start_up (hcb_p np, int reason)
/*
* For now, disable AIP generation on C1010-66.
*/
- if (np->device_id == PCI_ID_LSI53C1010_66)
+ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)
OUTB (nc_aipcntl1, DISAIP);
/*
@@ -1875,7 +1880,7 @@ void sym_start_up (hcb_p np, int reason)
* that from SCRIPTS for each selection/reselection, but
* I just don't want. :)
*/
- if (np->device_id == PCI_ID_LSI53C1010_33 &&
+ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
np->revision_id < 1)
OUTB (nc_stest1, INB(nc_stest1) | 0x30);
@@ -1884,9 +1889,9 @@ void sym_start_up (hcb_p np, int reason)
* Disable overlapped arbitration for some dual function devices,
* regardless revision id (kind of post-chip-design feature. ;-))
*/
- if (np->device_id == PCI_ID_SYM53C875)
+ if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
OUTB (nc_ctest0, (1<<5));
- else if (np->device_id == PCI_ID_SYM53C896)
+ else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
np->rv_ccntl0 |= DPR;
/*
@@ -2010,7 +2015,7 @@ void sym_start_up (hcb_p np, int reason)
/*
* Switch trans mode for current job and it's target.
*/
-static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
+static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
SYM_QUEHEAD *qp;
@@ -2119,7 +2124,7 @@ static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
* We received a WDTR.
* Let everything be aware of the changes.
*/
-static void sym_setwide(hcb_p np, int target, u_char wide)
+static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
{
tcb_p tp = &np->target[target];
@@ -2138,7 +2143,7 @@ static void sym_setwide(hcb_p np, int target, u_char wide)
* Let everything be aware of the changes.
*/
static void
-sym_setsync(hcb_p np, int target,
+sym_setsync(struct sym_hcb *np, int target,
u_char ofs, u_char per, u_char div, u_char fak)
{
tcb_p tp = &np->target[target];
@@ -2164,7 +2169,7 @@ sym_setsync(hcb_p np, int target,
* Let everything be aware of the changes.
*/
static void
-sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
+sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
tcb_p tp = &np->target[target];
@@ -2205,7 +2210,7 @@ sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
* pushes a DSA into a queue, we can trust it when it
* points to a CCB.
*/
-static void sym_recover_scsi_int (hcb_p np, u_char hsts)
+static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts)
{
u32 dsp = INL (nc_dsp);
u32 dsa = INL (nc_dsa);
@@ -2256,7 +2261,7 @@ reset_all:
/*
* chip exception handler for selection timeout
*/
-static void sym_int_sto (hcb_p np)
+static void sym_int_sto (struct sym_hcb *np)
{
u32 dsp = INL (nc_dsp);
@@ -2271,7 +2276,7 @@ static void sym_int_sto (hcb_p np)
/*
* chip exception handler for unexpected disconnect
*/
-static void sym_int_udc (hcb_p np)
+static void sym_int_udc (struct sym_hcb *np)
{
printf ("%s: unexpected disconnect\n", sym_name(np));
sym_recover_scsi_int(np, HS_UNEXPECTED);
@@ -2287,7 +2292,7 @@ static void sym_int_udc (hcb_p np)
* mode to eight bit asynchronous, etc...
* So, just reinitializing all except chip should be enough.
*/
-static void sym_int_sbmc (hcb_p np)
+static void sym_int_sbmc (struct sym_hcb *np)
{
u_char scsi_mode = INB (nc_stest4) & SMODE;
@@ -2328,7 +2333,7 @@ static void sym_int_sbmc (hcb_p np)
* The chip will load the DSP with the phase mismatch
* JUMP address and interrupt the host processor.
*/
-static void sym_int_par (hcb_p np, u_short sist)
+static void sym_int_par (struct sym_hcb *np, u_short sist)
{
u_char hsts = INB (HS_PRT);
u32 dsp = INL (nc_dsp);
@@ -2416,7 +2421,7 @@ reset_all:
* We have to construct a new transfer descriptor,
* to transfer the rest of the current block.
*/
-static void sym_int_ma (hcb_p np)
+static void sym_int_ma (struct sym_hcb *np)
{
u32 dbc;
u32 rest;
@@ -2826,7 +2831,7 @@ reset_all:
* Use at your own decision and risk.
*/
-void sym_interrupt (hcb_p np)
+void sym_interrupt (struct sym_hcb *np)
{
u_char istat, istatc;
u_char dstat;
@@ -2981,7 +2986,7 @@ unknown_int:
* It is called with SCRIPTS not running.
*/
static int
-sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
+sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task)
{
int j;
ccb_p cp;
@@ -3025,60 +3030,6 @@ sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
}
/*
- * Complete all CCBs queued to the COMP queue.
- *
- * These CCBs are assumed:
- * - Not to be referenced either by devices or
- * SCRIPTS-related queues and datas.
- * - To have to be completed with an error condition
- * or requeued.
- *
- * The device queue freeze count is incremented
- * for each CCB that does not prevent this.
- * This function is called when all CCBs involved
- * in error handling/recovery have been reaped.
- */
-void sym_flush_comp_queue(hcb_p np, int cam_status)
-{
- SYM_QUEHEAD *qp;
- ccb_p cp;
-
- while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
- cam_ccb_p ccb;
- cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
- sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
- /* Leave quiet CCBs waiting for resources */
- if (cp->host_status == HS_WAIT)
- continue;
- ccb = cp->cam_ccb;
- if (cam_status)
- sym_set_cam_status(ccb, cam_status);
-#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
- if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
- tcb_p tp = &np->target[cp->target];
- lcb_p lp = sym_lp(np, tp, cp->lun);
- if (lp) {
- sym_remque(&cp->link2_ccbq);
- sym_insque_tail(&cp->link2_ccbq,
- &lp->waiting_ccbq);
- if (cp->started) {
- if (cp->tag != NO_TAG)
- --lp->started_tags;
- else
- --lp->started_no_tag;
- }
- }
- cp->started = 0;
- continue;
- }
-#endif
- sym_free_ccb(np, cp);
- sym_freeze_cam_ccb(ccb);
- sym_xpt_done(np, ccb);
- }
-}
-
-/*
* chip handler for bad SCSI status condition
*
* In case of bad SCSI status, we unqueue all the tasks
@@ -3096,14 +3047,13 @@ void sym_flush_comp_queue(hcb_p np, int cam_status)
* SCRATCHA is assumed to have been loaded with STARTPOS
* before the SCRIPTS called the C code.
*/
-static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
+static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
{
tcb_p tp = &np->target[cp->target];
u32 startp;
u_char s_status = cp->ssss_status;
u_char h_flags = cp->host_flags;
int msglen;
- int nego;
int i;
/*
@@ -3178,16 +3128,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
* cp->nego_status is filled by sym_prepare_nego().
*/
cp->nego_status = 0;
- nego = 0;
- if (tp->tinfo.curr.options & PPR_OPT_MASK)
- nego = NS_PPR;
- else if (tp->tinfo.curr.width != BUS_8_BIT)
- nego = NS_WIDE;
- else if (tp->tinfo.curr.offset != 0)
- nego = NS_SYNC;
- if (nego)
- msglen +=
- sym_prepare_nego (np,cp, nego, &cp->scsi_smsg2[msglen]);
+ msglen += sym_prepare_nego(np, cp, &cp->scsi_smsg2[msglen]);
/*
* Message table indirect structure.
*/
@@ -3213,7 +3154,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
/*
* sense data
*/
- bzero(cp->sns_bbuf, SYM_SNS_BBUF_LEN);
+ memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
cp->phys.sense.addr = cpu_to_scr(vtobus(cp->sns_bbuf));
cp->phys.sense.size = cpu_to_scr(SYM_SNS_BBUF_LEN);
@@ -3263,7 +3204,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
* - lun=-1 means any logical UNIT otherwise a given one.
* - task=-1 means any task, otherwise a given one.
*/
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task)
{
SYM_QUEHEAD qtmp, *qp;
int i = 0;
@@ -3282,7 +3223,7 @@ int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
* the BUSY queue.
*/
while ((qp = sym_remque_head(&qtmp)) != 0) {
- cam_ccb_p ccb;
+ struct scsi_cmnd *ccb;
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
ccb = cp->cam_ccb;
if (cp->host_status != HS_DISCONNECT ||
@@ -3346,7 +3287,7 @@ printf("XXXX TASK @%p CLEARED\n", cp);
* all the CCBs that should have been aborted by the
* target according to our message.
*/
-static void sym_sir_task_recovery(hcb_p np, int num)
+static void sym_sir_task_recovery(struct sym_hcb *np, int num)
{
SYM_QUEHEAD *qp;
ccb_p cp;
@@ -3698,7 +3639,7 @@ static void sym_sir_task_recovery(hcb_p np, int num)
* the corresponding values of dp_sg and dp_ofs.
*/
-static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
+static int sym_evaluate_dp(struct sym_hcb *np, ccb_p cp, u32 scr, int *ofs)
{
u32 dp_scr;
int dp_ofs, dp_sg, dp_sgmin;
@@ -3816,7 +3757,7 @@ out_err:
* is equivalent to a MODIFY DATA POINTER (offset=-1).
*/
-static void sym_modify_dp(hcb_p np, tcb_p tp, ccb_p cp, int ofs)
+static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
{
int dp_ofs = ofs;
u32 dp_scr = sym_get_script_dp (np, cp);
@@ -3915,7 +3856,7 @@ out_reject:
* a relevant information. :)
*/
-int sym_compute_residual(hcb_p np, ccb_p cp)
+int sym_compute_residual(struct sym_hcb *np, ccb_p cp)
{
int dp_sg, dp_sgmin, resid = 0;
int dp_ofs = 0;
@@ -4015,7 +3956,7 @@ int sym_compute_residual(hcb_p np, ccb_p cp)
* chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message.
*/
static int
-sym_sync_nego_check(hcb_p np, int req, int target)
+sym_sync_nego_check(struct sym_hcb *np, int req, int target)
{
u_char chg, ofs, per, fak, div;
@@ -4096,7 +4037,7 @@ reject_it:
return -1;
}
-static void sym_sync_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
int req = 1;
int result;
@@ -4133,7 +4074,7 @@ reject_it:
* chip handler for PARALLEL PROTOCOL REQUEST (PPR) message.
*/
static int
-sym_ppr_nego_check(hcb_p np, int req, int target)
+sym_ppr_nego_check(struct sym_hcb *np, int req, int target)
{
tcb_p tp = &np->target[target];
unsigned char fak, div;
@@ -4176,7 +4117,7 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
if (ofs) {
unsigned char minsync = dt ? np->minsync_dt : np->minsync;
- if (per < np->minsync_dt) {
+ if (per < minsync) {
chg = 1;
per = minsync;
}
@@ -4242,7 +4183,7 @@ reject_it:
return -1;
}
-static void sym_ppr_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
int req = 1;
int result;
@@ -4279,7 +4220,7 @@ reject_it:
* chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message.
*/
static int
-sym_wide_nego_check(hcb_p np, int req, int target)
+sym_wide_nego_check(struct sym_hcb *np, int req, int target)
{
u_char chg, wide;
@@ -4344,7 +4285,7 @@ reject_it:
return -1;
}
-static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
int req = 1;
int result;
@@ -4413,7 +4354,7 @@ reject_it:
* So, if a PPR makes problems, we may just want to
* try a legacy negotiation later.
*/
-static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
switch (cp->nego_status) {
case NS_PPR:
@@ -4443,7 +4384,7 @@ static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
* chip handler for MESSAGE REJECT received in response to
* PPR, WIDE or SYNCHRONOUS negotiation.
*/
-static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_rejected(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
sym_nego_default(np, tp, cp);
OUTB (HS_PRT, HS_BUSY);
@@ -4452,7 +4393,7 @@ static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
/*
* chip exception handler for programmed interrupts.
*/
-static void sym_int_sir (hcb_p np)
+static void sym_int_sir (struct sym_hcb *np)
{
u_char num = INB (nc_dsps);
u32 dsa = INL (nc_dsa);
@@ -4726,7 +4667,7 @@ out_stuck:
/*
* Acquire a control block
*/
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
{
tcb_p tp = &np->target[tn];
lcb_p lp = sym_lp(np, tp, ln);
@@ -4875,7 +4816,7 @@ out_free:
/*
* Release one control block
*/
-void sym_free_ccb (hcb_p np, ccb_p cp)
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
{
tcb_p tp = &np->target[cp->target];
lcb_p lp = sym_lp(np, tp, cp->lun);
@@ -4960,13 +4901,6 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
sym_remque(&cp->link_ccbq);
sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- /*
- * Cancel any pending timeout condition.
- */
- sym_untimeout_ccb(np, cp);
-#endif
-
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
if (lp) {
sym_remque(&cp->link2_ccbq);
@@ -4985,7 +4919,7 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
/*
* Allocate a CCB from memory and initialize its fixed part.
*/
-static ccb_p sym_alloc_ccb(hcb_p np)
+static ccb_p sym_alloc_ccb(struct sym_hcb *np)
{
ccb_p cp = NULL;
int hcode;
@@ -5053,9 +4987,6 @@ static ccb_p sym_alloc_ccb(hcb_p np)
/*
* Chain into optionnal lists.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-#endif
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
sym_insque_head(&cp->link2_ccbq, &np->dummy_ccbq);
#endif
@@ -5072,7 +5003,7 @@ out_free:
/*
* Look up a CCB from a DSA value.
*/
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa)
{
int hcode;
ccb_p cp;
@@ -5092,7 +5023,7 @@ static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
* Target control block initialisation.
* Nothing important to do at the moment.
*/
-static void sym_init_tcb (hcb_p np, u_char tn)
+static void sym_init_tcb (struct sym_hcb *np, u_char tn)
{
#if 0 /* Hmmm... this checking looks paranoid. */
/*
@@ -5108,7 +5039,7 @@ static void sym_init_tcb (hcb_p np, u_char tn)
/*
* Lun control block allocation and initialization.
*/
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
{
tcb_p tp = &np->target[tn];
lcb_p lp = sym_lp(np, tp, ln);
@@ -5210,7 +5141,7 @@ fail:
/*
* Allocate LCB resources for tagged command queuing.
*/
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
{
tcb_p tp = &np->target[tn];
lcb_p lp = sym_lp(np, tp, ln);
@@ -5262,7 +5193,7 @@ fail:
/*
* Queue a SCSI IO to the controller.
*/
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
{
tcb_p tp;
lcb_p lp;
@@ -5273,7 +5204,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
/*
* Keep track of the IO in our CCB.
*/
- cp->cam_ccb = (cam_ccb_p) csio;
+ cp->cam_ccb = csio;
/*
* Retrieve the target descriptor.
@@ -5351,7 +5282,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
tp->tinfo.curr.offset != tp->tinfo.goal.offset ||
tp->tinfo.curr.options != tp->tinfo.goal.options) {
if (!tp->nego_cp && lp)
- msglen += sym_prepare_nego(np, cp, 0, msgptr + msglen);
+ msglen += sym_prepare_nego(np, cp, msgptr + msglen);
}
/*
@@ -5401,7 +5332,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
/*
* Reset a SCSI target (all LUNs of this target).
*/
-int sym_reset_scsi_target(hcb_p np, int target)
+int sym_reset_scsi_target(struct sym_hcb *np, int target)
{
tcb_p tp;
@@ -5420,7 +5351,7 @@ int sym_reset_scsi_target(hcb_p np, int target)
/*
* Abort a SCSI IO.
*/
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out)
{
/*
* Check that the IO is active.
@@ -5450,7 +5381,7 @@ int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
return 0;
}
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
{
ccb_p cp;
SYM_QUEHEAD *qp;
@@ -5480,7 +5411,7 @@ int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
* SCRATCHA is assumed to have been loaded with STARTPOS
* before the SCRIPTS called the C code.
*/
-void sym_complete_error (hcb_p np, ccb_p cp)
+void sym_complete_error (struct sym_hcb *np, ccb_p cp)
{
tcb_p tp;
lcb_p lp;
@@ -5614,11 +5545,11 @@ finish:
* The SCRIPTS processor is running while we are
* completing successful commands.
*/
-void sym_complete_ok (hcb_p np, ccb_p cp)
+void sym_complete_ok (struct sym_hcb *np, ccb_p cp)
{
tcb_p tp;
lcb_p lp;
- cam_ccb_p ccb;
+ struct scsi_cmnd *ccb;
int resid;
/*
@@ -5724,7 +5655,7 @@ if (resid)
/*
* Soft-attach the controller.
*/
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram)
{
int i;
@@ -5815,17 +5746,9 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
sym_que_init(&np->comp_ccbq);
/*
- * Initializations for optional handling
- * of IO timeouts and device queueing.
+ * Initialization for optional handling
+ * of device queueing.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- sym_que_init(&np->tmo0_ccbq);
- np->tmo_ccbq =
- sym_calloc(2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
- "TMO_CCBQ");
- for (i = 0 ; i < 2*SYM_CONF_TIMEOUT_ORDER_MAX ; i++)
- sym_que_init(&np->tmo_ccbq[i]);
-#endif
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
sym_que_init(&np->dummy_ccbq);
#endif
@@ -5957,7 +5880,7 @@ attach_failed:
/*
* Free everything that has been allocated for this device.
*/
-void sym_hcb_free(hcb_p np)
+void sym_hcb_free(struct sym_hcb *np)
{
SYM_QUEHEAD *qp;
ccb_p cp;
@@ -5971,12 +5894,6 @@ void sym_hcb_free(hcb_p np)
sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0");
if (np->scripta0)
sym_mfree_dma(np->scripta0, np->scripta_sz, "SCRIPTA0");
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- if (np->tmo_ccbq)
- sym_mfree(np->tmo_ccbq,
- 2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
- "TMO_CCBQ");
-#endif
if (np->squeue)
sym_mfree_dma(np->squeue, sizeof(u32)*(MAX_QUEUE*2), "SQUEUE");
if (np->dqueue)
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 4d3b989539521e..e3509d4c879cbd 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -749,7 +749,7 @@ struct sym_ccb {
/*
* Pointer to CAM ccb and related stuff.
*/
- cam_ccb_p cam_ccb; /* CAM scsiio ccb */
+ struct scsi_cmnd *cam_ccb; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */
u8 *sns_bbuf; /* Bounce buffer for sense data */
#ifndef SYM_SNS_BBUF_LEN
@@ -796,10 +796,6 @@ struct sym_ccb {
/*
* Other fields.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- SYM_QUEHEAD tmo_linkq; /* Optional timeout handling */
- u_int tmo_clock; /* (link and dealine value) */
-#endif
u32 ccb_ba; /* BUS address of this CCB */
u_short tag; /* Tag for this transfer */
/* NO_TAG means no tag */
@@ -946,8 +942,8 @@ struct sym_hcb {
struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
- void (*fw_setup)(hcb_p np, struct sym_fw *fw);
- void (*fw_patch)(hcb_p np);
+ void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
+ void (*fw_patch)(struct sym_hcb *np);
char *fw_name;
/*
@@ -1025,15 +1021,6 @@ struct sym_hcb {
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
SYM_QUEHEAD dummy_ccbq;
#endif
- /*
- * Optional handling of IO timeouts.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- SYM_QUEHEAD tmo0_ccbq;
- SYM_QUEHEAD *tmo_ccbq; /* [2*SYM_TIMEOUT_ORDER_MAX] */
- u_int tmo_clock;
- u_int tmo_actq;
-#endif
/*
* IMMEDIATE ARBITRATION (IARB) control.
@@ -1082,54 +1069,39 @@ struct sym_hcb {
* FIRMWARES (sym_fw.c)
*/
struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
-void sym_fw_bind_script (hcb_p np, u32 *start, int len);
+void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len);
/*
* Driver methods called from O/S specific code.
*/
char *sym_driver_name(void);
void sym_print_xerr(ccb_p cp, int x_status);
-int sym_reset_scsi_bus(hcb_p np, int enab_int);
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_pci_chip *
sym_lookup_pci_chip_table (u_short device_id, u_char revision);
-void sym_put_start_queue(hcb_p np, ccb_p cp);
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn);
#endif
-void sym_start_up (hcb_p np, int reason);
-void sym_interrupt (hcb_p np);
-void sym_flush_comp_queue(hcb_p np, int cam_status);
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
-void sym_free_ccb (hcb_p np, ccb_p cp);
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-int sym_reset_scsi_target(hcb_p np, int target);
-void sym_hcb_free(hcb_p np);
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
-
-/*
- * Optionnaly, the driver may handle IO timeouts.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
-static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
-{
- sym_remque(&cp->tmo_linkq);
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-}
-void sym_clock(hcb_p np);
-#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
+void sym_start_up (struct sym_hcb *np, int reason);
+void sym_interrupt (struct sym_hcb *np);
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order);
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln);
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
+int sym_reset_scsi_target(struct sym_hcb *np, int target);
+void sym_hcb_free(struct sym_hcb *np);
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Optionnaly, the driver may provide a function
* to announce transfer rate changes.
*/
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
-void sym_announce_transfer_rate(hcb_p np, int target);
+void sym_announce_transfer_rate(struct sym_hcb *np, int target);
#endif
/*
@@ -1153,9 +1125,9 @@ do { \
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-int sym_lookup_dmap(hcb_p np, u32 h, int s);
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
-sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
+sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
int s = (h&SYM_DMAP_MASK);
diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
index 567a6dd31a27b4..01f380a2d28f8b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c
@@ -170,7 +170,7 @@ static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
}
if (p)
- bzero(p, size);
+ memset(p, 0, size);
else if (uflags & SYM_MEM_WARN)
printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
return p;
diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
index f27f52e651dccf..0b678ae73acca2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.c
@@ -37,109 +37,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
#include "sym_glue.h"
-#endif
-
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
-/*
- * Optional CCB timeout handling.
- *
- * This code is useful for O/Ses that allow or expect
- * SIMs (low-level drivers) to handle SCSI IO timeouts.
- * It uses a power-of-two based algorithm of my own:)
- * that avoids scanning of lists, provided that:
- *
- * - The IO does complete in less than half the associated
- * timeout value.
- * - The greatest delay between the queuing of the IO and
- * its completion is less than
- * (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
- *
- * For example, if tick is 1 second and the max order is 8,
- * any IO that is completed within less than 64 seconds will
- * just be put into some list at queuing and be removed
- * at completion without any additionnal overhead.
- */
-
-/*
- * Set a timeout condition on a CCB.
- */
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)
-{
- sym_remque(&cp->tmo_linkq);
- cp->tmo_clock = np->tmo_clock + ticks;
- if (!ticks) {
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
- }
- else {
- int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
- while (i > 0) {
- if (ticks >= (1<<(i+1)))
- break;
- --i;
- }
- if (!(np->tmo_actq & (1<<i)))
- i += SYM_CONF_TIMEOUT_ORDER_MAX;
- sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
- }
-}
-
-/*
- * Walk a list of CCB and handle timeout conditions.
- * Should never be called in normal situations.
- */
-static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
-{
- SYM_QUEHEAD qtmp, *qp;
- ccb_p cp;
-
- sym_que_move(tmoq, &qtmp);
- while ((qp = sym_remque_head(&qtmp)) != 0) {
- sym_insque_head(qp, &np->tmo0_ccbq);
- cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
- if (cp->tmo_clock != np->tmo_clock &&
- cp->tmo_clock + 1 != np->tmo_clock)
- sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
- else
- sym_abort_ccb(np, cp, 1);
- }
-}
-
-/*
- * Our clock handler called from the O/S specific side.
- */
-void sym_clock(hcb_p np)
-{
- int i, j;
- u_int tmp;
-
- tmp = np->tmo_clock;
- tmp ^= (++np->tmo_clock);
-
- for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
- if (!(tmp & 1))
- continue;
- j = i;
- if (np->tmo_actq & (1<<i))
- j += SYM_CONF_TIMEOUT_ORDER_MAX;
-
- if (!sym_que_empty(&np->tmo_ccbq[j])) {
- sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
- }
- np->tmo_actq ^= (1<<i);
- }
-}
-#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
-
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
/*
* Announce transfer rate if anything changed since last announcement.
*/
-void sym_announce_transfer_rate(hcb_p np, int target)
+void sym_announce_transfer_rate(struct sym_hcb *np, int target)
{
tcb_p tp = &np->target[target];
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index f3621324a73b78..0809437706e83b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -68,6 +68,21 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
case SYM_TEKRAM_NVRAM:
np->myaddr = nvram->data.Tekram.host_id & 0x0f;
break;
+#ifdef CONFIG_PARISC
+ case SYM_PARISC_PDC:
+ if (nvram->data.parisc.host_id != -1)
+ np->myaddr = nvram->data.parisc.host_id;
+ if (nvram->data.parisc.factor != -1)
+ np->minsync = nvram->data.parisc.factor;
+ if (nvram->data.parisc.width != -1)
+ np->maxwide = nvram->data.parisc.width;
+ switch (nvram->data.parisc.mode) {
+ case 0: np->scsi_mode = SMODE_SE; break;
+ case 1: np->scsi_mode = SMODE_HVD; break;
+ case 2: np->scsi_mode = SMODE_LVD; break;
+ default: break;
+ }
+#endif
default:
break;
}
@@ -702,6 +717,28 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram)
return 0;
}
+#ifdef CONFIG_PARISC
+/*
+ * Host firmware (PDC) keeps a table for altering SCSI capabilities.
+ * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD.
+ * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID.
+ */
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
+{
+ struct hardware_path hwpath;
+ get_pci_node_path(np->pdev, &hwpath);
+ if (!pdc_get_initiator(&hwpath, pdc))
+ return 0;
+
+ return SYM_PARISC_PDC;
+}
+#else
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
+{
+ return 0;
+}
+#endif
+
/*
* Try reading Symbios or Tekram NVRAM
*/
@@ -714,7 +751,7 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
nvp->type = SYM_TEKRAM_NVRAM;
sym_display_Tekram_nvram(np, &nvp->data.Tekram);
} else {
- nvp->type = 0;
+ nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc);
}
return nvp->type;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h
index a6bd02afba4022..9572f87b599afb 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.h
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h
@@ -171,6 +171,10 @@ struct Tekram_nvram {
typedef struct Tekram_nvram Tekram_nvram;
typedef struct Tekram_target Tekram_target;
+#ifndef CONFIG_PARISC
+struct pdc_initiator { int dummy; };
+#endif
+
/*
* Union of supported NVRAM formats.
*/
@@ -178,10 +182,12 @@ struct sym_nvram {
int type;
#define SYM_SYMBIOS_NVRAM (1)
#define SYM_TEKRAM_NVRAM (2)
+#define SYM_PARISC_PDC (3)
#if SYM_CONF_NVRAM_SUPPORT
union {
Symbios_nvram Symbios;
Tekram_nvram Tekram;
+ struct pdc_initiator parisc;
} data;
#endif
};
diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h
index 7ca14db3475481..04ebe5486d5bf8 100644
--- a/drivers/scsi/sym53c8xx_comm.h
+++ b/drivers/scsi/sym53c8xx_comm.h
@@ -505,8 +505,6 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
-#define sync_scsi_data_for_cpu(np, cmd) __sync_scsi_data_for_cpu(np->dev, cmd)
-#define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd)
/*==========================================================
**
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index c2afeb7775633e..31ba6a9168c771 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -87,7 +87,7 @@ zalon_probe(struct parisc_device *dev)
{
struct gsc_irq gsc_irq;
u32 zalon_vers;
- int irq, error = -ENODEV;
+ int error = -ENODEV;
unsigned long zalon = dev->hpa;
unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
@@ -107,10 +107,10 @@ zalon_probe(struct parisc_device *dev)
/* Setup the interrupts first.
** Later on request_irq() will register the handler.
*/
- irq = gsc_alloc_irq(&gsc_irq);
+ dev->irq = gsc_alloc_irq(&gsc_irq);
printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
- zalon_vers, irq);
+ zalon_vers, dev->irq);
__raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
@@ -130,16 +130,16 @@ zalon_probe(struct parisc_device *dev)
device.dev = &dev->dev;
device.slot.base = (u_long)io_port;
device.slot.base_c = (u_long)io_port;
- device.slot.irq = irq;
+ device.slot.irq = dev->irq;
device.differential = 2;
host = ncr_attach(&zalon7xx_template, unit, &device);
if (!host)
goto fail;
- if (request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.bus_id, host)) {
+ if (request_irq(dev->irq, ncr53c8xx_intr, SA_SHIRQ, "zalon", host)) {
printk(KERN_ERR "%s: irq problem with %d, detaching\n ",
- dev->dev.bus_id, irq);
+ dev->dev.bus_id, dev->irq);
goto fail;
}
@@ -155,7 +155,7 @@ zalon_probe(struct parisc_device *dev)
return 0;
fail_free_irq:
- free_irq(irq, host);
+ free_irq(dev->irq, host);
fail:
ncr53c8xx_release(host);
return error;
@@ -171,18 +171,16 @@ MODULE_DEVICE_TABLE(parisc, zalon_tbl);
static int __exit zalon_remove(struct parisc_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
- int irq = host->irq;
scsi_remove_host(host);
ncr53c8xx_release(host);
- free_irq(irq, host);
+ free_irq(dev->irq, host);
return 0;
}
-
static struct parisc_driver zalon_driver = {
- .name = "GSC SCSI (Zalon)",
+ .name = "zalon",
.id_table = zalon_tbl,
.probe = zalon_probe,
.remove = __devexit_p(zalon_remove),
@@ -201,6 +199,7 @@ static int __init zalon7xx_init(void)
static void __exit zalon7xx_exit(void)
{
unregister_parisc_driver(&zalon_driver);
+ ncr53c8xx_exit();
}
module_init(zalon7xx_init);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6be72e5a2c4fc1..59dd5560fa1f89 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -237,7 +237,6 @@ static dev_link_t *serial_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -749,10 +748,7 @@ static int __init init_serial_cs(void)
static void __exit exit_serial_cs(void)
{
pcmcia_unregister_driver(&serial_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- serial_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_serial_cs);
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index f216f6a6db52fc..e1ef0d7ee8d129 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -69,7 +69,6 @@ static dev_link_t *ixj_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -313,10 +312,7 @@ static int __init ixj_pcmcia_init(void)
static void ixj_pcmcia_exit(void)
{
pcmcia_unregister_driver(&ixj_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- ixj_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(ixj_pcmcia_init);