diff options
| -rw-r--r-- | Documentation/SubmittingPatches | 26 | ||||
| -rw-r--r-- | Documentation/i2c/upgrading-clients | 281 | ||||
| -rw-r--r-- | drivers/acpi/processor_idle.c | 15 | ||||
| -rw-r--r-- | drivers/base/memory.c | 3 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.c | 275 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.h | 4 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/main.c | 86 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/main.h | 5 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/network.c | 58 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/network.h | 1 | ||||
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/tty.c | 2 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 35 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-gpio.c | 9 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 129 | ||||
| -rw-r--r-- | include/asm-arm/plat-s3c/iic.h | 1 |
16 files changed, 691 insertions, 241 deletions
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 118ca6e9404f..f79ad9ff6031 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches | |||
| @@ -528,7 +528,33 @@ See more details on the proper patch format in the following | |||
| 528 | references. | 528 | references. |
| 529 | 529 | ||
| 530 | 530 | ||
| 531 | 16) Sending "git pull" requests (from Linus emails) | ||
| 531 | 532 | ||
| 533 | Please write the git repo address and branch name alone on the same line | ||
| 534 | so that I can't even by mistake pull from the wrong branch, and so | ||
| 535 | that a triple-click just selects the whole thing. | ||
| 536 | |||
| 537 | So the proper format is something along the lines of: | ||
| 538 | |||
| 539 | "Please pull from | ||
| 540 | |||
| 541 | git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus | ||
| 542 | |||
| 543 | to get these changes:" | ||
| 544 | |||
| 545 | so that I don't have to hunt-and-peck for the address and inevitably | ||
| 546 | get it wrong (actually, I've only gotten it wrong a few times, and | ||
| 547 | checking against the diffstat tells me when I get it wrong, but I'm | ||
| 548 | just a lot more comfortable when I don't have to "look for" the right | ||
| 549 | thing to pull, and double-check that I have the right branch-name). | ||
| 550 | |||
| 551 | |||
| 552 | Please use "git diff -M --stat --summary" to generate the diffstat: | ||
| 553 | the -M enables rename detection, and the summary enables a summary of | ||
| 554 | new/deleted or renamed files. | ||
| 555 | |||
| 556 | With rename detection, the statistics are rather different [...] | ||
| 557 | because git will notice that a fair number of the changes are renames. | ||
| 532 | 558 | ||
| 533 | ----------------------------------- | 559 | ----------------------------------- |
| 534 | SECTION 2 - HINTS, TIPS, AND TRICKS | 560 | SECTION 2 - HINTS, TIPS, AND TRICKS |
diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients new file mode 100644 index 000000000000..9a45f9bb6a25 --- /dev/null +++ b/Documentation/i2c/upgrading-clients | |||
| @@ -0,0 +1,281 @@ | |||
| 1 | Upgrading I2C Drivers to the new 2.6 Driver Model | ||
| 2 | ================================================= | ||
| 3 | |||
| 4 | Ben Dooks <ben-linux@fluff.org> | ||
| 5 | |||
| 6 | Introduction | ||
| 7 | ------------ | ||
| 8 | |||
| 9 | This guide outlines how to alter existing Linux 2.6 client drivers from | ||
| 10 | the old to the new new binding methods. | ||
| 11 | |||
| 12 | |||
| 13 | Example old-style driver | ||
| 14 | ------------------------ | ||
| 15 | |||
| 16 | |||
| 17 | struct example_state { | ||
| 18 | struct i2c_client client; | ||
| 19 | .... | ||
| 20 | }; | ||
| 21 | |||
| 22 | static struct i2c_driver example_driver; | ||
| 23 | |||
| 24 | static unsigned short ignore[] = { I2C_CLIENT_END }; | ||
| 25 | static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; | ||
| 26 | |||
| 27 | I2C_CLIENT_INSMOD; | ||
| 28 | |||
| 29 | static int example_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 30 | { | ||
| 31 | struct example_state *state; | ||
| 32 | struct device *dev = &adap->dev; /* to use for dev_ reports */ | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | state = kzalloc(sizeof(struct example_state), GFP_KERNEL); | ||
| 36 | if (state == NULL) { | ||
| 37 | dev_err(dev, "failed to create our state\n"); | ||
| 38 | return -ENOMEM; | ||
| 39 | } | ||
| 40 | |||
| 41 | example->client.addr = addr; | ||
| 42 | example->client.flags = 0; | ||
| 43 | example->client.adapter = adap; | ||
| 44 | |||
| 45 | i2c_set_clientdata(&state->i2c_client, state); | ||
| 46 | strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE); | ||
| 47 | |||
| 48 | ret = i2c_attach_client(&state->i2c_client); | ||
| 49 | if (ret < 0) { | ||
| 50 | dev_err(dev, "failed to attach client\n"); | ||
| 51 | kfree(state); | ||
| 52 | return ret; | ||
| 53 | } | ||
| 54 | |||
| 55 | dev = &state->i2c_client.dev; | ||
| 56 | |||
| 57 | /* rest of the initialisation goes here. */ | ||
| 58 | |||
| 59 | dev_info(dev, "example client created\n"); | ||
| 60 | |||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int __devexit example_detach(struct i2c_client *client) | ||
| 65 | { | ||
| 66 | struct example_state *state = i2c_get_clientdata(client); | ||
| 67 | |||
| 68 | i2c_detach_client(client); | ||
| 69 | kfree(state); | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int example_attach_adapter(struct i2c_adapter *adap) | ||
| 74 | { | ||
| 75 | return i2c_probe(adap, &addr_data, example_attach); | ||
| 76 | } | ||
| 77 | |||
| 78 | static struct i2c_driver example_driver = { | ||
| 79 | .driver = { | ||
| 80 | .owner = THIS_MODULE, | ||
| 81 | .name = "example", | ||
| 82 | }, | ||
| 83 | .attach_adapter = example_attach_adapter, | ||
| 84 | .detach_client = __devexit_p(example_detach), | ||
| 85 | .suspend = example_suspend, | ||
| 86 | .resume = example_resume, | ||
| 87 | }; | ||
| 88 | |||
| 89 | |||
| 90 | Updating the client | ||
| 91 | ------------------- | ||
| 92 | |||
| 93 | The new style binding model will check against a list of supported | ||
| 94 | devices and their associated address supplied by the code registering | ||
| 95 | the busses. This means that the driver .attach_adapter and | ||
| 96 | .detach_adapter methods can be removed, along with the addr_data, | ||
| 97 | as follows: | ||
| 98 | |||
| 99 | - static struct i2c_driver example_driver; | ||
| 100 | |||
| 101 | - static unsigned short ignore[] = { I2C_CLIENT_END }; | ||
| 102 | - static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; | ||
| 103 | |||
| 104 | - I2C_CLIENT_INSMOD; | ||
| 105 | |||
| 106 | - static int example_attach_adapter(struct i2c_adapter *adap) | ||
| 107 | - { | ||
| 108 | - return i2c_probe(adap, &addr_data, example_attach); | ||
| 109 | - } | ||
| 110 | |||
| 111 | static struct i2c_driver example_driver = { | ||
| 112 | - .attach_adapter = example_attach_adapter, | ||
| 113 | - .detach_client = __devexit_p(example_detach), | ||
| 114 | } | ||
| 115 | |||
| 116 | Add the probe and remove methods to the i2c_driver, as so: | ||
| 117 | |||
| 118 | static struct i2c_driver example_driver = { | ||
| 119 | + .probe = example_probe, | ||
| 120 | + .remove = __devexit_p(example_remove), | ||
| 121 | } | ||
| 122 | |||
| 123 | Change the example_attach method to accept the new parameters | ||
| 124 | which include the i2c_client that it will be working with: | ||
| 125 | |||
| 126 | - static int example_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 127 | + static int example_probe(struct i2c_client *client, | ||
| 128 | + const struct i2c_device_id *id) | ||
| 129 | |||
| 130 | Change the name of example_attach to example_probe to align it with the | ||
| 131 | i2c_driver entry names. The rest of the probe routine will now need to be | ||
| 132 | changed as the i2c_client has already been setup for use. | ||
| 133 | |||
| 134 | The necessary client fields have already been setup before | ||
| 135 | the probe function is called, so the following client setup | ||
| 136 | can be removed: | ||
| 137 | |||
| 138 | - example->client.addr = addr; | ||
| 139 | - example->client.flags = 0; | ||
| 140 | - example->client.adapter = adap; | ||
| 141 | - | ||
| 142 | - strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE); | ||
| 143 | |||
| 144 | The i2c_set_clientdata is now: | ||
| 145 | |||
| 146 | - i2c_set_clientdata(&state->client, state); | ||
| 147 | + i2c_set_clientdata(client, state); | ||
| 148 | |||
| 149 | The call to i2c_attach_client is no longer needed, if the probe | ||
| 150 | routine exits successfully, then the driver will be automatically | ||
| 151 | attached by the core. Change the probe routine as so: | ||
| 152 | |||
| 153 | - ret = i2c_attach_client(&state->i2c_client); | ||
| 154 | - if (ret < 0) { | ||
| 155 | - dev_err(dev, "failed to attach client\n"); | ||
| 156 | - kfree(state); | ||
| 157 | - return ret; | ||
| 158 | - } | ||
| 159 | |||
| 160 | |||
| 161 | Remove the storage of 'struct i2c_client' from the 'struct example_state' | ||
| 162 | as we are provided with the i2c_client in our example_probe. Instead we | ||
| 163 | store a pointer to it for when it is needed. | ||
| 164 | |||
| 165 | struct example_state { | ||
| 166 | - struct i2c_client client; | ||
| 167 | + struct i2c_client *client; | ||
| 168 | |||
| 169 | the new i2c client as so: | ||
| 170 | |||
| 171 | - struct device *dev = &adap->dev; /* to use for dev_ reports */ | ||
| 172 | + struct device *dev = &i2c_client->dev; /* to use for dev_ reports */ | ||
| 173 | |||
| 174 | And remove the change after our client is attached, as the driver no | ||
| 175 | longer needs to register a new client structure with the core: | ||
| 176 | |||
| 177 | - dev = &state->i2c_client.dev; | ||
| 178 | |||
| 179 | In the probe routine, ensure that the new state has the client stored | ||
| 180 | in it: | ||
| 181 | |||
| 182 | static int example_probe(struct i2c_client *i2c_client, | ||
| 183 | const struct i2c_device_id *id) | ||
| 184 | { | ||
| 185 | struct example_state *state; | ||
| 186 | struct device *dev = &i2c_client->dev; | ||
| 187 | int ret; | ||
| 188 | |||
| 189 | state = kzalloc(sizeof(struct example_state), GFP_KERNEL); | ||
| 190 | if (state == NULL) { | ||
| 191 | dev_err(dev, "failed to create our state\n"); | ||
| 192 | return -ENOMEM; | ||
| 193 | } | ||
| 194 | |||
| 195 | + state->client = i2c_client; | ||
| 196 | |||
| 197 | Update the detach method, by changing the name to _remove and | ||
| 198 | to delete the i2c_detach_client call. It is possible that you | ||
| 199 | can also remove the ret variable as it is not not needed for | ||
| 200 | any of the core functions. | ||
| 201 | |||
| 202 | - static int __devexit example_detach(struct i2c_client *client) | ||
| 203 | + static int __devexit example_remove(struct i2c_client *client) | ||
| 204 | { | ||
| 205 | struct example_state *state = i2c_get_clientdata(client); | ||
| 206 | |||
| 207 | - i2c_detach_client(client); | ||
| 208 | |||
| 209 | And finally ensure that we have the correct ID table for the i2c-core | ||
| 210 | and other utilities: | ||
| 211 | |||
| 212 | + struct i2c_device_id example_idtable[] = { | ||
| 213 | + { "example", 0 }, | ||
| 214 | + { } | ||
| 215 | +}; | ||
| 216 | + | ||
| 217 | +MODULE_DEVICE_TABLE(i2c, example_idtable); | ||
| 218 | |||
| 219 | static struct i2c_driver example_driver = { | ||
| 220 | .driver = { | ||
| 221 | .owner = THIS_MODULE, | ||
| 222 | .name = "example", | ||
| 223 | }, | ||
| 224 | + .id_table = example_ids, | ||
| 225 | |||
| 226 | |||
| 227 | Our driver should now look like this: | ||
| 228 | |||
| 229 | struct example_state { | ||
| 230 | struct i2c_client *client; | ||
| 231 | .... | ||
| 232 | }; | ||
| 233 | |||
| 234 | static int example_probe(struct i2c_client *client, | ||
| 235 | const struct i2c_device_id *id) | ||
| 236 | { | ||
| 237 | struct example_state *state; | ||
| 238 | struct device *dev = &client->dev; | ||
| 239 | |||
| 240 | state = kzalloc(sizeof(struct example_state), GFP_KERNEL); | ||
| 241 | if (state == NULL) { | ||
| 242 | dev_err(dev, "failed to create our state\n"); | ||
| 243 | return -ENOMEM; | ||
| 244 | } | ||
| 245 | |||
| 246 | state->client = client; | ||
| 247 | i2c_set_clientdata(client, state); | ||
| 248 | |||
| 249 | /* rest of the initialisation goes here. */ | ||
| 250 | |||
| 251 | dev_info(dev, "example client created\n"); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static int __devexit example_remove(struct i2c_client *client) | ||
| 257 | { | ||
| 258 | struct example_state *state = i2c_get_clientdata(client); | ||
| 259 | |||
| 260 | kfree(state); | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static struct i2c_device_id example_idtable[] = { | ||
| 265 | { "example", 0 }, | ||
| 266 | { } | ||
| 267 | }; | ||
| 268 | |||
| 269 | MODULE_DEVICE_TABLE(i2c, example_idtable); | ||
| 270 | |||
| 271 | static struct i2c_driver example_driver = { | ||
| 272 | .driver = { | ||
| 273 | .owner = THIS_MODULE, | ||
| 274 | .name = "example", | ||
| 275 | }, | ||
| 276 | .id_table = example_idtable, | ||
| 277 | .probe = example_probe, | ||
| 278 | .remove = __devexit_p(example_remove), | ||
| 279 | .suspend = example_suspend, | ||
| 280 | .resume = example_resume, | ||
| 281 | }; | ||
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index b7f2963693a7..283c08f5f4d4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -1332,9 +1332,15 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
| 1332 | if (!pr->flags.power_setup_done) | 1332 | if (!pr->flags.power_setup_done) |
| 1333 | return -ENODEV; | 1333 | return -ENODEV; |
| 1334 | 1334 | ||
| 1335 | /* Fall back to the default idle loop */ | 1335 | /* |
| 1336 | pm_idle = pm_idle_save; | 1336 | * Fall back to the default idle loop, when pm_idle_save had |
| 1337 | synchronize_sched(); /* Relies on interrupts forcing exit from idle. */ | 1337 | * been initialized. |
| 1338 | */ | ||
| 1339 | if (pm_idle_save) { | ||
| 1340 | pm_idle = pm_idle_save; | ||
| 1341 | /* Relies on interrupts forcing exit from idle. */ | ||
| 1342 | synchronize_sched(); | ||
| 1343 | } | ||
| 1338 | 1344 | ||
| 1339 | pr->flags.power = 0; | 1345 | pr->flags.power = 0; |
| 1340 | result = acpi_processor_get_power_info(pr); | 1346 | result = acpi_processor_get_power_info(pr); |
| @@ -1896,7 +1902,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
| 1896 | 1902 | ||
| 1897 | /* Unregister the idle handler when processor #0 is removed. */ | 1903 | /* Unregister the idle handler when processor #0 is removed. */ |
| 1898 | if (pr->id == 0) { | 1904 | if (pr->id == 0) { |
| 1899 | pm_idle = pm_idle_save; | 1905 | if (pm_idle_save) |
| 1906 | pm_idle = pm_idle_save; | ||
| 1900 | 1907 | ||
| 1901 | /* | 1908 | /* |
| 1902 | * We are about to unload the current idle thread pm callback | 1909 | * We are about to unload the current idle thread pm callback |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 3ad49a00029f..af0d175c025d 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
| @@ -103,7 +103,8 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, | |||
| 103 | /* | 103 | /* |
| 104 | * Show whether the section of memory is likely to be hot-removable | 104 | * Show whether the section of memory is likely to be hot-removable |
| 105 | */ | 105 | */ |
| 106 | static ssize_t show_mem_removable(struct sys_device *dev, char *buf) | 106 | static ssize_t show_mem_removable(struct sys_device *dev, |
| 107 | struct sysdev_attribute *attr, char *buf) | ||
| 107 | { | 108 | { |
| 108 | unsigned long start_pfn; | 109 | unsigned long start_pfn; |
| 109 | int ret; | 110 | int ret; |
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 929101ecbae2..7d500f82195a 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c | |||
| @@ -30,11 +30,11 @@ | |||
| 30 | static void ipw_send_setup_packet(struct ipw_hardware *hw); | 30 | static void ipw_send_setup_packet(struct ipw_hardware *hw); |
| 31 | static void handle_received_SETUP_packet(struct ipw_hardware *ipw, | 31 | static void handle_received_SETUP_packet(struct ipw_hardware *ipw, |
| 32 | unsigned int address, | 32 | unsigned int address, |
| 33 | unsigned char *data, int len, | 33 | const unsigned char *data, int len, |
| 34 | int is_last); | 34 | int is_last); |
| 35 | static void ipwireless_setup_timer(unsigned long data); | 35 | static void ipwireless_setup_timer(unsigned long data); |
| 36 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, | 36 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, |
| 37 | unsigned int channel_idx, unsigned char *data, int len); | 37 | unsigned int channel_idx, const unsigned char *data, int len); |
| 38 | 38 | ||
| 39 | /*#define TIMING_DIAGNOSTICS*/ | 39 | /*#define TIMING_DIAGNOSTICS*/ |
| 40 | 40 | ||
| @@ -79,8 +79,7 @@ static void report_timing(void) | |||
| 79 | timing_stats.last_report_time = jiffies; | 79 | timing_stats.last_report_time = jiffies; |
| 80 | if (!first) | 80 | if (!first) |
| 81 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 81 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
| 82 | ": %u us elapsed - read %lu bytes in %u us, " | 82 | ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n", |
| 83 | "wrote %lu bytes in %u us\n", | ||
| 84 | jiffies_to_usecs(since), | 83 | jiffies_to_usecs(since), |
| 85 | timing_stats.read_bytes, | 84 | timing_stats.read_bytes, |
| 86 | jiffies_to_usecs(timing_stats.read_time), | 85 | jiffies_to_usecs(timing_stats.read_time), |
| @@ -133,29 +132,17 @@ enum { | |||
| 133 | #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 | 132 | #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 |
| 134 | 133 | ||
| 135 | struct nl_first_packet_header { | 134 | struct nl_first_packet_header { |
| 136 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
| 137 | unsigned char packet_rank:2; | ||
| 138 | unsigned char address:3; | ||
| 139 | unsigned char protocol:3; | ||
| 140 | #else | ||
| 141 | unsigned char protocol:3; | 135 | unsigned char protocol:3; |
| 142 | unsigned char address:3; | 136 | unsigned char address:3; |
| 143 | unsigned char packet_rank:2; | 137 | unsigned char packet_rank:2; |
| 144 | #endif | ||
| 145 | unsigned char length_lsb; | 138 | unsigned char length_lsb; |
| 146 | unsigned char length_msb; | 139 | unsigned char length_msb; |
| 147 | }; | 140 | }; |
| 148 | 141 | ||
| 149 | struct nl_packet_header { | 142 | struct nl_packet_header { |
| 150 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
| 151 | unsigned char packet_rank:2; | ||
| 152 | unsigned char address:3; | ||
| 153 | unsigned char protocol:3; | ||
| 154 | #else | ||
| 155 | unsigned char protocol:3; | 143 | unsigned char protocol:3; |
| 156 | unsigned char address:3; | 144 | unsigned char address:3; |
| 157 | unsigned char packet_rank:2; | 145 | unsigned char packet_rank:2; |
| 158 | #endif | ||
| 159 | }; | 146 | }; |
| 160 | 147 | ||
| 161 | /* Value of 'packet_rank' above */ | 148 | /* Value of 'packet_rank' above */ |
| @@ -227,15 +214,12 @@ struct MEMINFREG { | |||
| 227 | unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ | 214 | unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ |
| 228 | }; | 215 | }; |
| 229 | 216 | ||
| 230 | #define IODMADPR 0x00 /* DMA Data Port Register (R/W) */ | ||
| 231 | |||
| 232 | #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) | 217 | #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) |
| 233 | 218 | ||
| 234 | #define MEMTX_TX 0x0001 | 219 | #define MEMTX_TX 0x0001 |
| 235 | #define MEMRX_RX 0x0001 | 220 | #define MEMRX_RX 0x0001 |
| 236 | #define MEMRX_RX_DONE 0x0001 | 221 | #define MEMRX_RX_DONE 0x0001 |
| 237 | #define MEMRX_PCINTACKK 0x0001 | 222 | #define MEMRX_PCINTACKK 0x0001 |
| 238 | #define MEMRX_MEMSPURIOUSINT 0x0001 | ||
| 239 | 223 | ||
| 240 | #define NL_NUM_OF_PRIORITIES 3 | 224 | #define NL_NUM_OF_PRIORITIES 3 |
| 241 | #define NL_NUM_OF_PROTOCOLS 3 | 225 | #define NL_NUM_OF_PROTOCOLS 3 |
| @@ -245,7 +229,7 @@ struct ipw_hardware { | |||
| 245 | unsigned int base_port; | 229 | unsigned int base_port; |
| 246 | short hw_version; | 230 | short hw_version; |
| 247 | unsigned short ll_mtu; | 231 | unsigned short ll_mtu; |
| 248 | spinlock_t spinlock; | 232 | spinlock_t lock; |
| 249 | 233 | ||
| 250 | int initializing; | 234 | int initializing; |
| 251 | int init_loops; | 235 | int init_loops; |
| @@ -386,26 +370,52 @@ static void dump_data_bytes(const char *type, const unsigned char *data, | |||
| 386 | length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); | 370 | length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); |
| 387 | } | 371 | } |
| 388 | 372 | ||
| 389 | static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | 373 | static void swap_packet_bitfield_to_le(unsigned char *data) |
| 374 | { | ||
| 375 | #ifdef __BIG_ENDIAN_BITFIELD | ||
| 376 | unsigned char tmp = *data, ret = 0; | ||
| 377 | |||
| 378 | /* | ||
| 379 | * transform bits from aa.bbb.ccc to ccc.bbb.aa | ||
| 380 | */ | ||
| 381 | ret |= tmp & 0xc0 >> 6; | ||
| 382 | ret |= tmp & 0x38 >> 1; | ||
| 383 | ret |= tmp & 0x07 << 5; | ||
| 384 | *data = ret & 0xff; | ||
| 385 | #endif | ||
| 386 | } | ||
| 387 | |||
| 388 | static void swap_packet_bitfield_from_le(unsigned char *data) | ||
| 389 | { | ||
| 390 | #ifdef __BIG_ENDIAN_BITFIELD | ||
| 391 | unsigned char tmp = *data, ret = 0; | ||
| 392 | |||
| 393 | /* | ||
| 394 | * transform bits from ccc.bbb.aa to aa.bbb.ccc | ||
| 395 | */ | ||
| 396 | ret |= tmp & 0xe0 >> 5; | ||
| 397 | ret |= tmp & 0x1c << 1; | ||
| 398 | ret |= tmp & 0x03 << 6; | ||
| 399 | *data = ret & 0xff; | ||
| 400 | #endif | ||
| 401 | } | ||
| 402 | |||
| 403 | static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data, | ||
| 390 | unsigned length) | 404 | unsigned length) |
| 391 | { | 405 | { |
| 392 | int i; | 406 | unsigned i; |
| 393 | unsigned long flags; | 407 | unsigned long flags; |
| 394 | 408 | ||
| 395 | start_timing(); | 409 | start_timing(); |
| 396 | 410 | BUG_ON(length > hw->ll_mtu); | |
| 397 | if (length == 0) | ||
| 398 | return 0; | ||
| 399 | |||
| 400 | if (length > hw->ll_mtu) | ||
| 401 | return -1; | ||
| 402 | 411 | ||
| 403 | if (ipwireless_debug) | 412 | if (ipwireless_debug) |
| 404 | dump_data_bytes("send", data, length); | 413 | dump_data_bytes("send", data, length); |
| 405 | 414 | ||
| 406 | spin_lock_irqsave(&hw->spinlock, flags); | 415 | spin_lock_irqsave(&hw->lock, flags); |
| 407 | 416 | ||
| 408 | hw->tx_ready = 0; | 417 | hw->tx_ready = 0; |
| 418 | swap_packet_bitfield_to_le(data); | ||
| 409 | 419 | ||
| 410 | if (hw->hw_version == HW_VERSION_1) { | 420 | if (hw->hw_version == HW_VERSION_1) { |
| 411 | outw((unsigned short) length, hw->base_port + IODWR); | 421 | outw((unsigned short) length, hw->base_port + IODWR); |
| @@ -414,7 +424,7 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | |||
| 414 | unsigned short d = data[i]; | 424 | unsigned short d = data[i]; |
| 415 | __le16 raw_data; | 425 | __le16 raw_data; |
| 416 | 426 | ||
| 417 | if (likely(i + 1 < length)) | 427 | if (i + 1 < length) |
| 418 | d |= data[i + 1] << 8; | 428 | d |= data[i + 1] << 8; |
| 419 | raw_data = cpu_to_le16(d); | 429 | raw_data = cpu_to_le16(d); |
| 420 | outw(raw_data, hw->base_port + IODWR); | 430 | outw(raw_data, hw->base_port + IODWR); |
| @@ -422,32 +432,30 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | |||
| 422 | 432 | ||
| 423 | outw(DCR_TXDONE, hw->base_port + IODCR); | 433 | outw(DCR_TXDONE, hw->base_port + IODCR); |
| 424 | } else if (hw->hw_version == HW_VERSION_2) { | 434 | } else if (hw->hw_version == HW_VERSION_2) { |
| 425 | outw((unsigned short) length, hw->base_port + IODMADPR); | 435 | outw((unsigned short) length, hw->base_port); |
| 426 | 436 | ||
| 427 | for (i = 0; i < length; i += 2) { | 437 | for (i = 0; i < length; i += 2) { |
| 428 | unsigned short d = data[i]; | 438 | unsigned short d = data[i]; |
| 429 | __le16 raw_data; | 439 | __le16 raw_data; |
| 430 | 440 | ||
| 431 | if ((i + 1 < length)) | 441 | if (i + 1 < length) |
| 432 | d |= data[i + 1] << 8; | 442 | d |= data[i + 1] << 8; |
| 433 | raw_data = cpu_to_le16(d); | 443 | raw_data = cpu_to_le16(d); |
| 434 | outw(raw_data, hw->base_port + IODMADPR); | 444 | outw(raw_data, hw->base_port); |
| 435 | } | 445 | } |
| 436 | while ((i & 3) != 2) { | 446 | while ((i & 3) != 2) { |
| 437 | outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR); | 447 | outw((unsigned short) 0xDEAD, hw->base_port); |
| 438 | i += 2; | 448 | i += 2; |
| 439 | } | 449 | } |
| 440 | writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); | 450 | writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); |
| 441 | } | 451 | } |
| 442 | 452 | ||
| 443 | spin_unlock_irqrestore(&hw->spinlock, flags); | 453 | spin_unlock_irqrestore(&hw->lock, flags); |
| 444 | 454 | ||
| 445 | end_write_timing(length); | 455 | end_write_timing(length); |
| 446 | |||
| 447 | return 0; | ||
| 448 | } | 456 | } |
| 449 | 457 | ||
| 450 | static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | 458 | static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) |
| 451 | { | 459 | { |
| 452 | unsigned short fragment_data_len; | 460 | unsigned short fragment_data_len; |
| 453 | unsigned short data_left = packet->length - packet->offset; | 461 | unsigned short data_left = packet->length - packet->offset; |
| @@ -462,6 +470,10 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | |||
| 462 | if (data_left < fragment_data_len) | 470 | if (data_left < fragment_data_len) |
| 463 | fragment_data_len = data_left; | 471 | fragment_data_len = data_left; |
| 464 | 472 | ||
| 473 | /* | ||
| 474 | * hdr_first is now in machine bitfield order, which will be swapped | ||
| 475 | * to le just before it goes to hw | ||
| 476 | */ | ||
| 465 | pkt.hdr_first.protocol = packet->protocol; | 477 | pkt.hdr_first.protocol = packet->protocol; |
| 466 | pkt.hdr_first.address = packet->dest_addr; | 478 | pkt.hdr_first.address = packet->dest_addr; |
| 467 | pkt.hdr_first.packet_rank = 0; | 479 | pkt.hdr_first.packet_rank = 0; |
| @@ -493,25 +505,23 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | |||
| 493 | */ | 505 | */ |
| 494 | unsigned long flags; | 506 | unsigned long flags; |
| 495 | 507 | ||
| 496 | spin_lock_irqsave(&hw->spinlock, flags); | 508 | spin_lock_irqsave(&hw->lock, flags); |
| 497 | list_add(&packet->queue, &hw->tx_queue[0]); | 509 | list_add(&packet->queue, &hw->tx_queue[0]); |
| 498 | hw->tx_queued++; | 510 | hw->tx_queued++; |
| 499 | spin_unlock_irqrestore(&hw->spinlock, flags); | 511 | spin_unlock_irqrestore(&hw->lock, flags); |
| 500 | } else { | 512 | } else { |
| 501 | if (packet->packet_callback) | 513 | if (packet->packet_callback) |
| 502 | packet->packet_callback(packet->callback_data, | 514 | packet->packet_callback(packet->callback_data, |
| 503 | packet->length); | 515 | packet->length); |
| 504 | kfree(packet); | 516 | kfree(packet); |
| 505 | } | 517 | } |
| 506 | |||
| 507 | return 0; | ||
| 508 | } | 518 | } |
| 509 | 519 | ||
| 510 | static void ipw_setup_hardware(struct ipw_hardware *hw) | 520 | static void ipw_setup_hardware(struct ipw_hardware *hw) |
| 511 | { | 521 | { |
| 512 | unsigned long flags; | 522 | unsigned long flags; |
| 513 | 523 | ||
| 514 | spin_lock_irqsave(&hw->spinlock, flags); | 524 | spin_lock_irqsave(&hw->lock, flags); |
| 515 | if (hw->hw_version == HW_VERSION_1) { | 525 | if (hw->hw_version == HW_VERSION_1) { |
| 516 | /* Reset RX FIFO */ | 526 | /* Reset RX FIFO */ |
| 517 | outw(DCR_RXRESET, hw->base_port + IODCR); | 527 | outw(DCR_RXRESET, hw->base_port + IODCR); |
| @@ -530,7 +540,7 @@ static void ipw_setup_hardware(struct ipw_hardware *hw) | |||
| 530 | csr |= 1; | 540 | csr |= 1; |
| 531 | writew(csr, &hw->memregs_CCR->reg_config_and_status); | 541 | writew(csr, &hw->memregs_CCR->reg_config_and_status); |
| 532 | } | 542 | } |
| 533 | spin_unlock_irqrestore(&hw->spinlock, flags); | 543 | spin_unlock_irqrestore(&hw->lock, flags); |
| 534 | } | 544 | } |
| 535 | 545 | ||
| 536 | /* | 546 | /* |
| @@ -549,28 +559,23 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, | |||
| 549 | if (!packet) { | 559 | if (!packet) { |
| 550 | unsigned long flags; | 560 | unsigned long flags; |
| 551 | 561 | ||
| 552 | /* | 562 | spin_lock_irqsave(&hw->lock, flags); |
| 553 | * If this is the first fragment, then we will need to fetch a | ||
| 554 | * packet to put it in. | ||
| 555 | */ | ||
| 556 | spin_lock_irqsave(&hw->spinlock, flags); | ||
| 557 | /* If we have one in our pool, then pull it out. */ | ||
| 558 | if (!list_empty(&hw->rx_pool)) { | 563 | if (!list_empty(&hw->rx_pool)) { |
| 559 | packet = list_first_entry(&hw->rx_pool, | 564 | packet = list_first_entry(&hw->rx_pool, |
| 560 | struct ipw_rx_packet, queue); | 565 | struct ipw_rx_packet, queue); |
| 561 | list_del(&packet->queue); | ||
| 562 | hw->rx_pool_size--; | 566 | hw->rx_pool_size--; |
| 563 | spin_unlock_irqrestore(&hw->spinlock, flags); | 567 | spin_unlock_irqrestore(&hw->lock, flags); |
| 568 | list_del(&packet->queue); | ||
| 564 | } else { | 569 | } else { |
| 565 | /* Otherwise allocate a new one. */ | 570 | const int min_capacity = |
| 566 | static int min_capacity = 256; | 571 | ipwireless_ppp_mru(hw->network + 2); |
| 567 | int new_capacity; | 572 | int new_capacity; |
| 568 | 573 | ||
| 569 | spin_unlock_irqrestore(&hw->spinlock, flags); | 574 | spin_unlock_irqrestore(&hw->lock, flags); |
| 570 | new_capacity = | 575 | new_capacity = |
| 571 | minimum_free_space > min_capacity | 576 | (minimum_free_space > min_capacity |
| 572 | ? minimum_free_space | 577 | ? minimum_free_space |
| 573 | : min_capacity; | 578 | : min_capacity); |
| 574 | packet = kmalloc(sizeof(struct ipw_rx_packet) | 579 | packet = kmalloc(sizeof(struct ipw_rx_packet) |
| 575 | + new_capacity, GFP_ATOMIC); | 580 | + new_capacity, GFP_ATOMIC); |
| 576 | if (!packet) | 581 | if (!packet) |
| @@ -580,10 +585,6 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, | |||
| 580 | packet->length = 0; | 585 | packet->length = 0; |
| 581 | } | 586 | } |
| 582 | 587 | ||
| 583 | /* | ||
| 584 | * If this packet does not have sufficient capacity for the data we | ||
| 585 | * want to add, then make it bigger. | ||
| 586 | */ | ||
| 587 | if (packet->length + minimum_free_space > packet->capacity) { | 588 | if (packet->length + minimum_free_space > packet->capacity) { |
| 588 | struct ipw_rx_packet *old_packet = packet; | 589 | struct ipw_rx_packet *old_packet = packet; |
| 589 | 590 | ||
| @@ -610,13 +611,15 @@ static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) | |||
| 610 | kfree(packet); | 611 | kfree(packet); |
| 611 | else { | 612 | else { |
| 612 | hw->rx_pool_size++; | 613 | hw->rx_pool_size++; |
| 613 | list_add_tail(&packet->queue, &hw->rx_pool); | 614 | list_add(&packet->queue, &hw->rx_pool); |
| 614 | } | 615 | } |
| 615 | } | 616 | } |
| 616 | 617 | ||
| 617 | static void queue_received_packet(struct ipw_hardware *hw, | 618 | static void queue_received_packet(struct ipw_hardware *hw, |
| 618 | unsigned int protocol, unsigned int address, | 619 | unsigned int protocol, |
| 619 | unsigned char *data, int length, int is_last) | 620 | unsigned int address, |
| 621 | const unsigned char *data, int length, | ||
| 622 | int is_last) | ||
| 620 | { | 623 | { |
| 621 | unsigned int channel_idx = address - 1; | 624 | unsigned int channel_idx = address - 1; |
| 622 | struct ipw_rx_packet *packet = NULL; | 625 | struct ipw_rx_packet *packet = NULL; |
| @@ -658,9 +661,9 @@ static void queue_received_packet(struct ipw_hardware *hw, | |||
| 658 | packet = *assem; | 661 | packet = *assem; |
| 659 | *assem = NULL; | 662 | *assem = NULL; |
| 660 | /* Count queued DATA bytes only */ | 663 | /* Count queued DATA bytes only */ |
| 661 | spin_lock_irqsave(&hw->spinlock, flags); | 664 | spin_lock_irqsave(&hw->lock, flags); |
| 662 | hw->rx_bytes_queued += packet->length; | 665 | hw->rx_bytes_queued += packet->length; |
| 663 | spin_unlock_irqrestore(&hw->spinlock, flags); | 666 | spin_unlock_irqrestore(&hw->lock, flags); |
| 664 | } | 667 | } |
| 665 | } else { | 668 | } else { |
| 666 | /* If it's a CTRL packet, don't assemble, just queue it. */ | 669 | /* If it's a CTRL packet, don't assemble, just queue it. */ |
| @@ -682,13 +685,13 @@ static void queue_received_packet(struct ipw_hardware *hw, | |||
| 682 | * network layer. | 685 | * network layer. |
| 683 | */ | 686 | */ |
| 684 | if (packet) { | 687 | if (packet) { |
| 685 | spin_lock_irqsave(&hw->spinlock, flags); | 688 | spin_lock_irqsave(&hw->lock, flags); |
| 686 | list_add_tail(&packet->queue, &hw->rx_queue); | 689 | list_add_tail(&packet->queue, &hw->rx_queue); |
| 687 | /* Block reception of incoming packets if queue is full. */ | 690 | /* Block reception of incoming packets if queue is full. */ |
| 688 | hw->blocking_rx = | 691 | hw->blocking_rx = |
| 689 | hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; | 692 | (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE); |
| 690 | 693 | ||
| 691 | spin_unlock_irqrestore(&hw->spinlock, flags); | 694 | spin_unlock_irqrestore(&hw->lock, flags); |
| 692 | schedule_work(&hw->work_rx); | 695 | schedule_work(&hw->work_rx); |
| 693 | } | 696 | } |
| 694 | } | 697 | } |
| @@ -702,7 +705,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
| 702 | container_of(work_rx, struct ipw_hardware, work_rx); | 705 | container_of(work_rx, struct ipw_hardware, work_rx); |
| 703 | unsigned long flags; | 706 | unsigned long flags; |
| 704 | 707 | ||
| 705 | spin_lock_irqsave(&hw->spinlock, flags); | 708 | spin_lock_irqsave(&hw->lock, flags); |
| 706 | while (!list_empty(&hw->rx_queue)) { | 709 | while (!list_empty(&hw->rx_queue)) { |
| 707 | struct ipw_rx_packet *packet = | 710 | struct ipw_rx_packet *packet = |
| 708 | list_first_entry(&hw->rx_queue, | 711 | list_first_entry(&hw->rx_queue, |
| @@ -720,7 +723,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
| 720 | if (packet->protocol == TL_PROTOCOLID_COM_DATA) { | 723 | if (packet->protocol == TL_PROTOCOLID_COM_DATA) { |
| 721 | if (hw->network != NULL) { | 724 | if (hw->network != NULL) { |
| 722 | /* If the network hasn't been disconnected. */ | 725 | /* If the network hasn't been disconnected. */ |
| 723 | spin_unlock_irqrestore(&hw->spinlock, flags); | 726 | spin_unlock_irqrestore(&hw->lock, flags); |
| 724 | /* | 727 | /* |
| 725 | * This must run unlocked due to tty processing | 728 | * This must run unlocked due to tty processing |
| 726 | * and mutex locking | 729 | * and mutex locking |
| @@ -731,7 +734,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
| 731 | (unsigned char *)packet | 734 | (unsigned char *)packet |
| 732 | + sizeof(struct ipw_rx_packet), | 735 | + sizeof(struct ipw_rx_packet), |
| 733 | packet->length); | 736 | packet->length); |
| 734 | spin_lock_irqsave(&hw->spinlock, flags); | 737 | spin_lock_irqsave(&hw->lock, flags); |
| 735 | } | 738 | } |
| 736 | /* Count queued DATA bytes only */ | 739 | /* Count queued DATA bytes only */ |
| 737 | hw->rx_bytes_queued -= packet->length; | 740 | hw->rx_bytes_queued -= packet->length; |
| @@ -755,15 +758,15 @@ static void ipw_receive_data_work(struct work_struct *work_rx) | |||
| 755 | if (hw->shutting_down) | 758 | if (hw->shutting_down) |
| 756 | break; | 759 | break; |
| 757 | } | 760 | } |
| 758 | spin_unlock_irqrestore(&hw->spinlock, flags); | 761 | spin_unlock_irqrestore(&hw->lock, flags); |
| 759 | } | 762 | } |
| 760 | 763 | ||
| 761 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, | 764 | static void handle_received_CTRL_packet(struct ipw_hardware *hw, |
| 762 | unsigned int channel_idx, | 765 | unsigned int channel_idx, |
| 763 | unsigned char *data, int len) | 766 | const unsigned char *data, int len) |
| 764 | { | 767 | { |
| 765 | struct ipw_control_packet_body *body = | 768 | const struct ipw_control_packet_body *body = |
| 766 | (struct ipw_control_packet_body *) data; | 769 | (const struct ipw_control_packet_body *) data; |
| 767 | unsigned int changed_mask; | 770 | unsigned int changed_mask; |
| 768 | 771 | ||
| 769 | if (len != sizeof(struct ipw_control_packet_body)) { | 772 | if (len != sizeof(struct ipw_control_packet_body)) { |
| @@ -805,13 +808,13 @@ static void handle_received_CTRL_packet(struct ipw_hardware *hw, | |||
| 805 | } | 808 | } |
| 806 | 809 | ||
| 807 | static void handle_received_packet(struct ipw_hardware *hw, | 810 | static void handle_received_packet(struct ipw_hardware *hw, |
| 808 | union nl_packet *packet, | 811 | const union nl_packet *packet, |
| 809 | unsigned short len) | 812 | unsigned short len) |
| 810 | { | 813 | { |
| 811 | unsigned int protocol = packet->hdr.protocol; | 814 | unsigned int protocol = packet->hdr.protocol; |
| 812 | unsigned int address = packet->hdr.address; | 815 | unsigned int address = packet->hdr.address; |
| 813 | unsigned int header_length; | 816 | unsigned int header_length; |
| 814 | unsigned char *data; | 817 | const unsigned char *data; |
| 815 | unsigned int data_len; | 818 | unsigned int data_len; |
| 816 | int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; | 819 | int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; |
| 817 | 820 | ||
| @@ -850,7 +853,7 @@ static void acknowledge_data_read(struct ipw_hardware *hw) | |||
| 850 | static void do_receive_packet(struct ipw_hardware *hw) | 853 | static void do_receive_packet(struct ipw_hardware *hw) |
| 851 | { | 854 | { |
| 852 | unsigned len; | 855 | unsigned len; |
| 853 | unsigned int i; | 856 | unsigned i; |
| 854 | unsigned char pkt[LL_MTU_MAX]; | 857 | unsigned char pkt[LL_MTU_MAX]; |
| 855 | 858 | ||
| 856 | start_timing(); | 859 | start_timing(); |
| @@ -859,8 +862,7 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
| 859 | len = inw(hw->base_port + IODRR); | 862 | len = inw(hw->base_port + IODRR); |
| 860 | if (len > hw->ll_mtu) { | 863 | if (len > hw->ll_mtu) { |
| 861 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 864 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
| 862 | ": received a packet of %u bytes - " | 865 | ": received a packet of %u bytes - longer than the MTU!\n", len); |
| 863 | "longer than the MTU!\n", len); | ||
| 864 | outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); | 866 | outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); |
| 865 | return; | 867 | return; |
| 866 | } | 868 | } |
| @@ -873,18 +875,17 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
| 873 | pkt[i + 1] = (unsigned char) (data >> 8); | 875 | pkt[i + 1] = (unsigned char) (data >> 8); |
| 874 | } | 876 | } |
| 875 | } else { | 877 | } else { |
| 876 | len = inw(hw->base_port + IODMADPR); | 878 | len = inw(hw->base_port); |
| 877 | if (len > hw->ll_mtu) { | 879 | if (len > hw->ll_mtu) { |
| 878 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 880 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
| 879 | ": received a packet of %u bytes - " | 881 | ": received a packet of %u bytes - longer than the MTU!\n", len); |
| 880 | "longer than the MTU!\n", len); | ||
| 881 | writew(MEMRX_PCINTACKK, | 882 | writew(MEMRX_PCINTACKK, |
| 882 | &hw->memory_info_regs->memreg_pc_interrupt_ack); | 883 | &hw->memory_info_regs->memreg_pc_interrupt_ack); |
| 883 | return; | 884 | return; |
| 884 | } | 885 | } |
| 885 | 886 | ||
| 886 | for (i = 0; i < len; i += 2) { | 887 | for (i = 0; i < len; i += 2) { |
| 887 | __le16 raw_data = inw(hw->base_port + IODMADPR); | 888 | __le16 raw_data = inw(hw->base_port); |
| 888 | unsigned short data = le16_to_cpu(raw_data); | 889 | unsigned short data = le16_to_cpu(raw_data); |
| 889 | 890 | ||
| 890 | pkt[i] = (unsigned char) data; | 891 | pkt[i] = (unsigned char) data; |
| @@ -892,13 +893,15 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
| 892 | } | 893 | } |
| 893 | 894 | ||
| 894 | while ((i & 3) != 2) { | 895 | while ((i & 3) != 2) { |
| 895 | inw(hw->base_port + IODMADPR); | 896 | inw(hw->base_port); |
| 896 | i += 2; | 897 | i += 2; |
| 897 | } | 898 | } |
| 898 | } | 899 | } |
| 899 | 900 | ||
| 900 | acknowledge_data_read(hw); | 901 | acknowledge_data_read(hw); |
| 901 | 902 | ||
| 903 | swap_packet_bitfield_from_le(pkt); | ||
| 904 | |||
| 902 | if (ipwireless_debug) | 905 | if (ipwireless_debug) |
| 903 | dump_data_bytes("recv", pkt, len); | 906 | dump_data_bytes("recv", pkt, len); |
| 904 | 907 | ||
| @@ -916,8 +919,7 @@ static int get_current_packet_priority(struct ipw_hardware *hw) | |||
| 916 | * until setup is complete. | 919 | * until setup is complete. |
| 917 | */ | 920 | */ |
| 918 | return (hw->to_setup || hw->initializing | 921 | return (hw->to_setup || hw->initializing |
| 919 | ? PRIO_SETUP + 1 : | 922 | ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES); |
| 920 | NL_NUM_OF_PRIORITIES); | ||
| 921 | } | 923 | } |
| 922 | 924 | ||
| 923 | /* | 925 | /* |
| @@ -928,17 +930,17 @@ static int get_packets_from_hw(struct ipw_hardware *hw) | |||
| 928 | int received = 0; | 930 | int received = 0; |
| 929 | unsigned long flags; | 931 | unsigned long flags; |
| 930 | 932 | ||
| 931 | spin_lock_irqsave(&hw->spinlock, flags); | 933 | spin_lock_irqsave(&hw->lock, flags); |
| 932 | while (hw->rx_ready && !hw->blocking_rx) { | 934 | while (hw->rx_ready && !hw->blocking_rx) { |
| 933 | received = 1; | 935 | received = 1; |
| 934 | hw->rx_ready--; | 936 | hw->rx_ready--; |
| 935 | spin_unlock_irqrestore(&hw->spinlock, flags); | 937 | spin_unlock_irqrestore(&hw->lock, flags); |
| 936 | 938 | ||
| 937 | do_receive_packet(hw); | 939 | do_receive_packet(hw); |
| 938 | 940 | ||
| 939 | spin_lock_irqsave(&hw->spinlock, flags); | 941 | spin_lock_irqsave(&hw->lock, flags); |
| 940 | } | 942 | } |
| 941 | spin_unlock_irqrestore(&hw->spinlock, flags); | 943 | spin_unlock_irqrestore(&hw->lock, flags); |
| 942 | 944 | ||
| 943 | return received; | 945 | return received; |
| 944 | } | 946 | } |
| @@ -954,7 +956,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
| 954 | int more_to_send = 0; | 956 | int more_to_send = 0; |
| 955 | unsigned long flags; | 957 | unsigned long flags; |
| 956 | 958 | ||
| 957 | spin_lock_irqsave(&hw->spinlock, flags); | 959 | spin_lock_irqsave(&hw->lock, flags); |
| 958 | if (hw->tx_queued && hw->tx_ready) { | 960 | if (hw->tx_queued && hw->tx_ready) { |
| 959 | int priority; | 961 | int priority; |
| 960 | struct ipw_tx_packet *packet = NULL; | 962 | struct ipw_tx_packet *packet = NULL; |
| @@ -975,17 +977,17 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
| 975 | } | 977 | } |
| 976 | if (!packet) { | 978 | if (!packet) { |
| 977 | hw->tx_queued = 0; | 979 | hw->tx_queued = 0; |
| 978 | spin_unlock_irqrestore(&hw->spinlock, flags); | 980 | spin_unlock_irqrestore(&hw->lock, flags); |
| 979 | return 0; | 981 | return 0; |
| 980 | } | 982 | } |
| 981 | 983 | ||
| 982 | spin_unlock_irqrestore(&hw->spinlock, flags); | 984 | spin_unlock_irqrestore(&hw->lock, flags); |
| 983 | 985 | ||
| 984 | /* Send */ | 986 | /* Send */ |
| 985 | do_send_packet(hw, packet); | 987 | do_send_packet(hw, packet); |
| 986 | 988 | ||
| 987 | /* Check if more to send */ | 989 | /* Check if more to send */ |
| 988 | spin_lock_irqsave(&hw->spinlock, flags); | 990 | spin_lock_irqsave(&hw->lock, flags); |
| 989 | for (priority = 0; priority < priority_limit; priority++) | 991 | for (priority = 0; priority < priority_limit; priority++) |
| 990 | if (!list_empty(&hw->tx_queue[priority])) { | 992 | if (!list_empty(&hw->tx_queue[priority])) { |
| 991 | more_to_send = 1; | 993 | more_to_send = 1; |
| @@ -995,7 +997,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) | |||
| 995 | if (!more_to_send) | 997 | if (!more_to_send) |
| 996 | hw->tx_queued = 0; | 998 | hw->tx_queued = 0; |
| 997 | } | 999 | } |
| 998 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1000 | spin_unlock_irqrestore(&hw->lock, flags); |
| 999 | 1001 | ||
| 1000 | return more_to_send; | 1002 | return more_to_send; |
| 1001 | } | 1003 | } |
| @@ -1008,9 +1010,9 @@ static void ipwireless_do_tasklet(unsigned long hw_) | |||
| 1008 | struct ipw_hardware *hw = (struct ipw_hardware *) hw_; | 1010 | struct ipw_hardware *hw = (struct ipw_hardware *) hw_; |
| 1009 | unsigned long flags; | 1011 | unsigned long flags; |
| 1010 | 1012 | ||
| 1011 | spin_lock_irqsave(&hw->spinlock, flags); | 1013 | spin_lock_irqsave(&hw->lock, flags); |
| 1012 | if (hw->shutting_down) { | 1014 | if (hw->shutting_down) { |
| 1013 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1015 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1014 | return; | 1016 | return; |
| 1015 | } | 1017 | } |
| 1016 | 1018 | ||
| @@ -1019,7 +1021,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) | |||
| 1019 | * Initial setup data sent to hardware | 1021 | * Initial setup data sent to hardware |
| 1020 | */ | 1022 | */ |
| 1021 | hw->to_setup = 2; | 1023 | hw->to_setup = 2; |
| 1022 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1024 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1023 | 1025 | ||
| 1024 | ipw_setup_hardware(hw); | 1026 | ipw_setup_hardware(hw); |
| 1025 | ipw_send_setup_packet(hw); | 1027 | ipw_send_setup_packet(hw); |
| @@ -1030,7 +1032,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) | |||
| 1030 | int priority_limit = get_current_packet_priority(hw); | 1032 | int priority_limit = get_current_packet_priority(hw); |
| 1031 | int again; | 1033 | int again; |
| 1032 | 1034 | ||
| 1033 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1035 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1034 | 1036 | ||
| 1035 | do { | 1037 | do { |
| 1036 | again = send_pending_packet(hw, priority_limit); | 1038 | again = send_pending_packet(hw, priority_limit); |
| @@ -1068,16 +1070,16 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, | |||
| 1068 | /* Transmit complete. */ | 1070 | /* Transmit complete. */ |
| 1069 | if (irqn & IR_TXINTR) { | 1071 | if (irqn & IR_TXINTR) { |
| 1070 | ack |= IR_TXINTR; | 1072 | ack |= IR_TXINTR; |
| 1071 | spin_lock_irqsave(&hw->spinlock, flags); | 1073 | spin_lock_irqsave(&hw->lock, flags); |
| 1072 | hw->tx_ready = 1; | 1074 | hw->tx_ready = 1; |
| 1073 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1075 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1074 | } | 1076 | } |
| 1075 | /* Received data */ | 1077 | /* Received data */ |
| 1076 | if (irqn & IR_RXINTR) { | 1078 | if (irqn & IR_RXINTR) { |
| 1077 | ack |= IR_RXINTR; | 1079 | ack |= IR_RXINTR; |
| 1078 | spin_lock_irqsave(&hw->spinlock, flags); | 1080 | spin_lock_irqsave(&hw->lock, flags); |
| 1079 | hw->rx_ready++; | 1081 | hw->rx_ready++; |
| 1080 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1082 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1081 | } | 1083 | } |
| 1082 | if (ack != 0) { | 1084 | if (ack != 0) { |
| 1083 | outw(ack, hw->base_port + IOIR); | 1085 | outw(ack, hw->base_port + IOIR); |
| @@ -1128,9 +1130,8 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
| 1128 | } else { | 1130 | } else { |
| 1129 | return IRQ_NONE; | 1131 | return IRQ_NONE; |
| 1130 | } | 1132 | } |
| 1131 | } else { | 1133 | } else |
| 1132 | return IRQ_NONE; | 1134 | return IRQ_NONE; |
| 1133 | } | ||
| 1134 | } | 1135 | } |
| 1135 | 1136 | ||
| 1136 | /* | 1137 | /* |
| @@ -1149,9 +1150,9 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
| 1149 | if (hw->serial_number_detected) { | 1150 | if (hw->serial_number_detected) { |
| 1150 | if (memtx_serial != hw->last_memtx_serial) { | 1151 | if (memtx_serial != hw->last_memtx_serial) { |
| 1151 | hw->last_memtx_serial = memtx_serial; | 1152 | hw->last_memtx_serial = memtx_serial; |
| 1152 | spin_lock_irqsave(&hw->spinlock, flags); | 1153 | spin_lock_irqsave(&hw->lock, flags); |
| 1153 | hw->rx_ready++; | 1154 | hw->rx_ready++; |
| 1154 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1155 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1155 | rx = 1; | 1156 | rx = 1; |
| 1156 | } else | 1157 | } else |
| 1157 | /* Ignore 'Timer Recovery' duplicates. */ | 1158 | /* Ignore 'Timer Recovery' duplicates. */ |
| @@ -1166,18 +1167,18 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
| 1166 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME | 1167 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME |
| 1167 | ": memreg_tx serial num detected\n"); | 1168 | ": memreg_tx serial num detected\n"); |
| 1168 | 1169 | ||
| 1169 | spin_lock_irqsave(&hw->spinlock, flags); | 1170 | spin_lock_irqsave(&hw->lock, flags); |
| 1170 | hw->rx_ready++; | 1171 | hw->rx_ready++; |
| 1171 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1172 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1172 | } | 1173 | } |
| 1173 | rx = 1; | 1174 | rx = 1; |
| 1174 | } | 1175 | } |
| 1175 | } | 1176 | } |
| 1176 | if (memrxdone & MEMRX_RX_DONE) { | 1177 | if (memrxdone & MEMRX_RX_DONE) { |
| 1177 | writew(0, &hw->memory_info_regs->memreg_rx_done); | 1178 | writew(0, &hw->memory_info_regs->memreg_rx_done); |
| 1178 | spin_lock_irqsave(&hw->spinlock, flags); | 1179 | spin_lock_irqsave(&hw->lock, flags); |
| 1179 | hw->tx_ready = 1; | 1180 | hw->tx_ready = 1; |
| 1180 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1181 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1181 | tx = 1; | 1182 | tx = 1; |
| 1182 | } | 1183 | } |
| 1183 | if (tx) | 1184 | if (tx) |
| @@ -1195,8 +1196,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
| 1195 | ": spurious interrupt - new_tx mode\n"); | 1196 | ": spurious interrupt - new_tx mode\n"); |
| 1196 | else { | 1197 | else { |
| 1197 | printk(KERN_WARNING IPWIRELESS_PCCARD_NAME | 1198 | printk(KERN_WARNING IPWIRELESS_PCCARD_NAME |
| 1198 | ": no valid memreg_tx value - " | 1199 | ": no valid memreg_tx value - switching to the old memreg_tx\n"); |
| 1199 | "switching to the old memreg_tx\n"); | ||
| 1200 | hw->memreg_tx = | 1200 | hw->memreg_tx = |
| 1201 | &hw->memory_info_regs->memreg_tx_old; | 1201 | &hw->memory_info_regs->memreg_tx_old; |
| 1202 | try_mem_tx_old = 1; | 1202 | try_mem_tx_old = 1; |
| @@ -1211,7 +1211,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, | |||
| 1211 | return IRQ_HANDLED; | 1211 | return IRQ_HANDLED; |
| 1212 | } | 1212 | } |
| 1213 | 1213 | ||
| 1214 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 1214 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id) |
| 1215 | { | 1215 | { |
| 1216 | struct ipw_hardware *hw = dev_id; | 1216 | struct ipw_hardware *hw = dev_id; |
| 1217 | 1217 | ||
| @@ -1226,9 +1226,9 @@ static void flush_packets_to_hw(struct ipw_hardware *hw) | |||
| 1226 | int priority_limit; | 1226 | int priority_limit; |
| 1227 | unsigned long flags; | 1227 | unsigned long flags; |
| 1228 | 1228 | ||
| 1229 | spin_lock_irqsave(&hw->spinlock, flags); | 1229 | spin_lock_irqsave(&hw->lock, flags); |
| 1230 | priority_limit = get_current_packet_priority(hw); | 1230 | priority_limit = get_current_packet_priority(hw); |
| 1231 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1231 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1232 | 1232 | ||
| 1233 | while (send_pending_packet(hw, priority_limit)); | 1233 | while (send_pending_packet(hw, priority_limit)); |
| 1234 | } | 1234 | } |
| @@ -1238,10 +1238,10 @@ static void send_packet(struct ipw_hardware *hw, int priority, | |||
| 1238 | { | 1238 | { |
| 1239 | unsigned long flags; | 1239 | unsigned long flags; |
| 1240 | 1240 | ||
| 1241 | spin_lock_irqsave(&hw->spinlock, flags); | 1241 | spin_lock_irqsave(&hw->lock, flags); |
| 1242 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); | 1242 | list_add_tail(&packet->queue, &hw->tx_queue[priority]); |
| 1243 | hw->tx_queued++; | 1243 | hw->tx_queued++; |
| 1244 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1244 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1245 | 1245 | ||
| 1246 | flush_packets_to_hw(hw); | 1246 | flush_packets_to_hw(hw); |
| 1247 | } | 1247 | } |
| @@ -1291,21 +1291,20 @@ static void *alloc_ctrl_packet(int header_size, | |||
| 1291 | } | 1291 | } |
| 1292 | 1292 | ||
| 1293 | int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, | 1293 | int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, |
| 1294 | unsigned char *data, unsigned int length, | 1294 | const unsigned char *data, unsigned int length, |
| 1295 | void (*callback) (void *cb, unsigned int length), | 1295 | void (*callback) (void *cb, unsigned int length), |
| 1296 | void *callback_data) | 1296 | void *callback_data) |
| 1297 | { | 1297 | { |
| 1298 | struct ipw_tx_packet *packet; | 1298 | struct ipw_tx_packet *packet; |
| 1299 | 1299 | ||
| 1300 | packet = alloc_data_packet(length, | 1300 | packet = alloc_data_packet(length, (channel_idx + 1), |
| 1301 | (unsigned char) (channel_idx + 1), | 1301 | TL_PROTOCOLID_COM_DATA); |
| 1302 | TL_PROTOCOLID_COM_DATA); | ||
| 1303 | if (!packet) | 1302 | if (!packet) |
| 1304 | return -ENOMEM; | 1303 | return -ENOMEM; |
| 1305 | packet->packet_callback = callback; | 1304 | packet->packet_callback = callback; |
| 1306 | packet->callback_data = callback_data; | 1305 | packet->callback_data = callback_data; |
| 1307 | memcpy((unsigned char *) packet + | 1306 | memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data, |
| 1308 | sizeof(struct ipw_tx_packet), data, length); | 1307 | length); |
| 1309 | 1308 | ||
| 1310 | send_packet(hw, PRIO_DATA, packet); | 1309 | send_packet(hw, PRIO_DATA, packet); |
| 1311 | return 0; | 1310 | return 0; |
| @@ -1321,12 +1320,11 @@ static int set_control_line(struct ipw_hardware *hw, int prio, | |||
| 1321 | protocolid = TL_PROTOCOLID_SETUP; | 1320 | protocolid = TL_PROTOCOLID_SETUP; |
| 1322 | 1321 | ||
| 1323 | packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), | 1322 | packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), |
| 1324 | (unsigned char) (channel_idx + 1), | 1323 | (channel_idx + 1), protocolid, line); |
| 1325 | protocolid, line); | ||
| 1326 | if (!packet) | 1324 | if (!packet) |
| 1327 | return -ENOMEM; | 1325 | return -ENOMEM; |
| 1328 | packet->header.length = sizeof(struct ipw_control_packet_body); | 1326 | packet->header.length = sizeof(struct ipw_control_packet_body); |
| 1329 | packet->body.value = (unsigned char) (state == 0 ? 0 : 1); | 1327 | packet->body.value = (state == 0 ? 0 : 1); |
| 1330 | send_packet(hw, prio, &packet->header); | 1328 | send_packet(hw, prio, &packet->header); |
| 1331 | return 0; | 1329 | return 0; |
| 1332 | } | 1330 | } |
| @@ -1504,8 +1502,7 @@ static void handle_setup_get_version_rsp(struct ipw_hardware *hw, | |||
| 1504 | if (vers_no == TL_SETUP_VERSION) | 1502 | if (vers_no == TL_SETUP_VERSION) |
| 1505 | __handle_setup_get_version_rsp(hw); | 1503 | __handle_setup_get_version_rsp(hw); |
| 1506 | else | 1504 | else |
| 1507 | printk(KERN_ERR | 1505 | printk(KERN_ERR IPWIRELESS_PCCARD_NAME |
| 1508 | IPWIRELESS_PCCARD_NAME | ||
| 1509 | ": invalid hardware version no %u\n", | 1506 | ": invalid hardware version no %u\n", |
| 1510 | (unsigned int) vers_no); | 1507 | (unsigned int) vers_no); |
| 1511 | } | 1508 | } |
| @@ -1528,10 +1525,10 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw) | |||
| 1528 | 1525 | ||
| 1529 | static void handle_received_SETUP_packet(struct ipw_hardware *hw, | 1526 | static void handle_received_SETUP_packet(struct ipw_hardware *hw, |
| 1530 | unsigned int address, | 1527 | unsigned int address, |
| 1531 | unsigned char *data, int len, | 1528 | const unsigned char *data, int len, |
| 1532 | int is_last) | 1529 | int is_last) |
| 1533 | { | 1530 | { |
| 1534 | union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data; | 1531 | const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data; |
| 1535 | 1532 | ||
| 1536 | if (address != ADDR_SETUP_PROT) { | 1533 | if (address != ADDR_SETUP_PROT) { |
| 1537 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 1534 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
| @@ -1629,7 +1626,7 @@ struct ipw_hardware *ipwireless_hardware_create(void) | |||
| 1629 | 1626 | ||
| 1630 | INIT_LIST_HEAD(&hw->rx_queue); | 1627 | INIT_LIST_HEAD(&hw->rx_queue); |
| 1631 | INIT_LIST_HEAD(&hw->rx_pool); | 1628 | INIT_LIST_HEAD(&hw->rx_pool); |
| 1632 | spin_lock_init(&hw->spinlock); | 1629 | spin_lock_init(&hw->lock); |
| 1633 | tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); | 1630 | tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); |
| 1634 | INIT_WORK(&hw->work_rx, ipw_receive_data_work); | 1631 | INIT_WORK(&hw->work_rx, ipw_receive_data_work); |
| 1635 | setup_timer(&hw->setup_timer, ipwireless_setup_timer, | 1632 | setup_timer(&hw->setup_timer, ipwireless_setup_timer, |
| @@ -1651,8 +1648,8 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw, | |||
| 1651 | enable_irq(hw->irq); | 1648 | enable_irq(hw->irq); |
| 1652 | } | 1649 | } |
| 1653 | hw->base_port = base_port; | 1650 | hw->base_port = base_port; |
| 1654 | hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1; | 1651 | hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1); |
| 1655 | hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2; | 1652 | hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2); |
| 1656 | hw->memregs_CCR = (struct MEMCCR __iomem *) | 1653 | hw->memregs_CCR = (struct MEMCCR __iomem *) |
| 1657 | ((unsigned short __iomem *) attr_memory + 0x200); | 1654 | ((unsigned short __iomem *) attr_memory + 0x200); |
| 1658 | hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; | 1655 | hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; |
| @@ -1695,10 +1692,10 @@ static void ipwireless_setup_timer(unsigned long data) | |||
| 1695 | if (is_card_present(hw)) { | 1692 | if (is_card_present(hw)) { |
| 1696 | unsigned long flags; | 1693 | unsigned long flags; |
| 1697 | 1694 | ||
| 1698 | spin_lock_irqsave(&hw->spinlock, flags); | 1695 | spin_lock_irqsave(&hw->lock, flags); |
| 1699 | hw->to_setup = 1; | 1696 | hw->to_setup = 1; |
| 1700 | hw->tx_ready = 1; | 1697 | hw->tx_ready = 1; |
| 1701 | spin_unlock_irqrestore(&hw->spinlock, flags); | 1698 | spin_unlock_irqrestore(&hw->lock, flags); |
| 1702 | tasklet_schedule(&hw->tasklet); | 1699 | tasklet_schedule(&hw->tasklet); |
| 1703 | } | 1700 | } |
| 1704 | 1701 | ||
diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h index 19ce5eb266b1..90a8590e43b0 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.h +++ b/drivers/char/pcmcia/ipwireless/hardware.h | |||
| @@ -34,14 +34,14 @@ struct ipw_network; | |||
| 34 | 34 | ||
| 35 | struct ipw_hardware *ipwireless_hardware_create(void); | 35 | struct ipw_hardware *ipwireless_hardware_create(void); |
| 36 | void ipwireless_hardware_free(struct ipw_hardware *hw); | 36 | void ipwireless_hardware_free(struct ipw_hardware *hw); |
| 37 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 37 | irqreturn_t ipwireless_interrupt(int irq, void *dev_id); |
| 38 | int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, | 38 | int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, |
| 39 | int state); | 39 | int state); |
| 40 | int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, | 40 | int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, |
| 41 | int state); | 41 | int state); |
| 42 | int ipwireless_send_packet(struct ipw_hardware *hw, | 42 | int ipwireless_send_packet(struct ipw_hardware *hw, |
| 43 | unsigned int channel_idx, | 43 | unsigned int channel_idx, |
| 44 | unsigned char *data, | 44 | const unsigned char *data, |
| 45 | unsigned int length, | 45 | unsigned int length, |
| 46 | void (*packet_sent_callback) (void *cb, | 46 | void (*packet_sent_callback) (void *cb, |
| 47 | unsigned int length), | 47 | unsigned int length), |
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index cc7dcea2d283..5eca7a99afe6 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c | |||
| @@ -49,7 +49,7 @@ static void ipwireless_detach(struct pcmcia_device *link); | |||
| 49 | /* Debug mode: more verbose, print sent/recv bytes */ | 49 | /* Debug mode: more verbose, print sent/recv bytes */ |
| 50 | int ipwireless_debug; | 50 | int ipwireless_debug; |
| 51 | int ipwireless_loopback; | 51 | int ipwireless_loopback; |
| 52 | int ipwireless_out_queue = 1; | 52 | int ipwireless_out_queue = 10; |
| 53 | 53 | ||
| 54 | module_param_named(debug, ipwireless_debug, int, 0); | 54 | module_param_named(debug, ipwireless_debug, int, 0); |
| 55 | module_param_named(loopback, ipwireless_loopback, int, 0); | 55 | module_param_named(loopback, ipwireless_loopback, int, 0); |
| @@ -57,7 +57,7 @@ module_param_named(out_queue, ipwireless_out_queue, int, 0); | |||
| 57 | MODULE_PARM_DESC(debug, "switch on debug messages [0]"); | 57 | MODULE_PARM_DESC(debug, "switch on debug messages [0]"); |
| 58 | MODULE_PARM_DESC(loopback, | 58 | MODULE_PARM_DESC(loopback, |
| 59 | "debug: enable ras_raw channel [0]"); | 59 | "debug: enable ras_raw channel [0]"); |
| 60 | MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]"); | 60 | MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); |
| 61 | 61 | ||
| 62 | /* Executes in process context. */ | 62 | /* Executes in process context. */ |
| 63 | static void signalled_reboot_work(struct work_struct *work_reboot) | 63 | static void signalled_reboot_work(struct work_struct *work_reboot) |
| @@ -88,8 +88,6 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
| 88 | unsigned short buf[64]; | 88 | unsigned short buf[64]; |
| 89 | cisparse_t parse; | 89 | cisparse_t parse; |
| 90 | unsigned short cor_value; | 90 | unsigned short cor_value; |
| 91 | win_req_t request_attr_memory; | ||
| 92 | win_req_t request_common_memory; | ||
| 93 | memreq_t memreq_attr_memory; | 91 | memreq_t memreq_attr_memory; |
| 94 | memreq_t memreq_common_memory; | 92 | memreq_t memreq_common_memory; |
| 95 | 93 | ||
| @@ -188,6 +186,9 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
| 188 | goto exit0; | 186 | goto exit0; |
| 189 | } | 187 | } |
| 190 | 188 | ||
| 189 | request_region(link->io.BasePort1, link->io.NumPorts1, | ||
| 190 | IPWIRELESS_PCCARD_NAME); | ||
| 191 | |||
| 191 | /* memory settings */ | 192 | /* memory settings */ |
| 192 | 193 | ||
| 193 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 194 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
| @@ -214,16 +215,16 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
| 214 | } | 215 | } |
| 215 | 216 | ||
| 216 | if (parse.cftable_entry.mem.nwin > 0) { | 217 | if (parse.cftable_entry.mem.nwin > 0) { |
| 217 | request_common_memory.Attributes = | 218 | ipw->request_common_memory.Attributes = |
| 218 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; | 219 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
| 219 | request_common_memory.Base = | 220 | ipw->request_common_memory.Base = |
| 220 | parse.cftable_entry.mem.win[0].host_addr; | 221 | parse.cftable_entry.mem.win[0].host_addr; |
| 221 | request_common_memory.Size = parse.cftable_entry.mem.win[0].len; | 222 | ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; |
| 222 | if (request_common_memory.Size < 0x1000) | 223 | if (ipw->request_common_memory.Size < 0x1000) |
| 223 | request_common_memory.Size = 0x1000; | 224 | ipw->request_common_memory.Size = 0x1000; |
| 224 | request_common_memory.AccessSpeed = 0; | 225 | ipw->request_common_memory.AccessSpeed = 0; |
| 225 | 226 | ||
| 226 | ret = pcmcia_request_window(&link, &request_common_memory, | 227 | ret = pcmcia_request_window(&link, &ipw->request_common_memory, |
| 227 | &ipw->handle_common_memory); | 228 | &ipw->handle_common_memory); |
| 228 | 229 | ||
| 229 | if (ret != CS_SUCCESS) { | 230 | if (ret != CS_SUCCESS) { |
| @@ -246,16 +247,18 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
| 246 | ipw->is_v2_card = | 247 | ipw->is_v2_card = |
| 247 | parse.cftable_entry.mem.win[0].len == 0x100; | 248 | parse.cftable_entry.mem.win[0].len == 0x100; |
| 248 | 249 | ||
| 249 | ipw->common_memory = ioremap(request_common_memory.Base, | 250 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, |
| 250 | request_common_memory.Size); | 251 | ipw->request_common_memory.Size); |
| 252 | request_mem_region(ipw->request_common_memory.Base, | ||
| 253 | ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); | ||
| 251 | 254 | ||
| 252 | request_attr_memory.Attributes = | 255 | ipw->request_attr_memory.Attributes = |
| 253 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | 256 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; |
| 254 | request_attr_memory.Base = 0; | 257 | ipw->request_attr_memory.Base = 0; |
| 255 | request_attr_memory.Size = 0; /* this used to be 0x1000 */ | 258 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ |
| 256 | request_attr_memory.AccessSpeed = 0; | 259 | ipw->request_attr_memory.AccessSpeed = 0; |
| 257 | 260 | ||
| 258 | ret = pcmcia_request_window(&link, &request_attr_memory, | 261 | ret = pcmcia_request_window(&link, &ipw->request_attr_memory, |
| 259 | &ipw->handle_attr_memory); | 262 | &ipw->handle_attr_memory); |
| 260 | 263 | ||
| 261 | if (ret != CS_SUCCESS) { | 264 | if (ret != CS_SUCCESS) { |
| @@ -274,8 +277,10 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
| 274 | goto exit2; | 277 | goto exit2; |
| 275 | } | 278 | } |
| 276 | 279 | ||
| 277 | ipw->attr_memory = ioremap(request_attr_memory.Base, | 280 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, |
| 278 | request_attr_memory.Size); | 281 | ipw->request_attr_memory.Size); |
| 282 | request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, | ||
| 283 | IPWIRELESS_PCCARD_NAME); | ||
| 279 | } | 284 | } |
| 280 | 285 | ||
| 281 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); | 286 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); |
| @@ -311,14 +316,13 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
| 311 | (unsigned int) link->irq.AssignedIRQ); | 316 | (unsigned int) link->irq.AssignedIRQ); |
| 312 | if (ipw->attr_memory && ipw->common_memory) | 317 | if (ipw->attr_memory && ipw->common_memory) |
| 313 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 318 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
| 314 | ": attr memory 0x%08lx-0x%08lx, " | 319 | ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", |
| 315 | "common memory 0x%08lx-0x%08lx\n", | 320 | ipw->request_attr_memory.Base, |
| 316 | request_attr_memory.Base, | 321 | ipw->request_attr_memory.Base |
| 317 | request_attr_memory.Base | 322 | + ipw->request_attr_memory.Size - 1, |
| 318 | + request_attr_memory.Size - 1, | 323 | ipw->request_common_memory.Base, |
| 319 | request_common_memory.Base, | 324 | ipw->request_common_memory.Base |
| 320 | request_common_memory.Base | 325 | + ipw->request_common_memory.Size - 1); |
| 321 | + request_common_memory.Size - 1); | ||
| 322 | 326 | ||
| 323 | ipw->network = ipwireless_network_create(ipw->hardware); | 327 | ipw->network = ipwireless_network_create(ipw->hardware); |
| 324 | if (!ipw->network) | 328 | if (!ipw->network) |
| @@ -350,12 +354,16 @@ exit4: | |||
| 350 | pcmcia_disable_device(link); | 354 | pcmcia_disable_device(link); |
| 351 | exit3: | 355 | exit3: |
| 352 | if (ipw->attr_memory) { | 356 | if (ipw->attr_memory) { |
| 357 | release_mem_region(ipw->request_attr_memory.Base, | ||
| 358 | ipw->request_attr_memory.Size); | ||
| 353 | iounmap(ipw->attr_memory); | 359 | iounmap(ipw->attr_memory); |
| 354 | pcmcia_release_window(ipw->handle_attr_memory); | 360 | pcmcia_release_window(ipw->handle_attr_memory); |
| 355 | pcmcia_disable_device(link); | 361 | pcmcia_disable_device(link); |
| 356 | } | 362 | } |
| 357 | exit2: | 363 | exit2: |
| 358 | if (ipw->common_memory) { | 364 | if (ipw->common_memory) { |
| 365 | release_mem_region(ipw->request_common_memory.Base, | ||
| 366 | ipw->request_common_memory.Size); | ||
| 359 | iounmap(ipw->common_memory); | 367 | iounmap(ipw->common_memory); |
| 360 | pcmcia_release_window(ipw->handle_common_memory); | 368 | pcmcia_release_window(ipw->handle_common_memory); |
| 361 | } | 369 | } |
| @@ -367,19 +375,25 @@ exit0: | |||
| 367 | 375 | ||
| 368 | static void release_ipwireless(struct ipw_dev *ipw) | 376 | static void release_ipwireless(struct ipw_dev *ipw) |
| 369 | { | 377 | { |
| 370 | struct pcmcia_device *link = ipw->link; | 378 | pcmcia_disable_device(ipw->link); |
| 371 | |||
| 372 | pcmcia_disable_device(link); | ||
| 373 | 379 | ||
| 374 | if (ipw->common_memory) | 380 | if (ipw->common_memory) { |
| 381 | release_mem_region(ipw->request_common_memory.Base, | ||
| 382 | ipw->request_common_memory.Size); | ||
| 375 | iounmap(ipw->common_memory); | 383 | iounmap(ipw->common_memory); |
| 376 | if (ipw->attr_memory) | 384 | } |
| 385 | if (ipw->attr_memory) { | ||
| 386 | release_mem_region(ipw->request_attr_memory.Base, | ||
| 387 | ipw->request_attr_memory.Size); | ||
| 377 | iounmap(ipw->attr_memory); | 388 | iounmap(ipw->attr_memory); |
| 389 | } | ||
| 378 | if (ipw->common_memory) | 390 | if (ipw->common_memory) |
| 379 | pcmcia_release_window(ipw->handle_common_memory); | 391 | pcmcia_release_window(ipw->handle_common_memory); |
| 380 | if (ipw->attr_memory) | 392 | if (ipw->attr_memory) |
| 381 | pcmcia_release_window(ipw->handle_attr_memory); | 393 | pcmcia_release_window(ipw->handle_attr_memory); |
| 382 | pcmcia_disable_device(link); | 394 | |
| 395 | /* Break the link with Card Services */ | ||
| 396 | pcmcia_disable_device(ipw->link); | ||
| 383 | } | 397 | } |
| 384 | 398 | ||
| 385 | /* | 399 | /* |
| @@ -437,10 +451,6 @@ static void ipwireless_detach(struct pcmcia_device *link) | |||
| 437 | 451 | ||
| 438 | release_ipwireless(ipw); | 452 | release_ipwireless(ipw); |
| 439 | 453 | ||
| 440 | /* Break the link with Card Services */ | ||
| 441 | if (link) | ||
| 442 | pcmcia_disable_device(link); | ||
| 443 | |||
| 444 | if (ipw->tty != NULL) | 454 | if (ipw->tty != NULL) |
| 445 | ipwireless_tty_free(ipw->tty); | 455 | ipwireless_tty_free(ipw->tty); |
| 446 | if (ipw->network != NULL) | 456 | if (ipw->network != NULL) |
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index 1bfdcc8d47d6..0e0363af9ab2 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h | |||
| @@ -45,10 +45,15 @@ struct ipw_tty; | |||
| 45 | struct ipw_dev { | 45 | struct ipw_dev { |
| 46 | struct pcmcia_device *link; | 46 | struct pcmcia_device *link; |
| 47 | int is_v2_card; | 47 | int is_v2_card; |
| 48 | |||
| 48 | window_handle_t handle_attr_memory; | 49 | window_handle_t handle_attr_memory; |
| 49 | void __iomem *attr_memory; | 50 | void __iomem *attr_memory; |
| 51 | win_req_t request_attr_memory; | ||
| 52 | |||
| 50 | window_handle_t handle_common_memory; | 53 | window_handle_t handle_common_memory; |
| 51 | void __iomem *common_memory; | 54 | void __iomem *common_memory; |
| 55 | win_req_t request_common_memory; | ||
| 56 | |||
| 52 | dev_node_t nodes[2]; | 57 | dev_node_t nodes[2]; |
| 53 | /* Reference to attribute memory, containing CIS data */ | 58 | /* Reference to attribute memory, containing CIS data */ |
| 54 | void *attribute_memory; | 59 | void *attribute_memory; |
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index fe914d34f7f6..590762a7f217 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include "main.h" | 29 | #include "main.h" |
| 30 | #include "tty.h" | 30 | #include "tty.h" |
| 31 | 31 | ||
| 32 | #define MAX_OUTGOING_PACKETS_QUEUED ipwireless_out_queue | ||
| 33 | #define MAX_ASSOCIATED_TTYS 2 | 32 | #define MAX_ASSOCIATED_TTYS 2 |
| 34 | 33 | ||
| 35 | #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) | 34 | #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) |
| @@ -46,7 +45,7 @@ struct ipw_network { | |||
| 46 | /* Number of packets queued up in hardware module. */ | 45 | /* Number of packets queued up in hardware module. */ |
| 47 | int outgoing_packets_queued; | 46 | int outgoing_packets_queued; |
| 48 | /* Spinlock to avoid interrupts during shutdown */ | 47 | /* Spinlock to avoid interrupts during shutdown */ |
| 49 | spinlock_t spinlock; | 48 | spinlock_t lock; |
| 50 | struct mutex close_lock; | 49 | struct mutex close_lock; |
| 51 | 50 | ||
| 52 | /* PPP ioctl data, not actually used anywere */ | 51 | /* PPP ioctl data, not actually used anywere */ |
| @@ -68,20 +67,20 @@ static void notify_packet_sent(void *callback_data, unsigned int packet_length) | |||
| 68 | struct ipw_network *network = callback_data; | 67 | struct ipw_network *network = callback_data; |
| 69 | unsigned long flags; | 68 | unsigned long flags; |
| 70 | 69 | ||
| 71 | spin_lock_irqsave(&network->spinlock, flags); | 70 | spin_lock_irqsave(&network->lock, flags); |
| 72 | network->outgoing_packets_queued--; | 71 | network->outgoing_packets_queued--; |
| 73 | if (network->ppp_channel != NULL) { | 72 | if (network->ppp_channel != NULL) { |
| 74 | if (network->ppp_blocked) { | 73 | if (network->ppp_blocked) { |
| 75 | network->ppp_blocked = 0; | 74 | network->ppp_blocked = 0; |
| 76 | spin_unlock_irqrestore(&network->spinlock, flags); | 75 | spin_unlock_irqrestore(&network->lock, flags); |
| 77 | ppp_output_wakeup(network->ppp_channel); | 76 | ppp_output_wakeup(network->ppp_channel); |
| 78 | if (ipwireless_debug) | 77 | if (ipwireless_debug) |
| 79 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 78 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME |
| 80 | ": ppp unblocked\n"); | 79 | ": ppp unblocked\n"); |
| 81 | } else | 80 | } else |
| 82 | spin_unlock_irqrestore(&network->spinlock, flags); | 81 | spin_unlock_irqrestore(&network->lock, flags); |
| 83 | } else | 82 | } else |
| 84 | spin_unlock_irqrestore(&network->spinlock, flags); | 83 | spin_unlock_irqrestore(&network->lock, flags); |
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | /* | 86 | /* |
| @@ -93,8 +92,8 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, | |||
| 93 | struct ipw_network *network = ppp_channel->private; | 92 | struct ipw_network *network = ppp_channel->private; |
| 94 | unsigned long flags; | 93 | unsigned long flags; |
| 95 | 94 | ||
| 96 | spin_lock_irqsave(&network->spinlock, flags); | 95 | spin_lock_irqsave(&network->lock, flags); |
| 97 | if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) { | 96 | if (network->outgoing_packets_queued < ipwireless_out_queue) { |
| 98 | unsigned char *buf; | 97 | unsigned char *buf; |
| 99 | static unsigned char header[] = { | 98 | static unsigned char header[] = { |
| 100 | PPP_ALLSTATIONS, /* 0xff */ | 99 | PPP_ALLSTATIONS, /* 0xff */ |
| @@ -103,7 +102,7 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, | |||
| 103 | int ret; | 102 | int ret; |
| 104 | 103 | ||
| 105 | network->outgoing_packets_queued++; | 104 | network->outgoing_packets_queued++; |
| 106 | spin_unlock_irqrestore(&network->spinlock, flags); | 105 | spin_unlock_irqrestore(&network->lock, flags); |
| 107 | 106 | ||
| 108 | /* | 107 | /* |
| 109 | * If we have the requested amount of headroom in the skb we | 108 | * If we have the requested amount of headroom in the skb we |
| @@ -144,7 +143,9 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, | |||
| 144 | * needs to be unblocked once we are ready to send. | 143 | * needs to be unblocked once we are ready to send. |
| 145 | */ | 144 | */ |
| 146 | network->ppp_blocked = 1; | 145 | network->ppp_blocked = 1; |
| 147 | spin_unlock_irqrestore(&network->spinlock, flags); | 146 | spin_unlock_irqrestore(&network->lock, flags); |
| 147 | if (ipwireless_debug) | ||
| 148 | printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n"); | ||
| 148 | return 0; | 149 | return 0; |
| 149 | } | 150 | } |
| 150 | } | 151 | } |
| @@ -249,11 +250,11 @@ static void do_go_online(struct work_struct *work_go_online) | |||
| 249 | work_go_online); | 250 | work_go_online); |
| 250 | unsigned long flags; | 251 | unsigned long flags; |
| 251 | 252 | ||
| 252 | spin_lock_irqsave(&network->spinlock, flags); | 253 | spin_lock_irqsave(&network->lock, flags); |
| 253 | if (!network->ppp_channel) { | 254 | if (!network->ppp_channel) { |
| 254 | struct ppp_channel *channel; | 255 | struct ppp_channel *channel; |
| 255 | 256 | ||
| 256 | spin_unlock_irqrestore(&network->spinlock, flags); | 257 | spin_unlock_irqrestore(&network->lock, flags); |
| 257 | channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); | 258 | channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); |
| 258 | if (!channel) { | 259 | if (!channel) { |
| 259 | printk(KERN_ERR IPWIRELESS_PCCARD_NAME | 260 | printk(KERN_ERR IPWIRELESS_PCCARD_NAME |
| @@ -273,10 +274,10 @@ static void do_go_online(struct work_struct *work_go_online) | |||
| 273 | network->xaccm[3] = 0x60000000U; | 274 | network->xaccm[3] = 0x60000000U; |
| 274 | network->raccm = ~0U; | 275 | network->raccm = ~0U; |
| 275 | ppp_register_channel(channel); | 276 | ppp_register_channel(channel); |
| 276 | spin_lock_irqsave(&network->spinlock, flags); | 277 | spin_lock_irqsave(&network->lock, flags); |
| 277 | network->ppp_channel = channel; | 278 | network->ppp_channel = channel; |
| 278 | } | 279 | } |
| 279 | spin_unlock_irqrestore(&network->spinlock, flags); | 280 | spin_unlock_irqrestore(&network->lock, flags); |
| 280 | } | 281 | } |
| 281 | 282 | ||
| 282 | static void do_go_offline(struct work_struct *work_go_offline) | 283 | static void do_go_offline(struct work_struct *work_go_offline) |
| @@ -287,16 +288,16 @@ static void do_go_offline(struct work_struct *work_go_offline) | |||
| 287 | unsigned long flags; | 288 | unsigned long flags; |
| 288 | 289 | ||
| 289 | mutex_lock(&network->close_lock); | 290 | mutex_lock(&network->close_lock); |
| 290 | spin_lock_irqsave(&network->spinlock, flags); | 291 | spin_lock_irqsave(&network->lock, flags); |
| 291 | if (network->ppp_channel != NULL) { | 292 | if (network->ppp_channel != NULL) { |
| 292 | struct ppp_channel *channel = network->ppp_channel; | 293 | struct ppp_channel *channel = network->ppp_channel; |
| 293 | 294 | ||
| 294 | network->ppp_channel = NULL; | 295 | network->ppp_channel = NULL; |
| 295 | spin_unlock_irqrestore(&network->spinlock, flags); | 296 | spin_unlock_irqrestore(&network->lock, flags); |
| 296 | mutex_unlock(&network->close_lock); | 297 | mutex_unlock(&network->close_lock); |
| 297 | ppp_unregister_channel(channel); | 298 | ppp_unregister_channel(channel); |
| 298 | } else { | 299 | } else { |
| 299 | spin_unlock_irqrestore(&network->spinlock, flags); | 300 | spin_unlock_irqrestore(&network->lock, flags); |
| 300 | mutex_unlock(&network->close_lock); | 301 | mutex_unlock(&network->close_lock); |
| 301 | } | 302 | } |
| 302 | } | 303 | } |
| @@ -381,18 +382,18 @@ void ipwireless_network_packet_received(struct ipw_network *network, | |||
| 381 | * the PPP layer. | 382 | * the PPP layer. |
| 382 | */ | 383 | */ |
| 383 | mutex_lock(&network->close_lock); | 384 | mutex_lock(&network->close_lock); |
| 384 | spin_lock_irqsave(&network->spinlock, flags); | 385 | spin_lock_irqsave(&network->lock, flags); |
| 385 | if (network->ppp_channel != NULL) { | 386 | if (network->ppp_channel != NULL) { |
| 386 | struct sk_buff *skb; | 387 | struct sk_buff *skb; |
| 387 | 388 | ||
| 388 | spin_unlock_irqrestore(&network->spinlock, | 389 | spin_unlock_irqrestore(&network->lock, |
| 389 | flags); | 390 | flags); |
| 390 | 391 | ||
| 391 | /* Send the data to the ppp_generic module. */ | 392 | /* Send the data to the ppp_generic module. */ |
| 392 | skb = ipw_packet_received_skb(data, length); | 393 | skb = ipw_packet_received_skb(data, length); |
| 393 | ppp_input(network->ppp_channel, skb); | 394 | ppp_input(network->ppp_channel, skb); |
| 394 | } else | 395 | } else |
| 395 | spin_unlock_irqrestore(&network->spinlock, | 396 | spin_unlock_irqrestore(&network->lock, |
| 396 | flags); | 397 | flags); |
| 397 | mutex_unlock(&network->close_lock); | 398 | mutex_unlock(&network->close_lock); |
| 398 | } | 399 | } |
| @@ -410,7 +411,7 @@ struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) | |||
| 410 | if (!network) | 411 | if (!network) |
| 411 | return NULL; | 412 | return NULL; |
| 412 | 413 | ||
| 413 | spin_lock_init(&network->spinlock); | 414 | spin_lock_init(&network->lock); |
| 414 | mutex_init(&network->close_lock); | 415 | mutex_init(&network->close_lock); |
| 415 | 416 | ||
| 416 | network->hardware = hw; | 417 | network->hardware = hw; |
| @@ -478,10 +479,10 @@ int ipwireless_ppp_channel_index(struct ipw_network *network) | |||
| 478 | int ret = -1; | 479 | int ret = -1; |
| 479 | unsigned long flags; | 480 | unsigned long flags; |
| 480 | 481 | ||
| 481 | spin_lock_irqsave(&network->spinlock, flags); | 482 | spin_lock_irqsave(&network->lock, flags); |
| 482 | if (network->ppp_channel != NULL) | 483 | if (network->ppp_channel != NULL) |
| 483 | ret = ppp_channel_index(network->ppp_channel); | 484 | ret = ppp_channel_index(network->ppp_channel); |
| 484 | spin_unlock_irqrestore(&network->spinlock, flags); | 485 | spin_unlock_irqrestore(&network->lock, flags); |
| 485 | 486 | ||
| 486 | return ret; | 487 | return ret; |
| 487 | } | 488 | } |
| @@ -491,10 +492,15 @@ int ipwireless_ppp_unit_number(struct ipw_network *network) | |||
| 491 | int ret = -1; | 492 | int ret = -1; |
| 492 | unsigned long flags; | 493 | unsigned long flags; |
| 493 | 494 | ||
| 494 | spin_lock_irqsave(&network->spinlock, flags); | 495 | spin_lock_irqsave(&network->lock, flags); |
| 495 | if (network->ppp_channel != NULL) | 496 | if (network->ppp_channel != NULL) |
| 496 | ret = ppp_unit_number(network->ppp_channel); | 497 | ret = ppp_unit_number(network->ppp_channel); |
| 497 | spin_unlock_irqrestore(&network->spinlock, flags); | 498 | spin_unlock_irqrestore(&network->lock, flags); |
| 498 | 499 | ||
| 499 | return ret; | 500 | return ret; |
| 500 | } | 501 | } |
| 502 | |||
| 503 | int ipwireless_ppp_mru(const struct ipw_network *network) | ||
| 504 | { | ||
| 505 | return network->mru; | ||
| 506 | } | ||
diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h index ccacd26fc7ef..561f765b3334 100644 --- a/drivers/char/pcmcia/ipwireless/network.h +++ b/drivers/char/pcmcia/ipwireless/network.h | |||
| @@ -48,5 +48,6 @@ void ipwireless_ppp_open(struct ipw_network *net); | |||
| 48 | void ipwireless_ppp_close(struct ipw_network *net); | 48 | void ipwireless_ppp_close(struct ipw_network *net); |
| 49 | int ipwireless_ppp_channel_index(struct ipw_network *net); | 49 | int ipwireless_ppp_channel_index(struct ipw_network *net); |
| 50 | int ipwireless_ppp_unit_number(struct ipw_network *net); | 50 | int ipwireless_ppp_unit_number(struct ipw_network *net); |
| 51 | int ipwireless_ppp_mru(const struct ipw_network *net); | ||
| 51 | 52 | ||
| 52 | #endif | 53 | #endif |
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 42f3815c5ce3..b1414507997c 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c | |||
| @@ -259,7 +259,7 @@ static int ipw_write(struct tty_struct *linux_tty, | |||
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, | 261 | ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, |
| 262 | (unsigned char *) buf, count, | 262 | buf, count, |
| 263 | ipw_write_packet_sent_callback, tty); | 263 | ipw_write_packet_sent_callback, tty); |
| 264 | if (ret == -1) { | 264 | if (ret == -1) { |
| 265 | mutex_unlock(&tty->ipw_tty_mutex); | 265 | mutex_unlock(&tty->ipw_tty_mutex); |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 5405769020a1..5ce07b517c58 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
| @@ -94,7 +94,7 @@ void cpuidle_install_idle_handler(void) | |||
| 94 | */ | 94 | */ |
| 95 | void cpuidle_uninstall_idle_handler(void) | 95 | void cpuidle_uninstall_idle_handler(void) |
| 96 | { | 96 | { |
| 97 | if (enabled_devices && (pm_idle != pm_idle_old)) { | 97 | if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) { |
| 98 | pm_idle = pm_idle_old; | 98 | pm_idle = pm_idle_old; |
| 99 | cpuidle_kick_cpus(); | 99 | cpuidle_kick_cpus(); |
| 100 | } | 100 | } |
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 48d084bdf7c8..3c855ff2992f 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c | |||
| @@ -49,6 +49,8 @@ struct bfin_twi_iface { | |||
| 49 | struct i2c_msg *pmsg; | 49 | struct i2c_msg *pmsg; |
| 50 | int msg_num; | 50 | int msg_num; |
| 51 | int cur_msg; | 51 | int cur_msg; |
| 52 | u16 saved_clkdiv; | ||
| 53 | u16 saved_control; | ||
| 52 | void __iomem *regs_base; | 54 | void __iomem *regs_base; |
| 53 | }; | 55 | }; |
| 54 | 56 | ||
| @@ -565,32 +567,43 @@ static u32 bfin_twi_functionality(struct i2c_adapter *adap) | |||
| 565 | I2C_FUNC_I2C; | 567 | I2C_FUNC_I2C; |
| 566 | } | 568 | } |
| 567 | 569 | ||
| 568 | |||
| 569 | static struct i2c_algorithm bfin_twi_algorithm = { | 570 | static struct i2c_algorithm bfin_twi_algorithm = { |
| 570 | .master_xfer = bfin_twi_master_xfer, | 571 | .master_xfer = bfin_twi_master_xfer, |
| 571 | .smbus_xfer = bfin_twi_smbus_xfer, | 572 | .smbus_xfer = bfin_twi_smbus_xfer, |
| 572 | .functionality = bfin_twi_functionality, | 573 | .functionality = bfin_twi_functionality, |
| 573 | }; | 574 | }; |
| 574 | 575 | ||
| 575 | 576 | static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state) | |
| 576 | static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state) | ||
| 577 | { | 577 | { |
| 578 | struct bfin_twi_iface *iface = platform_get_drvdata(dev); | 578 | struct bfin_twi_iface *iface = platform_get_drvdata(pdev); |
| 579 | |||
| 580 | iface->saved_clkdiv = read_CLKDIV(iface); | ||
| 581 | iface->saved_control = read_CONTROL(iface); | ||
| 582 | |||
| 583 | free_irq(iface->irq, iface); | ||
| 579 | 584 | ||
| 580 | /* Disable TWI */ | 585 | /* Disable TWI */ |
| 581 | write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA); | 586 | write_CONTROL(iface, iface->saved_control & ~TWI_ENA); |
| 582 | SSYNC(); | ||
| 583 | 587 | ||
| 584 | return 0; | 588 | return 0; |
| 585 | } | 589 | } |
| 586 | 590 | ||
| 587 | static int i2c_bfin_twi_resume(struct platform_device *dev) | 591 | static int i2c_bfin_twi_resume(struct platform_device *pdev) |
| 588 | { | 592 | { |
| 589 | struct bfin_twi_iface *iface = platform_get_drvdata(dev); | 593 | struct bfin_twi_iface *iface = platform_get_drvdata(pdev); |
| 590 | 594 | ||
| 591 | /* Enable TWI */ | 595 | int rc = request_irq(iface->irq, bfin_twi_interrupt_entry, |
| 592 | write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); | 596 | IRQF_DISABLED, pdev->name, iface); |
| 593 | SSYNC(); | 597 | if (rc) { |
| 598 | dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); | ||
| 599 | return -ENODEV; | ||
| 600 | } | ||
| 601 | |||
| 602 | /* Resume TWI interface clock as specified */ | ||
| 603 | write_CLKDIV(iface, iface->saved_clkdiv); | ||
| 604 | |||
| 605 | /* Resume TWI */ | ||
| 606 | write_CONTROL(iface, iface->saved_control); | ||
| 594 | 607 | ||
| 595 | return 0; | 608 | return 0; |
| 596 | } | 609 | } |
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 79b455a1f090..32104eac8d3d 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c | |||
| @@ -77,7 +77,7 @@ static int i2c_gpio_getscl(void *data) | |||
| 77 | return gpio_get_value(pdata->scl_pin); | 77 | return gpio_get_value(pdata->scl_pin); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static int __init i2c_gpio_probe(struct platform_device *pdev) | 80 | static int __devinit i2c_gpio_probe(struct platform_device *pdev) |
| 81 | { | 81 | { |
| 82 | struct i2c_gpio_platform_data *pdata; | 82 | struct i2c_gpio_platform_data *pdata; |
| 83 | struct i2c_algo_bit_data *bit_data; | 83 | struct i2c_algo_bit_data *bit_data; |
| @@ -174,7 +174,7 @@ err_alloc_adap: | |||
| 174 | return ret; | 174 | return ret; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static int __exit i2c_gpio_remove(struct platform_device *pdev) | 177 | static int __devexit i2c_gpio_remove(struct platform_device *pdev) |
| 178 | { | 178 | { |
| 179 | struct i2c_gpio_platform_data *pdata; | 179 | struct i2c_gpio_platform_data *pdata; |
| 180 | struct i2c_adapter *adap; | 180 | struct i2c_adapter *adap; |
| @@ -196,14 +196,15 @@ static struct platform_driver i2c_gpio_driver = { | |||
| 196 | .name = "i2c-gpio", | 196 | .name = "i2c-gpio", |
| 197 | .owner = THIS_MODULE, | 197 | .owner = THIS_MODULE, |
| 198 | }, | 198 | }, |
| 199 | .remove = __exit_p(i2c_gpio_remove), | 199 | .probe = i2c_gpio_probe, |
| 200 | .remove = __devexit_p(i2c_gpio_remove), | ||
| 200 | }; | 201 | }; |
| 201 | 202 | ||
| 202 | static int __init i2c_gpio_init(void) | 203 | static int __init i2c_gpio_init(void) |
| 203 | { | 204 | { |
| 204 | int ret; | 205 | int ret; |
| 205 | 206 | ||
| 206 | ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe); | 207 | ret = platform_driver_register(&i2c_gpio_driver); |
| 207 | if (ret) | 208 | if (ret) |
| 208 | printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); | 209 | printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); |
| 209 | 210 | ||
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 007390ad9810..4864723c7425 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
| 34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
| 36 | #include <linux/cpufreq.h> | ||
| 36 | 37 | ||
| 37 | #include <asm/hardware.h> | 38 | #include <asm/hardware.h> |
| 38 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
| @@ -64,6 +65,7 @@ struct s3c24xx_i2c { | |||
| 64 | unsigned int tx_setup; | 65 | unsigned int tx_setup; |
| 65 | 66 | ||
| 66 | enum s3c24xx_i2c_state state; | 67 | enum s3c24xx_i2c_state state; |
| 68 | unsigned long clkrate; | ||
| 67 | 69 | ||
| 68 | void __iomem *regs; | 70 | void __iomem *regs; |
| 69 | struct clk *clk; | 71 | struct clk *clk; |
| @@ -71,6 +73,10 @@ struct s3c24xx_i2c { | |||
| 71 | struct resource *irq; | 73 | struct resource *irq; |
| 72 | struct resource *ioarea; | 74 | struct resource *ioarea; |
| 73 | struct i2c_adapter adap; | 75 | struct i2c_adapter adap; |
| 76 | |||
| 77 | #ifdef CONFIG_CPU_FREQ | ||
| 78 | struct notifier_block freq_transition; | ||
| 79 | #endif | ||
| 74 | }; | 80 | }; |
| 75 | 81 | ||
| 76 | /* default platform data to use if not supplied in the platform_device | 82 | /* default platform data to use if not supplied in the platform_device |
| @@ -501,6 +507,9 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int | |||
| 501 | unsigned long timeout; | 507 | unsigned long timeout; |
| 502 | int ret; | 508 | int ret; |
| 503 | 509 | ||
| 510 | if (!readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN) | ||
| 511 | return -EIO; | ||
| 512 | |||
| 504 | ret = s3c24xx_i2c_set_master(i2c); | 513 | ret = s3c24xx_i2c_set_master(i2c); |
| 505 | if (ret != 0) { | 514 | if (ret != 0) { |
| 506 | dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); | 515 | dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); |
| @@ -636,27 +645,28 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted) | |||
| 636 | return (diff >= -2 && diff <= 2); | 645 | return (diff >= -2 && diff <= 2); |
| 637 | } | 646 | } |
| 638 | 647 | ||
| 639 | /* s3c24xx_i2c_getdivisor | 648 | /* s3c24xx_i2c_clockrate |
| 640 | * | 649 | * |
| 641 | * work out a divisor for the user requested frequency setting, | 650 | * work out a divisor for the user requested frequency setting, |
| 642 | * either by the requested frequency, or scanning the acceptable | 651 | * either by the requested frequency, or scanning the acceptable |
| 643 | * range of frequencies until something is found | 652 | * range of frequencies until something is found |
| 644 | */ | 653 | */ |
| 645 | 654 | ||
| 646 | static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c, | 655 | static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) |
| 647 | struct s3c2410_platform_i2c *pdata, | ||
| 648 | unsigned long *iicon, | ||
| 649 | unsigned int *got) | ||
| 650 | { | 656 | { |
| 657 | struct s3c2410_platform_i2c *pdata; | ||
| 651 | unsigned long clkin = clk_get_rate(i2c->clk); | 658 | unsigned long clkin = clk_get_rate(i2c->clk); |
| 652 | |||
| 653 | unsigned int divs, div1; | 659 | unsigned int divs, div1; |
| 660 | u32 iiccon; | ||
| 654 | int freq; | 661 | int freq; |
| 655 | int start, end; | 662 | int start, end; |
| 656 | 663 | ||
| 664 | i2c->clkrate = clkin; | ||
| 665 | |||
| 666 | pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent); | ||
| 657 | clkin /= 1000; /* clkin now in KHz */ | 667 | clkin /= 1000; /* clkin now in KHz */ |
| 658 | 668 | ||
| 659 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", | 669 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", |
| 660 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); | 670 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); |
| 661 | 671 | ||
| 662 | if (pdata->bus_freq != 0) { | 672 | if (pdata->bus_freq != 0) { |
| @@ -688,11 +698,79 @@ static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c, | |||
| 688 | 698 | ||
| 689 | found: | 699 | found: |
| 690 | *got = freq; | 700 | *got = freq; |
| 691 | *iicon |= (divs-1); | 701 | |
| 692 | *iicon |= (div1 == 512) ? S3C2410_IICCON_TXDIV_512 : 0; | 702 | iiccon = readl(i2c->regs + S3C2410_IICCON); |
| 703 | iiccon &= ~(S3C2410_IICCON_SCALEMASK | S3C2410_IICCON_TXDIV_512); | ||
| 704 | iiccon |= (divs-1); | ||
| 705 | |||
| 706 | if (div1 == 512) | ||
| 707 | iiccon |= S3C2410_IICCON_TXDIV_512; | ||
| 708 | |||
| 709 | writel(iiccon, i2c->regs + S3C2410_IICCON); | ||
| 710 | |||
| 711 | return 0; | ||
| 712 | } | ||
| 713 | |||
| 714 | #ifdef CONFIG_CPU_FREQ | ||
| 715 | |||
| 716 | #define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) | ||
| 717 | |||
| 718 | static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, | ||
| 719 | unsigned long val, void *data) | ||
| 720 | { | ||
| 721 | struct s3c24xx_i2c *i2c = freq_to_i2c(nb); | ||
| 722 | unsigned long flags; | ||
| 723 | unsigned int got; | ||
| 724 | int delta_f; | ||
| 725 | int ret; | ||
| 726 | |||
| 727 | delta_f = clk_get_rate(i2c->clk) - i2c->clkrate; | ||
| 728 | |||
| 729 | /* if we're post-change and the input clock has slowed down | ||
| 730 | * or at pre-change and the clock is about to speed up, then | ||
| 731 | * adjust our clock rate. <0 is slow, >0 speedup. | ||
| 732 | */ | ||
| 733 | |||
| 734 | if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || | ||
| 735 | (val == CPUFREQ_PRECHANGE && delta_f > 0)) { | ||
| 736 | spin_lock_irqsave(&i2c->lock, flags); | ||
| 737 | ret = s3c24xx_i2c_clockrate(i2c, &got); | ||
| 738 | spin_unlock_irqrestore(&i2c->lock, flags); | ||
| 739 | |||
| 740 | if (ret < 0) | ||
| 741 | dev_err(i2c->dev, "cannot find frequency\n"); | ||
| 742 | else | ||
| 743 | dev_info(i2c->dev, "setting freq %d\n", got); | ||
| 744 | } | ||
| 745 | |||
| 746 | return 0; | ||
| 747 | } | ||
| 748 | |||
| 749 | static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 750 | { | ||
| 751 | i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition; | ||
| 752 | |||
| 753 | return cpufreq_register_notifier(&i2c->freq_transition, | ||
| 754 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 755 | } | ||
| 756 | |||
| 757 | static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 758 | { | ||
| 759 | cpufreq_unregister_notifier(&i2c->freq_transition, | ||
| 760 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 761 | } | ||
| 762 | |||
| 763 | #else | ||
| 764 | static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 765 | { | ||
| 693 | return 0; | 766 | return 0; |
| 694 | } | 767 | } |
| 695 | 768 | ||
| 769 | static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 770 | { | ||
| 771 | } | ||
| 772 | #endif | ||
| 773 | |||
| 696 | /* s3c24xx_i2c_init | 774 | /* s3c24xx_i2c_init |
| 697 | * | 775 | * |
| 698 | * initialise the controller, set the IO lines and frequency | 776 | * initialise the controller, set the IO lines and frequency |
| @@ -719,9 +797,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
| 719 | 797 | ||
| 720 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); | 798 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); |
| 721 | 799 | ||
| 800 | writel(iicon, i2c->regs + S3C2410_IICCON); | ||
| 801 | |||
| 722 | /* we need to work out the divisors for the clock... */ | 802 | /* we need to work out the divisors for the clock... */ |
| 723 | 803 | ||
| 724 | if (s3c24xx_i2c_getdivisor(i2c, pdata, &iicon, &freq) != 0) { | 804 | if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) { |
| 805 | writel(0, i2c->regs + S3C2410_IICCON); | ||
| 725 | dev_err(i2c->dev, "cannot meet bus frequency required\n"); | 806 | dev_err(i2c->dev, "cannot meet bus frequency required\n"); |
| 726 | return -EINVAL; | 807 | return -EINVAL; |
| 727 | } | 808 | } |
| @@ -730,8 +811,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
| 730 | 811 | ||
| 731 | dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); | 812 | dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); |
| 732 | dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); | 813 | dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); |
| 733 | |||
| 734 | writel(iicon, i2c->regs + S3C2410_IICCON); | ||
| 735 | 814 | ||
| 736 | /* check for s3c2440 i2c controller */ | 815 | /* check for s3c2440 i2c controller */ |
| 737 | 816 | ||
| @@ -752,9 +831,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
| 752 | static int s3c24xx_i2c_probe(struct platform_device *pdev) | 831 | static int s3c24xx_i2c_probe(struct platform_device *pdev) |
| 753 | { | 832 | { |
| 754 | struct s3c24xx_i2c *i2c = &s3c24xx_i2c; | 833 | struct s3c24xx_i2c *i2c = &s3c24xx_i2c; |
| 834 | struct s3c2410_platform_i2c *pdata; | ||
| 755 | struct resource *res; | 835 | struct resource *res; |
| 756 | int ret; | 836 | int ret; |
| 757 | 837 | ||
| 838 | pdata = s3c24xx_i2c_get_platformdata(&pdev->dev); | ||
| 839 | |||
| 758 | /* find the clock and enable it */ | 840 | /* find the clock and enable it */ |
| 759 | 841 | ||
| 760 | i2c->dev = &pdev->dev; | 842 | i2c->dev = &pdev->dev; |
| @@ -832,17 +914,34 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
| 832 | dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res, | 914 | dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res, |
| 833 | (unsigned long)res->start); | 915 | (unsigned long)res->start); |
| 834 | 916 | ||
| 835 | ret = i2c_add_adapter(&i2c->adap); | 917 | ret = s3c24xx_i2c_register_cpufreq(i2c); |
| 836 | if (ret < 0) { | 918 | if (ret < 0) { |
| 837 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); | 919 | dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); |
| 838 | goto err_irq; | 920 | goto err_irq; |
| 839 | } | 921 | } |
| 840 | 922 | ||
| 923 | /* Note, previous versions of the driver used i2c_add_adapter() | ||
| 924 | * to add the bus at any number. We now pass the bus number via | ||
| 925 | * the platform data, so if unset it will now default to always | ||
| 926 | * being bus 0. | ||
| 927 | */ | ||
| 928 | |||
| 929 | i2c->adap.nr = pdata->bus_num; | ||
| 930 | |||
| 931 | ret = i2c_add_numbered_adapter(&i2c->adap); | ||
| 932 | if (ret < 0) { | ||
| 933 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); | ||
| 934 | goto err_cpufreq; | ||
| 935 | } | ||
| 936 | |||
| 841 | platform_set_drvdata(pdev, i2c); | 937 | platform_set_drvdata(pdev, i2c); |
| 842 | 938 | ||
| 843 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); | 939 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); |
| 844 | return 0; | 940 | return 0; |
| 845 | 941 | ||
| 942 | err_cpufreq: | ||
| 943 | s3c24xx_i2c_deregister_cpufreq(i2c); | ||
| 944 | |||
| 846 | err_irq: | 945 | err_irq: |
| 847 | free_irq(i2c->irq->start, i2c); | 946 | free_irq(i2c->irq->start, i2c); |
| 848 | 947 | ||
| @@ -870,6 +969,8 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) | |||
| 870 | { | 969 | { |
| 871 | struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); | 970 | struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); |
| 872 | 971 | ||
| 972 | s3c24xx_i2c_deregister_cpufreq(i2c); | ||
| 973 | |||
| 873 | i2c_del_adapter(&i2c->adap); | 974 | i2c_del_adapter(&i2c->adap); |
| 874 | free_irq(i2c->irq->start, i2c); | 975 | free_irq(i2c->irq->start, i2c); |
| 875 | 976 | ||
diff --git a/include/asm-arm/plat-s3c/iic.h b/include/asm-arm/plat-s3c/iic.h index 71211c8b5384..d08a1f2863e4 100644 --- a/include/asm-arm/plat-s3c/iic.h +++ b/include/asm-arm/plat-s3c/iic.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | struct s3c2410_platform_i2c { | 23 | struct s3c2410_platform_i2c { |
| 24 | int bus_num; /* bus number to use */ | ||
| 24 | unsigned int flags; | 25 | unsigned int flags; |
| 25 | unsigned int slave_addr; /* slave address for controller */ | 26 | unsigned int slave_addr; /* slave address for controller */ |
| 26 | unsigned long bus_freq; /* standard bus frequency */ | 27 | unsigned long bus_freq; /* standard bus frequency */ |
