aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2005-06-29 15:21:41 -0700
committerTony Luck <tony.luck@intel.com>2005-06-29 15:21:41 -0700
commitd18bfacff20f08aecf01bb971b110ca108eef3c7 (patch)
tree255f862839c593c796e609328575b611e3f56cf3 /drivers
parenta68db763af9b676590c3fe9ec3f17bf18015eb2f (diff)
parentfd782a4a99d2d3e818b9465c427b10f7f027d7da (diff)
Auto merge with /home/aegl/GIT/linus
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/container.c2
-rw-r--r--drivers/acpi/pci_bind.c27
-rw-r--r--drivers/acpi/pci_root.c24
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/scan.c126
-rw-r--r--drivers/base/firmware_class.c13
-rw-r--r--drivers/block/cciss.c1
-rw-r--r--drivers/block/ll_rw_blk.c151
-rw-r--r--drivers/char/agp/amd64-agp.c9
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c4
-rw-r--r--drivers/char/moxa.c2
-rw-r--r--drivers/char/rio/rio_linux.c4
-rw-r--r--drivers/char/rtc.c16
-rw-r--r--drivers/char/tipar.c2
-rw-r--r--drivers/char/tty_ioctl.c4
-rw-r--r--drivers/char/vt_ioctl.c5
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c2
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c2
-rw-r--r--drivers/isdn/hardware/eicon/dadapter.c2
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c8
-rw-r--r--drivers/isdn/hysdn/hycapi.c20
-rw-r--r--drivers/isdn/hysdn/hysdn_boot.c4
-rw-r--r--drivers/isdn/hysdn/hysdn_defs.h12
-rw-r--r--drivers/isdn/hysdn/hysdn_init.c2
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c4
-rw-r--r--drivers/md/md.c1
-rw-r--r--drivers/media/video/Makefile3
-rw-r--r--drivers/media/video/bttv-driver.c73
-rw-r--r--drivers/media/video/bttvp.h5
-rw-r--r--drivers/media/video/mt20xx.c6
-rw-r--r--drivers/media/video/tda8290.c20
-rw-r--r--drivers/media/video/tda9887.c7
-rw-r--r--drivers/media/video/tea5767.c334
-rw-r--r--drivers/media/video/tuner-core.c163
-rw-r--r--drivers/media/video/tuner-simple.c34
-rw-r--r--drivers/message/fusion/mptfc.c4
-rw-r--r--drivers/message/fusion/mptscsih.c10
-rw-r--r--drivers/message/fusion/mptscsih.h2
-rw-r--r--drivers/message/fusion/mptspi.c4
-rw-r--r--drivers/net/3c515.c4
-rw-r--r--drivers/net/3c59x.c6
-rw-r--r--drivers/net/8139cp.c4
-rw-r--r--drivers/net/82596.c14
-rwxr-xr-xdrivers/net/amd8111e.c8
-rw-r--r--drivers/net/at1700.c4
-rw-r--r--drivers/net/dl2k.c8
-rw-r--r--drivers/net/e100.c9
-rw-r--r--drivers/net/eepro100.c8
-rw-r--r--drivers/net/epic100.c6
-rw-r--r--drivers/net/fealnx.c8
-rw-r--r--drivers/net/hamachi.c12
-rw-r--r--drivers/net/lance.c2
-rw-r--r--drivers/net/lasi_82596.c8
-rw-r--r--drivers/net/natsemi.c4
-rw-r--r--drivers/net/ns83820.c4
-rw-r--r--drivers/net/pcnet32.c6
-rw-r--r--drivers/net/r8169.c4
-rw-r--r--drivers/net/s2io.c8
-rw-r--r--drivers/net/sb1250-mac.c4
-rw-r--r--drivers/net/sis900.c6
-rw-r--r--drivers/net/skge.c1710
-rw-r--r--drivers/net/skge.h586
-rw-r--r--drivers/net/slip.c1
-rw-r--r--drivers/net/smc91x.c2
-rw-r--r--drivers/net/smc91x.h13
-rw-r--r--drivers/net/starfire.c6
-rw-r--r--drivers/net/sundance.c6
-rw-r--r--drivers/net/tulip/de2104x.c6
-rw-r--r--drivers/net/tulip/dmfe.c10
-rw-r--r--drivers/net/tulip/interrupt.c10
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/tulip/winbond-840.c6
-rw-r--r--drivers/net/tulip/xircom_tulip_cb.c4
-rw-r--r--drivers/net/typhoon.c4
-rw-r--r--drivers/net/via-rhine.c17
-rw-r--r--drivers/net/via-velocity.c6
-rw-r--r--drivers/net/wan/hdlc_cisco.c2
-rw-r--r--drivers/net/yellowfin.c8
-rw-r--r--drivers/parisc/dino.c1
-rw-r--r--drivers/parisc/lba_pci.c2
-rw-r--r--drivers/pci/bus.c11
-rw-r--r--drivers/pci/hotplug/Makefile4
-rw-r--r--drivers/pci/hotplug/acpiphp.h47
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c9
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c882
-rw-r--r--drivers/pci/hotplug/acpiphp_pci.c449
-rw-r--r--drivers/pci/hotplug/acpiphp_res.c700
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c5
-rw-r--r--drivers/pci/msi.c88
-rw-r--r--drivers/pci/msi.h9
-rw-r--r--drivers/pci/pci-sysfs.c26
-rw-r--r--drivers/pci/probe.c29
-rw-r--r--drivers/pci/proc.c14
-rw-r--r--drivers/pci/remove.c14
-rw-r--r--drivers/pci/setup-bus.c5
-rw-r--r--drivers/scsi/3w-9xxx.c8
-rw-r--r--drivers/scsi/3w-xxxx.c8
-rw-r--r--drivers/scsi/ahci.c22
-rw-r--r--drivers/scsi/ipr.c10
-rw-r--r--drivers/scsi/libata-core.c6
-rw-r--r--drivers/scsi/megaraid.c8
-rw-r--r--drivers/scsi/scsi_lib.c2
102 files changed, 2520 insertions, 3489 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 5a0adbf8bc0..97013ddfa20 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -153,7 +153,7 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
return_VALUE(-ENODEV);
}
- result = acpi_bus_scan(*device);
+ result = acpi_bus_start(*device);
return_VALUE(result);
}
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 5d19b39e9e2..5148f3c10b5 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -61,15 +61,14 @@ acpi_pci_data_handler (
/**
- * acpi_os_get_pci_id
+ * acpi_get_pci_id
* ------------------
* This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
* to resolve PCI information for ACPI-PCI devices defined in the namespace.
* This typically occurs when resolving PCI operation region information.
*/
-#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_os_get_pci_id (
+acpi_get_pci_id (
acpi_handle handle,
struct acpi_pci_id *id)
{
@@ -78,7 +77,7 @@ acpi_os_get_pci_id (
struct acpi_device *device = NULL;
struct acpi_pci_data *data = NULL;
- ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");
+ ACPI_FUNCTION_TRACE("acpi_get_pci_id");
if (!id)
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -92,7 +91,7 @@ acpi_os_get_pci_id (
}
status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
- if (ACPI_FAILURE(status) || !data || !data->dev) {
+ if (ACPI_FAILURE(status) || !data) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Invalid ACPI-PCI context for device %s\n",
acpi_device_bid(device)));
@@ -115,7 +114,7 @@ acpi_os_get_pci_id (
return_ACPI_STATUS(AE_OK);
}
-#endif /* ACPI_FUTURE_USAGE */
+EXPORT_SYMBOL(acpi_get_pci_id);
int
@@ -129,6 +128,8 @@ acpi_pci_bind (
char *pathname = NULL;
struct acpi_buffer buffer = {0, NULL};
acpi_handle handle = NULL;
+ struct pci_dev *dev;
+ struct pci_bus *bus;
ACPI_FUNCTION_TRACE("acpi_pci_bind");
@@ -193,8 +194,20 @@ acpi_pci_bind (
* Locate matching device in PCI namespace. If it doesn't exist
* this typically means that the device isn't currently inserted
* (e.g. docking station, port replicator, etc.).
+ * We cannot simply search the global pci device list, since
+ * PCI devices are added to the global pci list when the root
+ * bridge start ops are run, which may not have happened yet.
*/
- data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));
+ bus = pci_find_bus(data->id.segment, data->id.bus);
+ if (bus) {
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (dev->devfn == PCI_DEVFN(data->id.device,
+ data->id.function)) {
+ data->dev = dev;
+ break;
+ }
+ }
+ }
if (!data->dev) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7e6b8e3b2ed..5d2f77fcd50 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -46,6 +46,7 @@ ACPI_MODULE_NAME ("pci_root")
static int acpi_pci_root_add (struct acpi_device *device);
static int acpi_pci_root_remove (struct acpi_device *device, int type);
+static int acpi_pci_root_start (struct acpi_device *device);
static struct acpi_driver acpi_pci_root_driver = {
.name = ACPI_PCI_ROOT_DRIVER_NAME,
@@ -54,6 +55,7 @@ static struct acpi_driver acpi_pci_root_driver = {
.ops = {
.add = acpi_pci_root_add,
.remove = acpi_pci_root_remove,
+ .start = acpi_pci_root_start,
},
};
@@ -169,6 +171,7 @@ acpi_pci_root_add (
if (!root)
return_VALUE(-ENOMEM);
memset(root, 0, sizeof(struct acpi_pci_root));
+ INIT_LIST_HEAD(&root->node);
root->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
@@ -298,12 +301,31 @@ acpi_pci_root_add (
root->id.bus);
end:
- if (result)
+ if (result) {
+ if (!list_empty(&root->node))
+ list_del(&root->node);
kfree(root);
+ }
return_VALUE(result);
}
+static int
+acpi_pci_root_start (
+ struct acpi_device *device)
+{
+ struct acpi_pci_root *root;
+
+ ACPI_FUNCTION_TRACE("acpi_pci_root_start");
+
+ list_for_each_entry(root, &acpi_pci_roots, node) {
+ if (root->handle == device->handle) {
+ pci_bus_add_devices(root->bus);
+ return_VALUE(0);
+ }
+ }
+ return_VALUE(-ENODEV);
+}
static int
acpi_pci_root_remove (
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index f4778747e88..76156ac91bd 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -723,7 +723,7 @@ int acpi_processor_device_add(
return_VALUE(-ENODEV);
}
- acpi_bus_scan(*device);
+ acpi_bus_start(*device);
pr = acpi_driver_data(*device);
if (!pr)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e8588559328..337d49b5564 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -553,20 +553,29 @@ acpi_bus_driver_init (
* upon possible configuration and currently allocated resources.
*/
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
+ return_VALUE(0);
+}
+
+int
+acpi_start_single_object (
+ struct acpi_device *device)
+{
+ int result = 0;
+ struct acpi_driver *driver;
+
+ ACPI_FUNCTION_TRACE("acpi_start_single_object");
+
+ if (!(driver = device->driver))
+ return_VALUE(0);
+
if (driver->ops.start) {
result = driver->ops.start(device);
if (result && driver->ops.remove)
driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
- return_VALUE(result);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
-
- if (driver->ops.scan) {
- driver->ops.scan(device);
- }
-
- return_VALUE(0);
+ return_VALUE(result);
}
static int acpi_driver_attach(struct acpi_driver * drv)
@@ -586,6 +595,7 @@ static int acpi_driver_attach(struct acpi_driver * drv)
if (!acpi_bus_match(dev, drv)) {
if (!acpi_bus_driver_init(dev, drv)) {
+ acpi_start_single_object(dev);
atomic_inc(&drv->references);
count++;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
@@ -1009,8 +1019,8 @@ acpi_bus_remove (
}
-int
-acpi_bus_add (
+static int
+acpi_add_single_object (
struct acpi_device **child,
struct acpi_device *parent,
acpi_handle handle,
@@ -1019,7 +1029,7 @@ acpi_bus_add (
int result = 0;
struct acpi_device *device = NULL;
- ACPI_FUNCTION_TRACE("acpi_bus_add");
+ ACPI_FUNCTION_TRACE("acpi_add_single_object");
if (!child)
return_VALUE(-EINVAL);
@@ -1140,7 +1150,7 @@ acpi_bus_add (
*
* TBD: Assumes LDM provides driver hot-plug capability.
*/
- acpi_bus_find_driver(device);
+ result = acpi_bus_find_driver(device);
end:
if (!result)
@@ -1153,10 +1163,10 @@ end:
return_VALUE(result);
}
-EXPORT_SYMBOL(acpi_bus_add);
-int acpi_bus_scan (struct acpi_device *start)
+static int acpi_bus_scan (struct acpi_device *start,
+ struct acpi_bus_ops *ops)
{
acpi_status status = AE_OK;
struct acpi_device *parent = NULL;
@@ -1229,9 +1239,20 @@ int acpi_bus_scan (struct acpi_device *start)
continue;
}
- status = acpi_bus_add(&child, parent, chandle, type);
- if (ACPI_FAILURE(status))
- continue;
+ if (ops->acpi_op_add)
+ status = acpi_add_single_object(&child, parent,
+ chandle, type);
+ else
+ status = acpi_bus_get_device(chandle, &child);
+
+ if (ACPI_FAILURE(status))
+ continue;
+
+ if (ops->acpi_op_start) {
+ status = acpi_start_single_object(child);
+ if (ACPI_FAILURE(status))
+ continue;
+ }
/*
* If the device is present, enabled, and functioning then
@@ -1257,8 +1278,50 @@ int acpi_bus_scan (struct acpi_device *start)
return_VALUE(0);
}
-EXPORT_SYMBOL(acpi_bus_scan);
+int
+acpi_bus_add (
+ struct acpi_device **child,
+ struct acpi_device *parent,
+ acpi_handle handle,
+ int type)
+{
+ int result;
+ struct acpi_bus_ops ops;
+
+ ACPI_FUNCTION_TRACE("acpi_bus_add");
+
+ result = acpi_add_single_object(child, parent, handle, type);
+ if (!result) {
+ memset(&ops, 0, sizeof(ops));
+ ops.acpi_op_add = 1;
+ result = acpi_bus_scan(*child, &ops);
+ }
+ return_VALUE(result);
+}
+EXPORT_SYMBOL(acpi_bus_add);
+
+int
+acpi_bus_start (
+ struct acpi_device *device)
+{
+ int result;
+ struct acpi_bus_ops ops;
+
+ ACPI_FUNCTION_TRACE("acpi_bus_start");
+
+ if (!device)
+ return_VALUE(-EINVAL);
+
+ result = acpi_start_single_object(device);
+ if (!result) {
+ memset(&ops, 0, sizeof(ops));
+ ops.acpi_op_start = 1;
+ result = acpi_bus_scan(device, &ops);
+ }
+ return_VALUE(result);
+}
+EXPORT_SYMBOL(acpi_bus_start);
static int
acpi_bus_trim(struct acpi_device *start,
@@ -1331,13 +1394,19 @@ acpi_bus_scan_fixed (
/*
* Enumerate all fixed-feature devices.
*/
- if (acpi_fadt.pwr_button == 0)
- result = acpi_bus_add(&device, acpi_root,
+ if (acpi_fadt.pwr_button == 0) {
+ result = acpi_add_single_object(&device, acpi_root,
NULL, ACPI_BUS_TYPE_POWER_BUTTON);
+ if (!result)
+ result = acpi_start_single_object(device);
+ }
- if (acpi_fadt.sleep_button == 0)
- result = acpi_bus_add(&device, acpi_root,
+ if (acpi_fadt.sleep_button == 0) {
+ result = acpi_add_single_object(&device, acpi_root,
NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
+ if (!result)
+ result = acpi_start_single_object(device);
+ }
return_VALUE(result);
}
@@ -1346,6 +1415,7 @@ acpi_bus_scan_fixed (
static int __init acpi_scan_init(void)
{
int result;
+ struct acpi_bus_ops ops;
ACPI_FUNCTION_TRACE("acpi_scan_init");
@@ -1357,17 +1427,23 @@ static int __init acpi_scan_init(void)
/*
* Create the root device in the bus's device tree
*/
- result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
+ result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
ACPI_BUS_TYPE_SYSTEM);
if (result)
goto Done;
+ result = acpi_start_single_object(acpi_root);
+
/*
* Enumerate devices in the ACPI namespace.
*/
result = acpi_bus_scan_fixed(acpi_root);
- if (!result)
- result = acpi_bus_scan(acpi_root);
+ if (!result) {
+ memset(&ops, 0, sizeof(ops));
+ ops.acpi_op_add = 1;
+ ops.acpi_op_start = 1;
+ result = acpi_bus_scan(acpi_root, &ops);
+ }
if (result)
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 97fe13f7f07..652281402c9 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -74,6 +74,8 @@ static ssize_t
firmware_timeout_store(struct class *class, const char *buf, size_t count)
{
loading_timeout = simple_strtol(buf, NULL, 10);
+ if (loading_timeout < 0)
+ loading_timeout = 0;
return count;
}
@@ -138,6 +140,10 @@ firmware_loading_store(struct class_device *class_dev,
switch (loading) {
case 1:
down(&fw_lock);
+ if (!fw_priv->fw) {
+ up(&fw_lock);
+ break;
+ }
vfree(fw_priv->fw->data);
fw_priv->fw->data = NULL;
fw_priv->fw->size = 0;
@@ -178,7 +184,7 @@ firmware_data_read(struct kobject *kobj,
down(&fw_lock);
fw = fw_priv->fw;
- if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+ if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
ret_count = -ENODEV;
goto out;
}
@@ -238,9 +244,10 @@ firmware_data_write(struct kobject *kobj,
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
+
down(&fw_lock);
fw = fw_priv->fw;
- if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+ if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
retval = -ENODEV;
goto out;
}
@@ -418,7 +425,7 @@ request_firmware(const struct firmware **firmware_p, const char *name,
fw_priv = class_get_devdata(class_dev);
- if (loading_timeout) {
+ if (loading_timeout > 0) {
fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
add_timer(&fw_priv->timeout);
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 653512b7757..3e9fb6e4a52 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -786,7 +786,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
case CCISS_GETLUNINFO: {
LogvolInfo_struct luninfo;
- int i;
luninfo.LunID = drv->LunID;
luninfo.num_opens = drv->usage_count;
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 234fdcfbdf0..692a5fced76 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1867,19 +1867,20 @@ static void freed_request(request_queue_t *q, int rw)
#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
/*
- * Get a free request, queue_lock must not be held
+ * Get a free request, queue_lock must be held.
+ * Returns NULL on failure, with queue_lock held.
+ * Returns !NULL on success, with queue_lock *not held*.
*/
static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
int gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
- struct io_context *ioc = get_io_context(gfp_mask);
+ struct io_context *ioc = current_io_context(GFP_ATOMIC);
if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
goto out;
- spin_lock_irq(q->queue_lock);
if (rl->count[rw]+1 >= q->nr_requests) {
/*
* The queue will fill after this allocation, so set it as
@@ -1907,11 +1908,18 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
* The queue is full and the allocating process is not a
* "batcher", and not exempted by the IO scheduler
*/
- spin_unlock_irq(q->queue_lock);
goto out;
}
get_rq:
+ /*
+ * Only allow batching queuers to allocate up to 50% over the defined
+ * limit of requests, otherwise we could have thousands of requests
+ * allocated with any setting of ->nr_requests
+ */
+ if (rl->count[rw] >= (3 * q->nr_requests / 2))
+ goto out;
+
rl->count[rw]++;
rl->starved[rw] = 0;
if (rl->count[rw] >= queue_congestion_on_threshold(q))
@@ -1941,7 +1949,6 @@ rq_starved:
if (unlikely(rl->count[rw] == 0))
rl->starved[rw] = 1;
- spin_unlock_irq(q->queue_lock);
goto out;
}
@@ -1951,21 +1958,23 @@ rq_starved:
rq_init(q, rq);
rq->rl = rl;
out:
- put_io_context(ioc);
return rq;
}
/*
* No available requests for this queue, unplug the device and wait for some
* requests to become available.
+ *
+ * Called with q->queue_lock held, and returns with it unlocked.
*/
static struct request *get_request_wait(request_queue_t *q, int rw,
struct bio *bio)
{
- DEFINE_WAIT(wait);
struct request *rq;
- do {
+ rq = get_request(q, rw, bio, GFP_NOIO);
+ while (!rq) {
+ DEFINE_WAIT(wait);
struct request_list *rl = &q->rq;
prepare_to_wait_exclusive(&rl->wait[rw], &wait,
@@ -1976,7 +1985,8 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
if (!rq) {
struct io_context *ioc;
- generic_unplug_device(q);
+ __generic_unplug_device(q);
+ spin_unlock_irq(q->queue_lock);
io_schedule();
/*
@@ -1985,12 +1995,13 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
* up to a big batch of them for a small period time.
* See ioc_batching, ioc_set_batching
*/
- ioc = get_io_context(GFP_NOIO);
+ ioc = current_io_context(GFP_NOIO);
ioc_set_batching(q, ioc);
- put_io_context(ioc);
+
+ spin_lock_irq(q->queue_lock);
}
finish_wait(&rl->wait[rw], &wait);
- } while (!rq);
+ }
return rq;
}
@@ -2001,14 +2012,18 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
BUG_ON(rw != READ && rw != WRITE);
- if (gfp_mask & __GFP_WAIT)
+ spin_lock_irq(q->queue_lock);
+ if (gfp_mask & __GFP_WAIT) {
rq = get_request_wait(q, rw, NULL);
- else
+ } else {
rq = get_request(q, rw, NULL, gfp_mask);
+ if (!rq)
+ spin_unlock_irq(q->queue_lock);
+ }
+ /* q->queue_lock is unlocked at this point */
return rq;
}
-
EXPORT_SYMBOL(blk_get_request);
/**
@@ -2512,7 +2527,7 @@ EXPORT_SYMBOL(blk_attempt_remerge);
static int __make_request(request_queue_t *q, struct bio *bio)
{
- struct request *req, *freereq = NULL;
+ struct request *req;
int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
unsigned short prio;
sector_t sector;
@@ -2540,14 +2555,9 @@ static int __make_request(request_queue_t *q, struct bio *bio)
goto end_io;
}
-again:
spin_lock_irq(q->queue_lock);
- if (elv_queue_empty(q)) {
- blk_plug_device(q);
- goto get_rq;
- }
- if (barrier)
+ if (unlikely(barrier) || elv_queue_empty(q))
goto get_rq;
el_ret = elv_merge(q, &req, bio);
@@ -2592,40 +2602,24 @@ again:
elv_merged_request(q, req);
goto out;
- /*
- * elevator says don't/can't merge. get new request
- */
- case ELEVATOR_NO_MERGE:
- break;
-
+ /* ELV_NO_MERGE: elevator says don't/can't merge. */
default:
- printk("elevator returned crap (%d)\n", el_ret);
- BUG();
+ ;
}
+get_rq:
/*
- * Grab a free request from the freelist - if that is empty, check
- * if we are doing read ahead and abort instead of blocking for
- * a free slot.
+ * Grab a free request. This is might sleep but can not fail.
+ * Returns with the queue unlocked.
+ */
+ req = get_request_wait(q, rw, bio);
+
+ /*
+ * After dropping the lock and possibly sleeping here, our request
+ * may now be mergeable after it had proven unmergeable (above).
+ * We don't worry about that case for efficiency. It won't happen
+ * often, and the elevators are able to handle it.
*/
-get_rq:
- if (freereq) {
- req = freereq;
- freereq = NULL;
- } else {
- spin_unlock_irq(q->queue_lock);
- if ((freereq = get_request(q, rw, bio, GFP_ATOMIC)) == NULL) {
- /*
- * READA bit set
- */
- err = -EWOULDBLOCK;
- if (bio_rw_ahead(bio))
- goto end_io;
-
- freereq = get_request_wait(q, rw, bio);
- }
- goto again;
- }
req->flags |= REQ_CMD;
@@ -2654,10 +2648,11 @@ get_rq:
req->rq_disk = bio->bi_bdev->bd_disk;
req->start_time = jiffies;
+ spin_lock_irq(q->queue_lock);
+ if (elv_queue_empty(q))
+ blk_plug_device(q);
add_request(q, req);
out:
- if (freereq)
- __blk_put_request(q, freereq);
if (sync)
__generic_unplug_device(q);
@@ -3284,24 +3279,20 @@ void exit_io_context(void)
/*
* If the current task has no IO context then create one and initialise it.
- * If it does have a context, take a ref on it.
+ * Otherwise, return its existing IO context.
*
- * This is always called in the context of the task which submitted the I/O.
- * But weird things happen, so we disable local interrupts to ensure exclusive
- * access to *current.
+ * This returned IO context doesn't have a specifically elevated refcount,
+ * but since the current task itself holds a reference, the context can be
+ * used in general code, so long as it stays within `current` context.
*/
-struct io_context *get_io_context(int gfp_flags)
+struct io_context *current_io_context(int gfp_flags)
{
struct task_struct *tsk = current;
- unsigned long flags;
struct io_context *ret;
- local_irq_save(flags);
ret = tsk->io_context;
- if (ret)
- goto out;
-
- local_irq_restore(flags);
+ if (likely(ret))
+ return ret;
ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
if (ret) {
@@ -3312,25 +3303,25 @@ struct io_context *get_io_context(int gfp_flags)
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
ret->cic = NULL;
+ tsk->io_context = ret;
+ }
- local_irq_save(flags);
-
- /*
- * very unlikely, someone raced with us in setting up the task
- * io context. free new context and just grab a reference.
- */
- if (!tsk->io_context)
- tsk->io_context = ret;
- else {
- kmem_cache_free(iocontext_cachep, ret);
- ret = tsk->io_context;
- }
+ return ret;
+}
+EXPORT_SYMBOL(current_io_context);
-out:
+/*
+ * If the current task has no IO context then create one and initialise it.
+ * If it does have a context, take a ref on it.
+ *
+ * This is always called in the context of the task which submitted the I/O.
+ */
+struct io_context *get_io_context(int gfp_flags)
+{
+ struct io_context *ret;
+ ret = current_io_context(gfp_flags);
+ if (likely(ret))
atomic_inc(&ret->refcount);
- local_irq_restore(flags);
- }
-
return ret;
}
EXPORT_SYMBOL(get_io_context);
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 1407945a589..59f589d733f 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -686,6 +686,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
+ /* SIS 760 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_760,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
{ }
};
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 1813d0d198f..e16c13fe698 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -1088,8 +1088,8 @@ static inline int i_ipmi_request(ipmi_user_t user,
long seqid;
int broadcast = 0;
- if (addr->channel > IPMI_NUM_CHANNELS) {
- spin_lock_irqsave(&intf->counter_lock, flags);
+ if (addr->channel >= IPMI_MAX_CHANNELS) {
+ spin_lock_irqsave(&intf->counter_lock, flags);
intf->sent_invalid_commands++;
spin_unlock_irqrestore(&intf->counter_lock, flags);
rv = -EINVAL;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 7c24fbe831f..95f7046ff05 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -451,7 +451,7 @@ static int __init moxa_init(void)
int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
i = 0;
while (i < n) {
- while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
+ while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
{
if (pci_enable_device(p))
continue;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 7db3370f497..d7d484024e2 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -1095,7 +1095,7 @@ static int __init rio_init(void)
#ifdef CONFIG_PCI
/* First look for the JET devices: */
- while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+ while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
pdev))) {
if (pci_enable_device(pdev)) continue;
@@ -1169,7 +1169,7 @@ static int __init rio_init(void)
*/
/* Then look for the older RIO/PCI devices: */
- while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+ while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
PCI_DEVICE_ID_SPECIALIX_RIO,
pdev))) {
if (pci_enable_device(pdev)) continue;
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index ff4f0980486..d8f9e94ae47 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -78,6 +78,7 @@
#include <linux/sysctl.h>
#include <linux/wait.h>
#include <linux/bcd.h>
+#include <linux/delay.h>
#include <asm/current.h>
#include <asm/uaccess.h>
@@ -894,7 +895,6 @@ static int __init rtc_init(void)
struct proc_dir_entry *ent;
#if defined(__alpha__) || defined(__mips__)
unsigned int year, ctrl;
- unsigned long uip_watchdog;
char *guess = NULL;
#endif
#ifdef __sparc__
@@ -1000,12 +1000,8 @@ no_irq:
/* Each operating system on an Alpha uses its own epoch.
Let's try to guess which one we are using now. */
- uip_watchdog = jiffies;
if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100) {
- barrier();
- cpu_relax();
- }
+ msleep(20);
spin_lock_irq(&rtc_lock);
year = CMOS_READ(RTC_YEAR);
@@ -1213,7 +1209,6 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
{
- unsigned long uip_watchdog = jiffies;
unsigned char ctrl;
#ifdef CONFIG_MACH_DECSTATION
unsigned int real_year;
@@ -1221,7 +1216,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
/*
* read RTC once any update in progress is done. The update
- * can take just over 2ms. We wait 10 to 20ms. There is no need to
+ * can take just over 2ms. We wait 20ms. There is no need to
* to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
* If you need to know *exactly* when a second has started, enable
* periodic update complete interrupts, (via ioctl) and then
@@ -1230,10 +1225,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
*/
if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100) {
- barrier();
- cpu_relax();
- }
+ msleep(20);
/*
* Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 659335d80ee..ec78d2f161f 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -396,7 +396,7 @@ static struct file_operations tipar_fops = {
static int __init
tipar_setup(char *str)
{
- int ints[2];
+ int ints[3];
str = get_options(str, ARRAY_SIZE(ints), ints);
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 58597993954..f19cf9d7792 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -476,11 +476,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
ld = tty_ldisc_ref(tty);
switch (arg) {
case TCIFLUSH:
- if (ld->flush_buffer)
+ if (ld && ld->flush_buffer)
ld->flush_buffer(tty);
break;
case TCIOFLUSH:
- if (ld->flush_buffer)
+ if (ld && ld->flush_buffer)
ld->flush_buffer(tty);
/* fall through */
case TCOFLUSH:
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 8971484b956..1d44f69e1fd 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -25,6 +25,7 @@
#include <linux/fs.h>
#include <linux/console.h>
#include <linux/signal.h>
+#include <linux/timex.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -386,7 +387,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
if (!perm)
return -EPERM;
if (arg)
- arg = 1193182 / arg;
+ arg = CLOCK_TICK_RATE / arg;
kd_mksound(arg, 0);
return 0;
@@ -403,7 +404,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
count = ticks ? (arg & 0xffff) : 0;
if (count)
- count = 1193182 / count;
+ count = CLOCK_TICK_RATE / count;
kd_mksound(count, ticks);
return 0;
}
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index 4e98c215e5b..4b039516cc8 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -162,7 +162,7 @@ ixp2000_wdt_release(struct inode *inode, struct file *file)
if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
wdt_disable();
} else {
- printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - "
+ printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
"timer will not stop\n");
}
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index 82396e06c8a..83df369113a 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -156,7 +156,7 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file)
if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
wdt_disable();
} else {
- printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - "
+ printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
"timer will not stop\n");
}
diff --git a/drivers/isdn/hardware/eicon/dadapter.c b/drivers/isdn/hardware/eicon/dadapter.c
index 6e548a222ef..89497890158 100644
--- a/drivers/isdn/hardware/eicon/dadapter.c
+++ b/drivers/isdn/hardware/eicon/dadapter.c
@@ -44,7 +44,7 @@ static didd_adapter_change_notification_t\
Array to held adapter information
-------------------------------------------------------------------------- */
static DESCRIPTOR HandleTable[NEW_MAX_DESCRIPTORS];
-dword Adapters = 0; /* Number of adapters */
+static dword Adapters = 0; /* Number of adapters */
/* --------------------------------------------------------------------------
Shadow IDI_DIMAINT
and 'shadow' debug stuff
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 6e7e060716b..7333377ab31 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -312,7 +312,7 @@ wait_busy(hfc4s8s_hw * a)
/* function to read critical counter registers that */
/* may be udpated by the chip during read */
/******************************************************/
-static volatile u_char
+static u_char
Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
{
u_char ref8;
@@ -324,7 +324,7 @@ Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
return in8;
}
-static volatile int
+static int
Read_hfc16_stable(hfc4s8s_hw * hw, int reg)
{
int ref16;
@@ -1465,7 +1465,7 @@ hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
/******************************************/
/* disable memory mapped ports / io ports */
/******************************************/
-void
+static void
release_pci_ports(hfc4s8s_hw * hw)
{
pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
@@ -1481,7 +1481,7 @@ release_pci_ports(hfc4s8s_hw * hw)
/*****************************************/
/* enable memory mapped ports / io ports */
/*****************************************/
-void
+static void
enable_pci_ports(hfc4s8s_hw * hw)
{
#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index 8ee25b2ccce..1fd3d4e5f28 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -42,6 +42,8 @@ typedef struct _hycapi_appl {
static hycapi_appl hycapi_applications[CAPI_MAXAPPL];
+static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+
static inline int _hycapi_appCheck(int app_id, int ctrl_no)
{
if((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) ||
@@ -57,7 +59,7 @@ static inline int _hycapi_appCheck(int app_id, int ctrl_no)
Kernel-Capi callback reset_ctr
******************************/
-void
+static void
hycapi_reset_ctr(struct capi_ctr *ctrl)
{
hycapictrl_info *cinfo = ctrl->driverdata;
@@ -73,7 +75,7 @@ hycapi_reset_ctr(struct capi_ctr *ctrl)
Kernel-Capi callback remove_ctr
******************************/
-void
+static void
hycapi_remove_ctr(struct capi_ctr *ctrl)
{
int i;
@@ -215,7 +217,7 @@ Error-checking is done for CAPI-compliance.
The application is recorded in the internal list.
*************************************************************/
-void
+static void
hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl,
capi_register_params *rp)
{
@@ -291,7 +293,7 @@ Release the application from the internal list an remove it's
registration at controller-level
******************************************************************/
-void
+static void
hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl)
{
int chk;
@@ -364,7 +366,7 @@ firmware-releases that do not check the MsgLen-Indication!
***************************************************************/
-u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
{
__u16 appl_id;
int _len, _len2;
@@ -437,8 +439,8 @@ Informations provided in the /proc/capi-entries.
*********************************************************************/
-int hycapi_read_proc(char *page, char **start, off_t off,
- int count, int *eof, struct capi_ctr *ctrl)
+static int hycapi_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, struct capi_ctr *ctrl)
{
hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
hysdn_card *card = cinfo->card;
@@ -485,7 +487,7 @@ on capi-interface registration.
**************************************************************/
-int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+static int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
{
#ifdef HYCAPI_PRINTFNAMES
printk(KERN_NOTICE "hycapi_load_firmware\n");
@@ -494,7 +496,7 @@ int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
}
-char *hycapi_procinfo(struct capi_ctr *ctrl)
+static char *hycapi_procinfo(struct capi_ctr *ctrl)
{
hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
#ifdef HYCAPI_PRINTFNAMES
diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c
index 6c04281e57b..7bfba196f31 100644
--- a/drivers/isdn/hysdn/hysdn_boot.c
+++ b/drivers/isdn/hysdn/hysdn_boot.c
@@ -53,7 +53,7 @@ struct boot_data {
/* to be called at start of POF file reading, */
/* before starting any decryption on any POF record. */
/*****************************************************/
-void
+static void
StartDecryption(struct boot_data *boot)
{
boot->Cryptor = CRYPT_STARTTERM;
@@ -66,7 +66,7 @@ StartDecryption(struct boot_data *boot)
/* to HI and LO boot loader and (all) seq tags, because */
/* global Cryptor is started for whole POF. */
/***************************************************************/
-void
+static void
DecryptBuf(struct boot_data *boot, int cnt)
{
uchar *bufp = boot->buf.BootBuf;
diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h
index 4cee26e558e..432f6f99089 100644
--- a/drivers/isdn/hysdn/hysdn_defs.h
+++ b/drivers/isdn/hysdn/hysdn_defs.h
@@ -227,7 +227,6 @@ typedef struct hycapictrl_info hycapictrl_info;
/*****************/
/* exported vars */
/*****************/
-extern int cardmax; /* number of found cards */
extern hysdn_card *card_root; /* pointer to first card */
@@ -244,7 +243,6 @@ extern void hysdn_procconf_release(void); /* deinit proc config filesys */
/* hysdn_proclog.c */
extern int hysdn_proclog_init(hysdn_card *); /* init proc log entry */
extern void hysdn_proclog_release(hysdn_card *); /* deinit proc log entry */
-extern void put_log_buffer(hysdn_card *, char *); /* output log data */
extern void hysdn_addlog(hysdn_card *, char *,...); /* output data to log */
extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int); /* output card log */
@@ -278,16 +276,6 @@ extern unsigned int hycapi_enable;
extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */
extern int hycapi_capi_release(hysdn_card *); /* delete the device */
extern int hycapi_capi_stop(hysdn_card *card); /* suspend */
-extern int hycapi_load_firmware(struct capi_ctr *, capiloaddata *);
-extern void hycapi_reset_ctr(struct capi_ctr *);
-extern void hycapi_remove_ctr(struct capi_ctr *);
-extern void hycapi_register_appl(struct capi_ctr *, __u16 appl,
- capi_register_params *);
-extern void hycapi_release_appl(struct capi_ctr *, __u16 appl);
-extern u16 hycapi_send_message(struct capi_ctr *, struct sk_buff *skb);
-extern char *hycapi_procinfo(struct capi_ctr *);
-extern int hycapi_read_proc(char *page, char **start, off_t off,
- int count, int *eof, struct capi_ctr *card);
extern void hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len);
extern void hycapi_tx_capiack(hysdn_card * card);
extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card);
diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c
index 5cac2bf5f4b..12c8137b516 100644
--- a/drivers/isdn/hysdn/hysdn_init.c
+++ b/drivers/isdn/hysdn/hysdn_init.c
@@ -34,7 +34,7 @@ MODULE_AUTHOR("Werner Cornelius");
MODULE_LICENSE("GPL");
static char *hysdn_init_revision = "$Revision: 1.6.6.6 $";
-int cardmax; /* number of found cards */
+static int cardmax; /* number of found cards */
hysdn_card *card_root = NULL; /* pointer to first card */
/**********************************************/
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 8ef2b7c952a..4d57011c573 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -22,6 +22,8 @@
/* the proc subdir for the interface is defined in the procconf module */
extern struct proc_dir_entry *hysdn_proc_entry;
+static void put_log_buffer(hysdn_card * card, char *cp);
+
/*************************************************/
/* structure keeping ascii log for device output */
/*************************************************/
@@ -93,7 +95,7 @@ hysdn_addlog(hysdn_card * card, char *fmt,...)
/* opened for read got the contents. */
/* Flushes buffers not longer in use. */
/********************************************/
-void
+static void
put_log_buffer(hysdn_card * card, char *cp)
{
struct log_data *ib;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3802f7a17f1..4a0c57db2b6 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -338,6 +338,7 @@ static int super_written(struct bio *bio, unsigned int bytes_done, int error)
if (atomic_dec_and_test(&rdev->mddev->pending_writes))
wake_up(&rdev->mddev->sb_wait);
+ bio_put(bio);
return 0;
}
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 2dc906fdfa5..810e7aac0a5 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -7,8 +7,7 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
-tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o
-
+tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 290289a9975..7d62b394c50 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-driver.c,v 1.38 2005/06/10 17:20:24 mchehab Exp $
+ $Id: bttv-driver.c,v 1.40 2005/06/16 21:38:45 nsh Exp $
bttv - Bt848 frame grabber driver
@@ -76,6 +76,9 @@ static unsigned int whitecrush_upper = 0xCF;
static unsigned int whitecrush_lower = 0x7F;
static unsigned int vcr_hack = 0;
static unsigned int irq_iswitch = 0;
+static unsigned int uv_ratio = 50;
+static unsigned int full_luma_range = 0;
+static unsigned int coring = 0;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
@@ -106,6 +109,9 @@ module_param(adc_crush, int, 0444);
module_param(whitecrush_upper, int, 0444);
module_param(whitecrush_lower, int, 0444);
module_param(vcr_hack, int, 0444);
+module_param(uv_ratio, int, 0444);
+module_param(full_luma_range, int, 0444);
+module_param(coring, int, 0444);
module_param_array(radio, int, NULL, 0444);
@@ -124,6 +130,9 @@ MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is
MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
@@ -484,7 +493,10 @@ static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
#define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5)
#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6)
#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_UV_RATIO (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_PRIVATE_CORING (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 11)
static const struct v4l2_queryctrl no_ctl = {
.name = "42",
@@ -618,8 +630,32 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
.step = 1,
.default_value = 0x7F,
.type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_PRIVATE_UV_RATIO,
+ .name = "uv ratio",
+ .minimum = 0,
+ .maximum = 100,
+ .step = 1,
+ .default_value = 50,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+ .name = "full luma range",
+ .minimum = 0,
+ .maximum = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },{
+ .id = V4L2_CID_PRIVATE_CORING,
+ .name = "coring",
+ .minimum = 0,
+ .maximum = 3,
+ .step = 1,
+ .default_value = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
}
+
+
};
static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
@@ -833,8 +869,8 @@ static void bt848_sat(struct bttv *btv, int color)
btv->saturation = color;
/* 0-511 for the color */
- val_u = color >> 7;
- val_v = ((color>>7)*180L)/254;
+ val_u = ((color * btv->opt_uv_ratio) / 50) >> 7;
+ val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
hibits = (val_u >> 7) & 2;
hibits |= (val_v >> 8) & 1;
btwrite(val_u & 0xff, BT848_SAT_U_LO);
@@ -1151,6 +1187,15 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
c->value = btv->opt_whitecrush_lower;
break;
+ case V4L2_CID_PRIVATE_UV_RATIO:
+ c->value = btv->opt_uv_ratio;
+ break;
+ case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+ c->value = btv->opt_full_luma_range;
+ break;
+ case V4L2_CID_PRIVATE_CORING:
+ c->value = btv->opt_coring;
+ break;
default:
return -EINVAL;
}
@@ -1247,6 +1292,18 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
btv->opt_whitecrush_lower = c->value;
btwrite(c->value, BT848_WC_DOWN);
break;
+ case V4L2_CID_PRIVATE_UV_RATIO:
+ btv->opt_uv_ratio = c->value;
+ bt848_sat(btv, btv->saturation);
+ break;
+ case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+ btv->opt_full_luma_range = c->value;
+ btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+ break;
+ case V4L2_CID_PRIVATE_CORING:
+ btv->opt_coring = c->value;
+ btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+ break;
default:
return -EINVAL;
}
@@ -3117,11 +3174,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
memset(v,0,sizeof(*v));
strcpy(v->name, "Radio");
- /* japan: 76.0 MHz - 89.9 MHz
- western europe: 87.5 MHz - 108.0 MHz
- russia: 65.0 MHz - 108.0 MHz */
- v->rangelow=(int)(65*16);
- v->rangehigh=(int)(108*16);
bttv_call_i2c_clients(btv,cmd,v);
return 0;
}
@@ -3876,6 +3928,9 @@ static int __devinit bttv_probe(struct pci_dev *dev,
btv->opt_vcr_hack = vcr_hack;
btv->opt_whitecrush_upper = whitecrush_upper;
btv->opt_whitecrush_lower = whitecrush_lower;
+ btv->opt_uv_ratio = uv_ratio;
+ btv->opt_full_luma_range = full_luma_range;
+ btv->opt_coring = coring;
/* fill struct bttv with some useful defaults */
btv->init.btv = btv;
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 7b6f1e85602..f3293e4a15a 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -1,5 +1,5 @@
/*
- $Id: bttvp.h,v 1.17 2005/02/16 12:14:10 kraxel Exp $
+ $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $
bttv - Bt848 frame grabber driver
@@ -326,6 +326,9 @@ struct bttv {
int opt_vcr_hack;
int opt_whitecrush_upper;
int opt_whitecrush_lower;
+ int opt_uv_ratio;
+ int opt_full_luma_range;
+ int opt_coring;
/* radio data/state */
int has_radio;
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index 95ad17b7f38..9c005cb128d 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -1,5 +1,5 @@
/*
- * $Id: mt20xx.c,v 1.4 2005/03/04 09:24:56 kraxel Exp $
+ * $Id: mt20xx.c,v 1.5 2005/06/16 08:29:49 nsh Exp $
*
* i2c tv tuner chip device driver
* controls microtune tuners, mt2032 + mt2050 at the moment.
@@ -295,8 +295,8 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
int if2 = t->radio_if2;
// per Manual for FM tuning: first if center freq. 1085 MHz
- mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
- 1085*1000*1000,if2,if2,if2);
+ mt2032_set_if_freq(c, freq * 1000 / 16,
+ 1085*1000*1000,if2,if2,if2);
}
// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index b27cc348d95..f59d4601cc6 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -1,5 +1,5 @@
/*
- * $Id: tda8290.c,v 1.7 2005/03/07 12:01:51 kraxel Exp $
+ * $Id: tda8290.c,v 1.11 2005/06/18 06:09:06 nsh Exp $
*
* i2c tv tuner chip device driver
* controls the philips tda8290+75 tuner chip combo.
@@ -69,7 +69,7 @@ static __u8 get_freq_entry( struct freq_entry* table, __u16 freq)
static unsigned char i2c_enable_bridge[2] = { 0x21, 0xC0 };
static unsigned char i2c_disable_bridge[2] = { 0x21, 0x80 };
static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00,
- 0x7C, 0x04, 0xA3, 0x3F,
+ 0xfC, 0x04, 0xA3, 0x3F,
0x2A, 0x04, 0xFF, 0x00,
0x00, 0x40 };
static unsigned char i2c_set_VS[2] = { 0x30, 0x6F };
@@ -138,16 +138,24 @@ static int tda8290_tune(struct i2c_client *c)
static void set_frequency(struct tuner *t, u16 ifc)
{
- u32 N = (((t->freq<<3)+ifc)&0x3fffc);
+ u32 freq;
+ u32 N;
- N = N >> get_freq_entry(div_table, t->freq);
+ if (t->mode == V4L2_TUNER_RADIO)
+ freq = t->freq / 1000;
+ else
+ freq = t->freq;
+
+ N = (((freq<<3)+ifc)&0x3fffc);
+
+ N = N >> get_freq_entry(div_table, freq);
t->i2c_set_freq[0] = 0;
t->i2c_set_freq[1] = (unsigned char)(N>>8);
t->i2c_set_freq[2] = (unsigned char) N;
t->i2c_set_freq[3] = 0x40;
t->i2c_set_freq[4] = 0x52;
- t->i2c_set_freq[5] = get_freq_entry(band_table, t->freq);
- t->i2c_set_freq[6] = get_freq_entry(agc_table, t->freq);
+ t->i2c_set_freq[5] = get_freq_entry(band_table, freq);
+ t->i2c_set_freq[6] = get_freq_entry(agc_table, freq);
t->i2c_set_freq[7] = 0x8f;
}
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 39773633cc3..ee35562f4d1 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -368,7 +368,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
if (t->radio_mode == V4L2_TUNER_MODE_MONO)
norm = &radio_mono;
else
- norm = &radio_stereo;
+ norm = &radio_stereo;
} else {
for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
if (tvnorms[i].std & t->std) {
@@ -566,7 +566,6 @@ static int tda9887_configure(struct tda9887 *t)
if (UNSET != t->pinnacle_id) {
tda9887_set_pinnacle(t,buf);
}
-
tda9887_set_config(t,buf);
tda9887_set_insmod(t,buf);
@@ -615,8 +614,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
t->pinnacle_id = UNSET;
t->radio_mode = V4L2_TUNER_MODE_STEREO;
- i2c_set_clientdata(&t->client, t);
- i2c_attach_client(&t->client);
+ i2c_set_clientdata(&t->client, t);
+ i2c_attach_client(&t->client);
return 0;
}
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
new file mode 100644
index 00000000000..a29f08f81f6
--- /dev/null
+++ b/drivers/media/video/tea5767.c
@@ -0,0 +1,334 @@
+/*
+ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
+ * I2C address is allways 0xC0.
+ *
+ * $Id: tea5767.c,v 1.11 2005/06/21 15:40:33 mchehab Exp $
+ *
+ * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
+ * This code is placed under the terms of the GNU General Public License
+ *
+ * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
+ * from their contributions on DScaler.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <media/tuner.h>
+
+/* Declared at tuner-core.c */
+extern unsigned int tuner_debug;
+
+#define PREFIX "TEA5767 "
+
+/*****************************************************************************/
+
+/******************************
+ * Write mode register values *
+ ******************************/
+
+/* First register */
+#define TEA5767_MUTE 0x80 /* Mutes output */
+#define TEA5767_SEARCH 0x40 /* Activates station search */
+/* Bits 0-5 for divider MSB */
+
+/* Second register */
+/* Bits 0-7 for divider LSB */
+
+/* Third register */
+
+/* Station search from botton to up */
+#define TEA5767_SEARCH_UP 0x80
+
+/* Searches with ADC output = 10 */
+#define TEA5767_SRCH_HIGH_LVL 0x60
+
+/* Searches with ADC output = 10 */
+#define TEA5767_SRCH_MID_LVL 0x40
+
+/* Searches with ADC output = 5 */
+#define TEA5767_SRCH_LOW_LVL 0x20
+
+/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
+#define TEA5767_HIGH_LO_INJECT 0x10
+
+/* Disable stereo */
+#define TEA5767_MONO 0x08
+
+/* Disable right channel and turns to mono */
+#define TEA5767_MUTE_RIGHT 0x04
+
+/* Disable left channel and turns to mono */
+#define TEA5767_MUTE_LEFT 0x02
+
+#define TEA5767_PORT1_HIGH 0x01
+
+/* Forth register */
+#define TEA5767_PORT2_HIGH 0x80
+/* Chips stops working. Only I2C bus remains on */
+#define TEA5767_STDBY 0x40
+
+/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
+#define TEA5767_JAPAN_BAND 0x20
+
+/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
+#define TEA5767_XTAL_32768 0x10
+
+/* Cuts weak signals */
+#define TEA5767_SOFT_MUTE 0x08
+
+/* Activates high cut control */
+#define TEA5767_HIGH_CUT_CTRL 0x04
+
+/* Activates stereo noise control */
+#define TEA5767_ST_NOISE_CTL 0x02
+
+/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
+#define TEA5767_SRCH_IND 0x01
+
+/* Fiveth register */
+
+/* By activating, it will use Xtal at 13 MHz as reference for divider */
+#define TEA5767_PLLREF_ENABLE 0x80
+
+/* By activating, deemphasis=50, or else, deemphasis of 50us */
+#define TEA5767_DEEMPH_75 0X40
+
+/*****************************
+ * Read mode register values *
+ *****************************/
+
+/* First register */
+#define TEA5767_READY_FLAG_MASK 0x80
+#define TEA5767_BAND_LIMIT_MASK 0X40
+/* Bits 0-5 for divider MSB after search or preset */
+
+/* Second register */
+/* Bits 0-7 for divider LSB after search or preset */
+
+/* Third register */
+#define TEA5767_STEREO_MASK 0x80
+#define TEA5767_IF_CNTR_MASK 0x7f
+
+/* Four register */
+#define TEA5767_ADC_LEVEL_MASK 0xf0
+
+/* should be 0 */
+#define TEA5767_CHIP_ID_MASK 0x0f
+
+/* Fiveth register */
+/* Reserved for future extensions */
+#define TEA5767_RESERVED_MASK 0xff
+
+/*****************************************************************************/
+
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ tuner_warn("This tuner doesn't support TV freq.\n");
+}
+
+static void tea5767_status_dump(unsigned char *buffer)
+{
+ unsigned int div, frq;
+
+ if (TEA5767_READY_FLAG_MASK & buffer[0])
+ printk(PREFIX "Ready Flag ON\n");
+ else
+ printk(PREFIX "Ready Flag OFF\n");
+
+ if (TEA5767_BAND_LIMIT_MASK & buffer[0])
+ printk(PREFIX "Tuner at band limit\n");
+ else
+ printk(PREFIX "Tuner not at band limit\n");
+
+ div=((buffer[0]&0x3f)<<8) | buffer[1];
+
+ switch (TEA5767_HIGH_LO_32768) {
+ case TEA5767_HIGH_LO_13MHz:
+ frq = 1000*(div*50-700-225)/4; /* Freq in KHz */
+ break;
+ case TEA5767_LOW_LO_13MHz:
+ frq = 1000*(div*50+700+225)/4; /* Freq in KHz */
+ break;
+ case TEA5767_LOW_LO_32768:
+ frq = 1000*(div*32768/1000+700+225)/4; /* Freq in KHz */
+ break;
+ case TEA5767_HIGH_LO_32768:
+ default:
+ frq = 1000*(div*32768/1000-700-225)/4; /* Freq in KHz */
+ break;
+ }
+ buffer[0] = (div>>8) & 0x3f;
+ buffer[1] = div & 0xff;
+
+ printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+ frq/1000,frq%1000,div);
+
+ if (TEA5767_STEREO_MASK & buffer[2])
+ printk(PREFIX "Stereo\n");
+ else
+ printk(PREFIX "Mono\n");
+
+ printk(PREFIX "IF Counter = %d\n",buffer[2] & TEA5767_IF_CNTR_MASK);
+
+ printk(PREFIX "ADC Level = %d\n",(buffer[3] & TEA5767_ADC_LEVEL_MASK)>>4);
+
+ printk(PREFIX "Chip ID = %d\n",(buffer[3] & TEA5767_CHIP_ID_MASK));
+
+ printk(PREFIX "Reserved = 0x%02x\n",(buffer[4] & TEA5767_RESERVED_MASK));
+}
+
+/* Freq should be specifyed at 62.5 Hz */
+static void set_radio_freq(struct i2c_client *c, unsigned int frq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned char buffer[5];
+ unsigned div;
+ int rc;
+
+ if ( tuner_debug )
+ printk(PREFIX "radio freq counter %d\n",frq);
+
+ /* Rounds freq to next decimal value - for 62.5 KHz step */
+ /* frq = 20*(frq/16)+radio_frq[frq%16]; */
+
+ buffer[2] = TEA5767_PORT1_HIGH;
+ buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
+ buffer[4]=0;
+
+ if (t->audmode == V4L2_TUNER_MODE_MONO) {
+ tuner_dbg("TEA5767 set to mono\n");
+ buffer[2] |= TEA5767_MONO;
+ } else
+ tuner_dbg("TEA5767 set to stereo\n");
+
+ switch (t->type) {
+ case TEA5767_HIGH_LO_13MHz:
+ tuner_dbg("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
+ buffer[2] |= TEA5767_HIGH_LO_INJECT;
+ buffer[4] |= TEA5767_PLLREF_ENABLE;
+ div = (frq*4/16+700+225+25)/50;
+ break;
+ case TEA5767_LOW_LO_13MHz:
+ tuner_dbg("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
+
+ buffer[4] |= TEA5767_PLLREF_ENABLE;
+ div = (frq*4/16-700-225+25)/50;
+ break;
+ case TEA5767_LOW_LO_32768:
+ tuner_dbg("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
+ buffer[3] |= TEA5767_XTAL_32768;
+ /* const 700=4000*175 Khz - to adjust freq to right value */
+ div = (1000*(frq*4/16-700-225)+16384)>>15;
+ break;
+ case TEA5767_HIGH_LO_32768:
+ default:
+ tuner_dbg("TEA5767 radio HIGH LO inject xtal @ 32,768 MHz\n");
+
+ buffer[2] |= TEA5767_HIGH_LO_INJECT;
+ buffer[3] |= TEA5767_XTAL_32768;
+ div = (1000*(frq*4/16+700+225)+16384)>>15;
+ break;
+ }
+ buffer[0] = (div>>8) & 0x3f;
+ buffer[1] = div & 0xff;
+
+ if ( tuner_debug )
+ tea5767_status_dump(buffer);
+
+ if (5 != (rc = i2c_master_send(c,buffer,5)))
+ tuner_warn("i2c i/o error: rc == %d (should be 5)\n",rc);
+}
+
+static int tea5767_signal(struct i2c_client *c)
+{
+ unsigned char buffer[5];
+ int rc;
+ struct tuner *t = i2c_get_clientdata(c);
+
+ memset(buffer,0,sizeof(buffer));
+ if (5 != (rc = i2c_master_recv(c,buffer,5)))
+ tuner_warn ( "i2c i/o error: rc == %d (should be 5)\n",rc);
+
+ return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) <<(13-4));
+}
+
+static int tea5767_stereo(struct i2c_client *c)
+{
+ unsigned char buffer[5];
+ int rc;
+ struct tuner *t = i2c_get_clientdata(c);
+
+ memset(buffer,0,sizeof(buffer));
+ if (5 != (rc = i2c_master_recv(c,buffer,5)))
+ tuner_warn ( "i2c i/o error: rc == %d (should be 5)\n",rc);
+
+ rc = buffer[2] & TEA5767_STEREO_MASK;
+
+ if ( tuner_debug )
+ tuner_dbg("TEA5767 radio ST GET = %02x\n", rc);
+
+ return ( (buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO: 0);
+}
+
+int tea_detection(struct i2c_client *c)
+{
+ unsigned char buffer[5]= { 0xff, 0xff, 0xff, 0xff, 0xff };
+ int rc;
+ struct tuner *t = i2c_get_clientdata(c);
+
+ if (5 != (rc = i2c_master_recv(c,buffer,5))) {
+ tuner_warn ( "it is not a TEA5767. Received %i chars.\n",rc );
+ return EINVAL;
+ }
+
+ /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */
+ if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
+ buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
+ tuner_warn ( "All bytes are equal. It is not a TEA5767\n" );
+ return EINVAL;
+ }
+
+ /* Status bytes:
+ * Byte 4: bit 3:1 : CI (Chip Identification) == 0
+ * bit 0 : internally set to 0
+ * Byte 5: bit 7:0 : == 0
+ */
+
+ if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
+ tuner_warn ( "Chip ID is not zero. It is not a TEA5767\n" );
+ return EINVAL;
+ }
+ tuner_warn ( "TEA5767 detected.\n" );
+ return 0;
+}
+
+int tea5767_tuner_init(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ if (tea_detection(c)==EINVAL) return EINVAL;
+
+ tuner_info("type set to %d (%s)\n",
+ t->type, TEA5767_TUNER_NAME);
+ strlcpy(c->name, TEA5767_TUNER_NAME, sizeof(c->name));
+
+ t->tv_freq = set_tv_freq;
+ t->radio_freq = set_radio_freq;
+ t->has_signal = tea5767_signal;
+ t->is_stereo = tea5767_stereo;
+
+ return (0);
+}
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index eaabfc85870..6f6bf4a633f 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $
+ * $Id: tuner-core.c,v 1.29 2005/06/21 15:40:33 mchehab Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -26,7 +26,6 @@
/*
* comment line bellow to return to old behavor, where only one I2C device is supported
*/
-#define CONFIG_TUNER_MULTI_I2C /**/
#define UNSET (-1U)
@@ -58,9 +57,7 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
MODULE_LICENSE("GPL");
static int this_adap;
-#ifdef CONFIG_TUNER_MULTI_I2C
static unsigned short first_tuner, tv_tuner, radio_tuner;
-#endif
static struct i2c_driver driver;
static struct i2c_client client_template;
@@ -81,26 +78,9 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
return;
}
if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
-
- if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
- /* V4L2_TUNER_CAP_LOW frequency */
-
- tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
-
- t->tv_freq(c,freq>>10);
-
- return;
- } else {
- /* FIXME: better do that chip-specific, but
- right now we don't have that in the config
- struct and this way is still better than no
- check at all */
tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
- return;
- }
}
- tuner_dbg("62.5 Khz freq step selected for TV.\n");
t->tv_freq(c,freq);
}
@@ -116,31 +96,18 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_info("no radio tuning for this one, sorry.\n");
return;
}
- if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
- if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
- /* V4L2_TUNER_CAP_LOW frequency */
- if (t->type == TUNER_TEA5767) {
- tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
- t->radio_freq(c,freq>>10);
- return;
- }
-
- tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
-
- tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
-
- t->radio_freq(c,freq>>10);
- return;
-
- } else {
- tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
- freq/16,freq%16*100/16,
- radio_range[0],radio_range[1]);
- return;
- }
+ if (freq >= radio_range[0]*16000 && freq <= radio_range[1]*16000) {
+ if (tuner_debug)
+ tuner_info("radio freq step 62.5Hz (%d.%06d)\n",
+ freq/16000,freq%16000*1000/16);
+ t->radio_freq(c,freq);
+ } else {
+ tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+ freq/16,freq%16*100/16,
+ radio_range[0],radio_range[1]);
}
- tuner_dbg("62.5 Khz freq step selected for Radio.\n");
- t->radio_freq(c,freq);
+
+ return;
}
static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -166,8 +133,8 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
static void set_type(struct i2c_client *c, unsigned int type)
{
struct tuner *t = i2c_get_clientdata(c);
+ unsigned char buffer[4];
- tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
/* sanity check */
if (type == UNSET || type == TUNER_ABSENT)
return;
@@ -179,8 +146,8 @@ static void set_type(struct i2c_client *c, unsigned int type)
t->type = type;
return;
}
- if (t->initialized)
- /* run only once */
+ if ((t->initialized) && (t->type == type))
+ /* run only once except type change Hac 04/05*/
return;
t->initialized = 1;
@@ -193,25 +160,42 @@ static void set_type(struct i2c_client *c, unsigned int type)
case TUNER_PHILIPS_TDA8290:
tda8290_init(c);
break;
+ case TUNER_TEA5767:
+ if (tea5767_tuner_init(c)==EINVAL) t->type=TUNER_ABSENT;
+ break;
+ case TUNER_PHILIPS_FMD1216ME_MK3:
+ buffer[0] = 0x0b;
+ buffer[1] = 0xdc;
+ buffer[2] = 0x9c;
+ buffer[3] = 0x60;
+ i2c_master_send(c,buffer,4);
+ mdelay(1);
+ buffer[2] = 0x86;
+ buffer[3] = 0x54;
+ i2c_master_send(c,buffer,4);
+ default_tuner_init(c);
+ break;
default:
+ /* TEA5767 autodetection code */
+ if (tea5767_tuner_init(c)!=EINVAL) {
+ t->type = TUNER_TEA5767;
+ if (first_tuner == 0x60)
+ first_tuner++;
+ break;
+ }
+
default_tuner_init(c);
break;
}
+ tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
}
-#ifdef CONFIG_TUNER_MULTI_I2C
#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \
- return 0; } else \
+ return 0; } else if (tuner_debug) \
tuner_info ("Cmd %s accepted to "tun"\n",cmd);
#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \
CHECK_ADDR(radio_tuner,cmd,"radio") } else \
{ CHECK_ADDR(tv_tuner,cmd,"TV"); }
-#else
-#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
-#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
-#endif
-
-#ifdef CONFIG_TUNER_MULTI_I2C
static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
{
@@ -242,9 +226,6 @@ static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
}
set_type(c,tun_addr->type);
}
-#else
-#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
-#endif
static char pal[] = "-";
module_param_string(pal, pal, sizeof(pal), 0644);
@@ -284,17 +265,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct tuner *t;
-#ifndef CONFIG_TUNER_MULTI_I2C
- if (this_adap > 0)
- return -1;
-#else
/* by default, first I2C card is both tv and radio tuner */
if (this_adap == 0) {
first_tuner = addr;
tv_tuner = addr;
radio_tuner = addr;
}
-#endif
this_adap++;
client_template.adapter = adap;
@@ -308,6 +284,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(&t->i2c, t);
t->type = UNSET;
t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */
+ t->audmode = V4L2_TUNER_MODE_STEREO;
i2c_attach_client(&t->i2c);
tuner_info("chip found @ 0x%x (%s)\n",
@@ -325,11 +302,9 @@ static int tuner_probe(struct i2c_adapter *adap)
}
this_adap = 0;
-#ifdef CONFIG_TUNER_MULTI_I2C
first_tuner = 0;
tv_tuner = 0;
radio_tuner = 0;
-#endif
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tuner_attach);
@@ -392,8 +367,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->radio_if2 = 41300 * 1000;
break;
}
- break;
-
+ break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
kernel pointer here... */
@@ -440,11 +414,18 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
vt->signal = t->has_signal(client);
if (t->is_stereo) {
if (t->is_stereo(client))
- vt-> flags |= VIDEO_TUNER_STEREO_ON;
+ vt->flags |= VIDEO_TUNER_STEREO_ON;
else
- vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON;
+ vt->flags &= ~VIDEO_TUNER_STEREO_ON;
}
vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
+
+ vt->rangelow = radio_range[0] * 16000;
+ vt->rangehigh = radio_range[1] * 16000;
+
+ } else {
+ vt->rangelow = tv_range[0] * 16;
+ vt->rangehigh = tv_range[1] * 16;
}
return 0;
@@ -510,20 +491,46 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
tuner -> signal = t->has_signal(client);
if (t->is_stereo) {
if (t->is_stereo(client)) {
- tuner -> capability |= V4L2_TUNER_CAP_STEREO;
- tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ tuner -> rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
} else {
- tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO;
+ tuner -> rxsubchans = V4L2_TUNER_SUB_MONO;
}
}
+ tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+ tuner->audmode = t->audmode;
+
+ tuner->rangelow = radio_range[0] * 16000;
+ tuner->rangehigh = radio_range[1] * 16000;
+ } else {
+ tuner->rangelow = tv_range[0] * 16;
+ tuner->rangehigh = tv_range[1] * 16;
}
- /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step to high at 62.5 Hz */
- tuner->rangelow = tv_range[0] * 16;
-// tuner->rangehigh = tv_range[1] * 16;
-// tuner->rangelow = tv_range[0] * 16384;
- tuner->rangehigh = tv_range[1] * 16384;
break;
}
+ case VIDIOC_S_TUNER: /* Allow changing radio range and audio mode */
+ {
+ struct v4l2_tuner *tuner = arg;
+
+ CHECK_ADDR(radio_tuner,"VIDIOC_S_TUNER","radio");
+ SWITCH_V4L2;
+
+ /* To switch the audio mode, applications initialize the
+ index and audmode fields and the reserved array and
+ call the VIDIOC_S_TUNER ioctl. */
+ /* rxsubchannels: V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO,
+ V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2,
+ V4L2_TUNER_MODE_SAP */
+
+ if (tuner->audmode == V4L2_TUNER_MODE_MONO)
+ t->audmode = V4L2_TUNER_MODE_MONO;
+ else
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+
+ set_radio_freq(client, t->freq);
+ break;
+ }
+ case TDA9887_SET_CONFIG: /* Nothing to do on tuner-core */
+ break;
default:
tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
/* nothing */
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 539f3055731..c39ed6226ee 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $
+ * $Id: tuner-simple.c,v 1.31 2005/06/21 16:02:25 mkrufky Exp $
*
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
@@ -207,28 +207,27 @@ static struct tunertype tuners[] = {
{ "LG PAL (TAPE series)", LGINNOTEK, PAL,
16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623},
- { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
- 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
- { "Philips FQ1236A MK4", Philips, NTSC,
- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
+ { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
+ 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
+ { "Philips FQ1236A MK4", Philips, NTSC,
+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
/* Should work for TVF8531MF, TVF8831MF, TVF8731MF */
{ "Ymec TVision TVF-8531MF", Philips, NTSC,
16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
{ "Ymec TVision TVF-5533MF", Philips, NTSC,
16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
-
{ "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
- { "Tena TNF9533-D/IF", LGINNOTEK, PAL,
- 16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623},
+ /* Should work for TNF9533-D/IF, TNF9533-B/DF */
+ { "Tena TNF9533-D/IF", Philips, PAL,
+ 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623},
- /*
- * This entry is for TEA5767 FM radio only chip used on several boards
- * w/TV tuner
- */
+ /* This entry is for TEA5767 FM radio only chip used on several boards w/TV tuner */
{ TEA5767_TUNER_NAME, Philips, RADIO,
- -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
+ -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
+ { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
+ 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
};
unsigned const int tuner_count = ARRAY_SIZE(tuners);
@@ -455,24 +454,24 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
int rc;
tun=&tuners[t->type];
- div = freq + (int)(16*10.7);
+ div = (freq / 1000) + (int)(16*10.7);
buffer[2] = tun->config;
switch (t->type) {
case TUNER_TENA_9533_DI:
case TUNER_YMEC_TVF_5533MF:
-
/*These values are empirically determinated */
- div = (freq*122)/16 - 20;
+ div = (freq * 122) / 16000 - 20;
buffer[2] = 0x88; /* could be also 0x80 */
buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */
break;
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
+ case TUNER_PHILIPS_FMD1216ME_MK3:
buffer[3] = 0x19;
break;
case TUNER_PHILIPS_FM1256_IH3:
- div = (20 * freq)/16 + 333 * 2;
+ div = (20 * freq) / 16000 + 333 * 2;
buffer[2] = 0x80;
buffer[3] = 0x19;
break;
@@ -505,6 +504,7 @@ int default_tuner_init(struct i2c_client *c)
t->radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
t->is_stereo = tuner_stereo;
+
return 0;
}
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index d8d65397e06..353deb25e39 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -364,9 +364,7 @@ static struct pci_driver mptfc_driver = {
.id_table = mptfc_pci_table,
.probe = mptfc_probe,
.remove = __devexit_p(mptscsih_remove),
- .driver = {
- .shutdown = mptscsih_shutdown,
- },
+ .shutdown = mptscsih_shutdown,
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
.resume = mptscsih_resume,
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index a0078ae5b9b..4f973a49be4 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -170,7 +170,7 @@ static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
#endif
void mptscsih_remove(struct pci_dev *);
-void mptscsih_shutdown(struct device *);
+void mptscsih_shutdown(struct pci_dev *);
#ifdef CONFIG_PM
int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
int mptscsih_resume(struct pci_dev *pdev);
@@ -988,7 +988,7 @@ mptscsih_remove(struct pci_dev *pdev)
#endif
#endif
- mptscsih_shutdown(&pdev->dev);
+ mptscsih_shutdown(pdev);
sz1=0;
@@ -1026,9 +1026,9 @@ mptscsih_remove(struct pci_dev *pdev)
*
*/
void
-mptscsih_shutdown(struct device * dev)
+mptscsih_shutdown(struct pci_dev *pdev)
{
- MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct Scsi_Host *host = ioc->sh;
MPT_SCSI_HOST *hd;
@@ -1054,7 +1054,7 @@ mptscsih_shutdown(struct device * dev)
int
mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
- mptscsih_shutdown(&pdev->dev);
+ mptscsih_shutdown(pdev);
return mpt_suspend(pdev,state);
}
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index d73aec33e16..5ea89bf0df1 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -82,7 +82,7 @@
#endif
extern void mptscsih_remove(struct pci_dev *);
-extern void mptscsih_shutdown(struct device *);
+extern void mptscsih_shutdown(struct pci_dev *);
#ifdef CONFIG_PM
extern int mptscsih_suspend(struct pci_dev *pdev, u32 state);
extern int mptscsih_resume(struct pci_dev *pdev);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 5f9a61b85b3..e0c0ee5bc96 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -419,9 +419,7 @@ static struct pci_driver mptspi_driver = {
.id_table = mptspi_pci_table,
.probe = mptspi_probe,
.remove = __devexit_p(mptscsih_remove),
- .driver = {
- .shutdown = mptscsih_shutdown,
- },
+ .shutdown = mptscsih_shutdown,
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
.resume = mptscsih_resume,
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index d272ea36a57..91d1c4c24d9 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -822,7 +822,7 @@ static int corkscrew_open(struct net_device *dev)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[i].addr = isa_virt_to_bus(skb->tail);
+ vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
}
vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
@@ -1406,7 +1406,7 @@ static int boomerang_rx(struct net_device *dev)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[entry].addr = isa_virt_to_bus(skb->tail);
+ vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data);
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 80ec9aa575b..07746b95fd8 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1802,7 +1802,7 @@ vortex_open(struct net_device *dev)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
+ vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
}
if (i != RX_RING_SIZE) {
int j;
@@ -2632,7 +2632,7 @@ boomerang_rx(struct net_device *dev)
pci_dma_sync_single_for_cpu(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
/* 'skb_put()' points to the start of sk_buff data area. */
memcpy(skb_put(skb, pkt_len),
- vp->rx_skbuff[entry]->tail,
+ vp->rx_skbuff[entry]->data,
pkt_len);
pci_dma_sync_single_for_device(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
vp->rx_copy++;
@@ -2678,7 +2678,7 @@ boomerang_rx(struct net_device *dev)
}
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
+ vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index e4b3c5c8854..7b293f01c9e 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -596,7 +596,7 @@ rx_status_loop:
mapping =
cp->rx_skb[rx_tail].mapping =
- pci_map_single(cp->pdev, new_skb->tail,
+ pci_map_single(cp->pdev, new_skb->data,
buflen, PCI_DMA_FROMDEVICE);
cp->rx_skb[rx_tail].skb = new_skb;
@@ -1101,7 +1101,7 @@ static int cp_refill_rx (struct cp_private *cp)
skb_reserve(skb, RX_OFFSET);
cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
- skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
cp->rx_skb[i].skb = skb;
cp->rx_ring[i].opts2 = 0;
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 65f97b1dc58..13b745b3966 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -546,11 +546,11 @@ static inline void init_rx_bufs(struct net_device *dev)
rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1));
rbd->b_addr = WSWAPrbd(virt_to_bus(rbd));
rbd->skb = skb;
- rbd->v_data = skb->tail;
- rbd->b_data = WSWAPchar(virt_to_bus(skb->tail));
+ rbd->v_data = skb->data;
+ rbd->b_data = WSWAPchar(virt_to_bus(skb->data));
rbd->size = PKT_BUF_SZ;
#ifdef __mc68000__
- cache_clear(virt_to_phys(skb->tail), PKT_BUF_SZ);
+ cache_clear(virt_to_phys(skb->data), PKT_BUF_SZ);
#endif
}
lp->rbd_head = lp->rbds;
@@ -816,10 +816,10 @@ static inline int i596_rx(struct net_device *dev)
rx_in_place = 1;
rbd->skb = newskb;
newskb->dev = dev;
- rbd->v_data = newskb->tail;
- rbd->b_data = WSWAPchar(virt_to_bus(newskb->tail));
+ rbd->v_data = newskb->data;
+ rbd->b_data = WSWAPchar(virt_to_bus(newskb->data));
#ifdef __mc68000__
- cache_clear(virt_to_phys(newskb->tail), PKT_BUF_SZ);
+ cache_clear(virt_to_phys(newskb->data), PKT_BUF_SZ);
#endif
}
else
@@ -840,7 +840,7 @@ memory_squeeze:
skb->protocol=eth_type_trans(skb,dev);
skb->len = pkt_len;
#ifdef __mc68000__
- cache_clear(virt_to_phys(rbd->skb->tail),
+ cache_clear(virt_to_phys(rbd->skb->data),
pkt_len);
#endif
netif_rx(skb);
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index b7dd7260caf..8618012df06 100755
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -87,6 +87,7 @@ Revision History:
#include <linux/if_vlan.h>
#include <linux/ctype.h>
#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -2006,12 +2007,11 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
}
/* Initialize DMA */
- if(!pci_dma_supported(pdev, 0xffffffff)){
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) < 0) {
printk(KERN_ERR "amd8111e: DMA not supported,"
"exiting.\n");
- goto err_free_reg;
- } else
- pdev->dma_mask = 0xffffffff;
+ goto err_free_reg;
+ }
reg_addr = pci_resource_start(pdev, 0);
reg_len = pci_resource_len(pdev, 0);
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index b8ab2b6355e..e613cc28974 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -34,10 +34,6 @@
only is it difficult to detect, it also moves around in I/O space in
response to inb()s from other device probes!
*/
-/*
- 99/03/03 Allied Telesis RE1000 Plus support by T.Hagawa
- 99/12/30 port to 2.3.35 by K.Takai
-*/
#include <linux/config.h>
#include <linux/errno.h>
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index aa42b7a2773..430c628279b 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -547,7 +547,7 @@ rio_timer (unsigned long data)
skb_reserve (skb, 2);
np->rx_ring[entry].fraginfo =
cpu_to_le64 (pci_map_single
- (np->pdev, skb->tail, np->rx_buf_sz,
+ (np->pdev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
}
np->rx_ring[entry].fraginfo |=
@@ -618,7 +618,7 @@ alloc_list (struct net_device *dev)
/* Rubicon now supports 40 bits of addressing space. */
np->rx_ring[i].fraginfo =
cpu_to_le64 ( pci_map_single (
- np->pdev, skb->tail, np->rx_buf_sz,
+ np->pdev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48;
}
@@ -906,7 +906,7 @@ receive_packet (struct net_device *dev)
/* 16 byte align the IP header */
skb_reserve (skb, 2);
eth_copy_and_sum (skb,
- np->rx_skbuff[entry]->tail,
+ np->rx_skbuff[entry]->data,
pkt_len, 0);
skb_put (skb, pkt_len);
pci_dma_sync_single_for_device(np->pdev,
@@ -950,7 +950,7 @@ receive_packet (struct net_device *dev)
skb_reserve (skb, 2);
np->rx_ring[entry].fraginfo =
cpu_to_le64 (pci_map_single
- (np->pdev, skb->tail, np->rx_buf_sz,
+ (np->pdev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
}
np->rx_ring[entry].fraginfo |=
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 1e56c8eea35..d0fa2448761 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2447,9 +2447,8 @@ static int e100_resume(struct pci_dev *pdev)
#endif
-static void e100_shutdown(struct device *dev)
+static void e100_shutdown(struct pci_dev *pdev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
@@ -2470,11 +2469,7 @@ static struct pci_driver e100_driver = {
.suspend = e100_suspend,
.resume = e100_resume,
#endif
-
- .driver = {
- .shutdown = e100_shutdown,
- }
-
+ .shutdown = e100_shutdown,
};
static int __init e100_init_module(void)
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 98b3a2fdce9..1795425f512 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1269,7 +1269,7 @@ speedo_init_rx_ring(struct net_device *dev)
if (skb == NULL)
break; /* OK. Just initially short of Rx bufs. */
skb->dev = dev; /* Mark as being used by this device. */
- rxf = (struct RxFD *)skb->tail;
+ rxf = (struct RxFD *)skb->data;
sp->rx_ringp[i] = rxf;
sp->rx_ring_dma[i] =
pci_map_single(sp->pdev, rxf,
@@ -1661,7 +1661,7 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
sp->rx_ringp[entry] = NULL;
return NULL;
}
- rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
+ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->data;
sp->rx_ring_dma[entry] =
pci_map_single(sp->pdev, rxf,
PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
@@ -1808,10 +1808,10 @@ speedo_rx(struct net_device *dev)
#if 1 || USE_IP_CSUM
/* Packet is in one chunk -- we can copy + cksum. */
- eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0);
+ eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
skb_put(skb, pkt_len);
#else
- memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail,
+ memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->data,
pkt_len);
#endif
pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 81ebaedaa24..87f522738bf 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1003,7 +1003,7 @@ static void epic_init_ring(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
- skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn);
}
ep->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -1274,7 +1274,7 @@ static int epic_rx(struct net_device *dev, int budget)
ep->rx_ring[entry].bufaddr,
ep->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0);
+ eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(ep->pci_dev,
ep->rx_ring[entry].bufaddr,
@@ -1308,7 +1308,7 @@ static int epic_rx(struct net_device *dev, int budget)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev,
- skb->tail, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
work_done++;
}
ep->rx_ring[entry].rxstatus = cpu_to_le32(DescOwn);
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 9e0303f6d73..55dbe9a3fd5 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1107,7 +1107,7 @@ static void allocate_rx_buffers(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
np->lack_rxbuf->skbuff = skb;
- np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->tail,
+ np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->data,
np->rx_buf_sz, PCI_DMA_FROMDEVICE);
np->lack_rxbuf->status = RXOWN;
++np->really_rx_count;
@@ -1300,7 +1300,7 @@ static void init_ring(struct net_device *dev)
++np->really_rx_count;
np->rx_ring[i].skbuff = skb;
skb->dev = dev; /* Mark as being used by this device. */
- np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->tail,
+ np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->data,
np->rx_buf_sz, PCI_DMA_FROMDEVICE);
np->rx_ring[i].status = RXOWN;
np->rx_ring[i].control |= RXIC;
@@ -1737,11 +1737,11 @@ static int netdev_rx(struct net_device *dev)
#if ! defined(__alpha__)
eth_copy_and_sum(skb,
- np->cur_rx->skbuff->tail, pkt_len, 0);
+ np->cur_rx->skbuff->data, pkt_len, 0);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
- np->cur_rx->skbuff->tail, pkt_len);
+ np->cur_rx->skbuff->data, pkt_len);
#endif
pci_dma_sync_single_for_device(np->pci_dev,
np->cur_rx->buffer,
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 3d96714ed3c..d9df1d9a573 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1149,7 +1149,7 @@ static void hamachi_tx_timeout(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev,
- skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+ skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn |
DescEndPacket | DescIntr | (hmp->rx_buf_sz - 2));
}
@@ -1210,7 +1210,7 @@ static void hamachi_init_ring(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev,
- skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+ skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
/* -2 because it doesn't REALLY have that first 2 bytes -KDU */
hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn |
DescEndPacket | DescIntr | (hmp->rx_buf_sz -2));
@@ -1509,7 +1509,7 @@ static int hamachi_rx(struct net_device *dev)
desc->addr,
hmp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- buf_addr = (u8 *) hmp->rx_skbuff[entry]->tail;
+ buf_addr = (u8 *) hmp->rx_skbuff[entry]->data;
frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12])));
if (hamachi_debug > 4)
printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n",
@@ -1678,7 +1678,7 @@ static int hamachi_rx(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev,
- skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+ skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
}
desc->status_n_length = cpu_to_le32(hmp->rx_buf_sz);
if (entry >= RX_RING_SIZE-1)
@@ -1772,9 +1772,9 @@ static int hamachi_close(struct net_device *dev)
readl(ioaddr + RxCurPtr) == (long)&hmp->rx_ring[i] ? '>' : ' ',
i, hmp->rx_ring[i].status_n_length, hmp->rx_ring[i].addr);
if (hamachi_debug > 6) {
- if (*(u8*)hmp->rx_skbuff[i]->tail != 0x69) {
+ if (*(u8*)hmp->rx_skbuff[i]->data != 0x69) {
u16 *addr = (u16 *)
- hmp->rx_skbuff[i]->tail;
+ hmp->rx_skbuff[i]->data;
int j;
for (j = 0; j < 0x50; j++)
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index ca90f0d1e4b..b4929beb33b 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -862,7 +862,7 @@ lance_init_ring(struct net_device *dev, int gfp)
lp->rx_skbuff[i] = skb;
if (skb) {
skb->dev = dev;
- rx_buff = skb->tail;
+ rx_buff = skb->data;
} else
rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp);
if (rx_buff == NULL)
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 5e263fcba66..41bad07ac1a 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -553,14 +553,14 @@ static inline void init_rx_bufs(struct net_device *dev)
if (skb == NULL)
panic("%s: alloc_skb() failed", __FILE__);
skb_reserve(skb, 2);
- dma_addr = dma_map_single(lp->dev, skb->tail,PKT_BUF_SZ,
+ dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ,
DMA_FROM_DEVICE);
skb->dev = dev;
rbd->v_next = rbd+1;
rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
rbd->skb = skb;
- rbd->v_data = skb->tail;
+ rbd->v_data = skb->data;
rbd->b_data = WSWAPchar(dma_addr);
rbd->size = PKT_BUF_SZ;
}
@@ -783,8 +783,8 @@ static inline int i596_rx(struct net_device *dev)
rx_in_place = 1;
rbd->skb = newskb;
newskb->dev = dev;
- dma_addr = dma_map_single(lp->dev, newskb->tail, PKT_BUF_SZ, DMA_FROM_DEVICE);
- rbd->v_data = newskb->tail;
+ dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
+ rbd->v_data = newskb->data;
rbd->b_data = WSWAPchar(dma_addr);
CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));
}
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index babb59e146e..9d6d2548c2d 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -1926,7 +1926,7 @@ static void refill_rx(struct net_device *dev)
break; /* Better luck next round. */
skb->dev = dev; /* Mark as being used by this device. */
np->rx_dma[entry] = pci_map_single(np->pci_dev,
- skb->tail, buflen, PCI_DMA_FROMDEVICE);
+ skb->data, buflen, PCI_DMA_FROMDEVICE);
np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
}
np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz);
@@ -2280,7 +2280,7 @@ static void netdev_rx(struct net_device *dev)
buflen,
PCI_DMA_FROMDEVICE);
eth_copy_and_sum(skb,
- np->rx_skbuff[entry]->tail, pkt_len, 0);
+ np->rx_skbuff[entry]->data, pkt_len, 0);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(np->pci_dev,
np->rx_dma[entry],
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index cc796527177..e64df4d0800 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -574,7 +574,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb)
dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC;
cmdsts = REAL_RX_BUF_SIZE | CMDSTS_INTR;
- buf = pci_map_single(dev->pci_dev, skb->tail,
+ buf = pci_map_single(dev->pci_dev, skb->data,
REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
build_rx_desc(dev, sg, 0, buf, cmdsts, 0);
/* update link of previous rx */
@@ -604,7 +604,7 @@ static inline int rx_refill(struct net_device *ndev, int gfp)
if (unlikely(!skb))
break;
- res = (long)skb->tail & 0xf;
+ res = (long)skb->data & 0xf;
res = 0x10 - res;
res &= 0xf;
skb_reserve(skb, res);
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 3213f3e5048..113b6809921 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1602,7 +1602,7 @@ pcnet32_init_ring(struct net_device *dev)
rmb();
if (lp->rx_dma_addr[i] == 0)
- lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail,
+ lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->data,
PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]);
lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
@@ -1983,7 +1983,7 @@ pcnet32_rx(struct net_device *dev)
lp->rx_skbuff[entry] = newskb;
newskb->dev = dev;
lp->rx_dma_addr[entry] =
- pci_map_single(lp->pci_dev, newskb->tail,
+ pci_map_single(lp->pci_dev, newskb->data,
PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]);
rx_in_place = 1;
@@ -2020,7 +2020,7 @@ pcnet32_rx(struct net_device *dev)
PKT_BUF_SZ-2,
PCI_DMA_FROMDEVICE);
eth_copy_and_sum(skb,
- (unsigned char *)(lp->rx_skbuff[entry]->tail),
+ (unsigned char *)(lp->rx_skbuff[entry]->data),
pkt_len,0);
pci_dma_sync_single_for_device(lp->pci_dev,
lp->rx_dma_addr[entry],
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index ce449fe90e6..d5afe05cd82 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1876,7 +1876,7 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
skb_reserve(skb, NET_IP_ALIGN);
*sk_buff = skb;
- mapping = pci_map_single(pdev, skb->tail, rx_buf_sz,
+ mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
PCI_DMA_FROMDEVICE);
rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
@@ -2336,7 +2336,7 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
if (skb) {
skb_reserve(skb, NET_IP_ALIGN);
- eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0);
+ eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
*sk_buff = skb;
rtl8169_mark_to_asic(desc, rx_buf_sz);
ret = 0;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index bb639a8794d..ea638b162d3 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1699,11 +1699,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
#else
ba = &nic->ba[ring_no][block_no][off];
skb_reserve(skb, BUF0_LEN);
- tmp = (unsigned long) skb->data;
- tmp += ALIGN_SIZE;
- tmp &= ~ALIGN_SIZE;
- skb->data = (void *) tmp;
- skb->tail = (void *) tmp;
+ tmp = ((unsigned long) skb->data & ALIGN_SIZE);
+ if (tmp)
+ skb_reserve(skb, (ALIGN_SIZE + 1) - tmp);
memset(rxdp, 0, sizeof(RxD_t));
rxdp->Buffer2_ptr = pci_map_single
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index fd2e7c37490..7abd55a4fb2 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -963,11 +963,11 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
/*
* Do not interrupt per DMA transfer.
*/
- dsc->dscr_a = virt_to_phys(sb_new->tail) |
+ dsc->dscr_a = virt_to_phys(sb_new->data) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
0;
#else
- dsc->dscr_a = virt_to_phys(sb_new->tail) |
+ dsc->dscr_a = virt_to_phys(sb_new->data) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
M_DMA_DSCRA_INTERRUPT;
#endif
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 127324f014d..23b713c700b 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1154,7 +1154,7 @@ sis900_init_rx_ring(struct net_device *net_dev)
sis_priv->rx_skbuff[i] = skb;
sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE;
sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev,
- skb->tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
}
sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
@@ -1776,7 +1776,7 @@ static int sis900_rx(struct net_device *net_dev)
sis_priv->rx_skbuff[entry] = skb;
sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
sis_priv->rx_ring[entry].bufptr =
- pci_map_single(sis_priv->pci_dev, skb->tail,
+ pci_map_single(sis_priv->pci_dev, skb->data,
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
sis_priv->dirty_rx++;
}
@@ -1809,7 +1809,7 @@ static int sis900_rx(struct net_device *net_dev)
sis_priv->rx_skbuff[entry] = skb;
sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
sis_priv->rx_ring[entry].bufptr =
- pci_map_single(sis_priv->pci_dev, skb->tail,
+ pci_map_single(sis_priv->pci_dev, skb->data,
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
}
}
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 30e8d589d16..3dbb1cb09ed 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -7,7 +7,7 @@
* of the original driver such as link fail-over and link management because
* those should be done at higher levels.
*
- * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+ * Copyright (C) 2004, 2005 Stephen Hemminger <shemminger@osdl.org>
*
* 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
@@ -42,19 +42,20 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.6"
+#define DRV_VERSION "0.7"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
#define DEFAULT_RX_RING_SIZE 512
#define MAX_TX_RING_SIZE 1024
#define MAX_RX_RING_SIZE 4096
+#define RX_COPY_THRESHOLD 128
+#define RX_BUF_SIZE 1536
#define PHY_RETRIES 1000
#define ETH_JUMBO_MTU 9000
#define TX_WATCHDOG (5 * HZ)
#define NAPI_WEIGHT 64
#define BLINK_HZ (HZ/4)
-#define LINK_POLL_HZ (HZ/10)
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -70,28 +71,17 @@ module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
static const struct pci_device_id skge_id_table[] = {
- { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_SYSKONNECT, 0x9E00, /* SK-9Exx */
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_MARVELL, 0x4320, /* Gigabit Ethernet Controller */
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_MARVELL, 0x5005, /* Marvell (11ab), Belkin */
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064,
- PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) },
+ { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
+ { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
+ { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) },
+ { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -99,19 +89,22 @@ MODULE_DEVICE_TABLE(pci, skge_id_table);
static int skge_up(struct net_device *dev);
static int skge_down(struct net_device *dev);
static void skge_tx_clean(struct skge_port *skge);
-static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
-static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static void genesis_get_stats(struct skge_port *skge, u64 *data);
static void yukon_get_stats(struct skge_port *skge, u64 *data);
static void yukon_init(struct skge_hw *hw, int port);
static void yukon_reset(struct skge_hw *hw, int port);
static void genesis_mac_init(struct skge_hw *hw, int port);
static void genesis_reset(struct skge_hw *hw, int port);
+static void genesis_link_up(struct skge_port *skge);
+/* Avoid conditionals by using array */
static const int txqaddr[] = { Q_XA1, Q_XA2 };
static const int rxqaddr[] = { Q_R1, Q_R2 };
static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
+static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 };
/* Don't need to look at whole 16K.
* last interesting register is descriptor poll timer.
@@ -154,7 +147,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
static int wol_supported(const struct skge_hw *hw)
{
return !((hw->chip_id == CHIP_ID_GENESIS ||
- (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0)));
+ (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0)));
}
static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -170,7 +163,7 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct skge_port *skge = netdev_priv(dev);
struct skge_hw *hw = skge->hw;
- if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+ if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
return -EOPNOTSUPP;
if (wol->wolopts == WAKE_MAGIC && !wol_supported(hw))
@@ -190,6 +183,36 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
return 0;
}
+/* Determine supported/adverised modes based on hardware.
+ * Note: ethtoool ADVERTISED_xxx == SUPPORTED_xxx
+ */
+static u32 skge_supported_modes(const struct skge_hw *hw)
+{
+ u32 supported;
+
+ if (iscopper(hw)) {
+ supported = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full
+ | SUPPORTED_Autoneg| SUPPORTED_TP;
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ supported &= ~(SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full);
+
+ else if (hw->chip_id == CHIP_ID_YUKON)
+ supported &= ~SUPPORTED_1000baseT_Half;
+ } else
+ supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
+ | SUPPORTED_Autoneg;
+
+ return supported;
+}
static int skge_get_settings(struct net_device *dev,
struct ethtool_cmd *ecmd)
@@ -198,38 +221,13 @@ static int skge_get_settings(struct net_device *dev,
struct skge_hw *hw = skge->hw;
ecmd->transceiver = XCVR_INTERNAL;
+ ecmd->supported = skge_supported_modes(hw);
if (iscopper(hw)) {
- if (hw->chip_id == CHIP_ID_GENESIS)
- ecmd->supported = SUPPORTED_1000baseT_Full
- | SUPPORTED_1000baseT_Half
- | SUPPORTED_Autoneg | SUPPORTED_TP;
- else {
- ecmd->supported = SUPPORTED_10baseT_Half
- | SUPPORTED_10baseT_Full
- | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full
- | SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full
- | SUPPORTED_Autoneg| SUPPORTED_TP;
-
- if (hw->chip_id == CHIP_ID_YUKON)
- ecmd->supported &= ~SUPPORTED_1000baseT_Half;
-
- else if (hw->chip_id == CHIP_ID_YUKON_FE)
- ecmd->supported &= ~(SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full);
- }
-
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
- } else {
- ecmd->supported = SUPPORTED_1000baseT_Full
- | SUPPORTED_FIBRE
- | SUPPORTED_Autoneg;
-
+ } else
ecmd->port = PORT_FIBRE;
- }
ecmd->advertising = skge->advertising;
ecmd->autoneg = skge->autoneg;
@@ -238,65 +236,57 @@ static int skge_get_settings(struct net_device *dev,
return 0;
}
-static u32 skge_modes(const struct skge_hw *hw)
-{
- u32 modes = ADVERTISED_Autoneg
- | ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half
- | ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half
- | ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half;
-
- if (iscopper(hw)) {
- modes |= ADVERTISED_TP;
- switch(hw->chip_id) {
- case CHIP_ID_GENESIS:
- modes &= ~(ADVERTISED_100baseT_Full
- | ADVERTISED_100baseT_Half
- | ADVERTISED_10baseT_Full
- | ADVERTISED_10baseT_Half);
- break;
-
- case CHIP_ID_YUKON:
- modes &= ~ADVERTISED_1000baseT_Half;
- break;
-
- case CHIP_ID_YUKON_FE:
- modes &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full);
- break;
- }
- } else {
- modes |= ADVERTISED_FIBRE;
- modes &= ~ADVERTISED_1000baseT_Half;
- }
- return modes;
-}
-
static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct skge_port *skge = netdev_priv(dev);
const struct skge_hw *hw = skge->hw;
+ u32 supported = skge_supported_modes(hw);
if (ecmd->autoneg == AUTONEG_ENABLE) {
- if (ecmd->advertising & skge_modes(hw))
- return -EINVAL;
+ ecmd->advertising = supported;
+ skge->duplex = -1;
+ skge->speed = -1;
} else {
+ u32 setting;
+
switch(ecmd->speed) {
case SPEED_1000:
- if (hw->chip_id == CHIP_ID_YUKON_FE)
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_1000baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_1000baseT_Half;
+ else
return -EINVAL;
break;
case SPEED_100:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_100baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_100baseT_Half;
+ else
+ return -EINVAL;
+ break;
+
case SPEED_10:
- if (iscopper(hw) || hw->chip_id == CHIP_ID_GENESIS)
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_10baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_10baseT_Half;
+ else
return -EINVAL;
break;
default:
return -EINVAL;
}
+
+ if ((setting & supported) == 0)
+ return -EINVAL;
+
+ skge->speed = ecmd->speed;
+ skge->duplex = ecmd->duplex;
}
skge->autoneg = ecmd->autoneg;
- skge->speed = ecmd->speed;
- skge->duplex = ecmd->duplex;
skge->advertising = ecmd->advertising;
if (netif_running(dev)) {
@@ -393,7 +383,7 @@ static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
int i;
- switch(stringset) {
+ switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(skge_stats); i++)
memcpy(data + i * ETH_GSTRING_LEN,
@@ -511,14 +501,6 @@ static int skge_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
-/* Only Yukon II supports TSO (not implemented yet) */
-static int skge_set_tso(struct net_device *dev, u32 data)
-{
- if (data)
- return -EOPNOTSUPP;
- return 0;
-}
-
static void skge_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *ecmd)
{
@@ -540,9 +522,9 @@ static int skge_set_pauseparam(struct net_device *dev,
skge->autoneg = ecmd->autoneg;
if (ecmd->rx_pause && ecmd->tx_pause)
skge->flow_control = FLOW_MODE_SYMMETRIC;
- else if(ecmd->rx_pause && !ecmd->tx_pause)
+ else if (ecmd->rx_pause && !ecmd->tx_pause)
skge->flow_control = FLOW_MODE_REM_SEND;
- else if(!ecmd->rx_pause && ecmd->tx_pause)
+ else if (!ecmd->rx_pause && ecmd->tx_pause)
skge->flow_control = FLOW_MODE_LOC_SEND;
else
skge->flow_control = FLOW_MODE_NONE;
@@ -559,8 +541,6 @@ static inline u32 hwkhz(const struct skge_hw *hw)
{
if (hw->chip_id == CHIP_ID_GENESIS)
return 53215; /* or: 53.125 MHz */
- else if (hw->chip_id == CHIP_ID_YUKON_EC)
- return 125000; /* or: 125.000 MHz */
else
return 78215; /* or: 78.125 MHz */
}
@@ -643,30 +623,18 @@ static int skge_set_coalesce(struct net_device *dev,
static void skge_led_on(struct skge_hw *hw, int port)
{
if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
skge_write8(hw, B0_LED, LED_STAT_ON);
- skge_write8(hw, SKGEMAC_REG(port, RX_LED_TST), LED_T_ON);
- skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 100);
- skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START);
+ skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
- switch (hw->phy_type) {
- case SK_PHY_BCOM:
- skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL,
- PHY_B_PEC_LED_ON);
- break;
- case SK_PHY_LONE:
- skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG,
- 0x0800);
- break;
- default:
- skge_write8(hw, SKGEMAC_REG(port, TX_LED_TST), LED_T_ON);
- skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 100);
- skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START);
- }
+ /* For Broadcom Phy only */
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
} else {
- skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
- skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
PHY_M_LED_MO_DUP(MO_LED_ON) |
PHY_M_LED_MO_10(MO_LED_ON) |
PHY_M_LED_MO_100(MO_LED_ON) |
@@ -678,28 +646,17 @@ static void skge_led_on(struct skge_hw *hw, int port)
static void skge_led_off(struct skge_hw *hw, int port)
{
if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_OFF);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
skge_write8(hw, B0_LED, LED_STAT_OFF);
- skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 0);
- skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_T_OFF);
+ skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
- switch (hw->phy_type) {
- case SK_PHY_BCOM:
- skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL,
- PHY_B_PEC_LED_OFF);
- break;
- case SK_PHY_LONE:
- skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG,
- PHY_L_LC_LEDT);
- break;
- default:
- skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 0);
- skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_T_OFF);
- }
+ /* Broadcom only */
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
} else {
- skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
- skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
PHY_M_LED_MO_DUP(MO_LED_OFF) |
PHY_M_LED_MO_10(MO_LED_OFF) |
PHY_M_LED_MO_100(MO_LED_OFF) |
@@ -730,7 +687,7 @@ static int skge_phys_id(struct net_device *dev, u32 data)
{
struct skge_port *skge = netdev_priv(dev);
- if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+ if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
/* start blinking */
@@ -763,8 +720,6 @@ static struct ethtool_ops skge_ethtool_ops = {
.set_pauseparam = skge_set_pauseparam,
.get_coalesce = skge_get_coalesce,
.set_coalesce = skge_set_coalesce,
- .get_tso = ethtool_op_get_tso,
- .set_tso = skge_set_tso,
.get_sg = ethtool_op_get_sg,
.set_sg = skge_set_sg,
.get_tx_csum = ethtool_op_get_tx_csum,
@@ -793,6 +748,7 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) {
e->desc = d;
+ e->skb = NULL;
if (i == ring->count - 1) {
e->next = ring->start;
d->next_offset = base;
@@ -806,24 +762,23 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
return 0;
}
-/* Setup buffer for receiving */
-static inline int skge_rx_alloc(struct skge_port *skge,
- struct skge_element *e)
+static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size)
{
- unsigned long bufsize = skge->netdev->mtu + ETH_HLEN; /* VLAN? */
- struct skge_rx_desc *rd = e->desc;
- struct sk_buff *skb;
- u64 map;
+ struct sk_buff *skb = dev_alloc_skb(size);
- skb = dev_alloc_skb(bufsize + NET_IP_ALIGN);
- if (unlikely(!skb)) {
- printk(KERN_DEBUG PFX "%s: out of memory for receive\n",
- skge->netdev->name);
- return -ENOMEM;
+ if (likely(skb)) {
+ skb->dev = dev;
+ skb_reserve(skb, NET_IP_ALIGN);
}
+ return skb;
+}
- skb->dev = skge->netdev;
- skb_reserve(skb, NET_IP_ALIGN);
+/* Allocate and setup a new buffer for receiving */
+static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
+ struct sk_buff *skb, unsigned int bufsize)
+{
+ struct skge_rx_desc *rd = e->desc;
+ u64 map;
map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
PCI_DMA_FROMDEVICE);
@@ -841,55 +796,69 @@ static inline int skge_rx_alloc(struct skge_port *skge,
rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
pci_unmap_addr_set(e, mapaddr, map);
pci_unmap_len_set(e, maplen, bufsize);
- return 0;
}
-/* Free all unused buffers in receive ring, assumes receiver stopped */
+/* Resume receiving using existing skb,
+ * Note: DMA address is not changed by chip.
+ * MTU not changed while receiver active.
+ */
+static void skge_rx_reuse(struct skge_element *e, unsigned int size)
+{
+ struct skge_rx_desc *rd = e->desc;
+
+ rd->csum2 = 0;
+ rd->csum2_start = ETH_HLEN;
+
+ wmb();
+
+ rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size;
+}
+
+
+/* Free all buffers in receive ring, assumes receiver stopped */
static void skge_rx_clean(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
struct skge_ring *ring = &skge->rx_ring;
struct skge_element *e;
- for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+ e = ring->start;
+ do {
struct skge_rx_desc *rd = e->desc;
rd->control = 0;
-
- pci_unmap_single(hw->pdev,
- pci_unmap_addr(e, mapaddr),
- pci_unmap_len(e, maplen),
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb(e->skb);
- e->skb = NULL;
- }
- ring->to_clean = e;
+ if (e->skb) {
+ pci_unmap_single(hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ pci_unmap_len(e, maplen),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(e->skb);
+ e->skb = NULL;
+ }
+ } while ((e = e->next) != ring->start);
}
+
/* Allocate buffers for receive ring
- * For receive: to_use is refill location
- * to_clean is next received frame.
- *
- * if (to_use == to_clean)
- * then ring all frames in ring need buffers
- * if (to_use->next == to_clean)
- * then ring all frames in ring have buffers
+ * For receive: to_clean is next received frame.
*/
static int skge_rx_fill(struct skge_port *skge)
{
struct skge_ring *ring = &skge->rx_ring;
struct skge_element *e;
- int ret = 0;
+ unsigned int bufsize = skge->rx_buf_size;
- for (e = ring->to_use; e->next != ring->to_clean; e = e->next) {
- if (skge_rx_alloc(skge, e)) {
- ret = 1;
- break;
- }
+ e = ring->start;
+ do {
+ struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize);
- }
- ring->to_use = e;
+ if (!skb)
+ return -ENOMEM;
+
+ skge_rx_setup(skge, e, skb, bufsize);
+ } while ( (e = e->next) != ring->start);
- return ret;
+ ring->to_clean = ring->start;
+ return 0;
}
static void skge_link_up(struct skge_port *skge)
@@ -919,50 +888,50 @@ static void skge_link_down(struct skge_port *skge)
printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
}
-static u16 skge_xm_phy_read(struct skge_hw *hw, int port, u16 reg)
+static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg)
{
int i;
u16 v;
- skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
- v = skge_xm_read16(hw, port, XM_PHY_DATA);
- if (hw->phy_type != SK_PHY_XMAC) {
- for (i = 0; i < PHY_RETRIES; i++) {
- udelay(1);
- if (skge_xm_read16(hw, port, XM_MMU_CMD)
- & XM_MMU_PHY_RDY)
- goto ready;
- }
+ xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+ v = xm_read16(hw, port, XM_PHY_DATA);
- printk(KERN_WARNING PFX "%s: phy read timed out\n",
- hw->dev[port]->name);
- return 0;
- ready:
- v = skge_xm_read16(hw, port, XM_PHY_DATA);
+ /* Need to wait for external PHY */
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+ if (xm_read16(hw, port, XM_MMU_CMD)
+ & XM_MMU_PHY_RDY)
+ goto ready;
}
+ printk(KERN_WARNING PFX "%s: phy read timed out\n",
+ hw->dev[port]->name);
+ return 0;
+ ready:
+ v = xm_read16(hw, port, XM_PHY_DATA);
+
return v;
}
-static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
{
int i;
- skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+ xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
for (i = 0; i < PHY_RETRIES; i++) {
- if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
goto ready;
- cpu_relax();
+ udelay(1);
}
printk(KERN_WARNING PFX "%s: phy write failed to come ready\n",
hw->dev[port]->name);
ready:
- skge_xm_write16(hw, port, XM_PHY_DATA, val);
+ xm_write16(hw, port, XM_PHY_DATA, val);
for (i = 0; i < PHY_RETRIES; i++) {
udelay(1);
- if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
return;
}
printk(KERN_WARNING PFX "%s: phy write timed out\n",
@@ -999,34 +968,112 @@ static void genesis_init(struct skge_hw *hw)
static void genesis_reset(struct skge_hw *hw, int port)
{
- int i;
- u64 zero = 0;
+ const u8 zero[8] = { 0 };
/* reset the statistics module */
- skge_xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
- skge_xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
- skge_xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */
- skge_xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */
- skge_xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */
+ xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
+ xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
+ xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */
+ xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */
+ xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */
- /* disable all PHY IRQs */
- if (hw->phy_type == SK_PHY_BCOM)
- skge_xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+ /* disable Broadcom PHY IRQ */
+ xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
- skge_xm_outhash(hw, port, XM_HSM, (u8 *) &zero);
- for (i = 0; i < 15; i++)
- skge_xm_outaddr(hw, port, XM_EXM(i), (u8 *) &zero);
- skge_xm_outhash(hw, port, XM_SRC_CHK, (u8 *) &zero);
+ xm_outhash(hw, port, XM_HSM, zero);
}
-static void genesis_mac_init(struct skge_hw *hw, int port)
+/* Convert mode to MII values */
+static const u16 phy_pause_map[] = {
+ [FLOW_MODE_NONE] = 0,
+ [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM,
+ [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP,
+ [FLOW_MODE_REM_SEND] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM,
+};
+
+
+/* Check status of Broadcom phy link */
+static void bcom_check_link(struct skge_hw *hw, int port)
{
- struct skge_port *skge = netdev_priv(hw->dev[port]);
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+ u16 status;
+
+ /* read twice because of latch */
+ (void) xm_phy_read(hw, port, PHY_BCOM_STAT);
+ status = xm_phy_read(hw, port, PHY_BCOM_STAT);
+
+ pr_debug("bcom_check_link status=0x%x\n", status);
+
+ if ((status & PHY_ST_LSYNC) == 0) {
+ u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
+ cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ xm_write16(hw, port, XM_MMU_CMD, cmd);
+ /* dummy read to ensure writing */
+ (void) xm_read16(hw, port, XM_MMU_CMD);
+
+ if (netif_carrier_ok(dev))
+ skge_link_down(skge);
+ } else {
+ if (skge->autoneg == AUTONEG_ENABLE &&
+ (status & PHY_ST_AN_OVER)) {
+ u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP);
+ u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+
+ if (lpa & PHY_B_AN_RF) {
+ printk(KERN_NOTICE PFX "%s: remote fault\n",
+ dev->name);
+ return;
+ }
+
+ /* Check Duplex mismatch */
+ switch(aux & PHY_B_AS_AN_RES_MSK) {
+ case PHY_B_RES_1000FD:
+ skge->duplex = DUPLEX_FULL;
+ break;
+ case PHY_B_RES_1000HD:
+ skge->duplex = DUPLEX_HALF;
+ break;
+ default:
+ printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+ dev->name);
+ return;
+ }
+
+
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ switch (aux & PHY_B_AS_PAUSE_MSK) {
+ case PHY_B_AS_PAUSE_MSK:
+ skge->flow_control = FLOW_MODE_SYMMETRIC;
+ break;
+ case PHY_B_AS_PRR:
+ skge->flow_control = FLOW_MODE_REM_SEND;
+ break;
+ case PHY_B_AS_PRT:
+ skge->flow_control = FLOW_MODE_LOC_SEND;
+ break;
+ default:
+ skge->flow_control = FLOW_MODE_NONE;
+ }
+
+ skge->speed = SPEED_1000;
+ }
+
+ if (!netif_carrier_ok(dev))
+ genesis_link_up(skge);
+ }
+}
+
+/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
+ * Phy on for 100 or 10Mbit operation
+ */
+static void bcom_phy_init(struct skge_port *skge, int jumbo)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
int i;
- u32 r;
- u16 id1;
- u16 ctrl1, ctrl2, ctrl3, ctrl4, ctrl5;
+ u16 id1, r, ext, ctl;
/* magic workaround patterns for Broadcom */
static const struct {
@@ -1042,16 +1089,120 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
};
+ pr_debug("bcom_phy_init\n");
+
+ /* read Id from external PHY (all have the same address) */
+ id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
+
+ /* Optimize MDIO transfer by suppressing preamble. */
+ r = xm_read16(hw, port, XM_MMU_CMD);
+ r |= XM_MMU_NO_PRE;
+ xm_write16(hw, port, XM_MMU_CMD,r);
+
+ switch(id1) {
+ case PHY_BCOM_ID1_C0:
+ /*
+ * Workaround BCOM Errata for the C0 type.
+ * Write magic patterns to reserved registers.
+ */
+ for (i = 0; i < ARRAY_SIZE(C0hack); i++)
+ xm_phy_write(hw, port,
+ C0hack[i].reg, C0hack[i].val);
+
+ break;
+ case PHY_BCOM_ID1_A1:
+ /*
+ * Workaround BCOM Errata for the A1 type.
+ * Write magic patterns to reserved registers.
+ */
+ for (i = 0; i < ARRAY_SIZE(A1hack); i++)
+ xm_phy_write(hw, port,
+ A1hack[i].reg, A1hack[i].val);
+ break;
+ }
+
+ /*
+ * Workaround BCOM Errata (#10523) for all BCom PHYs.
+ * Disable Power Management after reset.
+ */
+ r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL);
+ r |= PHY_B_AC_DIS_PM;
+ xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r);
+
+ /* Dummy read */
+ xm_read16(hw, port, XM_ISRC);
+
+ ext = PHY_B_PEC_EN_LTR; /* enable tx led */
+ ctl = PHY_CT_SP1000; /* always 1000mbit */
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ /*
+ * Workaround BCOM Errata #1 for the C5 type.
+ * 1000Base-T Link Acquisition Failure in Slave Mode
+ * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+ */
+ u16 adv = PHY_B_1000C_RD;
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ adv |= PHY_B_1000C_AHD;
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ adv |= PHY_B_1000C_AFD;
+ xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv);
+
+ ctl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ if (skge->duplex == DUPLEX_FULL)
+ ctl |= PHY_CT_DUP_MD;
+ /* Force to slave */
+ xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE);
+ }
+
+ /* Set autonegotiation pause parameters */
+ xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV,
+ phy_pause_map[skge->flow_control] | PHY_AN_CSMA);
+
+ /* Handle Jumbo frames */
+ if (jumbo) {
+ xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+ PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK);
+
+ ext |= PHY_B_PEC_HIGH_LA;
+
+ }
+
+ xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext);
+ xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl);
+
+ /* Use link status change interrrupt */
+ xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+
+ bcom_check_link(hw, port);
+}
+
+static void genesis_mac_init(struct skge_hw *hw, int port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+ int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN;
+ int i;
+ u32 r;
+ const u8 zero[6] = { 0 };
+
+ /* Clear MIB counters */
+ xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+ /* Clear two times according to Errata #3 */
+ xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
/* initialize Rx, Tx and Link LED */
- skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON);
- skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
- skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START);
- skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
/* Unreset the XMAC. */
- skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
/*
* Perform additional initialization for external PHYs,
@@ -1059,67 +1210,56 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
* GMII mode.
*/
spin_lock_bh(&hw->phy_lock);
- if (hw->phy_type != SK_PHY_XMAC) {
- /* Take PHY out of reset. */
- r = skge_read32(hw, B2_GP_IO);
- if (port == 0)
- r |= GP_DIR_0|GP_IO_0;
- else
- r |= GP_DIR_2|GP_IO_2;
-
- skge_write32(hw, B2_GP_IO, r);
- skge_read32(hw, B2_GP_IO);
-
- /* Enable GMII mode on the XMAC. */
- skge_xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
-
- id1 = skge_xm_phy_read(hw, port, PHY_XMAC_ID1);
-
- /* Optimize MDIO transfer by suppressing preamble. */
- skge_xm_write16(hw, port, XM_MMU_CMD,
- skge_xm_read16(hw, port, XM_MMU_CMD)
- | XM_MMU_NO_PRE);
-
- if (id1 == PHY_BCOM_ID1_C0) {
- /*
- * Workaround BCOM Errata for the C0 type.
- * Write magic patterns to reserved registers.
- */
- for (i = 0; i < ARRAY_SIZE(C0hack); i++)
- skge_xm_phy_write(hw, port,
- C0hack[i].reg, C0hack[i].val);
-
- } else if (id1 == PHY_BCOM_ID1_A1) {
- /*
- * Workaround BCOM Errata for the A1 type.
- * Write magic patterns to reserved registers.
- */
- for (i = 0; i < ARRAY_SIZE(A1hack); i++)
- skge_xm_phy_write(hw, port,
- A1hack[i].reg, A1hack[i].val);
- }
+ /* Take external Phy out of reset */
+ r = skge_read32(hw, B2_GP_IO);
+ if (port == 0)
+ r |= GP_DIR_0|GP_IO_0;
+ else
+ r |= GP_DIR_2|GP_IO_2;
- /*
- * Workaround BCOM Errata (#10523) for all BCom PHYs.
- * Disable Power Management after reset.
- */
- r = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL);
- skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r | PHY_B_AC_DIS_PM);
- }
+ skge_write32(hw, B2_GP_IO, r);
+ skge_read32(hw, B2_GP_IO);
+ spin_unlock_bh(&hw->phy_lock);
- /* Dummy read */
- skge_xm_read16(hw, port, XM_ISRC);
+ /* Enable GMII interfac */
+ xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+
+ bcom_phy_init(skge, jumbo);
+
+ /* Set Station Address */
+ xm_outaddr(hw, port, XM_SA, dev->dev_addr);
+
+ /* We don't use match addresses so clear */
+ for (i = 1; i < 16; i++)
+ xm_outaddr(hw, port, XM_EXM(i), zero);
- r = skge_xm_read32(hw, port, XM_MODE);
- skge_xm_write32(hw, port, XM_MODE, r|XM_MD_CSA);
+ /* configure Rx High Water Mark (XM_RX_HI_WM) */
+ xm_write16(hw, port, XM_RX_HI_WM, 1450);
/* We don't need the FCS appended to the packet. */
- r = skge_xm_read16(hw, port, XM_RX_CMD);
- skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_STRIP_FCS);
+ r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS;
+ if (jumbo)
+ r |= XM_RX_BIG_PK_OK;
+
+ if (skge->duplex == DUPLEX_HALF) {
+ /*
+ * If in manual half duplex mode the other side might be in
+ * full duplex mode, so ignore if a carrier extension is not seen
+ * on frames received
+ */
+ r |= XM_RX_DIS_CEXT;
+ }
+ xm_write16(hw, port, XM_RX_CMD, r);
+
/* We want short frames padded to 60 bytes. */
- r = skge_xm_read16(hw, port, XM_TX_CMD);
- skge_xm_write16(hw, port, XM_TX_CMD, r | XM_TX_AUTO_PAD);
+ xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD);
+
+ /*
+ * Bump up the transmit threshold. This helps hold off transmit
+ * underruns when we're blasting traffic from both ports at once.
+ */
+ xm_write16(hw, port, XM_TX_THR, 512);
/*
* Enable the reception of all error frames. This is is
@@ -1135,19 +1275,22 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
* case the XMAC will start transfering frames out of the
* RX FIFO as soon as the FIFO threshold is reached.
*/
- r = skge_xm_read32(hw, port, XM_MODE);
- skge_xm_write32(hw, port, XM_MODE,
- XM_MD_RX_CRCE|XM_MD_RX_LONG|XM_MD_RX_RUNT|
- XM_MD_RX_ERR|XM_MD_RX_IRLE);
+ xm_write32(hw, port, XM_MODE, XM_DEF_MODE);
- skge_xm_outaddr(hw, port, XM_SA, hw->dev[port]->dev_addr);
- skge_xm_outaddr(hw, port, XM_EXM(0), hw->dev[port]->dev_addr);
/*
- * Bump up the transmit threshold. This helps hold off transmit
- * underruns when we're blasting traffic from both ports at once.
+ * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
+ * - Enable all bits excepting 'Octets Rx OK Low CntOv'
+ * and 'Octets Rx OK Hi Cnt Ov'.
*/
- skge_xm_write16(hw, port, XM_TX_THR, 512);
+ xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK);
+
+ /*
+ * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
+ * - Enable all bits excepting 'Octets Tx OK Low CntOv'
+ * and 'Octets Tx OK Hi Cnt Ov'.
+ */
+ xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK);
/* Configure MAC arbiter */
skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
@@ -1164,137 +1307,30 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
skge_write8(hw, B3_MA_RCINI_TX2, 0);
/* Configure Rx MAC FIFO */
- skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_CLR);
- skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT);
- skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+ skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_CLR);
+ skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT);
+ skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
/* Configure Tx MAC FIFO */
- skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_CLR);
- skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
- skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+ skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_CLR);
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+ skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
- if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+ if (jumbo) {
/* Enable frame flushing if jumbo frames used */
- skge_write16(hw, SKGEMAC_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH);
+ skge_write16(hw, SK_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH);
} else {
/* enable timeout timers if normal frames */
skge_write16(hw, B3_PA_CTRL,
- port == 0 ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2);
+ (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2);
}
-
-
- r = skge_xm_read16(hw, port, XM_RX_CMD);
- if (hw->dev[port]->mtu > ETH_DATA_LEN)
- skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_BIG_PK_OK);
- else
- skge_xm_write16(hw, port, XM_RX_CMD, r & ~(XM_RX_BIG_PK_OK));
-
- switch (hw->phy_type) {
- case SK_PHY_XMAC:
- if (skge->autoneg == AUTONEG_ENABLE) {
- ctrl1 = PHY_X_AN_FD | PHY_X_AN_HD;
-
- switch (skge->flow_control) {
- case FLOW_MODE_NONE:
- ctrl1 |= PHY_X_P_NO_PAUSE;
- break;
- case FLOW_MODE_LOC_SEND:
- ctrl1 |= PHY_X_P_ASYM_MD;
- break;
- case FLOW_MODE_SYMMETRIC:
- ctrl1 |= PHY_X_P_SYM_MD;
- break;
- case FLOW_MODE_REM_SEND:
- ctrl1 |= PHY_X_P_BOTH_MD;
- break;
- }
-
- skge_xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl1);
- ctrl2 = PHY_CT_ANE | PHY_CT_RE_CFG;
- } else {
- ctrl2 = 0;
- if (skge->duplex == DUPLEX_FULL)
- ctrl2 |= PHY_CT_DUP_MD;
- }
-
- skge_xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl2);
- break;
-
- case SK_PHY_BCOM:
- ctrl1 = PHY_CT_SP1000;
- ctrl2 = 0;
- ctrl3 = PHY_SEL_TYPE;
- ctrl4 = PHY_B_PEC_EN_LTR;
- ctrl5 = PHY_B_AC_TX_TST;
-
- if (skge->autoneg == AUTONEG_ENABLE) {
- /*
- * Workaround BCOM Errata #1 for the C5 type.
- * 1000Base-T Link Acquisition Failure in Slave Mode
- * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
- */
- ctrl2 |= PHY_B_1000C_RD;
- if (skge->advertising & ADVERTISED_1000baseT_Half)
- ctrl2 |= PHY_B_1000C_AHD;
- if (skge->advertising & ADVERTISED_1000baseT_Full)
- ctrl2 |= PHY_B_1000C_AFD;
-
- /* Set Flow-control capabilities */
- switch (skge->flow_control) {
- case FLOW_MODE_NONE:
- ctrl3 |= PHY_B_P_NO_PAUSE;
- break;
- case FLOW_MODE_LOC_SEND:
- ctrl3 |= PHY_B_P_ASYM_MD;
- break;
- case FLOW_MODE_SYMMETRIC:
- ctrl3 |= PHY_B_P_SYM_MD;
- break;
- case FLOW_MODE_REM_SEND:
- ctrl3 |= PHY_B_P_BOTH_MD;
- break;
- }
-
- /* Restart Auto-negotiation */
- ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
- } else {
- if (skge->duplex == DUPLEX_FULL)
- ctrl1 |= PHY_CT_DUP_MD;
-
- ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
- }
-
- skge_xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, ctrl2);
- skge_xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, ctrl3);
-
- if (skge->netdev->mtu > ETH_DATA_LEN) {
- ctrl4 |= PHY_B_PEC_HIGH_LA;
- ctrl5 |= PHY_B_AC_LONG_PACK;
-
- skge_xm_phy_write(hw, port,PHY_BCOM_AUX_CTRL, ctrl5);
- }
-
- skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ctrl4);
- skge_xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl1);
- break;
- }
- spin_unlock_bh(&hw->phy_lock);
-
- /* Clear MIB counters */
- skge_xm_write16(hw, port, XM_STAT_CMD,
- XM_SC_CLR_RXC | XM_SC_CLR_TXC);
- /* Clear two times according to Errata #3 */
- skge_xm_write16(hw, port, XM_STAT_CMD,
- XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-
- /* Start polling for link status */
- mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
}
static void genesis_stop(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
+ u32 reg;
/* Clear Tx packet arbiter timeout IRQ */
skge_write16(hw, B3_PA_CTRL,
@@ -1304,33 +1340,30 @@ static void genesis_stop(struct skge_port *skge)
* If the transfer stucks at the MAC the STOP command will not
* terminate if we don't flush the XMAC's transmit FIFO !
*/
- skge_xm_write32(hw, port, XM_MODE,
- skge_xm_read32(hw, port, XM_MODE)|XM_MD_FTF);
+ xm_write32(hw, port, XM_MODE,
+ xm_read32(hw, port, XM_MODE)|XM_MD_FTF);
/* Reset the MAC */
- skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
/* For external PHYs there must be special handling */
- if (hw->phy_type != SK_PHY_XMAC) {
- u32 reg = skge_read32(hw, B2_GP_IO);
-
- if (port == 0) {
- reg |= GP_DIR_0;
- reg &= ~GP_IO_0;
- } else {
- reg |= GP_DIR_2;
- reg &= ~GP_IO_2;
- }
- skge_write32(hw, B2_GP_IO, reg);
- skge_read32(hw, B2_GP_IO);
+ reg = skge_read32(hw, B2_GP_IO);
+ if (port == 0) {
+ reg |= GP_DIR_0;
+ reg &= ~GP_IO_0;
+ } else {
+ reg |= GP_DIR_2;
+ reg &= ~GP_IO_2;
}
+ skge_write32(hw, B2_GP_IO, reg);
+ skge_read32(hw, B2_GP_IO);
- skge_xm_write16(hw, port, XM_MMU_CMD,
- skge_xm_read16(hw, port, XM_MMU_CMD)
+ xm_write16(hw, port, XM_MMU_CMD,
+ xm_read16(hw, port, XM_MMU_CMD)
& ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
- skge_xm_read16(hw, port, XM_MMU_CMD);
+ xm_read16(hw, port, XM_MMU_CMD);
}
@@ -1341,11 +1374,11 @@ static void genesis_get_stats(struct skge_port *skge, u64 *data)
int i;
unsigned long timeout = jiffies + HZ;
- skge_xm_write16(hw, port,
+ xm_write16(hw, port,
XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
/* wait for update to complete */
- while (skge_xm_read16(hw, port, XM_STAT_CMD)
+ while (xm_read16(hw, port, XM_STAT_CMD)
& (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) {
if (time_after(jiffies, timeout))
break;
@@ -1353,68 +1386,60 @@ static void genesis_get_stats(struct skge_port *skge, u64 *data)
}
/* special case for 64 bit octet counter */
- data[0] = (u64) skge_xm_read32(hw, port, XM_TXO_OK_HI) << 32
- | skge_xm_read32(hw, port, XM_TXO_OK_LO);
- data[1] = (u64) skge_xm_read32(hw, port, XM_RXO_OK_HI) << 32
- | skge_xm_read32(hw, port, XM_RXO_OK_LO);
+ data[0] = (u64) xm_read32(hw, port, XM_TXO_OK_HI) << 32
+ | xm_read32(hw, port, XM_TXO_OK_LO);
+ data[1] = (u64) xm_read32(hw, port, XM_RXO_OK_HI) << 32
+ | xm_read32(hw, port, XM_RXO_OK_LO);
for (i = 2; i < ARRAY_SIZE(skge_stats); i++)
- data[i] = skge_xm_read32(hw, port, skge_stats[i].xmac_offset);
+ data[i] = xm_read32(hw, port, skge_stats[i].xmac_offset);
}
static void genesis_mac_intr(struct skge_hw *hw, int port)
{
struct skge_port *skge = netdev_priv(hw->dev[port]);
- u16 status = skge_xm_read16(hw, port, XM_ISRC);
-
- pr_debug("genesis_intr status %x\n", status);
- if (hw->phy_type == SK_PHY_XMAC) {
- /* LInk down, start polling for state change */
- if (status & XM_IS_INP_ASS) {
- skge_xm_write16(hw, port, XM_IMSK,
- skge_xm_read16(hw, port, XM_IMSK) | XM_IS_INP_ASS);
- mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
- }
- else if (status & XM_IS_AND)
- mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
- }
+ u16 status = xm_read16(hw, port, XM_ISRC);
+
+ if (netif_msg_intr(skge))
+ printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
+ skge->netdev->name, status);
if (status & XM_IS_TXF_UR) {
- skge_xm_write32(hw, port, XM_MODE, XM_MD_FTF);
+ xm_write32(hw, port, XM_MODE, XM_MD_FTF);
++skge->net_stats.tx_fifo_errors;
}
if (status & XM_IS_RXF_OV) {
- skge_xm_write32(hw, port, XM_MODE, XM_MD_FRF);
+ xm_write32(hw, port, XM_MODE, XM_MD_FRF);
++skge->net_stats.rx_fifo_errors;
}
}
-static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
{
int i;
- skge_gma_write16(hw, port, GM_SMI_DATA, val);
- skge_gma_write16(hw, port, GM_SMI_CTRL,
+ gma_write16(hw, port, GM_SMI_DATA, val);
+ gma_write16(hw, port, GM_SMI_CTRL,
GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg));
for (i = 0; i < PHY_RETRIES; i++) {
udelay(1);
- if (!(skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+ if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
break;
}
}
-static u16 skge_gm_phy_read(struct skge_hw *hw, int port, u16 reg)
+static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
{
int i;
- skge_gma_write16(hw, port, GM_SMI_CTRL,
+ gma_write16(hw, port, GM_SMI_CTRL,
GM_SMI_CT_PHY_AD(hw->phy_addr)
| GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
for (i = 0; i < PHY_RETRIES; i++) {
udelay(1);
- if (skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
+ if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
goto ready;
}
@@ -1422,24 +1447,7 @@ static u16 skge_gm_phy_read(struct skge_hw *hw, int port, u16 reg)
hw->dev[port]->name);
return 0;
ready:
- return skge_gma_read16(hw, port, GM_SMI_DATA);
-}
-
-static void genesis_link_down(struct skge_port *skge)
-{
- struct skge_hw *hw = skge->hw;
- int port = skge->port;
-
- pr_debug("genesis_link_down\n");
-
- skge_xm_write16(hw, port, XM_MMU_CMD,
- skge_xm_read16(hw, port, XM_MMU_CMD)
- & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
-
- /* dummy read to ensure writing */
- (void) skge_xm_read16(hw, port, XM_MMU_CMD);
-
- skge_link_down(skge);
+ return gma_read16(hw, port, GM_SMI_DATA);
}
static void genesis_link_up(struct skge_port *skge)
@@ -1450,7 +1458,7 @@ static void genesis_link_up(struct skge_port *skge)
u32 mode, msk;
pr_debug("genesis_link_up\n");
- cmd = skge_xm_read16(hw, port, XM_MMU_CMD);
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
/*
* enabling pause frame reception is required for 1000BT
@@ -1458,14 +1466,15 @@ static void genesis_link_up(struct skge_port *skge)
*/
if (skge->flow_control == FLOW_MODE_NONE ||
skge->flow_control == FLOW_MODE_LOC_SEND)
+ /* Disable Pause Frame Reception */
cmd |= XM_MMU_IGN_PF;
else
/* Enable Pause Frame Reception */
cmd &= ~XM_MMU_IGN_PF;
- skge_xm_write16(hw, port, XM_MMU_CMD, cmd);
+ xm_write16(hw, port, XM_MMU_CMD, cmd);
- mode = skge_xm_read32(hw, port, XM_MODE);
+ mode = xm_read32(hw, port, XM_MODE);
if (skge->flow_control == FLOW_MODE_SYMMETRIC ||
skge->flow_control == FLOW_MODE_LOC_SEND) {
/*
@@ -1479,10 +1488,10 @@ static void genesis_link_up(struct skge_port *skge)
/* XM_PAUSE_DA = '010000C28001' (default) */
/* XM_MAC_PTIME = 0xffff (maximum) */
/* remember this value is defined in big endian (!) */
- skge_xm_write16(hw, port, XM_MAC_PTIME, 0xffff);
+ xm_write16(hw, port, XM_MAC_PTIME, 0xffff);
mode |= XM_PAUSE_MODE;
- skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+ skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
} else {
/*
* disable pause frame generation is required for 1000BT
@@ -1491,125 +1500,68 @@ static void genesis_link_up(struct skge_port *skge)
/* Disable Pause Mode in Mode Register */
mode &= ~XM_PAUSE_MODE;
- skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+ skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
}
- skge_xm_write32(hw, port, XM_MODE, mode);
+ xm_write32(hw, port, XM_MODE, mode);
msk = XM_DEF_MSK;
- if (hw->phy_type != SK_PHY_XMAC)
- msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */
+ /* disable GP0 interrupt bit for external Phy */
+ msk |= XM_IS_INP_ASS;
- skge_xm_write16(hw, port, XM_IMSK, msk);
- skge_xm_read16(hw, port, XM_ISRC);
+ xm_write16(hw, port, XM_IMSK, msk);
+ xm_read16(hw, port, XM_ISRC);
/* get MMU Command Reg. */
- cmd = skge_xm_read16(hw, port, XM_MMU_CMD);
- if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
+ cmd = xm_read16(hw, port, XM_MMU_CMD);
+ if (skge->duplex == DUPLEX_FULL)
cmd |= XM_MMU_GMII_FD;
- if (hw->phy_type == SK_PHY_BCOM) {
- /*
- * Workaround BCOM Errata (#10523) for all BCom Phys
- * Enable Power Management after link up
- */
- skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
- skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
- & ~PHY_B_AC_DIS_PM);
- skge_xm_phy_write(hw, port, PHY_BCOM_INT_MASK,
- PHY_B_DEF_MSK);
- }
+ /*
+ * Workaround BCOM Errata (#10523) for all BCom Phys
+ * Enable Power Management after link up
+ */
+ xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+ xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+ & ~PHY_B_AC_DIS_PM);
+ xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
/* enable Rx/Tx */
- skge_xm_write16(hw, port, XM_MMU_CMD,
+ xm_write16(hw, port, XM_MMU_CMD,
cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
skge_link_up(skge);
}
-static void genesis_bcom_intr(struct skge_port *skge)
+static inline void bcom_phy_intr(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
int port = skge->port;
- u16 stat = skge_xm_phy_read(hw, port, PHY_BCOM_INT_STAT);
+ u16 isrc;
+
+ isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT);
+ if (netif_msg_intr(skge))
+ printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x\n",
+ skge->netdev->name, isrc);
- pr_debug("genesis_bcom intr stat=%x\n", stat);
+ if (isrc & PHY_B_IS_PSE)
+ printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n",
+ hw->dev[port]->name);
/* Workaround BCom Errata:
* enable and disable loopback mode if "NO HCD" occurs.
*/
- if (stat & PHY_B_IS_NO_HDCL) {
- u16 ctrl = skge_xm_phy_read(hw, port, PHY_BCOM_CTRL);
- skge_xm_phy_write(hw, port, PHY_BCOM_CTRL,
+ if (isrc & PHY_B_IS_NO_HDCL) {
+ u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL);
+ xm_phy_write(hw, port, PHY_BCOM_CTRL,
ctrl | PHY_CT_LOOP);
- skge_xm_phy_write(hw, port, PHY_BCOM_CTRL,
+ xm_phy_write(hw, port, PHY_BCOM_CTRL,
ctrl & ~PHY_CT_LOOP);
}
- stat = skge_xm_phy_read(hw, port, PHY_BCOM_STAT);
- if (stat & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) {
- u16 aux = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
- if ( !(aux & PHY_B_AS_LS) && netif_carrier_ok(skge->netdev))
- genesis_link_down(skge);
-
- else if (stat & PHY_B_IS_LST_CHANGE) {
- if (aux & PHY_B_AS_AN_C) {
- switch (aux & PHY_B_AS_AN_RES_MSK) {
- case PHY_B_RES_1000FD:
- skge->duplex = DUPLEX_FULL;
- break;
- case PHY_B_RES_1000HD:
- skge->duplex = DUPLEX_HALF;
- break;
- }
-
- switch (aux & PHY_B_AS_PAUSE_MSK) {
- case PHY_B_AS_PAUSE_MSK:
- skge->flow_control = FLOW_MODE_SYMMETRIC;
- break;
- case PHY_B_AS_PRR:
- skge->flow_control = FLOW_MODE_REM_SEND;
- break;
- case PHY_B_AS_PRT:
- skge->flow_control = FLOW_MODE_LOC_SEND;
- break;
- default:
- skge->flow_control = FLOW_MODE_NONE;
- }
- skge->speed = SPEED_1000;
- }
- genesis_link_up(skge);
- }
- else
- mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
- }
-}
+ if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+ bcom_check_link(hw, port);
-/* Perodic poll of phy status to check for link transistion */
-static void skge_link_timer(unsigned long __arg)
-{
- struct skge_port *skge = (struct skge_port *) __arg;
- struct skge_hw *hw = skge->hw;
- int port = skge->port;
-
- if (hw->chip_id != CHIP_ID_GENESIS || !netif_running(skge->netdev))
- return;
-
- spin_lock_bh(&hw->phy_lock);
- if (hw->phy_type == SK_PHY_BCOM)
- genesis_bcom_intr(skge);
- else {
- int i;
- for (i = 0; i < 3; i++)
- if (skge_xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
- break;
-
- if (i == 3)
- mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
- else
- genesis_link_up(skge);
- }
- spin_unlock_bh(&hw->phy_lock);
}
/* Marvell Phy Initailization */
@@ -1621,31 +1573,27 @@ static void yukon_init(struct skge_hw *hw, int port)
pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
- u16 ectrl = skge_gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+ u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
PHY_M_EC_MAC_S_MSK);
ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
- /* on PHY 88E1111 there is a change for downshift control */
- if (hw->chip_id == CHIP_ID_YUKON_EC)
- ectrl |= PHY_M_EC_M_DSC_2(0) | PHY_M_EC_DOWN_S_ENA;
- else
- ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+ ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
- skge_gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
}
- ctrl = skge_gm_phy_read(hw, port, PHY_MARV_CTRL);
+ ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
if (skge->autoneg == AUTONEG_DISABLE)
ctrl &= ~PHY_CT_ANE;
ctrl |= PHY_CT_RESET;
- skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
ctrl = 0;
ct1000 = 0;
- adv = PHY_SEL_TYPE;
+ adv = PHY_AN_CSMA;
if (skge->autoneg == AUTONEG_ENABLE) {
if (iscopper(hw)) {
@@ -1661,41 +1609,12 @@ static void yukon_init(struct skge_hw *hw, int port)
adv |= PHY_M_AN_10_FD;
if (skge->advertising & ADVERTISED_10baseT_Half)
adv |= PHY_M_AN_10_HD;
-
- /* Set Flow-control capabilities */
- switch (skge->flow_control) {
- case FLOW_MODE_NONE:
- adv |= PHY_B_P_NO_PAUSE;
- break;
- case FLOW_MODE_LOC_SEND:
- adv |= PHY_B_P_ASYM_MD;
- break;
- case FLOW_MODE_SYMMETRIC:
- adv |= PHY_B_P_SYM_MD;
- break;
- case FLOW_MODE_REM_SEND:
- adv |= PHY_B_P_BOTH_MD;
- break;
- }
- } else { /* special defines for FIBER (88E1011S only) */
+ } else /* special defines for FIBER (88E1011S only) */
adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
- /* Set Flow-control capabilities */
- switch (skge->flow_control) {
- case FLOW_MODE_NONE:
- adv |= PHY_M_P_NO_PAUSE_X;
- break;
- case FLOW_MODE_LOC_SEND:
- adv |= PHY_M_P_ASYM_MD_X;
- break;
- case FLOW_MODE_SYMMETRIC:
- adv |= PHY_M_P_SYM_MD_X;
- break;
- case FLOW_MODE_REM_SEND:
- adv |= PHY_M_P_BOTH_MD_X;
- break;
- }
- }
+ /* Set Flow-control capabilities */
+ adv |= phy_pause_map[skge->flow_control];
+
/* Restart Auto-negotiation */
ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
} else {
@@ -1717,36 +1636,23 @@ static void yukon_init(struct skge_hw *hw, int port)
ctrl |= PHY_CT_RESET;
}
- if (hw->chip_id != CHIP_ID_YUKON_FE)
- skge_gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
- skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
- skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
/* Setup Phy LED's */
ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
ledover = 0;
- if (hw->chip_id == CHIP_ID_YUKON_FE) {
- /* on 88E3082 these bits are at 11..9 (shifted left) */
- ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
-
- skge_gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR,
- ((skge_gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR)
-
- & ~PHY_M_FELP_LED1_MSK)
- | PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL)));
- } else {
- /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
- ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
- /* turn off the Rx LED (LED_RX) */
- ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
- }
+ /* turn off the Rx LED (LED_RX) */
+ ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
/* disable blink mode (LED_DUPLEX) on collisions */
ctrl |= PHY_M_LEDC_DP_CTRL;
- skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
/* turn on 100 Mbps LED (LED_LINK100) */
@@ -1754,25 +1660,25 @@ static void yukon_init(struct skge_hw *hw, int port)
}
if (ledover)
- skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
/* Enable phy interrupt on autonegotiation complete (or link up) */
if (skge->autoneg == AUTONEG_ENABLE)
- skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
else
- skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
}
static void yukon_reset(struct skge_hw *hw, int port)
{
- skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */
- skge_gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
- skge_gma_write16(hw, port, GM_MC_ADDR_H2, 0);
- skge_gma_write16(hw, port, GM_MC_ADDR_H3, 0);
- skge_gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */
+ gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
+ gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H4, 0);
- skge_gma_write16(hw, port, GM_RX_CTRL,
- skge_gma_read16(hw, port, GM_RX_CTRL)
+ gma_write16(hw, port, GM_RX_CTRL,
+ gma_read16(hw, port, GM_RX_CTRL)
| GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
}
@@ -1785,17 +1691,17 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev == CHIP_REV_YU_LITE_A3)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
/* hard reset */
- skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), GPC_RST_SET);
- skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_RST_SET);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev == CHIP_REV_YU_LITE_A3)
skge_write32(hw, B2_GP_IO,
(skge_read32(hw, B2_GP_IO) | GP_DIR_9)
& ~GP_IO_9);
@@ -1806,13 +1712,13 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
/* Clear GMC reset */
- skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
- skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
- skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
+ skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
if (skge->autoneg == AUTONEG_DISABLE) {
reg = GM_GPCR_AU_ALL_DIS;
- skge_gma_write16(hw, port, GM_GP_CTRL,
- skge_gma_read16(hw, port, GM_GP_CTRL) | reg);
+ gma_write16(hw, port, GM_GP_CTRL,
+ gma_read16(hw, port, GM_GP_CTRL) | reg);
switch (skge->speed) {
case SPEED_1000:
@@ -1828,7 +1734,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
switch (skge->flow_control) {
case FLOW_MODE_NONE:
- skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
break;
case FLOW_MODE_LOC_SEND:
@@ -1836,7 +1742,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
}
- skge_gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_write16(hw, port, GM_GP_CTRL, reg);
skge_read16(hw, GMAC_IRQ_SRC);
spin_lock_bh(&hw->phy_lock);
@@ -1844,25 +1750,25 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
spin_unlock_bh(&hw->phy_lock);
/* MIB clear */
- reg = skge_gma_read16(hw, port, GM_PHY_ADDR);
- skge_gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+ reg = gma_read16(hw, port, GM_PHY_ADDR);
+ gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
for (i = 0; i < GM_MIB_CNT_SIZE; i++)
- skge_gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i);
- skge_gma_write16(hw, port, GM_PHY_ADDR, reg);
+ gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i);
+ gma_write16(hw, port, GM_PHY_ADDR, reg);
/* transmit control */
- skge_gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+ gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
/* receive control reg: unicast + multicast + no FCS */
- skge_gma_write16(hw, port, GM_RX_CTRL,
+ gma_write16(hw, port, GM_RX_CTRL,
GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
/* transmit flow control */
- skge_gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+ gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
/* transmit parameter */
- skge_gma_write16(hw, port, GM_TX_PARAM,
+ gma_write16(hw, port, GM_TX_PARAM,
TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
TX_IPG_JAM_DATA(TX_IPG_JAM_DEF));
@@ -1872,33 +1778,33 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
if (hw->dev[port]->mtu > 1500)
reg |= GM_SMOD_JUMBO_ENA;
- skge_gma_write16(hw, port, GM_SERIAL_MODE, reg);
+ gma_write16(hw, port, GM_SERIAL_MODE, reg);
/* physical address: used for pause frames */
- skge_gm_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
/* virtual address for data */
- skge_gm_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
/* enable interrupt mask for counter overflows */
- skge_gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
- skge_gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
- skge_gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
/* Initialize Mac Fifo */
/* Configure Rx MAC FIFO */
- skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+ hw->chip_rev == CHIP_REV_YU_LITE_A3)
reg &= ~GMF_RX_F_FL_ON;
- skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
- skge_write16(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), reg);
- skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+ skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+ skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
+ skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
/* Configure Tx MAC FIFO */
- skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
- skge_write16(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+ skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
}
static void yukon_stop(struct skge_port *skge)
@@ -1907,19 +1813,19 @@ static void yukon_stop(struct skge_port *skge)
int port = skge->port;
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- chip_rev(hw) == CHIP_REV_YU_LITE_A3) {
+ hw->chip_rev == CHIP_REV_YU_LITE_A3) {
skge_write32(hw, B2_GP_IO,
skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
}
- skge_gma_write16(hw, port, GM_GP_CTRL,
- skge_gma_read16(hw, port, GM_GP_CTRL)
+ gma_write16(hw, port, GM_GP_CTRL,
+ gma_read16(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
- skge_gma_read16(hw, port, GM_GP_CTRL);
+ gma_read16(hw, port, GM_GP_CTRL);
/* set GPHY Control reset */
- skge_gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
- skge_gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+ gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
+ gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1928,39 +1834,40 @@ static void yukon_get_stats(struct skge_port *skge, u64 *data)
int port = skge->port;
int i;
- data[0] = (u64) skge_gma_read32(hw, port, GM_TXO_OK_HI) << 32
- | skge_gma_read32(hw, port, GM_TXO_OK_LO);
- data[1] = (u64) skge_gma_read32(hw, port, GM_RXO_OK_HI) << 32
- | skge_gma_read32(hw, port, GM_RXO_OK_LO);
+ data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32
+ | gma_read32(hw, port, GM_TXO_OK_LO);
+ data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32
+ | gma_read32(hw, port, GM_RXO_OK_LO);
for (i = 2; i < ARRAY_SIZE(skge_stats); i++)
- data[i] = skge_gma_read32(hw, port,
+ data[i] = gma_read32(hw, port,
skge_stats[i].gma_offset);
}
static void yukon_mac_intr(struct skge_hw *hw, int port)
{
- struct skge_port *skge = netdev_priv(hw->dev[port]);
- u8 status = skge_read8(hw, SKGEMAC_REG(port, GMAC_IRQ_SRC));
+ struct net_device *dev = hw->dev[port];
+ struct skge_port *skge = netdev_priv(dev);
+ u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ if (netif_msg_intr(skge))
+ printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n",
+ dev->name, status);
- pr_debug("yukon_intr status %x\n", status);
if (status & GM_IS_RX_FF_OR) {
++skge->net_stats.rx_fifo_errors;
- skge_gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+ gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
}
if (status & GM_IS_TX_FF_UR) {
++skge->net_stats.tx_fifo_errors;
- skge_gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+ gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
}
}
static u16 yukon_speed(const struct skge_hw *hw, u16 aux)
{
- if (hw->chip_id == CHIP_ID_YUKON_FE)
- return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
-
- switch(aux & PHY_M_PS_SPEED_MSK) {
+ switch (aux & PHY_M_PS_SPEED_MSK) {
case PHY_M_PS_SPEED_1000:
return SPEED_1000;
case PHY_M_PS_SPEED_100:
@@ -1981,15 +1888,15 @@ static void yukon_link_up(struct skge_port *skge)
/* Enable Transmit FIFO Underrun */
skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
- reg = skge_gma_read16(hw, port, GM_GP_CTRL);
+ reg = gma_read16(hw, port, GM_GP_CTRL);
if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
reg |= GM_GPCR_DUP_FULL;
/* enable Rx/Tx */
reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
- skge_gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_write16(hw, port, GM_GP_CTRL, reg);
- skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
skge_link_up(skge);
}
@@ -1999,16 +1906,15 @@ static void yukon_link_down(struct skge_port *skge)
int port = skge->port;
pr_debug("yukon_link_down\n");
- skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
- skge_gm_phy_write(hw, port, GM_GP_CTRL,
- skge_gm_phy_read(hw, port, GM_GP_CTRL)
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+ gm_phy_write(hw, port, GM_GP_CTRL,
+ gm_phy_read(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
- if (hw->chip_id != CHIP_ID_YUKON_FE &&
- skge->flow_control == FLOW_MODE_REM_SEND) {
+ if (skge->flow_control == FLOW_MODE_REM_SEND) {
/* restore Asymmetric Pause bit */
- skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
- skge_gm_phy_read(hw, port,
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
+ gm_phy_read(hw, port,
PHY_MARV_AUNE_ADV)
| PHY_M_AN_ASP);
@@ -2027,20 +1933,21 @@ static void yukon_phy_intr(struct skge_port *skge)
const char *reason = NULL;
u16 istatus, phystat;
- istatus = skge_gm_phy_read(hw, port, PHY_MARV_INT_STAT);
- phystat = skge_gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
- pr_debug("yukon phy intr istat=%x phy_stat=%x\n", istatus, phystat);
+ istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
+ phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
+
+ if (netif_msg_intr(skge))
+ printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x 0x%x\n",
+ skge->netdev->name, istatus, phystat);
if (istatus & PHY_M_IS_AN_COMPL) {
- if (skge_gm_phy_read(hw, port, PHY_MARV_AUNE_LP)
+ if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP)
& PHY_M_AN_RF) {
reason = "remote fault";
goto failed;
}
- if (!(hw->chip_id == CHIP_ID_YUKON_FE || hw->chip_id == CHIP_ID_YUKON_EC)
- && (skge_gm_phy_read(hw, port, PHY_MARV_1000T_STAT)
- & PHY_B_1000S_MSF)) {
+ if (gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) {
reason = "master/slave fault";
goto failed;
}
@@ -2054,10 +1961,6 @@ static void yukon_phy_intr(struct skge_port *skge)
? DUPLEX_FULL : DUPLEX_HALF;
skge->speed = yukon_speed(hw, phystat);
- /* Tx & Rx Pause Enabled bits are at 9..8 */
- if (hw->chip_id == CHIP_ID_YUKON_XL)
- phystat >>= 6;
-
/* We are using IEEE 802.3z/D5.0 Table 37-4 */
switch (phystat & PHY_M_PS_PAUSE_MSK) {
case PHY_M_PS_PAUSE_MSK:
@@ -2075,9 +1978,9 @@ static void yukon_phy_intr(struct skge_port *skge)
if (skge->flow_control == FLOW_MODE_NONE ||
(skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF))
- skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
else
- skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
yukon_link_up(skge);
return;
}
@@ -2161,6 +2064,12 @@ static int skge_up(struct net_device *dev)
if (netif_msg_ifup(skge))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+ if (dev->mtu > RX_BUF_SIZE)
+ skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN;
+ else
+ skge->rx_buf_size = RX_BUF_SIZE;
+
+
rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc);
tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc);
skge->mem_size = tx_size + rx_size;
@@ -2173,7 +2082,8 @@ static int skge_up(struct net_device *dev)
if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma)))
goto free_pci_mem;
- if (skge_rx_fill(skge))
+ err = skge_rx_fill(skge);
+ if (err)
goto free_rx_ring;
if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size,
@@ -2182,6 +2092,10 @@ static int skge_up(struct net_device *dev)
skge->tx_avail = skge->tx_ring.count - 1;
+ /* Enable IRQ from port */
+ hw->intr_mask |= portirqmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
/* Initialze MAC */
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_mac_init(hw, port);
@@ -2189,7 +2103,7 @@ static int skge_up(struct net_device *dev)
yukon_mac_init(hw, port);
/* Configure RAMbuffers */
- chunk = hw->ram_size / (isdualport(hw) ? 4 : 2);
+ chunk = hw->ram_size / ((hw->ports + 1)*2);
ram_addr = hw->ram_offset + 2 * chunk * port;
skge_ramset(hw, rxqaddr[port], ram_addr, chunk);
@@ -2227,7 +2141,6 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
del_timer_sync(&skge->led_blink);
- del_timer_sync(&skge->link_check);
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
@@ -2240,12 +2153,12 @@ static int skge_down(struct net_device *dev)
yukon_stop(skge);
/* Disable Force Sync bit and Enable Alloc bit */
- skge_write8(hw, SKGEMAC_REG(port, TXA_CTRL),
+ skge_write8(hw, SK_REG(port, TXA_CTRL),
TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
/* Stop Interval Timer and Limit Counter of Tx Arbiter */
- skge_write32(hw, SKGEMAC_REG(port, TXA_ITI_INI), 0L);
- skge_write32(hw, SKGEMAC_REG(port, TXA_LIM_INI), 0L);
+ skge_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+ skge_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
/* Reset PCI FIFO */
skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET);
@@ -2260,13 +2173,13 @@ static int skge_down(struct net_device *dev)
skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET);
if (hw->chip_id == CHIP_ID_GENESIS) {
- skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
- skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
- skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_STOP);
- skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_STOP);
+ skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
+ skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
+ skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP);
+ skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP);
} else {
- skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
- skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+ skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
}
/* turn off led's */
@@ -2299,10 +2212,10 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
local_irq_save(flags);
if (!spin_trylock(&skge->tx_lock)) {
- /* Collision - tell upper layer to requeue */
- local_irq_restore(flags);
- return NETDEV_TX_LOCKED;
- }
+ /* Collision - tell upper layer to requeue */
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) {
netif_stop_queue(dev);
@@ -2333,7 +2246,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
* does. Looks like hardware is wrong?
*/
if (ip->protocol == IPPROTO_UDP
- && chip_rev(hw) == 0 && hw->chip_id == CHIP_ID_YUKON)
+ && hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON)
control = BMU_TCP_CHECK;
else
control = BMU_UDP_CHECK;
@@ -2394,6 +2307,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e)
{
+ /* This ring element can be skb or fragment */
if (e->skb) {
pci_unmap_single(hw->pdev,
pci_unmap_addr(e, mapaddr),
@@ -2438,16 +2352,17 @@ static void skge_tx_timeout(struct net_device *dev)
static int skge_change_mtu(struct net_device *dev, int new_mtu)
{
int err = 0;
+ int running = netif_running(dev);
- if(new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
+ if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
return -EINVAL;
- dev->mtu = new_mtu;
- if (netif_running(dev)) {
+ if (running)
skge_down(dev);
+ dev->mtu = new_mtu;
+ if (running)
skge_up(dev);
- }
return err;
}
@@ -2462,7 +2377,9 @@ static void genesis_set_multicast(struct net_device *dev)
u32 mode;
u8 filter[8];
- mode = skge_xm_read32(hw, port, XM_MODE);
+ pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
+
+ mode = xm_read32(hw, port, XM_MODE);
mode |= XM_MD_ENA_HASH;
if (dev->flags & IFF_PROMISC)
mode |= XM_MD_ENA_PROM;
@@ -2473,17 +2390,16 @@ static void genesis_set_multicast(struct net_device *dev)
memset(filter, 0xff, sizeof(filter));
else {
memset(filter, 0, sizeof(filter));
- for(i = 0; list && i < count; i++, list = list->next) {
- u32 crc = crc32_le(~0, list->dmi_addr, ETH_ALEN);
- u8 bit = 63 - (crc & 63);
-
+ for (i = 0; list && i < count; i++, list = list->next) {
+ u32 crc, bit;
+ crc = ether_crc_le(ETH_ALEN, list->dmi_addr);
+ bit = ~crc & 0x3f;
filter[bit/8] |= 1 << (bit%8);
}
}
- skge_xm_outhash(hw, port, XM_HSM, filter);
-
- skge_xm_write32(hw, port, XM_MODE, mode);
+ xm_write32(hw, port, XM_MODE, mode);
+ xm_outhash(hw, port, XM_HSM, filter);
}
static void yukon_set_multicast(struct net_device *dev)
@@ -2497,7 +2413,7 @@ static void yukon_set_multicast(struct net_device *dev)
memset(filter, 0, sizeof(filter));
- reg = skge_gma_read16(hw, port, GM_RX_CTRL);
+ reg = gma_read16(hw, port, GM_RX_CTRL);
reg |= GM_RXCR_UCF_ENA;
if (dev->flags & IFF_PROMISC) /* promiscious */
@@ -2510,23 +2426,23 @@ static void yukon_set_multicast(struct net_device *dev)
int i;
reg |= GM_RXCR_MCF_ENA;
- for(i = 0; list && i < dev->mc_count; i++, list = list->next) {
+ for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
filter[bit/8] |= 1 << (bit%8);
}
}
- skge_gma_write16(hw, port, GM_MC_ADDR_H1,
+ gma_write16(hw, port, GM_MC_ADDR_H1,
(u16)filter[0] | ((u16)filter[1] << 8));
- skge_gma_write16(hw, port, GM_MC_ADDR_H2,
+ gma_write16(hw, port, GM_MC_ADDR_H2,
(u16)filter[2] | ((u16)filter[3] << 8));
- skge_gma_write16(hw, port, GM_MC_ADDR_H3,
+ gma_write16(hw, port, GM_MC_ADDR_H3,
(u16)filter[4] | ((u16)filter[5] << 8));
- skge_gma_write16(hw, port, GM_MC_ADDR_H4,
+ gma_write16(hw, port, GM_MC_ADDR_H4,
(u16)filter[6] | ((u16)filter[7] << 8));
- skge_gma_write16(hw, port, GM_RX_CTRL, reg);
+ gma_write16(hw, port, GM_RX_CTRL, reg);
}
static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
@@ -2545,28 +2461,76 @@ static void skge_rx_error(struct skge_port *skge, int slot,
printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n",
skge->netdev->name, slot, control, status);
- if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
- || (control & BMU_BBC) > skge->netdev->mtu + VLAN_ETH_HLEN)
+ if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF))
skge->net_stats.rx_length_errors++;
- else {
- if (skge->hw->chip_id == CHIP_ID_GENESIS) {
- if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
- skge->net_stats.rx_length_errors++;
- if (status & XMR_FS_FRA_ERR)
- skge->net_stats.rx_frame_errors++;
- if (status & XMR_FS_FCS_ERR)
- skge->net_stats.rx_crc_errors++;
- } else {
- if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
- skge->net_stats.rx_length_errors++;
- if (status & GMR_FS_FRAGMENT)
- skge->net_stats.rx_frame_errors++;
- if (status & GMR_FS_CRC_ERR)
- skge->net_stats.rx_crc_errors++;
+ else if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+ if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
+ skge->net_stats.rx_length_errors++;
+ if (status & XMR_FS_FRA_ERR)
+ skge->net_stats.rx_frame_errors++;
+ if (status & XMR_FS_FCS_ERR)
+ skge->net_stats.rx_crc_errors++;
+ } else {
+ if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
+ skge->net_stats.rx_length_errors++;
+ if (status & GMR_FS_FRAGMENT)
+ skge->net_stats.rx_frame_errors++;
+ if (status & GMR_FS_CRC_ERR)
+ skge->net_stats.rx_crc_errors++;
+ }
+}
+
+/* Get receive buffer from descriptor.
+ * Handles copy of small buffers and reallocation failures
+ */
+static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
+ struct skge_element *e,
+ unsigned int len)
+{
+ struct sk_buff *nskb, *skb;
+
+ if (len < RX_COPY_THRESHOLD) {
+ nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN);
+ if (unlikely(!nskb))
+ return NULL;
+
+ pci_dma_sync_single_for_cpu(skge->hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ len, PCI_DMA_FROMDEVICE);
+ memcpy(nskb->data, e->skb->data, len);
+ pci_dma_sync_single_for_device(skge->hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ len, PCI_DMA_FROMDEVICE);
+
+ if (skge->rx_csum) {
+ struct skge_rx_desc *rd = e->desc;
+ nskb->csum = le16_to_cpu(rd->csum2);
+ nskb->ip_summed = CHECKSUM_HW;
}
+ skge_rx_reuse(e, skge->rx_buf_size);
+ return nskb;
+ } else {
+ nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size);
+ if (unlikely(!nskb))
+ return NULL;
+
+ pci_unmap_single(skge->hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ pci_unmap_len(e, maplen),
+ PCI_DMA_FROMDEVICE);
+ skb = e->skb;
+ if (skge->rx_csum) {
+ struct skge_rx_desc *rd = e->desc;
+ skb->csum = le16_to_cpu(rd->csum2);
+ skb->ip_summed = CHECKSUM_HW;
+ }
+
+ skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
+ return skb;
}
}
+
static int skge_poll(struct net_device *dev, int *budget)
{
struct skge_port *skge = netdev_priv(dev);
@@ -2575,13 +2539,12 @@ static int skge_poll(struct net_device *dev, int *budget)
struct skge_element *e;
unsigned int to_do = min(dev->quota, *budget);
unsigned int work_done = 0;
- int done;
- static const u32 irqmask[] = { IS_PORT_1, IS_PORT_2 };
- for (e = ring->to_clean; e != ring->to_use && work_done < to_do;
- e = e->next) {
+ pr_debug("skge_poll\n");
+
+ for (e = ring->to_clean; work_done < to_do; e = e->next) {
struct skge_rx_desc *rd = e->desc;
- struct sk_buff *skb = e->skb;
+ struct sk_buff *skb;
u32 control, len, status;
rmb();
@@ -2590,19 +2553,12 @@ static int skge_poll(struct net_device *dev, int *budget)
break;
len = control & BMU_BBC;
- e->skb = NULL;
-
- pci_unmap_single(hw->pdev,
- pci_unmap_addr(e, mapaddr),
- pci_unmap_len(e, maplen),
- PCI_DMA_FROMDEVICE);
-
status = rd->status;
- if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
- || len > dev->mtu + VLAN_ETH_HLEN
- || bad_phy_status(hw, status)) {
+
+ if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
+ || bad_phy_status(hw, status))) {
skge_rx_error(skge, e - ring->start, control, status);
- dev_kfree_skb(skb);
+ skge_rx_reuse(e, skge->rx_buf_size);
continue;
}
@@ -2610,43 +2566,37 @@ static int skge_poll(struct net_device *dev, int *budget)
printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
dev->name, e - ring->start, rd->status, len);
- skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, dev);
-
- if (skge->rx_csum) {
- skb->csum = le16_to_cpu(rd->csum2);
- skb->ip_summed = CHECKSUM_HW;
- }
+ skb = skge_rx_get(skge, e, len);
+ if (likely(skb)) {
+ skb_put(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
- dev->last_rx = jiffies;
- netif_receive_skb(skb);
+ dev->last_rx = jiffies;
+ netif_receive_skb(skb);
- ++work_done;
+ ++work_done;
+ } else
+ skge_rx_reuse(e, skge->rx_buf_size);
}
ring->to_clean = e;
- *budget -= work_done;
- dev->quota -= work_done;
- done = work_done < to_do;
-
- if (skge_rx_fill(skge))
- done = 0;
-
/* restart receiver */
wmb();
skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR),
CSR_START | CSR_IRQ_CL_F);
- if (done) {
- local_irq_disable();
- hw->intr_mask |= irqmask[skge->port];
- /* Order is important since data can get interrupted */
- skge_write32(hw, B0_IMSK, hw->intr_mask);
- __netif_rx_complete(dev);
- local_irq_enable();
- }
+ *budget -= work_done;
+ dev->quota -= work_done;
- return !done;
+ if (work_done >= to_do)
+ return 1; /* not done */
+
+ local_irq_disable();
+ __netif_rx_complete(dev);
+ hw->intr_mask |= portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ local_irq_enable();
+ return 0;
}
static inline void skge_tx_intr(struct net_device *dev)
@@ -2657,7 +2607,7 @@ static inline void skge_tx_intr(struct net_device *dev)
struct skge_element *e;
spin_lock(&skge->tx_lock);
- for(e = ring->to_clean; e != ring->to_use; e = e->next) {
+ for (e = ring->to_clean; e != ring->to_use; e = e->next) {
struct skge_tx_desc *td = e->desc;
u32 control;
@@ -2690,12 +2640,12 @@ static void skge_mac_parity(struct skge_hw *hw, int port)
: (port == 0 ? "(port A)": "(port B"));
if (hw->chip_id == CHIP_ID_GENESIS)
- skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1),
+ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
MFF_CLR_PERR);
else
/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
- skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T),
- (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0)
+ skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T),
+ (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0)
? GMF_CLI_TX_FC : GMF_CLI_TX_PE);
}
@@ -2703,16 +2653,16 @@ static void skge_pci_clear(struct skge_hw *hw)
{
u16 status;
- status = skge_read16(hw, SKGEPCI_REG(PCI_STATUS));
+ pci_read_config_word(hw->pdev, PCI_STATUS, &status);
skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- skge_write16(hw, SKGEPCI_REG(PCI_STATUS),
- status | PCI_STATUS_ERROR_BITS);
+ pci_write_config_word(hw->pdev, PCI_STATUS,
+ status | PCI_STATUS_ERROR_BITS);
skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
static void skge_mac_intr(struct skge_hw *hw, int port)
{
- if (hw->chip_id == CHIP_ID_GENESIS)
+ if (hw->chip_id == CHIP_ID_GENESIS)
genesis_mac_intr(hw, port);
else
yukon_mac_intr(hw, port);
@@ -2726,9 +2676,9 @@ static void skge_error_irq(struct skge_hw *hw)
if (hw->chip_id == CHIP_ID_GENESIS) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
- skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+ skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
- skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+ skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
} else {
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
@@ -2803,8 +2753,8 @@ static void skge_extirq(unsigned long data)
if (hw->chip_id != CHIP_ID_GENESIS)
yukon_phy_intr(skge);
- else if (hw->phy_type == SK_PHY_BCOM)
- genesis_bcom_intr(skge);
+ else
+ bcom_phy_intr(skge);
}
}
spin_unlock(&hw->phy_lock);
@@ -2824,19 +2774,14 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_NONE;
status &= hw->intr_mask;
-
- if ((status & IS_R1_F) && netif_rx_schedule_prep(hw->dev[0])) {
- status &= ~IS_R1_F;
+ if (status & IS_R1_F) {
hw->intr_mask &= ~IS_R1_F;
- skge_write32(hw, B0_IMSK, hw->intr_mask);
- __netif_rx_schedule(hw->dev[0]);
+ netif_rx_schedule(hw->dev[0]);
}
- if ((status & IS_R2_F) && netif_rx_schedule_prep(hw->dev[1])) {
- status &= ~IS_R2_F;
+ if (status & IS_R2_F) {
hw->intr_mask &= ~IS_R2_F;
- skge_write32(hw, B0_IMSK, hw->intr_mask);
- __netif_rx_schedule(hw->dev[1]);
+ netif_rx_schedule(hw->dev[1]);
}
if (status & IS_XA1_F)
@@ -2845,9 +2790,27 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
if (status & IS_XA2_F)
skge_tx_intr(hw->dev[1]);
+ if (status & IS_PA_TO_RX1) {
+ struct skge_port *skge = netdev_priv(hw->dev[0]);
+ ++skge->net_stats.rx_over_errors;
+ skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
+ }
+
+ if (status & IS_PA_TO_RX2) {
+ struct skge_port *skge = netdev_priv(hw->dev[1]);
+ ++skge->net_stats.rx_over_errors;
+ skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
+ }
+
+ if (status & IS_PA_TO_TX1)
+ skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1);
+
+ if (status & IS_PA_TO_TX2)
+ skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2);
+
if (status & IS_MAC1)
skge_mac_intr(hw, 0);
-
+
if (status & IS_MAC2)
skge_mac_intr(hw, 1);
@@ -2859,8 +2822,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
tasklet_schedule(&hw->ext_tasklet);
}
- if (status)
- skge_write32(hw, B0_IMSK, hw->intr_mask);
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
return IRQ_HANDLED;
}
@@ -2904,9 +2866,6 @@ static const struct {
{ CHIP_ID_YUKON, "Yukon" },
{ CHIP_ID_YUKON_LITE, "Yukon-Lite"},
{ CHIP_ID_YUKON_LP, "Yukon-LP"},
- { CHIP_ID_YUKON_XL, "Yukon-2 XL"},
- { CHIP_ID_YUKON_EC, "YUKON-2 EC"},
- { CHIP_ID_YUKON_FE, "YUKON-2 FE"},
};
static const char *skge_board_name(const struct skge_hw *hw)
@@ -2930,8 +2889,8 @@ static const char *skge_board_name(const struct skge_hw *hw)
static int skge_reset(struct skge_hw *hw)
{
u16 ctst;
- u8 t8;
- int i, ports;
+ u8 t8, mac_cfg;
+ int i;
ctst = skge_read16(hw, B0_CTST);
@@ -2952,12 +2911,9 @@ static int skge_reset(struct skge_hw *hw)
hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
- switch(hw->chip_id) {
+ switch (hw->chip_id) {
case CHIP_ID_GENESIS:
switch (hw->phy_type) {
- case SK_PHY_XMAC:
- hw->phy_addr = PHY_ADDR_XMAC;
- break;
case SK_PHY_BCOM:
hw->phy_addr = PHY_ADDR_BCOM;
break;
@@ -2986,8 +2942,9 @@ static int skge_reset(struct skge_hw *hw)
return -EOPNOTSUPP;
}
- hw->mac_cfg = skge_read8(hw, B2_MAC_CFG);
- ports = isdualport(hw) ? 2 : 1;
+ mac_cfg = skge_read8(hw, B2_MAC_CFG);
+ hw->ports = (mac_cfg & CFG_SNG_MAC) ? 1 : 2;
+ hw->chip_rev = (mac_cfg & CFG_CHIP_R_MSK) >> 4;
/* read the adapters RAM size */
t8 = skge_read8(hw, B2_E_0);
@@ -3010,9 +2967,9 @@ static int skge_reset(struct skge_hw *hw)
/* switch power to VCC (WA for VAUX problem) */
skge_write8(hw, B0_POWER_CTRL,
PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
- for (i = 0; i < ports; i++) {
- skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
- skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+ for (i = 0; i < hw->ports; i++) {
+ skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+ skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
}
}
@@ -3022,8 +2979,8 @@ static int skge_reset(struct skge_hw *hw)
skge_write8(hw, B0_LED, LED_STAT_ON);
/* enable the Tx Arbiters */
- for (i = 0; i < ports; i++)
- skge_write8(hw, SKGEMAC_REG(i, TXA_CTRL), TXA_ENA_ARB);
+ for (i = 0; i < hw->ports; i++)
+ skge_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB);
/* Initialize ram interface */
skge_write16(hw, B3_RI_CTRL, RI_RST_CLR);
@@ -3050,16 +3007,14 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
skge_write32(hw, B2_IRQM_CTRL, TIM_START);
- hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
- if (isdualport(hw))
- hw->intr_mask |= IS_PORT_2;
+ hw->intr_mask = IS_HW_ERR | IS_EXT_REG;
skge_write32(hw, B0_IMSK, hw->intr_mask);
if (hw->chip_id != CHIP_ID_GENESIS)
skge_write8(hw, GMAC_IRQ_MSK, 0);
spin_lock_bh(&hw->phy_lock);
- for (i = 0; i < ports; i++) {
+ for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_reset(hw, i);
else
@@ -3071,7 +3026,8 @@ static int skge_reset(struct skge_hw *hw)
}
/* Initialize network device */
-static struct net_device *skge_devinit(struct skge_hw *hw, int port)
+static struct net_device *skge_devinit(struct skge_hw *hw, int port,
+ int highmem)
{
struct skge_port *skge;
struct net_device *dev = alloc_etherdev(sizeof(*skge));
@@ -3104,6 +3060,8 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port)
#endif
dev->irq = hw->pdev->irq;
dev->features = NETIF_F_LLTX;
+ if (highmem)
+ dev->features |= NETIF_F_HIGHDMA;
skge = netdev_priv(dev);
skge->netdev = dev;
@@ -3117,7 +3075,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port)
skge->flow_control = FLOW_MODE_SYMMETRIC;
skge->duplex = -1;
skge->speed = -1;
- skge->advertising = skge_modes(hw);
+ skge->advertising = skge_supported_modes(hw);
hw->dev[port] = dev;
@@ -3125,10 +3083,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port)
spin_lock_init(&skge->tx_lock);
- init_timer(&skge->link_check);
- skge->link_check.function = skge_link_timer;
- skge->link_check.data = (unsigned long) skge;
-
init_timer(&skge->led_blink);
skge->led_blink.function = skge_blink_timer;
skge->led_blink.data = (unsigned long) skge;
@@ -3232,14 +3186,11 @@ static int __devinit skge_probe(struct pci_dev *pdev,
printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n",
pci_resource_start(pdev, 0), pdev->irq,
- skge_board_name(hw), chip_rev(hw));
+ skge_board_name(hw), hw->chip_rev);
- if ((dev = skge_devinit(hw, 0)) == NULL)
+ if ((dev = skge_devinit(hw, 0, using_dac)) == NULL)
goto err_out_led_off;
- if (using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
if ((err = register_netdev(dev))) {
printk(KERN_ERR PFX "%s: cannot register net device\n",
pci_name(pdev));
@@ -3248,10 +3199,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
skge_show_addr(dev);
- if (isdualport(hw) && (dev1 = skge_devinit(hw, 1))) {
- if (using_dac)
- dev1->features |= NETIF_F_HIGHDMA;
-
+ if (hw->ports > 1 && (dev1 = skge_devinit(hw, 1, using_dac))) {
if (register_netdev(dev1) == 0)
skge_show_addr(dev1);
else {
@@ -3288,7 +3236,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
struct skge_hw *hw = pci_get_drvdata(pdev);
struct net_device *dev0, *dev1;
- if(!hw)
+ if (!hw)
return;
if ((dev1 = hw->dev[1]))
@@ -3316,7 +3264,7 @@ static int skge_suspend(struct pci_dev *pdev, u32 state)
struct skge_hw *hw = pci_get_drvdata(pdev);
int i, wol = 0;
- for(i = 0; i < 2; i++) {
+ for (i = 0; i < 2; i++) {
struct net_device *dev = hw->dev[i];
if (dev) {
@@ -3349,11 +3297,11 @@ static int skge_resume(struct pci_dev *pdev)
skge_reset(hw);
- for(i = 0; i < 2; i++) {
+ for (i = 0; i < 2; i++) {
struct net_device *dev = hw->dev[i];
if (dev) {
netif_device_attach(dev);
- if(netif_running(dev))
+ if (netif_running(dev))
skge_up(dev);
}
}
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 36c62b68fab..14d0cc01fb9 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -7,31 +7,6 @@
/* PCI config registers */
#define PCI_DEV_REG1 0x40
#define PCI_DEV_REG2 0x44
-#ifndef PCI_VPD
-#define PCI_VPD 0x50
-#endif
-
-/* PCI_OUR_REG_2 32 bit Our Register 2 */
-enum {
- PCI_VPD_WR_THR = 0xff<<24, /* Bit 31..24: VPD Write Threshold */
- PCI_DEV_SEL = 0x7f<<17, /* Bit 23..17: EEPROM Device Select */
- PCI_VPD_ROM_SZ = 7 <<14, /* Bit 16..14: VPD ROM Size */
- /* Bit 13..12: reserved */
- PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */
- PCI_REV_DESC = 1<<2, /* Reverse Desc. Bytes */
- PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
-};
-
-/* PCI_VPD_ADR_REG 16 bit VPD Address Register */
-enum {
- PCI_VPD_FLAG = 1<<15, /* starts VPD rd/wr cycle */
- PCI_VPD_ADR_MSK =0x7fffL, /* Bit 14.. 0: VPD Address Mask */
- VPD_RES_ID = 0x82,
- VPD_RES_READ = 0x90,
- VPD_RES_WRITE = 0x81,
- VPD_RES_END = 0x78,
-};
-
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -39,7 +14,6 @@ enum {
PCI_STATUS_REC_TARGET_ABORT | \
PCI_STATUS_PARITY)
-
enum csr_regs {
B0_RAP = 0x0000,
B0_CTST = 0x0004,
@@ -229,8 +203,11 @@ enum {
IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */
IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */
- IS_PORT_1 = IS_XA1_F| IS_R1_F| IS_MAC1,
- IS_PORT_2 = IS_XA2_F| IS_R2_F| IS_MAC2,
+ IS_TO_PORT1 = IS_PA_TO_RX1 | IS_PA_TO_TX1,
+ IS_TO_PORT2 = IS_PA_TO_RX2 | IS_PA_TO_TX2,
+
+ IS_PORT_1 = IS_XA1_F| IS_R1_F | IS_TO_PORT1 | IS_MAC1,
+ IS_PORT_2 = IS_XA2_F| IS_R2_F | IS_TO_PORT2 | IS_MAC2,
};
@@ -288,14 +265,6 @@ enum {
CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */
};
-/* B2_LD_TEST 8 bit EPROM loader test register */
-enum {
- LD_T_ON = 1<<3, /* Loader Test mode on */
- LD_T_OFF = 1<<2, /* Loader Test mode off */
- LD_T_STEP = 1<<1, /* Decrement FPROM addr. Counter */
- LD_START = 1<<0, /* Start loading FPROM */
-};
-
/* B2_TI_CTRL 8 bit Timer control */
/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
enum {
@@ -313,16 +282,6 @@ enum {
TIM_T_STEP = 1<<0, /* Test step */
};
-/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */
-/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */
-/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
-enum {
- DPT_MSK = 0x00ffffffL, /* Bit 23.. 0: Desc Poll Timer Bits */
-
- DPT_START = 1<<1, /* Start Descriptor Poll Timer */
- DPT_STOP = 1<<0, /* Stop Descriptor Poll Timer */
-};
-
/* B2_GP_IO 32 bit General Purpose I/O Register */
enum {
GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */
@@ -348,30 +307,6 @@ enum {
GP_IO_0 = 1<<0, /* IO_0 pin */
};
-/* Rx/Tx Path related Arbiter Test Registers */
-/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */
-/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */
-/* B3_PA_TEST 16 bit Packet Arbiter Test Register */
-/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
-enum {
- TX2_T_EV = 1<<15,/* TX2 Timeout/Recv Event occured */
- TX2_T_ON = 1<<14,/* TX2 Timeout/Recv Timer Test On */
- TX2_T_OFF = 1<<13,/* TX2 Timeout/Recv Timer Tst Off */
- TX2_T_STEP = 1<<12,/* TX2 Timeout/Recv Timer Step */
- TX1_T_EV = 1<<11,/* TX1 Timeout/Recv Event occured */
- TX1_T_ON = 1<<10,/* TX1 Timeout/Recv Timer Test On */
- TX1_T_OFF = 1<<9, /* TX1 Timeout/Recv Timer Tst Off */
- TX1_T_STEP = 1<<8, /* TX1 Timeout/Recv Timer Step */
- RX2_T_EV = 1<<7, /* RX2 Timeout/Recv Event occured */
- RX2_T_ON = 1<<6, /* RX2 Timeout/Recv Timer Test On */
- RX2_T_OFF = 1<<5, /* RX2 Timeout/Recv Timer Tst Off */
- RX2_T_STEP = 1<<4, /* RX2 Timeout/Recv Timer Step */
- RX1_T_EV = 1<<3, /* RX1 Timeout/Recv Event occured */
- RX1_T_ON = 1<<2, /* RX1 Timeout/Recv Timer Test On */
- RX1_T_OFF = 1<<1, /* RX1 Timeout/Recv Timer Tst Off */
- RX1_T_STEP = 1<<0, /* RX1 Timeout/Recv Timer Step */
-};
-
/* Descriptor Bit Definition */
/* TxCtrl Transmit Buffer Control Field */
/* RxCtrl Receive Buffer Control Field */
@@ -428,14 +363,6 @@ enum {
RI_RST_SET = 1<<0, /* Set RAM Interface Reset */
};
-/* B3_RI_TEST 8 bit RAM Iface Test Register */
-enum {
- RI_T_EV = 1<<3, /* Timeout Event occured */
- RI_T_ON = 1<<2, /* Timeout Timer Test On */
- RI_T_OFF = 1<<1, /* Timeout Timer Test Off */
- RI_T_STEP = 1<<0, /* Timeout Timer Step */
-};
-
/* MAC Arbiter Registers */
/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */
enum {
@@ -452,19 +379,6 @@ enum {
#define SK_PKT_TO_MAX 0xffff /* Maximum value */
#define SK_RI_TO_53 36 /* RAM interface timeout */
-
-/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */
-enum {
- MA_ENA_REC_TX2 = 1<<7, /* Enable Recovery Timer TX2 */
- MA_DIS_REC_TX2 = 1<<6, /* Disable Recovery Timer TX2 */
- MA_ENA_REC_TX1 = 1<<5, /* Enable Recovery Timer TX1 */
- MA_DIS_REC_TX1 = 1<<4, /* Disable Recovery Timer TX1 */
- MA_ENA_REC_RX2 = 1<<3, /* Enable Recovery Timer RX2 */
- MA_DIS_REC_RX2 = 1<<2, /* Disable Recovery Timer RX2 */
- MA_ENA_REC_RX1 = 1<<1, /* Enable Recovery Timer RX1 */
- MA_DIS_REC_RX1 = 1<<0, /* Disable Recovery Timer RX1 */
-};
-
/* Packet Arbiter Registers */
/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */
enum {
@@ -488,7 +402,7 @@ enum {
PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
@@ -511,7 +425,7 @@ enum {
/*
* Bank 4 - 5
*/
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
enum {
TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/
TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */
@@ -537,7 +451,7 @@ enum {
/* Queue Register Offsets, use Q_ADDR() to access */
enum {
- B8_Q_REGS = 0x0400, /* base of Queue registers */
+ B8_Q_REGS = 0x0400, /* base of Queue registers */
Q_D = 0x00, /* 8*32 bit Current Descriptor */
Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
@@ -618,8 +532,7 @@ enum {
enum {
PHY_ADDR_XMAC = 0<<8,
PHY_ADDR_BCOM = 1<<8,
- PHY_ADDR_LONE = 3<<8,
- PHY_ADDR_NAT = 0<<8,
+
/* GPHY address (bits 15..11 of SMI control reg) */
PHY_ADDR_MARV = 0,
};
@@ -986,7 +899,7 @@ enum {
LINKLED_BLINK_OFF = 0x10,
LINKLED_BLINK_ON = 0x20,
};
-
+
/* GMAC and GPHY Control Registers (YUKON only) */
enum {
GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */
@@ -1151,54 +1064,6 @@ enum {
PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */
};
-/* Level One-PHY Registers, indirect addressed over XMAC */
-enum {
- PHY_LONE_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
- PHY_LONE_STAT = 0x01,/* 16 bit r/o PHY Status Register */
- PHY_LONE_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
- PHY_LONE_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
- PHY_LONE_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
- PHY_LONE_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
- PHY_LONE_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
- PHY_LONE_NEPG = 0x07,/* 16 bit r/w Next Page Register */
- PHY_LONE_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
- /* Level One-specific registers */
- PHY_LONE_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
- PHY_LONE_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
- PHY_LONE_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
- PHY_LONE_PORT_CFG = 0x10,/* 16 bit r/w Port Configuration Reg*/
- PHY_LONE_Q_STAT = 0x11,/* 16 bit r/o Quick Status Reg */
- PHY_LONE_INT_ENAB = 0x12,/* 16 bit r/w Interrupt Enable Reg */
- PHY_LONE_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */
- PHY_LONE_LED_CFG = 0x14,/* 16 bit r/w LED Configuration Reg */
- PHY_LONE_PORT_CTRL = 0x15,/* 16 bit r/w Port Control Reg */
- PHY_LONE_CIM = 0x16,/* 16 bit r/o CIM Reg */
-};
-
-/* National-PHY Registers, indirect addressed over XMAC */
-enum {
- PHY_NAT_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
- PHY_NAT_STAT = 0x01,/* 16 bit r/w PHY Status Register */
- PHY_NAT_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
- PHY_NAT_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
- PHY_NAT_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
- PHY_NAT_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Ability Reg */
- PHY_NAT_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
- PHY_NAT_NEPG = 0x07,/* 16 bit r/w Next Page Register */
- PHY_NAT_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner Reg */
- /* National-specific registers */
- PHY_NAT_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
- PHY_NAT_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
- PHY_NAT_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Register */
- PHY_NAT_EXT_CTRL1 = 0x10,/* 16 bit r/o Extended Control Reg1 */
- PHY_NAT_Q_STAT1 = 0x11,/* 16 bit r/o Quick Status Reg1 */
- PHY_NAT_10B_OP = 0x12,/* 16 bit r/o 10Base-T Operations Reg */
- PHY_NAT_EXT_CTRL2 = 0x13,/* 16 bit r/o Extended Control Reg1 */
- PHY_NAT_Q_STAT2 = 0x14,/* 16 bit r/o Quick Status Reg2 */
-
- PHY_NAT_PHY_ADDR = 0x19,/* 16 bit r/o PHY Address Register */
-};
-
enum {
PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */
PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */
@@ -1253,8 +1118,29 @@ enum {
PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
};
+/* Advertisement register bits */
enum {
PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
+ PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
+ PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */
+
+ PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */
+ PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */
+ PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */
+ PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */
+ PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */
+ PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */
+ PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */
+ PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */
+ PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+ PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA,
+ PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL |
+ PHY_AN_100HALF | PHY_AN_100FULL,
+};
+
+/* Xmac Specific */
+enum {
+ PHY_X_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */
@@ -1263,82 +1149,6 @@ enum {
PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */
};
-enum {
- PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */
-
- PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */
- PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */
- PHY_B_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
-};
-
-enum {
- PHY_L_AN_RF = 1<<13, /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
- PHY_L_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */
- PHY_L_AN_PC = 1<<10, /* Bit 10: Pause Capable */
-
- PHY_L_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
-};
-
-/* PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement */
-/* PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
-enum {
- PHY_N_AN_RF = 1<<13, /* Bit 13: Remote Fault */
-
- PHY_N_AN_100F = 1<<11, /* Bit 11: 100Base-T2 FD Support */
- PHY_N_AN_100H = 1<<10, /* Bit 10: 100Base-T2 HD Support */
-
- PHY_N_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
-};
-
-/* field type definition for PHY_x_AN_SEL */
-enum {
- PHY_SEL_TYPE = 1, /* 00001 = Ethernet */
-};
-
-enum {
- PHY_ANE_LP_NP = 1<<3, /* Bit 3: Link Partner can Next Page */
- PHY_ANE_LOC_NP = 1<<2, /* Bit 2: Local PHY can Next Page */
- PHY_ANE_RX_PG = 1<<1, /* Bit 1: Page Received */
-};
-
-enum {
- PHY_ANE_PAR_DF = 1<<4, /* Bit 4: Parallel Detection Fault */
-
- PHY_ANE_LP_CAP = 1<<0, /* Bit 0: Link Partner Auto-Neg. Cap. */
-};
-
-enum {
- PHY_NP_MORE = 1<<15, /* Bit 15: More, Next Pages to follow */
- PHY_NP_ACK1 = 1<<14, /* Bit 14: (ro) Ack1, for receiving a message */
- PHY_NP_MSG_VAL = 1<<13, /* Bit 13: Message Page valid */
- PHY_NP_ACK2 = 1<<12, /* Bit 12: Ack2, comply with msg content */
- PHY_NP_TOG = 1<<11, /* Bit 11: Toggle Bit, ensure sync */
- PHY_NP_MSG = 0x07ff, /* Bit 10..0: Message from/to Link Partner */
-};
-
-enum {
- PHY_X_EX_FD = 1<<15, /* Bit 15: Device Supports Full Duplex */
- PHY_X_EX_HD = 1<<14, /* Bit 14: Device Supports Half Duplex */
-};
-
-enum {
- PHY_X_RS_PAUSE = 3<<7,/* Bit 8..7: selected Pause Mode */
- PHY_X_RS_HD = 1<<6, /* Bit 6: Half Duplex Mode selected */
- PHY_X_RS_FD = 1<<5, /* Bit 5: Full Duplex Mode selected */
- PHY_X_RS_ABLMIS = 1<<4, /* Bit 4: duplex or pause cap mismatch */
- PHY_X_RS_PAUMIS = 1<<3, /* Bit 3: pause capability mismatch */
-};
-
-/** Remote Fault Bits (PHY_X_AN_RFB) encoding */
-enum {
- X_RFB_OK = 0<<12,/* Bit 13..12 No errors, Link OK */
- X_RFB_LF = 1<<12, /* Bit 13..12 Link Failure */
- X_RFB_OFF = 2<<12,/* Bit 13..12 Offline */
- X_RFB_AN_ERR = 3<<12,/* Bit 13..12 Auto-Negotiation Error */
-};
-
/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
enum {
PHY_X_P_NO_PAUSE = 0<<7,/* Bit 8..7: no Pause Mode */
@@ -1418,6 +1228,16 @@ enum {
PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */
};
+/* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+/* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+enum {
+ PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */
+
+ PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */
+ PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */
+};
+
+
/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/
enum {
PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */
@@ -1478,7 +1298,9 @@ enum {
PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */
PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */
};
-#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+#define PHY_B_DEF_MSK \
+ (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \
+ PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE))
/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
enum {
@@ -1495,166 +1317,6 @@ enum {
PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */
};
-/*
- * Level One-Specific
- */
-/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-enum {
- PHY_L_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
- PHY_L_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */
- PHY_L_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */
- PHY_L_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */
- PHY_L_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */
- PHY_L_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */
-};
-
-/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-enum {
- PHY_L_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
- PHY_L_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
- PHY_L_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
- PHY_L_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */
- PHY_L_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */
- PHY_L_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */
-
- PHY_L_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
-
-/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/
- PHY_L_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */
- PHY_L_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */
- PHY_L_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */
- PHY_L_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */
-};
-
-/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/
-enum {
- PHY_L_PC_REP_MODE = 1<<15, /* Bit 15: Repeater Mode */
-
- PHY_L_PC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */
- PHY_L_PC_BY_SCR = 1<<12, /* Bit 12: Bypass Scrambler */
- PHY_L_PC_BY_45 = 1<<11, /* Bit 11: Bypass 4B5B-Decoder */
- PHY_L_PC_JAB_DIS = 1<<10, /* Bit 10: Jabber Disabled */
- PHY_L_PC_SQE = 1<<9, /* Bit 9: Enable Heartbeat */
- PHY_L_PC_TP_LOOP = 1<<8, /* Bit 8: TP Loopback */
- PHY_L_PC_SSS = 1<<7, /* Bit 7: Smart Speed Selection */
- PHY_L_PC_FIFO_SIZE = 1<<6, /* Bit 6: FIFO Size */
- PHY_L_PC_PRE_EN = 1<<5, /* Bit 5: Preamble Enable */
- PHY_L_PC_CIM = 1<<4, /* Bit 4: Carrier Integrity Mon */
- PHY_L_PC_10_SER = 1<<3, /* Bit 3: Use Serial Output */
- PHY_L_PC_ANISOL = 1<<2, /* Bit 2: Unisolate Port */
- PHY_L_PC_TEN_BIT = 1<<1, /* Bit 1: 10bit iface mode on */
- PHY_L_PC_ALTCLOCK = 1<<0, /* Bit 0: (ro) ALTCLOCK Mode on */
-};
-
-/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/
-enum {
- PHY_L_QS_D_RATE = 3<<14,/* Bit 15..14: Data Rate */
- PHY_L_QS_TX_STAT = 1<<13, /* Bit 13: Transmitting */
- PHY_L_QS_RX_STAT = 1<<12, /* Bit 12: Receiving */
- PHY_L_QS_COL_STAT = 1<<11, /* Bit 11: Collision */
- PHY_L_QS_L_STAT = 1<<10, /* Bit 10: Link is up */
- PHY_L_QS_DUP_MOD = 1<<9, /* Bit 9: Full/Half Duplex */
- PHY_L_QS_AN = 1<<8, /* Bit 8: AutoNeg is On */
- PHY_L_QS_AN_C = 1<<7, /* Bit 7: AN is Complete */
- PHY_L_QS_LLE = 7<<4,/* Bit 6..4: Line Length Estim. */
- PHY_L_QS_PAUSE = 1<<3, /* Bit 3: LP advertised Pause */
- PHY_L_QS_AS_PAUSE = 1<<2, /* Bit 2: LP adv. asym. Pause */
- PHY_L_QS_ISOLATE = 1<<1, /* Bit 1: CIM Isolated */
- PHY_L_QS_EVENT = 1<<0, /* Bit 0: Event has occurred */
-};
-
-/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/
-/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/
-enum {
- PHY_L_IS_AN_F = 1<<13, /* Bit 13: Auto-Negotiation fault */
- PHY_L_IS_CROSS = 1<<11, /* Bit 11: Crossover used */
- PHY_L_IS_POL = 1<<10, /* Bit 10: Polarity correct. used */
- PHY_L_IS_SS = 1<<9, /* Bit 9: Smart Speed Downgrade */
- PHY_L_IS_CFULL = 1<<8, /* Bit 8: Counter Full */
- PHY_L_IS_AN_C = 1<<7, /* Bit 7: AutoNeg Complete */
- PHY_L_IS_SPEED = 1<<6, /* Bit 6: Speed Changed */
- PHY_L_IS_DUP = 1<<5, /* Bit 5: Duplex Changed */
- PHY_L_IS_LS = 1<<4, /* Bit 4: Link Status Changed */
- PHY_L_IS_ISOL = 1<<3, /* Bit 3: Isolate Occured */
- PHY_L_IS_MDINT = 1<<2, /* Bit 2: (ro) STAT: MII Int Pending */
- PHY_L_IS_INTEN = 1<<1, /* Bit 1: ENAB: Enable IRQs */
- PHY_L_IS_FORCE = 1<<0, /* Bit 0: ENAB: Force Interrupt */
-};
-
-/* int. mask */
-#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
-
-/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/
-enum {
- PHY_L_LC_LEDC = 3<<14,/* Bit 15..14: Col/Blink/On/Off */
- PHY_L_LC_LEDR = 3<<12,/* Bit 13..12: Rx/Blink/On/Off */
- PHY_L_LC_LEDT = 3<<10,/* Bit 11..10: Tx/Blink/On/Off */
- PHY_L_LC_LEDG = 3<<8,/* Bit 9..8: Giga/Blink/On/Off */
- PHY_L_LC_LEDS = 3<<6,/* Bit 7..6: 10-100/Blink/On/Off */
- PHY_L_LC_LEDL = 3<<4,/* Bit 5..4: Link/Blink/On/Off */
- PHY_L_LC_LEDF = 3<<2,/* Bit 3..2: Duplex/Blink/On/Off */
- PHY_L_LC_PSTRECH= 1<<1, /* Bit 1: Strech LED Pulses */
- PHY_L_LC_FREQ = 1<<0, /* Bit 0: 30/100 ms */
-};
-
-/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/
-enum {
- PHY_L_PC_TX_TCLK = 1<<15, /* Bit 15: Enable TX_TCLK */
- PHY_L_PC_ALT_NP = 1<<13, /* Bit 14: Alternate Next Page */
- PHY_L_PC_GMII_ALT= 1<<12, /* Bit 13: Alternate GMII driver */
- PHY_L_PC_TEN_CRS = 1<<10, /* Bit 10: Extend CRS*/
-};
-
-/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/
-enum {
- PHY_L_CIM_ISOL = 0xff<<8,/* Bit 15..8: Isolate Count */
- PHY_L_CIM_FALSE_CAR = 0xff, /* Bit 7..0: False Carrier Count */
-};
-
-/*
- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
- */
-enum {
- PHY_L_P_NO_PAUSE= 0<<10,/* Bit 11..10: no Pause Mode */
- PHY_L_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */
- PHY_L_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */
- PHY_L_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */
-};
-
-/*
- * National-Specific
- */
-/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-enum {
- PHY_N_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */
- PHY_N_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */
- PHY_N_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */
- PHY_N_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */
- PHY_N_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */
- PHY_N_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */
- PHY_N_1000C_APC = 1<<7, /* Bit 7: Asymmetric Pause Cap. */};
-
-
-/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-enum {
- PHY_N_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
- PHY_N_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
- PHY_N_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
- PHY_N_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status*/
- PHY_N_1000S_LP_FD= 1<<11, /* Bit 11: Link Partner can FD */
- PHY_N_1000S_LP_HD= 1<<10, /* Bit 10: Link Partner can HD */
- PHY_N_1000C_LP_APC= 1<<9, /* Bit 9: LP Asym. Pause Cap. */
- PHY_N_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
-};
-
-/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/
-enum {
- PHY_N_ES_X_FD_CAP= 1<<15, /* Bit 15: 1000Base-X FD capable */
- PHY_N_ES_X_HD_CAP= 1<<14, /* Bit 14: 1000Base-X HD capable */
- PHY_N_ES_T_FD_CAP= 1<<13, /* Bit 13: 1000Base-T FD capable */
- PHY_N_ES_T_HD_CAP= 1<<12, /* Bit 12: 1000Base-T HD capable */
-};
-
/** Marvell-Specific */
enum {
PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */
@@ -1718,7 +1380,7 @@ enum {
PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */
};
-#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK)
+#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK)
enum {
PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */
@@ -2105,7 +1767,7 @@ enum {
GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */
GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */
};
-
+
/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
enum {
GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */
@@ -2127,7 +1789,7 @@ enum {
#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
-
+
/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
enum {
GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
@@ -2138,7 +1800,7 @@ enum {
#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
#define TX_COL_DEF 0x04
-
+
/* GM_RX_CTRL 16 bit r/w Receive Control Register */
enum {
GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */
@@ -2146,7 +1808,7 @@ enum {
GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */
GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */
};
-
+
/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
enum {
GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */
@@ -2171,7 +1833,7 @@ enum {
GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */
GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
};
-
+
#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK)
#define DATA_BLIND_DEF 0x04
@@ -2186,7 +1848,7 @@ enum {
GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */
GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */
};
-
+
#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK)
#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK)
@@ -2195,7 +1857,7 @@ enum {
GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */
GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */
};
-
+
/* Receive Frame Status Encoding */
enum {
GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
@@ -2217,12 +1879,12 @@ enum {
/*
* GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
*/
- GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR |
- GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
+ GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
GMR_FS_JABBER,
/* Rx GMAC FIFO Flush Mask (default) */
RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR |
- GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE |
+ GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE |
GMR_FS_JABBER,
};
@@ -2540,10 +2202,6 @@ enum {
};
-/* XM_PHY_ADDR 16 bit r/w PHY Address Register */
-#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */
-
-
/* XM_GP_PORT 32 bit r/w General Purpose Port Register */
enum {
XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */
@@ -2662,8 +2320,8 @@ enum {
};
#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
-#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
- XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
+#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+ XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA)
/* XM_STAT_CMD 16 bit r/w Statistics Command Register */
enum {
@@ -2793,28 +2451,20 @@ struct skge_hw {
u32 intr_mask;
struct net_device *dev[2];
- u8 mac_cfg;
u8 chip_id;
+ u8 chip_rev;
u8 phy_type;
u8 pmd_type;
u16 phy_addr;
+ u8 ports;
u32 ram_size;
u32 ram_offset;
-
+
struct tasklet_struct ext_tasklet;
spinlock_t phy_lock;
};
-static inline int isdualport(const struct skge_hw *hw)
-{
- return !(hw->mac_cfg & CFG_SNG_MAC);
-}
-
-static inline u8 chip_rev(const struct skge_hw *hw)
-{
- return (hw->mac_cfg & CFG_CHIP_R_MSK) >> 4;
-}
static inline int iscopper(const struct skge_hw *hw)
{
@@ -2827,7 +2477,7 @@ enum {
FLOW_MODE_REM_SEND = 2, /* Symmetric or just remote */
FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */
};
-
+
struct skge_port {
u32 msg_enable;
struct skge_hw *hw;
@@ -2853,8 +2503,8 @@ struct skge_port {
void *mem; /* PCI memory for rings */
dma_addr_t dma;
unsigned long mem_size;
+ unsigned int rx_buf_size;
- struct timer_list link_check;
struct timer_list led_blink;
};
@@ -2863,7 +2513,6 @@ struct skge_port {
static inline u32 skge_read32(const struct skge_hw *hw, int reg)
{
return readl(hw->regs + reg);
-
}
static inline u16 skge_read16(const struct skge_hw *hw, int reg)
@@ -2892,114 +2541,87 @@ static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val)
}
/* MAC Related Registers inside the device. */
-#define SKGEMAC_REG(port,reg) (((port)<<7)+(reg))
-
-/* PCI config space can be accessed via memory mapped space */
-#define SKGEPCI_REG(reg) ((reg)+ 0x380)
-
-#define SKGEXM_REG(port, reg) \
+#define SK_REG(port,reg) (((port)<<7)+(reg))
+#define SK_XMAC_REG(port, reg) \
((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1)
-static inline u32 skge_xm_read32(const struct skge_hw *hw, int port, int reg)
-{
- return skge_read32(hw, SKGEXM_REG(port,reg));
-}
-
-static inline u16 skge_xm_read16(const struct skge_hw *hw, int port, int reg)
+static inline u32 xm_read32(const struct skge_hw *hw, int port, int reg)
{
- return skge_read16(hw, SKGEXM_REG(port,reg));
+ u32 v;
+ v = skge_read16(hw, SK_XMAC_REG(port, reg));
+ v |= (u32)skge_read16(hw, SK_XMAC_REG(port, reg+2)) << 16;
+ return v;
}
-static inline u8 skge_xm_read8(const struct skge_hw *hw, int port, int reg)
+static inline u16 xm_read16(const struct skge_hw *hw, int port, int reg)
{
- return skge_read8(hw, SKGEXM_REG(port,reg));
+ return skge_read16(hw, SK_XMAC_REG(port,reg));
}
-static inline void skge_xm_write32(const struct skge_hw *hw, int port, int r, u32 v)
+static inline void xm_write32(const struct skge_hw *hw, int port, int r, u32 v)
{
- skge_write32(hw, SKGEXM_REG(port,r), v);
+ skge_write16(hw, SK_XMAC_REG(port,r), v & 0xffff);
+ skge_write16(hw, SK_XMAC_REG(port,r+2), v >> 16);
}
-static inline void skge_xm_write16(const struct skge_hw *hw, int port, int r, u16 v)
+static inline void xm_write16(const struct skge_hw *hw, int port, int r, u16 v)
{
- skge_write16(hw, SKGEXM_REG(port,r), v);
+ skge_write16(hw, SK_XMAC_REG(port,r), v);
}
-static inline void skge_xm_write8(const struct skge_hw *hw, int port, int r, u8 v)
-{
- skge_write8(hw, SKGEXM_REG(port,r), v);
-}
-
-static inline void skge_xm_outhash(const struct skge_hw *hw, int port, int reg,
+static inline void xm_outhash(const struct skge_hw *hw, int port, int reg,
const u8 *hash)
{
- skge_xm_write16(hw, port, reg,
- (u16)hash[0] | ((u16)hash[1] << 8));
- skge_xm_write16(hw, port, reg+2,
- (u16)hash[2] | ((u16)hash[3] << 8));
- skge_xm_write16(hw, port, reg+4,
- (u16)hash[4] | ((u16)hash[5] << 8));
- skge_xm_write16(hw, port, reg+6,
- (u16)hash[6] | ((u16)hash[7] << 8));
+ xm_write16(hw, port, reg, (u16)hash[0] | ((u16)hash[1] << 8));
+ xm_write16(hw, port, reg+2, (u16)hash[2] | ((u16)hash[3] << 8));
+ xm_write16(hw, port, reg+4, (u16)hash[4] | ((u16)hash[5] << 8));
+ xm_write16(hw, port, reg+6, (u16)hash[6] | ((u16)hash[7] << 8));
}
-static inline void skge_xm_outaddr(const struct skge_hw *hw, int port, int reg,
+static inline void xm_outaddr(const struct skge_hw *hw, int port, int reg,
const u8 *addr)
{
- skge_xm_write16(hw, port, reg,
- (u16)addr[0] | ((u16)addr[1] << 8));
- skge_xm_write16(hw, port, reg,
- (u16)addr[2] | ((u16)addr[3] << 8));
- skge_xm_write16(hw, port, reg,
- (u16)addr[4] | ((u16)addr[5] << 8));
+ xm_write16(hw, port, reg, (u16)addr[0] | ((u16)addr[1] << 8));
+ xm_write16(hw, port, reg+2, (u16)addr[2] | ((u16)addr[3] << 8));
+ xm_write16(hw, port, reg+4, (u16)addr[4] | ((u16)addr[5] << 8));
}
+#define SK_GMAC_REG(port,reg) \
+ (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg))
-#define SKGEGMA_REG(port,reg) \
- ((reg) + BASE_GMAC_1 + \
- (port) * (BASE_GMAC_2-BASE_GMAC_1))
-
-static inline u16 skge_gma_read16(const struct skge_hw *hw, int port, int reg)
+static inline u16 gma_read16(const struct skge_hw *hw, int port, int reg)
{
- return skge_read16(hw, SKGEGMA_REG(port,reg));
+ return skge_read16(hw, SK_GMAC_REG(port,reg));
}
-static inline u32 skge_gma_read32(const struct skge_hw *hw, int port, int reg)
+static inline u32 gma_read32(const struct skge_hw *hw, int port, int reg)
{
- return (u32) skge_read16(hw, SKGEGMA_REG(port,reg))
- | ((u32)skge_read16(hw, SKGEGMA_REG(port,reg+4)) << 16);
+ return (u32) skge_read16(hw, SK_GMAC_REG(port,reg))
+ | ((u32)skge_read16(hw, SK_GMAC_REG(port,reg+4)) << 16);
}
-static inline u8 skge_gma_read8(const struct skge_hw *hw, int port, int reg)
+static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
{
- return skge_read8(hw, SKGEGMA_REG(port,reg));
+ skge_write16(hw, SK_GMAC_REG(port,r), v);
}
-static inline void skge_gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
+static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v)
{
- skge_write16(hw, SKGEGMA_REG(port,r), v);
+ skge_write16(hw, SK_GMAC_REG(port, r), (u16) v);
+ skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16));
}
-static inline void skge_gma_write32(const struct skge_hw *hw, int port, int r, u32 v)
+static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v)
{
- skge_write16(hw, SKGEGMA_REG(port, r), (u16) v);
- skge_write32(hw, SKGEGMA_REG(port, r+4), (u16)(v >> 16));
+ skge_write8(hw, SK_GMAC_REG(port,r), v);
}
-static inline void skge_gma_write8(const struct skge_hw *hw, int port, int r, u8 v)
-{
- skge_write8(hw, SKGEGMA_REG(port,r), v);
-}
-
-static inline void skge_gm_set_addr(struct skge_hw *hw, int port, int reg,
+static inline void gma_set_addr(struct skge_hw *hw, int port, int reg,
const u8 *addr)
{
- skge_gma_write16(hw, port, reg,
- (u16) addr[0] | ((u16) addr[1] << 8));
- skge_gma_write16(hw, port, reg+4,
- (u16) addr[2] | ((u16) addr[3] << 8));
- skge_gma_write16(hw, port, reg+8,
- (u16) addr[4] | ((u16) addr[5] << 8));
+ gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8));
+ gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
+ gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
}
-
+
#endif
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 16363b5c6f5..404ea4297e3 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -74,6 +74,7 @@
#include <linux/rtnetlink.h>
#include <linux/if_arp.h>
#include <linux/if_slip.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include "slip.h"
#ifdef CONFIG_INET
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index cfb9d3cdb04..1438fdd2082 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1998,7 +1998,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
if (retval)
goto err_out;
- set_irq_type(dev->irq, IRQT_RISING);
+ set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE);
#ifdef SMC_USE_PXA_DMA
{
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 946528e6b74..7089d86e857 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -182,6 +182,16 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
+#include <asm/mach-types.h>
+#include <asm/arch/cpu.h>
+
+#define SMC_IRQ_TRIGGER_TYPE (( \
+ machine_is_omap_h2() \
+ || machine_is_omap_h3() \
+ || (machine_is_omap_innovator() && !cpu_is_omap150()) \
+ ) ? IRQT_FALLING : IRQT_RISING)
+
+
#elif defined(CONFIG_SH_SH4202_MICRODEV)
#define SMC_CAN_USE_8BIT 0
@@ -300,6 +310,9 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
#endif
+#ifndef SMC_IRQ_TRIGGER_TYPE
+#define SMC_IRQ_TRIGGER_TYPE IRQT_RISING
+#endif
#ifdef SMC_USE_PXA_DMA
/*
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 12e2b6826fa..88b89dc95c7 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1286,7 +1286,7 @@ static void init_ring(struct net_device *dev)
np->rx_info[i].skb = skb;
if (skb == NULL)
break;
- np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb->dev = dev; /* Mark as being used by this device. */
/* Grrr, we cannot offset to correctly align the IP header. */
np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
@@ -1572,7 +1572,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
pci_dma_sync_single_for_cpu(np->pci_dev,
np->rx_info[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
+ eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
pci_dma_sync_single_for_device(np->pci_dev,
np->rx_info[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
@@ -1696,7 +1696,7 @@ static void refill_rx_ring(struct net_device *dev)
if (skb == NULL)
break; /* Better luck next round. */
np->rx_info[entry].mapping =
- pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb->dev = dev; /* Mark as being used by this device. */
np->rx_ring[entry].rxaddr =
cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 08cb7177a17..d500a5771db 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -1028,7 +1028,7 @@ static void init_ring(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
np->rx_ring[i].frag[0].addr = cpu_to_le32(
- pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz,
+ pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag);
}
@@ -1341,7 +1341,7 @@ static void rx_poll(unsigned long data)
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
+ eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
pci_dma_sync_single_for_device(np->pci_dev,
desc->frag[0].addr,
np->rx_buf_sz,
@@ -1400,7 +1400,7 @@ static void refill_rx (struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
np->rx_ring[entry].frag[0].addr = cpu_to_le32(
- pci_map_single(np->pci_dev, skb->tail,
+ pci_map_single(np->pci_dev, skb->data,
np->rx_buf_sz, PCI_DMA_FROMDEVICE));
}
/* Perhaps we need not reset this field. */
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index dd357dd8c37..fc353e348f9 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -446,13 +446,13 @@ static void de_rx (struct de_private *de)
mapping =
de->rx_skb[rx_tail].mapping =
- pci_map_single(de->pdev, copy_skb->tail,
+ pci_map_single(de->pdev, copy_skb->data,
buflen, PCI_DMA_FROMDEVICE);
de->rx_skb[rx_tail].skb = copy_skb;
} else {
pci_dma_sync_single_for_cpu(de->pdev, mapping, len, PCI_DMA_FROMDEVICE);
skb_reserve(copy_skb, RX_OFFSET);
- memcpy(skb_put(copy_skb, len), skb->tail, len);
+ memcpy(skb_put(copy_skb, len), skb->data, len);
pci_dma_sync_single_for_device(de->pdev, mapping, len, PCI_DMA_FROMDEVICE);
@@ -1269,7 +1269,7 @@ static int de_refill_rx (struct de_private *de)
skb->dev = de->dev;
de->rx_skb[i].mapping = pci_map_single(de->pdev,
- skb->tail, de->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb->data, de->rx_buf_sz, PCI_DMA_FROMDEVICE);
de->rx_skb[i].skb = skb;
de->rx_ring[i].opts1 = cpu_to_le32(DescOwn);
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 7b899702ceb..74e9075d9c4 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -945,8 +945,8 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
/* Received Packet CRC check need or not */
if ( (db->dm910x_chk_mode & 1) &&
- (cal_CRC(skb->tail, rxlen, 1) !=
- (*(u32 *) (skb->tail+rxlen) ))) { /* FIXME (?) */
+ (cal_CRC(skb->data, rxlen, 1) !=
+ (*(u32 *) (skb->data+rxlen) ))) { /* FIXME (?) */
/* Found a error received packet */
dmfe_reuse_skb(db, rxptr->rx_skb_ptr);
db->dm910x_chk_mode = 3;
@@ -959,7 +959,7 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
/* size less than COPY_SIZE, allocate a rxlen SKB */
skb->dev = dev;
skb_reserve(skb, 2); /* 16byte align */
- memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->tail, rxlen);
+ memcpy(skb_put(skb, rxlen), rxptr->rx_skb_ptr->data, rxlen);
dmfe_reuse_skb(db, rxptr->rx_skb_ptr);
} else {
skb->dev = dev;
@@ -1252,7 +1252,7 @@ static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb)
if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {
rxptr->rx_skb_ptr = skb;
- rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
wmb();
rxptr->rdes0 = cpu_to_le32(0x80000000);
db->rx_avail_cnt++;
@@ -1463,7 +1463,7 @@ static void allocate_rx_buffer(struct dmfe_board_info *db)
if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
break;
rxptr->rx_skb_ptr = skb; /* FIXME (?) */
- rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
wmb();
rxptr->rdes0 = cpu_to_le32(0x80000000);
rxptr = rxptr->next_rx_desc;
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index afb5cda9d8e..bb3558164a5 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -78,7 +78,7 @@ int tulip_refill_rx(struct net_device *dev)
if (skb == NULL)
break;
- mapping = pci_map_single(tp->pdev, skb->tail, PKT_BUF_SZ,
+ mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
tp->rx_buffers[entry].mapping = mapping;
@@ -199,12 +199,12 @@ int tulip_poll(struct net_device *dev, int *budget)
tp->rx_buffers[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
#if ! defined(__alpha__)
- eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail,
+ eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
pkt_len, 0);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
- tp->rx_buffers[entry].skb->tail,
+ tp->rx_buffers[entry].skb->data,
pkt_len);
#endif
pci_dma_sync_single_for_device(tp->pdev,
@@ -423,12 +423,12 @@ static int tulip_rx(struct net_device *dev)
tp->rx_buffers[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
#if ! defined(__alpha__)
- eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail,
+ eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
pkt_len, 0);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
- tp->rx_buffers[entry].skb->tail,
+ tp->rx_buffers[entry].skb->data,
pkt_len);
#endif
pci_dma_sync_single_for_device(tp->pdev,
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 08e0f80f89d..d45d8f56e5b 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -625,7 +625,7 @@ static void tulip_init_ring(struct net_device *dev)
tp->rx_buffers[i].skb = skb;
if (skb == NULL)
break;
- mapping = pci_map_single(tp->pdev, skb->tail,
+ mapping = pci_map_single(tp->pdev, skb->data,
PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
tp->rx_buffers[i].mapping = mapping;
skb->dev = dev; /* Mark as being used by this device. */
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index db4b32c2369..5b1af3986ab 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -849,7 +849,7 @@ static void init_rxtx_rings(struct net_device *dev)
if (skb == NULL)
break;
skb->dev = dev; /* Mark as being used by this device. */
- np->rx_addr[i] = pci_map_single(np->pci_dev,skb->tail,
+ np->rx_addr[i] = pci_map_single(np->pci_dev,skb->data,
skb->len,PCI_DMA_FROMDEVICE);
np->rx_ring[i].buffer1 = np->rx_addr[i];
@@ -1269,7 +1269,7 @@ static int netdev_rx(struct net_device *dev)
pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
np->rx_skbuff[entry]->len,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
+ eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
np->rx_skbuff[entry]->len,
@@ -1315,7 +1315,7 @@ static int netdev_rx(struct net_device *dev)
break; /* Better luck next round. */
skb->dev = dev; /* Mark as being used by this device. */
np->rx_addr[entry] = pci_map_single(np->pci_dev,
- skb->tail,
+ skb->data,
skb->len, PCI_DMA_FROMDEVICE);
np->rx_ring[entry].buffer1 = np->rx_addr[entry];
}
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index b8a9b395c5e..887d7245fe7 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -899,7 +899,7 @@ static void xircom_init_ring(struct net_device *dev)
break;
skb->dev = dev; /* Mark as being used by this device. */
tp->rx_ring[i].status = Rx0DescOwned; /* Owned by Xircom chip */
- tp->rx_ring[i].buffer1 = virt_to_bus(skb->tail);
+ tp->rx_ring[i].buffer1 = virt_to_bus(skb->data);
}
tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -1291,7 +1291,7 @@ xircom_rx(struct net_device *dev)
if (skb == NULL)
break;
skb->dev = dev; /* Mark as being used by this device. */
- tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail);
+ tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data);
work_done++;
}
tp->rx_ring[entry].status = Rx0DescOwned;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 8f3392989a0..0b5ca253796 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1661,7 +1661,7 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx)
#endif
skb->dev = tp->dev;
- dma_addr = pci_map_single(tp->pdev, skb->tail,
+ dma_addr = pci_map_single(tp->pdev, skb->data,
PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
/* Since no card does 64 bit DAC, the high bits will never
@@ -1721,7 +1721,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready,
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(new_skb, skb->tail, pkt_len, 0);
+ eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
pci_dma_sync_single_for_device(tp->pdev, dma_addr,
PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index be1c1047b9b..fc7738ffbff 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -507,7 +507,7 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct ethtool_ops netdev_ethtool_ops;
static int rhine_close(struct net_device *dev);
-static void rhine_shutdown (struct device *gdev);
+static void rhine_shutdown (struct pci_dev *pdev);
#define RHINE_WAIT_FOR(condition) do { \
int i=1024; \
@@ -990,7 +990,7 @@ static void alloc_rbufs(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
rp->rx_skbuff_dma[i] =
- pci_map_single(rp->pdev, skb->tail, rp->rx_buf_sz,
+ pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]);
@@ -1518,7 +1518,7 @@ static void rhine_rx(struct net_device *dev)
PCI_DMA_FROMDEVICE);
eth_copy_and_sum(skb,
- rp->rx_skbuff[entry]->tail,
+ rp->rx_skbuff[entry]->data,
pkt_len, 0);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(rp->pdev,
@@ -1561,7 +1561,7 @@ static void rhine_rx(struct net_device *dev)
break; /* Better luck next round. */
skb->dev = dev; /* Mark as being used by this device. */
rp->rx_skbuff_dma[entry] =
- pci_map_single(rp->pdev, skb->tail,
+ pci_map_single(rp->pdev, skb->data,
rp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]);
@@ -1895,9 +1895,8 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-static void rhine_shutdown (struct device *gendev)
+static void rhine_shutdown (struct pci_dev *pdev)
{
- struct pci_dev *pdev = to_pci_dev(gendev);
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
@@ -1956,7 +1955,7 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
pci_save_state(pdev);
spin_lock_irqsave(&rp->lock, flags);
- rhine_shutdown(&pdev->dev);
+ rhine_shutdown(pdev);
spin_unlock_irqrestore(&rp->lock, flags);
free_irq(dev->irq, dev);
@@ -2010,9 +2009,7 @@ static struct pci_driver rhine_driver = {
.suspend = rhine_suspend,
.resume = rhine_resume,
#endif /* CONFIG_PM */
- .driver = {
- .shutdown = rhine_shutdown,
- }
+ .shutdown = rhine_shutdown,
};
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 15e71028349..abc5cee6eed 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1335,7 +1335,7 @@ static inline int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN)
skb_reserve(new_skb, 2);
- memcpy(new_skb->data, rx_skb[0]->tail, pkt_size);
+ memcpy(new_skb->data, rx_skb[0]->data, pkt_size);
*rx_skb = new_skb;
ret = 0;
}
@@ -1456,9 +1456,9 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
* Do the gymnastics to get the buffer head for data at
* 64byte alignment.
*/
- skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->tail & 63);
+ skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->data & 63);
rd_info->skb->dev = vptr->dev;
- rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->tail, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE);
/*
* Fill in the descriptor to match
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index c1b6896d700..87496843681 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
}
skb_reserve(skb, 4);
cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
- data = (cisco_packet*)skb->tail;
+ data = (cisco_packet*)skb->data;
data->type = htonl(type);
data->par1 = htonl(par1);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 9da92543010..1c2506535f7 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -786,7 +786,7 @@ static void yellowfin_init_ring(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
- skb->tail, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+ skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
}
yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP);
yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -1111,7 +1111,7 @@ static int yellowfin_rx(struct net_device *dev)
pci_dma_sync_single_for_cpu(yp->pci_dev, desc->addr,
yp->rx_buf_sz, PCI_DMA_FROMDEVICE);
desc_status = le32_to_cpu(desc->result_status) >> 16;
- buf_addr = rx_skb->tail;
+ buf_addr = rx_skb->data;
data_size = (le32_to_cpu(desc->dbdma_cmd) -
le32_to_cpu(desc->result_status)) & 0xffff;
frame_status = le16_to_cpu(get_unaligned((s16*)&(buf_addr[data_size - 2])));
@@ -1185,7 +1185,7 @@ static int yellowfin_rx(struct net_device *dev)
break;
skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte align the IP header */
- eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0);
+ eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
yp->rx_buf_sz,
@@ -1211,7 +1211,7 @@ static int yellowfin_rx(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
yp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
- skb->tail, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+ skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
}
yp->rx_ring[entry].dbdma_cmd = cpu_to_le32(CMD_STOP);
yp->rx_ring[entry].result_status = 0; /* Clear complete bit. */
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index b0d2a73d1d4..2f2dbef2c3b 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -993,6 +993,7 @@ dino_driver_callback(struct parisc_device *dev)
bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,
&dino_cfg_ops, NULL);
if(bus) {
+ pci_bus_add_devices(bus);
/* This code *depends* on scanning being single threaded
* if it isn't, this global bus number count will fail
*/
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index dc838804c0d..7fdd80b7eb4 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1570,6 +1570,8 @@ lba_driver_probe(struct parisc_device *dev)
lba_bus = lba_dev->hba.hba_bus =
pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
cfg_ops, NULL);
+ if (lba_bus)
+ pci_bus_add_devices(lba_bus);
/* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) {
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index dbd33605cc1..fedae89d8f7 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -121,10 +121,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
* If there is an unattached subordinate bus, attach
* it and then scan for unattached PCI devices.
*/
- if (dev->subordinate && list_empty(&dev->subordinate->node)) {
- spin_lock(&pci_bus_lock);
- list_add_tail(&dev->subordinate->node, &dev->bus->children);
- spin_unlock(&pci_bus_lock);
+ if (dev->subordinate) {
+ if (list_empty(&dev->subordinate->node)) {
+ spin_lock(&pci_bus_lock);
+ list_add_tail(&dev->subordinate->node,
+ &dev->bus->children);
+ spin_unlock(&pci_bus_lock);
+ }
pci_bus_add_devices(dev->subordinate);
sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 93c120ddbd3..3e632ff8c71 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -36,9 +36,7 @@ ibmphp-objs := ibmphp_core.o \
ibmphp_hpc.o
acpiphp-objs := acpiphp_core.o \
- acpiphp_glue.o \
- acpiphp_pci.o \
- acpiphp_res.o
+ acpiphp_glue.o
rpaphp-objs := rpaphp_core.o \
rpaphp_pci.o \
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index d9499874c8a..293603e1b7c 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -7,6 +7,8 @@
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
+ * Copyright (C) 2003-2005 Hewlett Packard
*
* All rights reserved.
*
@@ -52,7 +54,6 @@
struct acpiphp_bridge;
struct acpiphp_slot;
-struct pci_resource;
/*
* struct slot - slot information for each *physical* slot
@@ -65,15 +66,6 @@ struct slot {
struct acpiphp_slot *acpi_slot;
};
-/*
- * struct pci_resource - describes pci resource (mem, pfmem, io, bus)
- */
-struct pci_resource {
- struct pci_resource * next;
- u64 base;
- u32 length;
-};
-
/**
* struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
* @cache_line_size in DWORD
@@ -101,10 +93,6 @@ struct acpiphp_bridge {
int type;
int nr_slots;
- u8 seg;
- u8 bus;
- u8 sub;
-
u32 flags;
/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
@@ -117,12 +105,6 @@ struct acpiphp_bridge {
struct hpp_param hpp;
spinlock_t res_lock;
-
- /* available resources on this bus */
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
};
@@ -163,12 +145,6 @@ struct acpiphp_func {
u8 function; /* pci function# */
u32 flags; /* see below */
-
- /* resources used for this function */
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
};
/**
@@ -243,25 +219,6 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
-/* acpiphp_pci.c */
-extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn);
-extern int acpiphp_configure_slot (struct acpiphp_slot *slot);
-extern int acpiphp_configure_function (struct acpiphp_func *func);
-extern void acpiphp_unconfigure_function (struct acpiphp_func *func);
-extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge);
-extern int acpiphp_init_func_resource (struct acpiphp_func *func);
-
-/* acpiphp_res.c */
-extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size);
-extern int acpiphp_resource_sort_and_combine (struct pci_resource **head);
-extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length);
-extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to);
-extern void acpiphp_free_resource (struct pci_resource **res);
-extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */
-extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */
-
/* variables */
extern int acpiphp_debug;
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 4539e61a3dc..60c4c38047a 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -7,6 +7,8 @@
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
+ * Copyright (C) 2003-2005 Hewlett Packard
*
* All rights reserved.
*
@@ -53,8 +55,8 @@ int acpiphp_debug;
static int num_slots;
static struct acpiphp_attention_info *attention_info;
-#define DRIVER_VERSION "0.4"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>"
+#define DRIVER_VERSION "0.5"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>, Matthew Wilcox <willy@hp.com>"
#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver"
MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -281,8 +283,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
/**
* get_address - get pci address of a slot
* @hotplug_slot: slot to get status
- * @busdev: pointer to struct pci_busdev (seg, bus, dev)
- *
+ * @value: pointer to struct pci_busdev (seg, bus, dev)
*/
static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
{
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index e7f41294f81..424e7de181a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -4,6 +4,10 @@
* Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
+ * Copyright (C) 2003-2005 Hewlett Packard
+ * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com)
+ * Copyright (C) 2005 Intel Corporation
*
* All rights reserved.
*
@@ -26,6 +30,16 @@
*
*/
+/*
+ * Lifetime rules for pci_dev:
+ * - The one in acpiphp_func has its refcount elevated by pci_get_slot()
+ * when the driver is loaded or when an insertion event occurs. It loses
+ * a refcount when its ejected or the driver unloads.
+ * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
+ * when the bridge is scanned and it loses a refcount when the bridge
+ * is removed.
+ */
+
#include <linux/init.h>
#include <linux/module.h>
@@ -178,21 +192,18 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
bridge->nr_slots++;
- dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",
- slot->bridge->bus, slot->device, slot->sun);
+ dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
+ slot->sun, pci_domain_nr(bridge->pci_bus),
+ bridge->pci_bus->number, slot->device);
}
newfunc->slot = slot;
list_add_tail(&newfunc->sibling, &slot->funcs);
/* associate corresponding pci_dev */
- newfunc->pci_dev = pci_find_slot(bridge->bus,
+ newfunc->pci_dev = pci_get_slot(bridge->pci_bus,
PCI_DEVFN(device, function));
if (newfunc->pci_dev) {
- if (acpiphp_init_func_resource(newfunc) < 0) {
- kfree(newfunc);
- return AE_ERROR;
- }
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
}
@@ -227,62 +238,6 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle)
}
-/* decode ACPI _CRS data and convert into our internal resource list
- * TBD: _TRA, etc.
- */
-static acpi_status
-decode_acpi_resource(struct acpi_resource *resource, void *context)
-{
- struct acpiphp_bridge *bridge = (struct acpiphp_bridge *) context;
- struct acpi_resource_address64 address;
- struct pci_resource *res;
-
- if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
- resource->id != ACPI_RSTYPE_ADDRESS32 &&
- resource->id != ACPI_RSTYPE_ADDRESS64)
- return AE_OK;
-
- acpi_resource_to_address64(resource, &address);
-
- if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) {
- dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type,
- (unsigned long long)address.min_address_range,
- (unsigned long long)address.max_address_range);
- res = acpiphp_make_resource(address.min_address_range,
- address.address_length);
- if (!res) {
- err("out of memory\n");
- return AE_OK;
- }
-
- switch (address.resource_type) {
- case ACPI_MEMORY_RANGE:
- if (address.attribute.memory.cache_attribute == ACPI_PREFETCHABLE_MEMORY) {
- res->next = bridge->p_mem_head;
- bridge->p_mem_head = res;
- } else {
- res->next = bridge->mem_head;
- bridge->mem_head = res;
- }
- break;
- case ACPI_IO_RANGE:
- res->next = bridge->io_head;
- bridge->io_head = res;
- break;
- case ACPI_BUS_NUMBER_RANGE:
- res->next = bridge->bus_head;
- bridge->bus_head = res;
- break;
- default:
- /* invalid type */
- kfree(res);
- break;
- }
- }
-
- return AE_OK;
-}
-
/* decode ACPI 2.0 _HPP hot plug parameters */
static void decode_hpp(struct acpiphp_bridge *bridge)
{
@@ -346,34 +301,29 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
/* decode ACPI 2.0 _HPP (hot plug parameters) */
decode_hpp(bridge);
- /* subtract all resources already allocated */
- acpiphp_detect_pci_resource(bridge);
-
/* register all slot objects under this bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
register_slot, bridge, NULL);
/* install notify handler */
- status = acpi_install_notify_handler(bridge->handle,
+ if (bridge->type != BRIDGE_TYPE_HOST) {
+ status = acpi_install_notify_handler(bridge->handle,
ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge,
bridge);
- if (ACPI_FAILURE(status)) {
- err("failed to register interrupt notify handler\n");
+ if (ACPI_FAILURE(status)) {
+ err("failed to register interrupt notify handler\n");
+ }
}
list_add(&bridge->list, &bridge_list);
-
- dbg("Bridge resource:\n");
- acpiphp_dump_resource(bridge);
}
/* allocate and initialize host bridge data structure */
-static void add_host_bridge(acpi_handle *handle, int seg, int bus)
+static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
{
- acpi_status status;
struct acpiphp_bridge *bridge;
bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
@@ -384,52 +334,19 @@ static void add_host_bridge(acpi_handle *handle, int seg, int bus)
bridge->type = BRIDGE_TYPE_HOST;
bridge->handle = handle;
- bridge->seg = seg;
- bridge->bus = bus;
- bridge->pci_bus = pci_find_bus(seg, bus);
+ bridge->pci_bus = pci_bus;
spin_lock_init(&bridge->res_lock);
- /* to be overridden when we decode _CRS */
- bridge->sub = bridge->bus;
-
- /* decode resources */
-
- status = acpi_walk_resources(handle, METHOD_NAME__CRS,
- decode_acpi_resource, bridge);
-
- if (ACPI_FAILURE(status)) {
- err("failed to decode bridge resources\n");
- kfree(bridge);
- return;
- }
-
- acpiphp_resource_sort_and_combine(&bridge->io_head);
- acpiphp_resource_sort_and_combine(&bridge->mem_head);
- acpiphp_resource_sort_and_combine(&bridge->p_mem_head);
- acpiphp_resource_sort_and_combine(&bridge->bus_head);
-
- dbg("ACPI _CRS resource:\n");
- acpiphp_dump_resource(bridge);
-
- if (bridge->bus_head) {
- bridge->bus = bridge->bus_head->base;
- bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;
- }
-
init_bridge_misc(bridge);
}
/* allocate and initialize PCI-to-PCI bridge data structure */
-static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int fn)
+static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
{
struct acpiphp_bridge *bridge;
- u8 tmp8;
- u16 tmp16;
- u64 base64, limit64;
- u32 base, limit, base32u, limit32u;
bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
if (bridge == NULL) {
@@ -441,133 +358,22 @@ static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int f
bridge->type = BRIDGE_TYPE_P2P;
bridge->handle = handle;
- bridge->seg = seg;
-
- bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
- if (!bridge->pci_dev) {
- err("Can't get pci_dev\n");
- kfree(bridge);
- return;
- }
- bridge->pci_bus = bridge->pci_dev->subordinate;
+ bridge->pci_dev = pci_dev_get(pci_dev);
+ bridge->pci_bus = pci_dev->subordinate;
if (!bridge->pci_bus) {
err("This is not a PCI-to-PCI bridge!\n");
- kfree(bridge);
- return;
+ goto err;
}
spin_lock_init(&bridge->res_lock);
- bridge->bus = bridge->pci_bus->number;
- bridge->sub = bridge->pci_bus->subordinate;
-
- /*
- * decode resources under this P2P bridge
- */
-
- /* I/O resources */
- pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);
- base = tmp8;
- pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);
- limit = tmp8;
-
- switch (base & PCI_IO_RANGE_TYPE_MASK) {
- case PCI_IO_RANGE_TYPE_16:
- base = (base << 8) & 0xf000;
- limit = ((limit << 8) & 0xf000) + 0xfff;
- bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->io_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
- dbg("16bit I/O range: %04x-%04x\n",
- (u32)bridge->io_head->base,
- (u32)(bridge->io_head->base + bridge->io_head->length - 1));
- break;
- case PCI_IO_RANGE_TYPE_32:
- pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
- base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);
- pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
- limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
- bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->io_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
- dbg("32bit I/O range: %08x-%08x\n",
- (u32)bridge->io_head->base,
- (u32)(bridge->io_head->base + bridge->io_head->length - 1));
- break;
- case 0x0f:
- dbg("I/O space unsupported\n");
- break;
- default:
- warn("Unknown I/O range type\n");
- }
-
- /* Memory resources (mandatory for P2P bridge) */
- pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);
- base = (tmp16 & 0xfff0) << 16;
- pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);
- limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
- bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->mem_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
- dbg("32bit Memory range: %08x-%08x\n",
- (u32)bridge->mem_head->base,
- (u32)(bridge->mem_head->base + bridge->mem_head->length-1));
-
- /* Prefetchable Memory resources (optional) */
- pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
- base = tmp16;
- pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
- limit = tmp16;
-
- switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {
- case PCI_PREF_RANGE_TYPE_32:
- base = (base & 0xfff0) << 16;
- limit = ((limit & 0xfff0) << 16) | 0xfffff;
- bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
- if (!bridge->p_mem_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
- dbg("32bit Prefetchable memory range: %08x-%08x\n",
- (u32)bridge->p_mem_head->base,
- (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
- break;
- case PCI_PREF_RANGE_TYPE_64:
- pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
- pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
- base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);
- limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;
-
- bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
- if (!bridge->p_mem_head) {
- err("out of memory\n");
- kfree(bridge);
- return;
- }
- dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
- (u32)(bridge->p_mem_head->base >> 32),
- (u32)(bridge->p_mem_head->base & 0xffffffff),
- (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32),
- (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff));
- break;
- case 0x0f:
- break;
- default:
- warn("Unknown prefetchale memory type\n");
- }
-
init_bridge_misc(bridge);
+ return;
+ err:
+ pci_dev_put(pci_dev);
+ kfree(bridge);
+ return;
}
@@ -577,14 +383,10 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
acpi_handle dummy_handle;
- unsigned long *segbus = context;
unsigned long tmp;
- int seg, bus, device, function;
+ int device, function;
struct pci_dev *dev;
-
- /* get PCI address */
- seg = (*segbus >> 8) & 0xff;
- bus = *segbus & 0xff;
+ struct pci_bus *pci_bus = context;
status = acpi_get_handle(handle, "_ADR", &dummy_handle);
if (ACPI_FAILURE(status))
@@ -599,20 +401,19 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
device = (tmp >> 16) & 0xffff;
function = tmp & 0xffff;
- dev = pci_find_slot(bus, PCI_DEVFN(device, function));
+ dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
- if (!dev)
- return AE_OK;
-
- if (!dev->subordinate)
- return AE_OK;
+ if (!dev || !dev->subordinate)
+ goto out;
/* check if this bridge has ejectable slots */
if (detect_ejectable_slots(handle) > 0) {
dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
- add_p2p_bridge(handle, seg, bus, device, function);
+ add_p2p_bridge(handle, dev);
}
+ out:
+ pci_dev_put(dev);
return AE_OK;
}
@@ -624,6 +425,7 @@ static int add_bridge(acpi_handle handle)
unsigned long tmp;
int seg, bus;
acpi_handle dummy_handle;
+ struct pci_bus *pci_bus;
/* if the bridge doesn't have _STA, we assume it is always there */
status = acpi_get_handle(handle, "_STA", &dummy_handle);
@@ -653,18 +455,22 @@ static int add_bridge(acpi_handle handle)
bus = 0;
}
+ pci_bus = pci_find_bus(seg, bus);
+ if (!pci_bus) {
+ err("Can't find bus %04x:%02x\n", seg, bus);
+ return 0;
+ }
+
/* check if this bridge has ejectable slots */
if (detect_ejectable_slots(handle) > 0) {
dbg("found PCI host-bus bridge with hot-pluggable slots\n");
- add_host_bridge(handle, seg, bus);
+ add_host_bridge(handle, pci_bus);
return 0;
}
- tmp = seg << 8 | bus;
-
/* search P2P bridges under this host bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- find_p2p_bridge, &tmp, NULL);
+ find_p2p_bridge, pci_bus, NULL);
if (ACPI_FAILURE(status))
warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
@@ -672,12 +478,205 @@ static int add_bridge(acpi_handle handle)
return 0;
}
+static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
+{
+ struct list_head *head;
+ list_for_each(head, &bridge_list) {
+ struct acpiphp_bridge *bridge = list_entry(head,
+ struct acpiphp_bridge, list);
+ if (bridge->handle == handle)
+ return bridge;
+ }
+
+ return NULL;
+}
+
+static void cleanup_bridge(struct acpiphp_bridge *bridge)
+{
+ struct list_head *list, *tmp;
+ struct acpiphp_slot *slot;
+ acpi_status status;
+ acpi_handle handle = bridge->handle;
+
+ status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ handle_hotplug_event_bridge);
+ if (ACPI_FAILURE(status))
+ err("failed to remove notify handler\n");
+
+ slot = bridge->slots;
+ while (slot) {
+ struct acpiphp_slot *next = slot->next;
+ list_for_each_safe (list, tmp, &slot->funcs) {
+ struct acpiphp_func *func;
+ func = list_entry(list, struct acpiphp_func, sibling);
+ status = acpi_remove_notify_handler(func->handle,
+ ACPI_SYSTEM_NOTIFY,
+ handle_hotplug_event_func);
+ if (ACPI_FAILURE(status))
+ err("failed to remove notify handler\n");
+ pci_dev_put(func->pci_dev);
+ list_del(list);
+ kfree(func);
+ }
+ kfree(slot);
+ slot = next;
+ }
+
+ pci_dev_put(bridge->pci_dev);
+ list_del(&bridge->list);
+ kfree(bridge);
+}
+
+static acpi_status
+cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ struct acpiphp_bridge *bridge;
+
+ if (!(bridge = acpiphp_handle_to_bridge(handle)))
+ return AE_OK;
+ cleanup_bridge(bridge);
+ return AE_OK;
+}
static void remove_bridge(acpi_handle handle)
{
- /* No-op for now .. */
+ struct acpiphp_bridge *bridge;
+
+ bridge = acpiphp_handle_to_bridge(handle);
+ if (bridge) {
+ cleanup_bridge(bridge);
+ } else {
+ /* clean-up p2p bridges under this host bridge */
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+ (u32)1, cleanup_p2p_bridge, NULL, NULL);
+ }
+}
+
+static struct pci_dev * get_apic_pci_info(acpi_handle handle)
+{
+ struct acpi_pci_id id;
+ struct pci_bus *bus;
+ struct pci_dev *dev;
+
+ if (ACPI_FAILURE(acpi_get_pci_id(handle, &id)))
+ return NULL;
+
+ bus = pci_find_bus(id.segment, id.bus);
+ if (!bus)
+ return NULL;
+
+ dev = pci_get_slot(bus, PCI_DEVFN(id.device, id.function));
+ if (!dev)
+ return NULL;
+
+ if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&
+ (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))
+ {
+ pci_dev_put(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+
+static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
+{
+ acpi_status status;
+ int result = -1;
+ unsigned long gsb;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *obj;
+ void *table;
+
+ status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
+ if (ACPI_SUCCESS(status)) {
+ *gsi_base = (u32)gsb;
+ return 0;
+ }
+
+ status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);
+ if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)
+ return -1;
+
+ obj = buffer.pointer;
+ if (obj->type != ACPI_TYPE_BUFFER)
+ goto out;
+
+ table = obj->buffer.pointer;
+ switch (((acpi_table_entry_header *)table)->type) {
+ case ACPI_MADT_IOSAPIC:
+ *gsi_base = ((struct acpi_table_iosapic *)table)->global_irq_base;
+ result = 0;
+ break;
+ case ACPI_MADT_IOAPIC:
+ *gsi_base = ((struct acpi_table_ioapic *)table)->global_irq_base;
+ result = 0;
+ break;
+ default:
+ break;
+ }
+ out:
+ acpi_os_free(buffer.pointer);
+ return result;
+}
+
+static acpi_status
+ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ acpi_status status;
+ unsigned long sta;
+ acpi_handle tmp;
+ struct pci_dev *pdev;
+ u32 gsi_base;
+ u64 phys_addr;
+
+ /* Evaluate _STA if present */
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+ if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
+ return AE_CTRL_DEPTH;
+
+ /* Scan only PCI bus scope */
+ status = acpi_get_handle(handle, "_HID", &tmp);
+ if (ACPI_SUCCESS(status))
+ return AE_CTRL_DEPTH;
+
+ if (get_gsi_base(handle, &gsi_base))
+ return AE_OK;
+
+ pdev = get_apic_pci_info(handle);
+ if (!pdev)
+ return AE_OK;
+
+ if (pci_enable_device(pdev)) {
+ pci_dev_put(pdev);
+ return AE_OK;
+ }
+
+ pci_set_master(pdev);
+
+ if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) {
+ pci_disable_device(pdev);
+ pci_dev_put(pdev);
+ return AE_OK;
+ }
+
+ phys_addr = pci_resource_start(pdev, 0);
+ if (acpi_register_ioapic(handle, phys_addr, gsi_base)) {
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ pci_dev_put(pdev);
+ return AE_OK;
+ }
+
+ return AE_OK;
}
+static int acpiphp_configure_ioapics(acpi_handle handle)
+{
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+ ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
+ return 0;
+}
static int power_on_slot(struct acpiphp_slot *slot)
{
@@ -719,8 +718,6 @@ static int power_off_slot(struct acpiphp_slot *slot)
acpi_status status;
struct acpiphp_func *func;
struct list_head *l;
- struct acpi_object_list arg_list;
- union acpi_object arg;
int retval = 0;
@@ -731,7 +728,7 @@ static int power_off_slot(struct acpiphp_slot *slot)
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
- if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) {
+ if (func->flags & FUNC_HAS_PS3) {
status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
if (ACPI_FAILURE(status)) {
warn("%s: _PS3 failed\n", __FUNCTION__);
@@ -742,27 +739,6 @@ static int power_off_slot(struct acpiphp_slot *slot)
}
}
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
-
- /* We don't want to call _EJ0 on non-existing functions. */
- if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) {
- /* _EJ0 method take one argument */
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
- status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
- if (ACPI_FAILURE(status)) {
- warn("%s: _EJ0 failed\n", __FUNCTION__);
- retval = -1;
- goto err_exit;
- } else
- break;
- }
- }
-
/* TBD: evaluate _STA to check if the slot is disabled */
slot->flags &= (~SLOT_POWEREDON);
@@ -782,70 +758,56 @@ static int power_off_slot(struct acpiphp_slot *slot)
*/
static int enable_device(struct acpiphp_slot *slot)
{
- u8 bus;
struct pci_dev *dev;
- struct pci_bus *child;
+ struct pci_bus *bus = slot->bridge->pci_bus;
struct list_head *l;
struct acpiphp_func *func;
int retval = 0;
- int num;
+ int num, max, pass;
if (slot->flags & SLOT_ENABLED)
goto err_exit;
/* sanity check: dev should be NULL when hot-plugged in */
- dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
+ dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
if (dev) {
/* This case shouldn't happen */
err("pci_dev structure already exists.\n");
+ pci_dev_put(dev);
retval = -1;
goto err_exit;
}
- /* allocate resources to device */
- retval = acpiphp_configure_slot(slot);
- if (retval)
- goto err_exit;
-
- /* returned `dev' is the *first function* only! */
- num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
- if (num)
- pci_bus_add_devices(slot->bridge->pci_bus);
- dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
-
- if (!dev) {
+ num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
+ if (num == 0) {
err("No new device found\n");
retval = -1;
goto err_exit;
}
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);
- child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);
- pci_do_scan_bus(child);
+ max = bus->secondary;
+ for (pass = 0; pass < 2; pass++) {
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != slot->device)
+ continue;
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ max = pci_scan_bridge(bus, dev, max, pass);
+ }
}
+ pci_bus_assign_resources(bus);
+ pci_bus_add_devices(bus);
+
/* associate pci_dev to our representation */
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
-
- func->pci_dev = pci_find_slot(slot->bridge->bus,
- PCI_DEVFN(slot->device,
+ func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
func->function));
- if (!func->pci_dev)
- continue;
-
- /* configure device */
- retval = acpiphp_configure_function(func);
- if (retval)
- goto err_exit;
}
slot->flags |= SLOT_ENABLED;
- dbg("Available resources:\n");
- acpiphp_dump_resource(slot->bridge);
-
err_exit:
return retval;
}
@@ -866,9 +828,12 @@ static int disable_device(struct acpiphp_slot *slot)
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
+ if (!func->pci_dev)
+ continue;
- if (func->pci_dev)
- acpiphp_unconfigure_function(func);
+ pci_remove_bus_device(func->pci_dev);
+ pci_dev_put(func->pci_dev);
+ func->pci_dev = NULL;
}
slot->flags &= (~SLOT_ENABLED);
@@ -920,6 +885,39 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
}
/**
+ * acpiphp_eject_slot - physically eject the slot
+ */
+static int acpiphp_eject_slot(struct acpiphp_slot *slot)
+{
+ acpi_status status;
+ struct acpiphp_func *func;
+ struct list_head *l;
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+
+ list_for_each (l, &slot->funcs) {
+ func = list_entry(l, struct acpiphp_func, sibling);
+
+ /* We don't want to call _EJ0 on non-existing functions. */
+ if ((func->flags & FUNC_HAS_EJ0)) {
+ /* _EJ0 method take one argument */
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = 1;
+
+ status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
+ if (ACPI_FAILURE(status)) {
+ warn("%s: _EJ0 failed\n", __FUNCTION__);
+ return -1;
+ } else
+ break;
+ }
+ }
+ return 0;
+}
+
+/**
* acpiphp_check_bridge - re-enumerate devices
*
* Iterate over all slots under this bridge and make sure that if a
@@ -942,6 +940,8 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
if (retval) {
err("Error occurred in disabling\n");
goto err_exit;
+ } else {
+ acpiphp_eject_slot(slot);
}
disabled++;
} else {
@@ -962,6 +962,144 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
return retval;
}
+static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
+{
+ u16 pci_cmd, pci_bctl;
+ struct pci_dev *cdev;
+
+ /* Program hpp values for this device */
+ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+ (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+ return;
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+ bridge->hpp.cache_line_size);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER,
+ bridge->hpp.latency_timer);
+ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+ if (bridge->hpp.enable_SERR)
+ pci_cmd |= PCI_COMMAND_SERR;
+ else
+ pci_cmd &= ~PCI_COMMAND_SERR;
+ if (bridge->hpp.enable_PERR)
+ pci_cmd |= PCI_COMMAND_PARITY;
+ else
+ pci_cmd &= ~PCI_COMMAND_PARITY;
+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+ /* Program bridge control value and child devices */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+ bridge->hpp.latency_timer);
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+ if (bridge->hpp.enable_SERR)
+ pci_bctl |= PCI_BRIDGE_CTL_SERR;
+ else
+ pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+ if (bridge->hpp.enable_PERR)
+ pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+ else
+ pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+ if (dev->subordinate) {
+ list_for_each_entry(cdev, &dev->subordinate->devices,
+ bus_list)
+ program_hpp(cdev, bridge);
+ }
+ }
+}
+
+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
+{
+ struct acpiphp_bridge bridge;
+ struct pci_dev *dev;
+
+ memset(&bridge, 0, sizeof(bridge));
+ bridge.handle = handle;
+ decode_hpp(&bridge);
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ program_hpp(dev, &bridge);
+
+}
+
+/*
+ * Remove devices for which we could not assign resources, call
+ * arch specific code to fix-up the bus
+ */
+static void acpiphp_sanitize_bus(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+ int i;
+ unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
+ struct resource *res = &dev->resource[i];
+ if ((res->flags & type_mask) && !res->start &&
+ res->end) {
+ /* Could not assign a required resources
+ * for this device, remove it */
+ pci_remove_bus_device(dev);
+ break;
+ }
+ }
+ }
+}
+
+/* Program resources in newly inserted bridge */
+static int acpiphp_configure_bridge (acpi_handle handle)
+{
+ struct acpi_pci_id pci_id;
+ struct pci_bus *bus;
+
+ if (ACPI_FAILURE(acpi_get_pci_id(handle, &pci_id))) {
+ err("cannot get PCI domain and bus number for bridge\n");
+ return -EINVAL;
+ }
+ bus = pci_find_bus(pci_id.segment, pci_id.bus);
+ if (!bus) {
+ err("cannot find bus %d:%d\n",
+ pci_id.segment, pci_id.bus);
+ return -EINVAL;
+ }
+
+ pci_bus_size_bridges(bus);
+ pci_bus_assign_resources(bus);
+ acpiphp_sanitize_bus(bus);
+ acpiphp_set_hpp_values(handle, bus);
+ pci_enable_bridges(bus);
+ acpiphp_configure_ioapics(handle);
+ return 0;
+}
+
+static void handle_bridge_insertion(acpi_handle handle, u32 type)
+{
+ struct acpi_device *device, *pdevice;
+ acpi_handle phandle;
+
+ if ((type != ACPI_NOTIFY_BUS_CHECK) &&
+ (type != ACPI_NOTIFY_DEVICE_CHECK)) {
+ err("unexpected notification type %d\n", type);
+ return;
+ }
+
+ acpi_get_parent(handle, &phandle);
+ if (acpi_bus_get_device(phandle, &pdevice)) {
+ dbg("no parent device, assuming NULL\n");
+ pdevice = NULL;
+ }
+ if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
+ err("cannot add bridge to acpi list\n");
+ return;
+ }
+ if (!acpiphp_configure_bridge(handle) &&
+ !acpi_bus_start(device))
+ add_bridge(handle);
+ else
+ err("cannot configure and start bridge\n");
+
+}
+
/*
* ACPI event handlers
*/
@@ -982,8 +1120,19 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
+ struct acpi_device *device;
- bridge = (struct acpiphp_bridge *)context;
+ if (acpi_bus_get_device(handle, &device)) {
+ /* This bridge must have just been physically inserted */
+ handle_bridge_insertion(handle, type);
+ return;
+ }
+
+ bridge = acpiphp_handle_to_bridge(handle);
+ if (!bridge) {
+ err("cannot get bridge info\n");
+ return;
+ }
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1031,7 +1180,6 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
}
}
-
/**
* handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
*
@@ -1074,7 +1222,8 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */
dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
- acpiphp_disable_slot(func->slot);
+ if (!(acpiphp_disable_slot(func->slot)))
+ acpiphp_eject_slot(func->slot);
break;
default:
@@ -1083,6 +1232,47 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
}
}
+static int is_root_bridge(acpi_handle handle)
+{
+ acpi_status status;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ int i;
+
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
+ info = buffer.pointer;
+ if ((info->valid & ACPI_VALID_HID) &&
+ !strcmp(PCI_ROOT_HID_STRING,
+ info->hardware_id.value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ if (info->valid & ACPI_VALID_CID) {
+ for (i=0; i < info->compatibility_id.count; i++) {
+ if (!strcmp(PCI_ROOT_HID_STRING,
+ info->compatibility_id.id[i].value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static acpi_status
+find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ int *count = (int *)context;
+
+ if (is_root_bridge(handle)) {
+ acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ handle_hotplug_event_bridge, NULL);
+ (*count)++;
+ }
+ return AE_OK ;
+}
static struct acpi_pci_driver acpi_pci_hp_driver = {
.add = add_bridge,
@@ -1095,15 +1285,15 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
*/
int __init acpiphp_glue_init(void)
{
- int num;
-
- if (list_empty(&pci_root_buses))
- return -1;
+ int num = 0;
- num = acpi_pci_register_driver(&acpi_pci_hp_driver);
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, find_root_bridges, &num, NULL);
if (num <= 0)
return -1;
+ else
+ acpi_pci_register_driver(&acpi_pci_hp_driver);
return 0;
}
@@ -1116,46 +1306,6 @@ int __init acpiphp_glue_init(void)
*/
void __exit acpiphp_glue_exit(void)
{
- struct list_head *l1, *l2, *n1, *n2;
- struct acpiphp_bridge *bridge;
- struct acpiphp_slot *slot, *next;
- struct acpiphp_func *func;
- acpi_status status;
-
- list_for_each_safe (l1, n1, &bridge_list) {
- bridge = (struct acpiphp_bridge *)l1;
- slot = bridge->slots;
- while (slot) {
- next = slot->next;
- list_for_each_safe (l2, n2, &slot->funcs) {
- func = list_entry(l2, struct acpiphp_func, sibling);
- acpiphp_free_resource(&func->io_head);
- acpiphp_free_resource(&func->mem_head);
- acpiphp_free_resource(&func->p_mem_head);
- acpiphp_free_resource(&func->bus_head);
- status = acpi_remove_notify_handler(func->handle,
- ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_func);
- if (ACPI_FAILURE(status))
- err("failed to remove notify handler\n");
- kfree(func);
- }
- kfree(slot);
- slot = next;
- }
- status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_bridge);
- if (ACPI_FAILURE(status))
- err("failed to remove notify handler\n");
-
- acpiphp_free_resource(&bridge->io_head);
- acpiphp_free_resource(&bridge->mem_head);
- acpiphp_free_resource(&bridge->p_mem_head);
- acpiphp_free_resource(&bridge->bus_head);
-
- kfree(bridge);
- }
-
acpi_pci_unregister_driver(&acpi_pci_hp_driver);
}
@@ -1173,11 +1323,14 @@ int __init acpiphp_get_num_slots(void)
list_for_each (node, &bridge_list) {
bridge = (struct acpiphp_bridge *)node;
- dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);
+ dbg("Bus %04x:%02x has %d slot%s\n",
+ pci_domain_nr(bridge->pci_bus),
+ bridge->pci_bus->number, bridge->nr_slots,
+ bridge->nr_slots == 1 ? "" : "s");
num_slots += bridge->nr_slots;
}
- dbg("Total %dslots\n", num_slots);
+ dbg("Total %d slots\n", num_slots);
return num_slots;
}
@@ -1254,7 +1407,6 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
return retval;
}
-
/**
* acpiphp_disable_slot - power off slot
*/
@@ -1274,13 +1426,6 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
if (retval)
goto err_exit;
- acpiphp_resource_sort_and_combine(&slot->bridge->io_head);
- acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);
- acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);
- acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);
- dbg("Available resources:\n");
- acpiphp_dump_resource(slot->bridge);
-
err_exit:
up(&slot->crit_sect);
return retval;
@@ -1293,11 +1438,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
*/
u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
{
- unsigned int sta;
-
- sta = get_slot_status(slot);
-
- return (sta & ACPI_STA_ENABLED) ? 1 : 0;
+ return (slot->flags & SLOT_POWEREDON);
}
@@ -1335,9 +1476,10 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
u32 acpiphp_get_address(struct acpiphp_slot *slot)
{
u32 address;
+ struct pci_bus *pci_bus = slot->bridge->pci_bus;
- address = ((slot->bridge->seg) << 16) |
- ((slot->bridge->bus) << 8) |
+ address = (pci_domain_nr(pci_bus) << 16) |
+ (pci_bus->number << 8) |
slot->device;
return address;
diff --git a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c
deleted file mode 100644
index 54d97c9d1df..00000000000
--- a/drivers/pci/hotplug/acpiphp_pci.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * ACPI PCI HotPlug PCI configuration space management
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001,2002 IBM Corp.
- * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
- * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (C) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT. 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.
- *
- * Send feedback to <t-kochi@bq.jp.nec.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include "../pci.h"
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-#define MY_NAME "acpiphp_pci"
-
-
-/* allocate mem/pmem/io resource to a new function */
-static int init_config_space (struct acpiphp_func *func)
-{
- u32 bar, len;
- u32 address[] = {
- PCI_BASE_ADDRESS_0,
- PCI_BASE_ADDRESS_1,
- PCI_BASE_ADDRESS_2,
- PCI_BASE_ADDRESS_3,
- PCI_BASE_ADDRESS_4,
- PCI_BASE_ADDRESS_5,
- 0
- };
- int count;
- struct acpiphp_bridge *bridge;
- struct pci_resource *res;
- struct pci_bus *pbus;
- int bus, device, function;
- unsigned int devfn;
- u16 tmp;
-
- bridge = func->slot->bridge;
- pbus = bridge->pci_bus;
- bus = bridge->bus;
- device = func->slot->device;
- function = func->function;
- devfn = PCI_DEVFN(device, function);
-
- for (count = 0; address[count]; count++) { /* for 6 BARs */
- pci_bus_write_config_dword(pbus, devfn,
- address[count], 0xFFFFFFFF);
- pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
-
- if (!bar) /* This BAR is not implemented */
- continue;
-
- dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
-
- if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
- /* This is IO */
-
- len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
- len = len & ~(len - 1);
-
- dbg("len in IO %x, BAR %d\n", len, count);
-
- spin_lock(&bridge->res_lock);
- res = acpiphp_get_io_resource(&bridge->io_head, len);
- spin_unlock(&bridge->res_lock);
-
- if (!res) {
- err("cannot allocate requested io for %02x:%02x.%d len %x\n",
- bus, device, function, len);
- return -1;
- }
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)res->base);
- res->next = func->io_head;
- func->io_head = res;
-
- } else {
- /* This is Memory */
- if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
- /* pfmem */
-
- len = bar & 0xFFFFFFF0;
- len = ~len + 1;
-
- dbg("len in PFMEM %x, BAR %d\n", len, count);
-
- spin_lock(&bridge->res_lock);
- res = acpiphp_get_resource(&bridge->p_mem_head, len);
- spin_unlock(&bridge->res_lock);
-
- if (!res) {
- err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
- bus, device, function, len);
- return -1;
- }
-
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)res->base);
-
- if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
- dbg("inside the pfmem 64 case, count %d\n", count);
- count += 1;
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)(res->base >> 32));
- }
-
- res->next = func->p_mem_head;
- func->p_mem_head = res;
-
- } else {
- /* regular memory */
-
- len = bar & 0xFFFFFFF0;
- len = ~len + 1;
-
- dbg("len in MEM %x, BAR %d\n", len, count);
-
- spin_lock(&bridge->res_lock);
- res = acpiphp_get_resource(&bridge->mem_head, len);
- spin_unlock(&bridge->res_lock);
-
- if (!res) {
- err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
- bus, device, function, len);
- return -1;
- }
-
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)res->base);
-
- if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- /* takes up another dword */
- dbg("inside mem 64 case, reg. mem, count %d\n", count);
- count += 1;
- pci_bus_write_config_dword(pbus, devfn,
- address[count],
- (u32)(res->base >> 32));
- }
-
- res->next = func->mem_head;
- func->mem_head = res;
-
- }
- }
- }
-
- /* disable expansion rom */
- pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
-
- /* set PCI parameters from _HPP */
- pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
- bridge->hpp.cache_line_size);
- pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
- bridge->hpp.latency_timer);
-
- pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
- if (bridge->hpp.enable_SERR)
- tmp |= PCI_COMMAND_SERR;
- if (bridge->hpp.enable_PERR)
- tmp |= PCI_COMMAND_PARITY;
- pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
-
- return 0;
-}
-
-/* detect_used_resource - subtract resource under dev from bridge */
-static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
-{
- int count;
-
- dbg("Device %s\n", pci_name(dev));
-
- for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {
- struct pci_resource *res;
- struct pci_resource **head;
- unsigned long base = dev->resource[count].start;
- unsigned long len = dev->resource[count].end - base + 1;
- unsigned long flags = dev->resource[count].flags;
-
- if (!flags)
- continue;
-
- dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
- base + len - 1, flags);
-
- if (flags & IORESOURCE_IO) {
- head = &bridge->io_head;
- } else if (flags & IORESOURCE_PREFETCH) {
- head = &bridge->p_mem_head;
- } else {
- head = &bridge->mem_head;
- }
-
- spin_lock(&bridge->res_lock);
- res = acpiphp_get_resource_with_base(head, base, len);
- spin_unlock(&bridge->res_lock);
- if (res)
- kfree(res);
- }
-
- return 0;
-}
-
-
-/**
- * acpiphp_detect_pci_resource - detect resources under bridge
- * @bridge: detect all resources already used under this bridge
- *
- * collect all resources already allocated for all devices under a bridge.
- */
-int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
-{
- struct list_head *l;
- struct pci_dev *dev;
-
- list_for_each (l, &bridge->pci_bus->devices) {
- dev = pci_dev_b(l);
- detect_used_resource(bridge, dev);
- }
-
- return 0;
-}
-
-
-/**
- * acpiphp_init_slot_resource - gather resource usage information of a slot
- * @slot: ACPI slot object to be checked, should have valid pci_dev member
- *
- * TBD: PCI-to-PCI bridge case
- * use pci_dev->resource[]
- */
-int acpiphp_init_func_resource (struct acpiphp_func *func)
-{
- u64 base;
- u32 bar, len;
- u32 address[] = {
- PCI_BASE_ADDRESS_0,
- PCI_BASE_ADDRESS_1,
- PCI_BASE_ADDRESS_2,
- PCI_BASE_ADDRESS_3,
- PCI_BASE_ADDRESS_4,
- PCI_BASE_ADDRESS_5,
- 0
- };
- int count;
- struct pci_resource *res;
- struct pci_dev *dev;
-
- dev = func->pci_dev;
- dbg("Hot-pluggable device %s\n", pci_name(dev));
-
- for (count = 0; address[count]; count++) { /* for 6 BARs */
- pci_read_config_dword(dev, address[count], &bar);
-
- if (!bar) /* This BAR is not implemented */
- continue;
-
- pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
- pci_read_config_dword(dev, address[count], &len);
-
- if (len & PCI_BASE_ADDRESS_SPACE_IO) {
- /* This is IO */
- base = bar & 0xFFFFFFFC;
- len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
- len = len & ~(len - 1);
-
- dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
-
- res = acpiphp_make_resource(base, len);
- if (!res)
- goto no_memory;
-
- res->next = func->io_head;
- func->io_head = res;
-
- } else {
- /* This is Memory */
- base = bar & 0xFFFFFFF0;
- if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
- /* pfmem */
-
- len &= 0xFFFFFFF0;
- len = ~len + 1;
-
- if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
- dbg("prefetch mem 64\n");
- count += 1;
- }
- dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
- res = acpiphp_make_resource(base, len);
- if (!res)
- goto no_memory;
-
- res->next = func->p_mem_head;
- func->p_mem_head = res;
-
- } else {
- /* regular memory */
-
- len &= 0xFFFFFFF0;
- len = ~len + 1;
-
- if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- /* takes up another dword */
- dbg("mem 64\n");
- count += 1;
- }
- dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
- res = acpiphp_make_resource(base, len);
- if (!res)
- goto no_memory;
-
- res->next = func->mem_head;
- func->mem_head = res;
-
- }
- }
-
- pci_write_config_dword(dev, address[count], bar);
- }
-#if 1
- acpiphp_dump_func_resource(func);
-#endif
-
- return 0;
-
- no_memory:
- err("out of memory\n");
- acpiphp_free_resource(&func->io_head);
- acpiphp_free_resource(&func->mem_head);
- acpiphp_free_resource(&func->p_mem_head);
-
- return -1;
-}
-
-
-/**
- * acpiphp_configure_slot - allocate PCI resources
- * @slot: slot to be configured
- *
- * initializes a PCI functions on a device inserted
- * into the slot
- *
- */
-int acpiphp_configure_slot (struct acpiphp_slot *slot)
-{
- struct acpiphp_func *func;
- struct list_head *l;
- u8 hdr;
- u32 dvid;
- int retval = 0;
- int is_multi = 0;
-
- pci_bus_read_config_byte(slot->bridge->pci_bus,
- PCI_DEVFN(slot->device, 0),
- PCI_HEADER_TYPE, &hdr);
-
- if (hdr & 0x80)
- is_multi = 1;
-
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
- if (is_multi || func->function == 0) {
- pci_bus_read_config_dword(slot->bridge->pci_bus,
- PCI_DEVFN(slot->device,
- func->function),
- PCI_VENDOR_ID, &dvid);
- if (dvid != 0xffffffff) {
- retval = init_config_space(func);
- if (retval)
- break;
- }
- }
- }
-
- return retval;
-}
-
-/**
- * acpiphp_configure_function - configure PCI function
- * @func: function to be configured
- *
- * initializes a PCI functions on a device inserted
- * into the slot
- *
- */
-int acpiphp_configure_function (struct acpiphp_func *func)
-{
- /* all handled by the pci core now */
- return 0;
-}
-
-/**
- * acpiphp_unconfigure_function - unconfigure PCI function
- * @func: function to be unconfigured
- *
- */
-void acpiphp_unconfigure_function (struct acpiphp_func *func)
-{
- struct acpiphp_bridge *bridge;
-
- /* if pci_dev is NULL, ignore it */
- if (!func->pci_dev)
- return;
-
- pci_remove_bus_device(func->pci_dev);
-
- /* free all resources */
- bridge = func->slot->bridge;
-
- spin_lock(&bridge->res_lock);
- acpiphp_move_resource(&func->io_head, &bridge->io_head);
- acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
- acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
- acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
- spin_unlock(&bridge->res_lock);
-}
diff --git a/drivers/pci/hotplug/acpiphp_res.c b/drivers/pci/hotplug/acpiphp_res.c
deleted file mode 100644
index f54b1fa7b75..00000000000
--- a/drivers/pci/hotplug/acpiphp_res.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- * ACPI PCI HotPlug Utility functions
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
- * Copyright (C) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT. 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.
- *
- * Send feedback to <gregkh@us.ibm.com>, <t-kochi@bq.jp.nec.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sysctl.h>
-#include <linux/pci.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-
-#include <linux/ioctl.h>
-#include <linux/fcntl.h>
-
-#include <linux/list.h>
-
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-#define MY_NAME "acpiphp_res"
-
-
-/*
- * sort_by_size - sort nodes by their length, smallest first
- */
-static int sort_by_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return 1;
-
- if (!((*head)->next))
- return 0;
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length > (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length > current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return 0;
-}
-
-#if 0
-/*
- * sort_by_max_size - sort nodes by their length, largest first
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return 1;
-
- if (!((*head)->next))
- return 0;
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length < (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length < current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return 0;
-}
-#endif
-
-/**
- * get_io_resource - get resource for I/O ports
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window. If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- *
- * difference from get_resource is handling of ISA aliasing space.
- *
- */
-struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u64 temp_qword;
-
- if (!(*head))
- return NULL;
-
- if (acpiphp_resource_sort_and_combine(head))
- return NULL;
-
- if (sort_by_size(head))
- return NULL;
-
- for (node = *head; node; node = node->next) {
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_qword = (node->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((node->length - (temp_qword - node->base)) < size)
- continue;
-
- split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
- if (!split_node)
- return NULL;
-
- node->base = temp_qword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
- if (!split_node)
- return NULL;
-
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- /* For IO make sure it's not in the ISA aliasing space */
- if ((node->base & 0x300L) && !(node->base & 0xfffff000))
- continue;
-
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
-
- return node;
-}
-
-
-#if 0
-/**
- * get_max_resource - get the largest resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head. It aligns the node on top and bottom
- * to "size" alignment before returning it.
- */
-static struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *max;
- struct pci_resource *temp;
- struct pci_resource *split_node;
- u64 temp_qword;
-
- if (!(*head))
- return NULL;
-
- if (acpiphp_resource_sort_and_combine(head))
- return NULL;
-
- if (sort_by_max_size(head))
- return NULL;
-
- for (max = *head;max; max = max->next) {
-
- /* If not big enough we could probably just bail,
- instead we'll continue to the next. */
- if (max->length < size)
- continue;
-
- if (max->base & (size - 1)) {
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_qword = (max->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((max->length - (temp_qword - max->base)) < size)
- continue;
-
- split_node = acpiphp_make_resource(max->base, temp_qword - max->base);
-
- if (!split_node)
- return NULL;
-
- max->base = temp_qword;
- max->length -= split_node->length;
-
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- if ((max->base + max->length) & (size - 1)) {
- /* this one isn't end aligned properly at the top
- so we'll make a new entry and split it up */
- temp_qword = ((max->base + max->length) & ~(size - 1));
-
- split_node = acpiphp_make_resource(temp_qword,
- max->length + max->base - temp_qword);
-
- if (!split_node)
- return NULL;
-
- max->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- /* Make sure it didn't shrink too much when we aligned it */
- if (max->length < size)
- continue;
-
- /* Now take it out of the list */
- temp = (struct pci_resource*) *head;
- if (temp == max) {
- *head = max->next;
- } else {
- while (temp && temp->next != max) {
- temp = temp->next;
- }
-
- temp->next = max->next;
- }
-
- max->next = NULL;
- return max;
- }
-
- /* If we get here, we couldn't find one */
- return NULL;
-}
-#endif
-
-/**
- * get_resource - get resource (mem, pfmem)
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length. If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- *
- */
-struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u64 temp_qword;
-
- if (!(*head))
- return NULL;
-
- if (acpiphp_resource_sort_and_combine(head))
- return NULL;
-
- if (sort_by_size(head))
- return NULL;
-
- for (node = *head; node; node = node->next) {
- dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",
- __FUNCTION__, size, node, (u32)node->base, node->length);
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- dbg("%s: not aligned\n", __FUNCTION__);
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_qword = (node->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((node->length - (temp_qword - node->base)) < size)
- continue;
-
- split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
- if (!split_node)
- return NULL;
-
- node->base = temp_qword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- dbg("%s: too big\n", __FUNCTION__);
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
- if (!split_node)
- return NULL;
-
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- dbg("%s: got one!!!\n", __FUNCTION__);
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
- return node;
-}
-
-/**
- * get_resource_with_base - get resource with specific base address
- *
- * this function
- * returns the first node of "size" length located at specified base address.
- * If it finds a node larger than "size" it will split it up.
- *
- * size must be a power of two.
- *
- */
-struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u64 temp_qword;
-
- if (!(*head))
- return NULL;
-
- if (acpiphp_resource_sort_and_combine(head))
- return NULL;
-
- for (node = *head; node; node = node->next) {
- dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
- (u32)base, size, node, (u32)node->base, node->length);
- if (node->base > base)
- continue;
-
- if ((node->base + node->length) < (base + size))
- continue;
-
- if (node->base < base) {
- dbg(": split 1\n");
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_qword = base;
-
- /* Short circuit if adjusted size is too small */
- if ((node->length - (temp_qword - node->base)) < size)
- continue;
-
- split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
- if (!split_node)
- return NULL;
-
- node->base = temp_qword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- }
-
- dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
- (u32)base, size, node, (u32)node->base, node->length);
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- dbg(": split 2\n");
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
- if (!split_node)
- return NULL;
-
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- dbg(": got one!!!\n");
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
- return node;
-}
-
-
-/**
- * acpiphp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses. Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int acpiphp_resource_sort_and_combine (struct pci_resource **head)
-{
- struct pci_resource *node1;
- struct pci_resource *node2;
- int out_of_order = 1;
-
- if (!(*head))
- return 1;
-
- dbg("*head->next = %p\n",(*head)->next);
-
- if (!(*head)->next)
- return 0; /* only one item on the list, already sorted! */
-
- dbg("*head->base = 0x%x\n",(u32)(*head)->base);
- dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->base > (*head)->next->base)) {
- node1 = *head;
- (*head) = (*head)->next;
- node1->next = (*head)->next;
- (*head)->next = node1;
- out_of_order++;
- }
-
- node1 = (*head);
-
- while (node1->next && node1->next->next) {
- if (node1->next->base > node1->next->next->base) {
- out_of_order++;
- node2 = node1->next;
- node1->next = node1->next->next;
- node1 = node1->next;
- node2->next = node1->next;
- node1->next = node2;
- } else
- node1 = node1->next;
- }
- } /* End of out_of_order loop */
-
- node1 = *head;
-
- while (node1 && node1->next) {
- if ((node1->base + node1->length) == node1->next->base) {
- /* Combine */
- dbg("8..\n");
- node1->length += node1->next->length;
- node2 = node1->next;
- node1->next = node1->next->next;
- kfree(node2);
- } else
- node1 = node1->next;
- }
-
- return 0;
-}
-
-
-/**
- * acpiphp_make_resource - make resource structure
- * @base: base address of a resource
- * @length: length of a resource
- */
-struct pci_resource *acpiphp_make_resource (u64 base, u32 length)
-{
- struct pci_resource *res;
-
- res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (res) {
- memset(res, 0, sizeof(struct pci_resource));
- res->base = base;
- res->length = length;
- }
-
- return res;
-}
-
-
-/**
- * acpiphp_move_resource - move linked resources from one to another
- * @from: head of linked resource list
- * @to: head of linked resource list
- */
-void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to)
-{
- struct pci_resource *tmp;
-
- while (*from) {
- tmp = (*from)->next;
- (*from)->next = *to;
- *to = *from;
- *from = tmp;
- }
-
- /* *from = NULL is guaranteed */
-}
-
-
-/**
- * acpiphp_free_resource - free all linked resources
- * @res: head of linked resource list
- */
-void acpiphp_free_resource (struct pci_resource **res)
-{
- struct pci_resource *tmp;
-
- while (*res) {
- tmp = (*res)->next;
- kfree(*res);
- *res = tmp;
- }
-
- /* *res = NULL is guaranteed */
-}
-
-
-/* debug support functions; will go away sometime :) */
-static void dump_resource(struct pci_resource *head)
-{
- struct pci_resource *p;
- int cnt;
-
- p = head;
- cnt = 0;
-
- while (p) {
- dbg("[%02d] %08x - %08x\n",
- cnt++, (u32)p->base, (u32)p->base + p->length - 1);
- p = p->next;
- }
-}
-
-void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
-{
- dbg("I/O resource:\n");
- dump_resource(bridge->io_head);
- dbg("MEM resource:\n");
- dump_resource(bridge->mem_head);
- dbg("PMEM resource:\n");
- dump_resource(bridge->p_mem_head);
- dbg("BUS resource:\n");
- dump_resource(bridge->bus_head);
-}
-
-void acpiphp_dump_func_resource(struct acpiphp_func *func)
-{
- dbg("I/O resource:\n");
- dump_resource(func->io_head);
- dbg("MEM resource:\n");
- dump_resource(func->mem_head);
- dbg("PMEM resource:\n");
- dump_resource(func->p_mem_head);
- dbg("BUS resource:\n");
- dump_resource(func->bus_head);
-}
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index afbccfa5217..8c6d3987d46 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -60,6 +60,7 @@ static void __iomem *smbios_start;
static void __iomem *cpqhp_rom_start;
static int power_mode;
static int debug;
+static int initialized;
#define DRIVER_VERSION "0.9.8"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
@@ -1271,7 +1272,6 @@ static int one_time_init(void)
{
int loop;
int retval = 0;
- static int initialized = 0;
if (initialized)
return 0;
@@ -1441,7 +1441,8 @@ static void __exit unload_cpqphpd(void)
}
// Stop the notification mechanism
- cpqhp_event_stop_thread();
+ if (initialized)
+ cpqhp_event_stop_thread();
//unmap the rom address
if (cpqhp_rom_start)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 30206ac43c4..b5ab9aa6ff7 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -28,10 +28,10 @@ static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
static kmem_cache_t* msi_cachep;
static int pci_msi_enable = 1;
-static int last_alloc_vector = 0;
-static int nr_released_vectors = 0;
+static int last_alloc_vector;
+static int nr_released_vectors;
static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;
-static int nr_msix_devices = 0;
+static int nr_msix_devices;
#ifndef CONFIG_X86_IO_APIC
int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
@@ -170,44 +170,30 @@ static unsigned int startup_msi_irq_wo_maskbit(unsigned int vector)
return 0; /* never anything pending */
}
-static void release_msi(unsigned int vector);
-static void shutdown_msi_irq(unsigned int vector)
-{
- release_msi(vector);
-}
-
-#define shutdown_msi_irq_wo_maskbit shutdown_msi_irq
-static void enable_msi_irq_wo_maskbit(unsigned int vector) {}
-static void disable_msi_irq_wo_maskbit(unsigned int vector) {}
-static void ack_msi_irq_wo_maskbit(unsigned int vector) {}
-static void end_msi_irq_wo_maskbit(unsigned int vector)
+static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
{
- move_msi(vector);
- ack_APIC_irq();
+ startup_msi_irq_wo_maskbit(vector);
+ unmask_MSI_irq(vector);
+ return 0; /* never anything pending */
}
-static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
+static void shutdown_msi_irq(unsigned int vector)
{
struct msi_desc *entry;
unsigned long flags;
spin_lock_irqsave(&msi_lock, flags);
entry = msi_desc[vector];
- if (!entry || !entry->dev) {
- spin_unlock_irqrestore(&msi_lock, flags);
- return 0;
- }
- entry->msi_attrib.state = 1; /* Mark it active */
+ if (entry && entry->dev)
+ entry->msi_attrib.state = 0; /* Mark it not active */
spin_unlock_irqrestore(&msi_lock, flags);
-
- unmask_MSI_irq(vector);
- return 0; /* never anything pending */
}
-#define shutdown_msi_irq_w_maskbit shutdown_msi_irq
-#define enable_msi_irq_w_maskbit unmask_MSI_irq
-#define disable_msi_irq_w_maskbit mask_MSI_irq
-#define ack_msi_irq_w_maskbit mask_MSI_irq
+static void end_msi_irq_wo_maskbit(unsigned int vector)
+{
+ move_msi(vector);
+ ack_APIC_irq();
+}
static void end_msi_irq_w_maskbit(unsigned int vector)
{
@@ -216,6 +202,10 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
ack_APIC_irq();
}
+static void do_nothing(unsigned int vector)
+{
+}
+
/*
* Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices,
* which implement the MSI-X Capability Structure.
@@ -223,10 +213,10 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
static struct hw_interrupt_type msix_irq_type = {
.typename = "PCI-MSI-X",
.startup = startup_msi_irq_w_maskbit,
- .shutdown = shutdown_msi_irq_w_maskbit,
- .enable = enable_msi_irq_w_maskbit,
- .disable = disable_msi_irq_w_maskbit,
- .ack = ack_msi_irq_w_maskbit,
+ .shutdown = shutdown_msi_irq,
+ .enable = unmask_MSI_irq,
+ .disable = mask_MSI_irq,
+ .ack = mask_MSI_irq,
.end = end_msi_irq_w_maskbit,
.set_affinity = set_msi_irq_affinity
};
@@ -239,10 +229,10 @@ static struct hw_interrupt_type msix_irq_type = {
static struct hw_interrupt_type msi_irq_w_maskbit_type = {
.typename = "PCI-MSI",
.startup = startup_msi_irq_w_maskbit,
- .shutdown = shutdown_msi_irq_w_maskbit,
- .enable = enable_msi_irq_w_maskbit,
- .disable = disable_msi_irq_w_maskbit,
- .ack = ack_msi_irq_w_maskbit,
+ .shutdown = shutdown_msi_irq,
+ .enable = unmask_MSI_irq,
+ .disable = mask_MSI_irq,
+ .ack = mask_MSI_irq,
.end = end_msi_irq_w_maskbit,
.set_affinity = set_msi_irq_affinity
};
@@ -255,10 +245,10 @@ static struct hw_interrupt_type msi_irq_w_maskbit_type = {
static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
.typename = "PCI-MSI",
.startup = startup_msi_irq_wo_maskbit,
- .shutdown = shutdown_msi_irq_wo_maskbit,
- .enable = enable_msi_irq_wo_maskbit,
- .disable = disable_msi_irq_wo_maskbit,
- .ack = ack_msi_irq_wo_maskbit,
+ .shutdown = shutdown_msi_irq,
+ .enable = do_nothing,
+ .disable = do_nothing,
+ .ack = do_nothing,
.end = end_msi_irq_wo_maskbit,
.set_affinity = set_msi_irq_affinity
};
@@ -407,7 +397,7 @@ static struct msi_desc* alloc_msi_entry(void)
{
struct msi_desc *entry;
- entry = (struct msi_desc*) kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
+ entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
if (!entry)
return NULL;
@@ -796,18 +786,6 @@ void pci_disable_msi(struct pci_dev* dev)
}
}
-static void release_msi(unsigned int vector)
-{
- struct msi_desc *entry;
- unsigned long flags;
-
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[vector];
- if (entry && entry->dev)
- entry->msi_attrib.state = 0; /* Mark it not active */
- spin_unlock_irqrestore(&msi_lock, flags);
-}
-
static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
{
struct msi_desc *entry;
@@ -924,7 +902,7 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
/**
* pci_enable_msix - configure device's MSI-X capability structure
* @dev: pointer to the pci_dev data structure of MSI-X device function
- * @data: pointer to an array of MSI-X entries
+ * @entries: pointer to an array of MSI-X entries
* @nvec: number of MSI-X vectors requested for allocation by device driver
*
* Setup the MSI-X capability structure of device function with the number
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index bef21ae3cbd..390f1851c0f 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -41,11 +41,11 @@ static inline void move_msi(int vector) {}
#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
-#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
-#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
-#define PCI_MSIX_ENTRY_DATA_OFFSET 8
-#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12
#define PCI_MSIX_ENTRY_SIZE 16
+#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
+#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
+#define PCI_MSIX_ENTRY_DATA_OFFSET 8
+#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12
#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO)
@@ -64,7 +64,6 @@ static inline void move_msi(int vector) {}
#define msi_enable(control, num) multi_msi_enable(control, num); \
control |= PCI_MSI_FLAGS_ENABLE
-#define msix_control_reg msi_control_reg
#define msix_table_offset_reg(base) (base + 0x04)
#define msix_pba_offset_reg(base) (base + 0x08)
#define msix_enable(control) control |= PCI_MSIX_FLAGS_ENABLE
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index a15f94072a6..cc9d65388e6 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -60,15 +60,18 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)
char * str = buf;
int i;
int max = 7;
+ u64 start, end;
if (pci_dev->subordinate)
max = DEVICE_COUNT_RESOURCE;
for (i = 0; i < max; i++) {
- str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",
- pci_resource_start(pci_dev,i),
- pci_resource_end(pci_dev,i),
- pci_resource_flags(pci_dev,i));
+ struct resource *res = &pci_dev->resource[i];
+ pci_resource_to_user(pci_dev, i, res, &start, &end);
+ str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
+ (unsigned long long)start,
+ (unsigned long long)end,
+ (unsigned long long)res->flags);
}
return (str - buf);
}
@@ -313,8 +316,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
struct device, kobj));
struct resource *res = (struct resource *)attr->private;
enum pci_mmap_state mmap_type;
+ u64 start, end;
+ int i;
- vma->vm_pgoff += res->start >> PAGE_SHIFT;
+ for (i = 0; i < PCI_ROM_RESOURCE; i++)
+ if (res == &pdev->resource[i])
+ break;
+ if (i >= PCI_ROM_RESOURCE)
+ return -ENODEV;
+
+ /* pci_mmap_page_range() expects the same kind of entry as coming
+ * from /proc/bus/pci/ which is a "user visible" value. If this is
+ * different from the resource itself, arch will do necessary fixup.
+ */
+ pci_resource_to_user(pdev, i, res, &start, &end);
+ vma->vm_pgoff += start >> PAGE_SHIFT;
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
return pci_mmap_page_range(pdev, vma, mmap_type, 0);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fd48b201eb5..6a0a82f0508 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -374,8 +374,11 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
struct pci_bus *child;
child = pci_alloc_child_bus(parent, dev, busnr);
- if (child)
+ if (child) {
+ spin_lock(&pci_bus_lock);
list_add_tail(&child->node, &parent->children);
+ spin_unlock(&pci_bus_lock);
+ }
return child;
}
@@ -411,7 +414,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
{
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
- u32 buses;
+ u32 buses, i;
u16 bctl;
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
@@ -447,7 +450,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
return max;
}
- child = pci_alloc_child_bus(bus, dev, busnr);
+ child = pci_add_new_bus(bus, dev, busnr);
if (!child)
return max;
child->primary = buses & 0xFF;
@@ -470,7 +473,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
/* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
- child = pci_alloc_child_bus(bus, dev, ++max);
+ /* Prevent assigning a bus number that already exists.
+ * This can happen when a bridge is hot-plugged */
+ if (pci_find_bus(pci_domain_nr(bus), max+1))
+ return max;
+ child = pci_add_new_bus(bus, dev, ++max);
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->secondary) << 8)
@@ -501,7 +508,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
* as cards with a PCI-to-PCI bridge can be
* inserted later.
*/
- max += CARDBUS_RESERVE_BUSNR;
+ for (i=0; i<CARDBUS_RESERVE_BUSNR; i++)
+ if (pci_find_bus(pci_domain_nr(bus),
+ max+i+1))
+ break;
+ max += i;
}
/*
* Set the subordinate bus number to its real value.
@@ -757,7 +768,9 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
* and the bus list for fixup functions, etc.
*/
INIT_LIST_HEAD(&dev->global_list);
+ spin_lock(&pci_bus_lock);
list_add_tail(&dev->bus_list, &bus->devices);
+ spin_unlock(&pci_bus_lock);
return dev;
}
@@ -878,7 +891,9 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);
goto err_out;
}
+ spin_lock(&pci_bus_lock);
list_add_tail(&b->node, &pci_root_buses);
+ spin_unlock(&pci_bus_lock);
memset(dev, 0, sizeof(*dev));
dev->parent = parent;
@@ -911,8 +926,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
b->subordinate = pci_scan_child_bus(b);
- pci_bus_add_devices(b);
-
return b;
sys_create_link_err:
@@ -922,7 +935,9 @@ class_dev_create_file_err:
class_dev_reg_err:
device_unregister(dev);
dev_reg_err:
+ spin_lock(&pci_bus_lock);
list_del(&b->node);
+ spin_unlock(&pci_bus_lock);
err_out:
kfree(dev);
kfree(b);
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index e68bbfb1e7c..7988fc8df3f 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -355,14 +355,20 @@ static int show_device(struct seq_file *m, void *v)
dev->device,
dev->irq);
/* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
- for(i=0; i<7; i++)
+ for (i=0; i<7; i++) {
+ u64 start, end;
+ pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
seq_printf(m, LONG_FORMAT,
- dev->resource[i].start |
+ ((unsigned long)start) |
(dev->resource[i].flags & PCI_REGION_FLAG_MASK));
- for(i=0; i<7; i++)
+ }
+ for (i=0; i<7; i++) {
+ u64 start, end;
+ pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
seq_printf(m, LONG_FORMAT,
dev->resource[i].start < dev->resource[i].end ?
- dev->resource[i].end - dev->resource[i].start + 1 : 0);
+ (unsigned long)(end - start) + 1 : 0);
+ }
seq_putc(m, '\t');
if (drv)
seq_printf(m, "%s", drv->name);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 96f077f9a65..27a294b6965 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -18,17 +18,21 @@ static void pci_free_resources(struct pci_dev *dev)
static void pci_destroy_dev(struct pci_dev *dev)
{
- pci_proc_detach_device(dev);
- pci_remove_sysfs_dev_files(dev);
- device_unregister(&dev->dev);
+ if (!list_empty(&dev->global_list)) {
+ pci_proc_detach_device(dev);
+ pci_remove_sysfs_dev_files(dev);
+ device_unregister(&dev->dev);
+ spin_lock(&pci_bus_lock);
+ list_del(&dev->global_list);
+ dev->global_list.next = dev->global_list.prev = NULL;
+ spin_unlock(&pci_bus_lock);
+ }
/* Remove the device from the device lists, and prevent any further
* list accesses from this device */
spin_lock(&pci_bus_lock);
list_del(&dev->bus_list);
- list_del(&dev->global_list);
dev->bus_list.next = dev->bus_list.prev = NULL;
- dev->global_list.next = dev->global_list.prev = NULL;
spin_unlock(&pci_bus_lock);
pci_free_resources(dev);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1ba84be0b4c..6b628de948a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -72,7 +72,10 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
for (list = head.next; list;) {
res = list->res;
idx = res - &list->dev->resource[0];
- pci_assign_resource(list->dev, idx);
+ if (pci_assign_resource(list->dev, idx)) {
+ res->start = 0;
+ res->flags = 0;
+ }
tmp = list;
list = list->next;
kfree(tmp);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 34dbc37a79d..bc6e4627c7a 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1916,9 +1916,9 @@ static void __twa_shutdown(TW_Device_Extension *tw_dev)
} /* End __twa_shutdown() */
/* Wrapper for __twa_shutdown */
-static void twa_shutdown(struct device *dev)
+static void twa_shutdown(struct pci_dev *pdev)
{
- struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+ struct Scsi_Host *host = pci_get_drvdata(pdev);
TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
__twa_shutdown(tw_dev);
@@ -2140,9 +2140,7 @@ static struct pci_driver twa_driver = {
.id_table = twa_pci_tbl,
.probe = twa_probe,
.remove = twa_remove,
- .driver = {
- .shutdown = twa_shutdown
- }
+ .shutdown = twa_shutdown
};
/* This function is called on driver initialization */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index b6dc576da43..973c51fb0fe 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -2264,9 +2264,9 @@ static void __tw_shutdown(TW_Device_Extension *tw_dev)
} /* End __tw_shutdown() */
/* Wrapper for __tw_shutdown */
-static void tw_shutdown(struct device *dev)
+static void tw_shutdown(struct pci_dev *pdev)
{
- struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+ struct Scsi_Host *host = pci_get_drvdata(pdev);
TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
__tw_shutdown(tw_dev);
@@ -2451,9 +2451,7 @@ static struct pci_driver tw_driver = {
.id_table = tw_pci_tbl,
.probe = tw_probe,
.remove = tw_remove,
- .driver = {
- .shutdown = tw_shutdown
- }
+ .shutdown = tw_shutdown,
};
/* This function is called on driver initialization */
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 9a547ca9c86..c5623694d10 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -304,26 +304,19 @@ static int ahci_port_start(struct ata_port *ap)
struct device *dev = ap->host_set->dev;
struct ahci_host_priv *hpriv = ap->host_set->private_data;
struct ahci_port_priv *pp;
- int rc;
void *mem, *mmio = ap->host_set->mmio_base;
void *port_mmio = ahci_port_base(mmio, ap->port_no);
dma_addr_t mem_dma;
- rc = ata_port_start(ap);
- if (rc)
- return rc;
-
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
- if (!pp) {
- rc = -ENOMEM;
- goto err_out;
- }
+ if (!pp)
+ return -ENOMEM;
memset(pp, 0, sizeof(*pp));
mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
if (!mem) {
- rc = -ENOMEM;
- goto err_out_kfree;
+ kfree(pp);
+ return -ENOMEM;
}
memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
@@ -373,12 +366,6 @@ static int ahci_port_start(struct ata_port *ap)
readl(port_mmio + PORT_CMD); /* flush */
return 0;
-
-err_out_kfree:
- kfree(pp);
-err_out:
- ata_port_stop(ap);
- return rc;
}
@@ -404,7 +391,6 @@ static void ahci_port_stop(struct ata_port *ap)
dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
pp->cmd_slot, pp->cmd_slot_dma);
kfree(pp);
- ata_port_stop(ap);
}
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 80d022625c8..babd4836340 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -6012,7 +6012,7 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
/**
* ipr_shutdown - Shutdown handler.
- * @dev: device struct
+ * @pdev: pci device struct
*
* This function is invoked upon system shutdown/reboot. It will issue
* an adapter shutdown to the adapter to flush the write cache.
@@ -6020,9 +6020,9 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
* Return value:
* none
**/
-static void ipr_shutdown(struct device *dev)
+static void ipr_shutdown(struct pci_dev *pdev)
{
- struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(to_pci_dev(dev));
+ struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
unsigned long lock_flags = 0;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -6068,9 +6068,7 @@ static struct pci_driver ipr_driver = {
.id_table = ipr_pci_table,
.probe = ipr_probe,
.remove = ipr_remove,
- .driver = {
- .shutdown = ipr_shutdown,
- },
+ .shutdown = ipr_shutdown,
};
/**
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 36b401fee1f..cb535fa185b 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1408,7 +1408,9 @@ void __sata_phy_reset(struct ata_port *ap)
if (ap->flags & ATA_FLAG_SATA_RESET) {
/* issue phy wake/reset */
scr_write_flush(ap, SCR_CONTROL, 0x301);
- udelay(400); /* FIXME: a guess */
+ /* Couldn't find anything in SATA I/II specs, but
+ * AHCI-1.1 10.4.2 says at least 1 ms. */
+ mdelay(1);
}
scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
@@ -1920,6 +1922,7 @@ static const char * ata_dma_blacklist [] = {
"HITACHI CDR-8335",
"HITACHI CDR-8435",
"Toshiba CD-ROM XM-6202B",
+ "TOSHIBA CD-ROM XM-1702BC",
"CD-532E-A",
"E-IDE CD-ROM CR-840",
"CD-ROM Drive/F5A",
@@ -1927,7 +1930,6 @@ static const char * ata_dma_blacklist [] = {
"SAMSUNG CD-ROM SC-148C",
"SAMSUNG CD-ROM SC",
"SanDisk SDP3B-64",
- "SAMSUNG CD-ROM SN-124",
"ATAPI CD-ROM DRIVE 40X MAXIMUM",
"_NEC DV5800A",
};
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index ec81532eb84..a70cdf31311 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -5036,9 +5036,9 @@ megaraid_remove_one(struct pci_dev *pdev)
}
static void
-megaraid_shutdown(struct device *dev)
+megaraid_shutdown(struct pci_dev *pdev)
{
- struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+ struct Scsi_Host *host = pci_get_drvdata(pdev);
adapter_t *adapter = (adapter_t *)host->hostdata;
__megaraid_shutdown(adapter);
@@ -5070,9 +5070,7 @@ static struct pci_driver megaraid_pci_driver = {
.id_table = megaraid_pci_tbl,
.probe = megaraid_probe_one,
.remove = __devexit_p(megaraid_remove_one),
- .driver = {
- .shutdown = megaraid_shutdown,
- },
+ .shutdown = megaraid_shutdown,
};
static int __init megaraid_init(void)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 621dee8b8cb..10506f9cd0c 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -632,7 +632,7 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index)
{
struct scsi_host_sg_pool *sgp;
- BUG_ON(index > SG_MEMPOOL_NR);
+ BUG_ON(index >= SG_MEMPOOL_NR);
sgp = scsi_sg_pools + index;
mempool_free(sgl, sgp->pool);