Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'staging-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* 'staging-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (38 commits)
Revert "staging: tidspbridge: replace iommu custom for opensource implementation"
Revert "staging: tidspbridge - move shared memory iommu maps to tiomap3430.c"
Revert "staging: tidspbridge - rename bridge_brd_mem_map/unmap to a proper name"
Revert "staging: tidspbridge - remove custom mmu code from tiomap3430.c"
Revert "staging: tidspbridge - fix mmufault support"
Revert "staging: tidspbridge - remove hw directory"
Revert "staging: tidspbridge - move all iommu related code to a new file"
Revert "staging: tidspbridge: remove dw_dmmu_base from cfg_hostres struct"
Revert "staging: tidspbridge - remove reserved memory clean up"
Revert "staging: tidspbridge - deprecate reserve/unreserve_memory funtions"
Revert "staging: tidspbridge - remove dmm custom module"
Revert "staging: tidspbridge - update Kconfig to select IOMMU module"
staging: tidspbridge: hardcode SCM macros while fix is upstreamed
Staging: keucr driver: fix uninitialized variable & proper memset length
omap: dsp: remove shm from normal memory
Staging: wlan-ng: Fix wrong #ifdef #endif sequence
Staging: Update parameters for cfg80211 key management operation
Staging: ath6kl: Fix pointer casts on 64-bit architectures
Staging: batman-adv: suppress false warning when changing the mac address
Staging: batman-adv: fix interface alternating and bonding reggression
...

+3760 -800
+1 -1
MAINTAINERS
··· 5676 5676 5677 5677 STAGING SUBSYSTEM 5678 5678 M: Greg Kroah-Hartman <gregkh@suse.de> 5679 - T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-next-2.6.git 5679 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6.git 5680 5680 L: devel@driverdev.osuosl.org 5681 5681 S: Maintained 5682 5682 F: drivers/staging/
+3 -1
arch/arm/plat-omap/devices.c
··· 284 284 if (!size) 285 285 return; 286 286 287 - paddr = __memblock_alloc_base(size, SZ_1M, MEMBLOCK_REAL_LIMIT); 287 + paddr = memblock_alloc(size, SZ_1M); 288 288 if (!paddr) { 289 289 pr_err("%s: failed to reserve %x bytes\n", 290 290 __func__, size); 291 291 return; 292 292 } 293 + memblock_free(paddr, size); 294 + memblock_remove(paddr, size); 293 295 294 296 omap_dsp_phys_mempool_base = paddr; 295 297 }
+1 -1
drivers/staging/ath6kl/Kconfig
··· 102 102 103 103 config ATH6KL_CFG80211 104 104 bool "CFG80211 support" 105 - depends on ATH6K_LEGACY 105 + depends on ATH6K_LEGACY && CFG80211 106 106 help 107 107 Enables support for CFG80211 APIs. The default option is to use WEXT. Even with this option enabled, WEXT is not explicitly disabled and the onus of not exercising WEXT lies on the application(s) running in the user space. 108 108
+3 -2
drivers/staging/ath6kl/os/linux/ar6000_drv.c
··· 1126 1126 if ((board_ext_address) && (fw_entry->size == (board_data_size + board_ext_data_size))) { 1127 1127 A_UINT32 param; 1128 1128 1129 - status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (A_UCHAR *)(((A_UINT32)fw_entry->data) + board_data_size), board_ext_data_size); 1129 + status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (A_UCHAR *)(fw_entry->data + board_data_size), board_ext_data_size); 1130 1130 1131 1131 if (status != A_OK) { 1132 1132 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); ··· 3030 3030 A_UINT8 csumDest=0; 3031 3031 A_UINT8 csum=skb->ip_summed; 3032 3032 if(csumOffload && (csum==CHECKSUM_PARTIAL)){ 3033 - csumStart=skb->csum_start-(skb->network_header-skb->head)+sizeof(ATH_LLC_SNAP_HDR); 3033 + csumStart = (skb->head + skb->csum_start - skb_network_header(skb) + 3034 + sizeof(ATH_LLC_SNAP_HDR)); 3034 3035 csumDest=skb->csum_offset+csumStart; 3035 3036 } 3036 3037 #endif
+4 -3
drivers/staging/ath6kl/os/linux/cfg80211.c
··· 808 808 809 809 static int 810 810 ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, 811 - A_UINT8 key_index, const A_UINT8 *mac_addr, 811 + A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr, 812 812 struct key_params *params) 813 813 { 814 814 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev); ··· 901 901 902 902 static int 903 903 ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, 904 - A_UINT8 key_index, const A_UINT8 *mac_addr) 904 + A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr) 905 905 { 906 906 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev); 907 907 ··· 936 936 937 937 static int 938 938 ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, 939 - A_UINT8 key_index, const A_UINT8 *mac_addr, void *cookie, 939 + A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr, 940 + void *cookie, 940 941 void (*callback)(void *cookie, struct key_params*)) 941 942 { 942 943 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+10 -5
drivers/staging/batman-adv/hard-interface.c
··· 165 165 batman_if->net_dev->dev_addr, ETH_ALEN); 166 166 } 167 167 168 - static void check_known_mac_addr(uint8_t *addr) 168 + static void check_known_mac_addr(struct net_device *net_dev) 169 169 { 170 170 struct batman_if *batman_if; 171 171 ··· 175 175 (batman_if->if_status != IF_TO_BE_ACTIVATED)) 176 176 continue; 177 177 178 - if (!compare_orig(batman_if->net_dev->dev_addr, addr)) 178 + if (batman_if->net_dev == net_dev) 179 + continue; 180 + 181 + if (!compare_orig(batman_if->net_dev->dev_addr, 182 + net_dev->dev_addr)) 179 183 continue; 180 184 181 185 pr_warning("The newly added mac address (%pM) already exists " 182 - "on: %s\n", addr, batman_if->net_dev->name); 186 + "on: %s\n", net_dev->dev_addr, 187 + batman_if->net_dev->name); 183 188 pr_warning("It is strongly recommended to keep mac addresses " 184 189 "unique to avoid problems!\n"); 185 190 } ··· 435 430 atomic_set(&batman_if->refcnt, 0); 436 431 hardif_hold(batman_if); 437 432 438 - check_known_mac_addr(batman_if->net_dev->dev_addr); 433 + check_known_mac_addr(batman_if->net_dev); 439 434 440 435 spin_lock(&if_list_lock); 441 436 list_add_tail_rcu(&batman_if->list, &if_list); ··· 520 515 goto out; 521 516 } 522 517 523 - check_known_mac_addr(batman_if->net_dev->dev_addr); 518 + check_known_mac_addr(batman_if->net_dev); 524 519 update_mac_addresses(batman_if); 525 520 526 521 bat_priv = netdev_priv(batman_if->soft_iface);
+4 -8
drivers/staging/batman-adv/routing.c
··· 1000 1000 1001 1001 /* find a suitable router for this originator, and use 1002 1002 * bonding if possible. */ 1003 - struct neigh_node *find_router(struct orig_node *orig_node, 1003 + struct neigh_node *find_router(struct bat_priv *bat_priv, 1004 + struct orig_node *orig_node, 1004 1005 struct batman_if *recv_if) 1005 1006 { 1006 - struct bat_priv *bat_priv; 1007 1007 struct orig_node *primary_orig_node; 1008 1008 struct orig_node *router_orig; 1009 1009 struct neigh_node *router, *first_candidate, *best_router; ··· 1019 1019 /* without bonding, the first node should 1020 1020 * always choose the default router. */ 1021 1021 1022 - if (!recv_if) 1023 - return orig_node->router; 1024 - 1025 - bat_priv = netdev_priv(recv_if->soft_iface); 1026 1022 bonding_enabled = atomic_read(&bat_priv->bonding_enabled); 1027 1023 1028 - if (!bonding_enabled) 1024 + if ((!recv_if) && (!bonding_enabled)) 1029 1025 return orig_node->router; 1030 1026 1031 1027 router_orig = orig_node->router->orig_node; ··· 1150 1154 orig_node = ((struct orig_node *) 1151 1155 hash_find(bat_priv->orig_hash, unicast_packet->dest)); 1152 1156 1153 - router = find_router(orig_node, recv_if); 1157 + router = find_router(bat_priv, orig_node, recv_if); 1154 1158 1155 1159 if (!router) { 1156 1160 spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+2 -2
drivers/staging/batman-adv/routing.h
··· 38 38 int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if); 39 39 int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if); 40 40 int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if); 41 - struct neigh_node *find_router(struct orig_node *orig_node, 42 - struct batman_if *recv_if); 41 + struct neigh_node *find_router(struct bat_priv *bat_priv, 42 + struct orig_node *orig_node, struct batman_if *recv_if); 43 43 void update_bonding_candidates(struct bat_priv *bat_priv, 44 44 struct orig_node *orig_node); 45 45
+1 -1
drivers/staging/batman-adv/unicast.c
··· 224 224 if (!orig_node) 225 225 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 226 226 227 - router = find_router(orig_node, NULL); 227 + router = find_router(bat_priv, orig_node, NULL); 228 228 229 229 if (!router) 230 230 goto unlock;
+32 -17
drivers/staging/bcm/Bcmchar.c
··· 1001 1001 } 1002 1002 #endif 1003 1003 case IOCTL_BE_BUCKET_SIZE: 1004 - Adapter->BEBucketSize = *(PULONG)arg; 1005 - Status = STATUS_SUCCESS; 1004 + Status = 0; 1005 + if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg)) 1006 + Status = -EFAULT; 1006 1007 break; 1007 1008 1008 1009 case IOCTL_RTPS_BUCKET_SIZE: 1009 - Adapter->rtPSBucketSize = *(PULONG)arg; 1010 - Status = STATUS_SUCCESS; 1010 + Status = 0; 1011 + if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg)) 1012 + Status = -EFAULT; 1011 1013 break; 1012 1014 case IOCTL_CHIP_RESET: 1013 1015 { ··· 1030 1028 case IOCTL_QOS_THRESHOLD: 1031 1029 { 1032 1030 USHORT uiLoopIndex; 1033 - for(uiLoopIndex = 0 ; uiLoopIndex < NO_OF_QUEUES ; uiLoopIndex++) 1034 - { 1035 - Adapter->PackInfo[uiLoopIndex].uiThreshold = *(PULONG)arg; 1031 + 1032 + Status = 0; 1033 + for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) { 1034 + if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold, 1035 + (unsigned long __user *)arg)) { 1036 + Status = -EFAULT; 1037 + break; 1038 + } 1036 1039 } 1037 - Status = STATUS_SUCCESS; 1038 1040 break; 1039 1041 } 1040 1042 ··· 1099 1093 } 1100 1094 case IOCTL_BCM_GET_CURRENT_STATUS: 1101 1095 { 1102 - LINK_STATE *plink_state = NULL; 1096 + LINK_STATE plink_state; 1097 + 1103 1098 /* Copy Ioctl Buffer structure */ 1104 1099 if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) 1105 1100 { ··· 1108 1101 Status = -EFAULT; 1109 1102 break; 1110 1103 } 1111 - plink_state = (LINK_STATE*)arg; 1112 - plink_state->bIdleMode = (UCHAR)Adapter->IdleMode; 1113 - plink_state->bShutdownMode = Adapter->bShutStatus; 1114 - plink_state->ucLinkStatus = (UCHAR)Adapter->LinkStatus; 1115 - if(copy_to_user(IoBuffer.OutputBuffer, 1116 - (PUCHAR)plink_state, (UINT)IoBuffer.OutputLength)) 1117 - { 1104 + if (IoBuffer.OutputLength != sizeof(plink_state)) { 1105 + Status = -EINVAL; 1106 + break; 1107 + } 1108 + 1109 + if (copy_from_user(&plink_state, (void __user *)arg, sizeof(plink_state))) { 1110 + Status = -EFAULT; 1111 + break; 1112 + } 1113 + plink_state.bIdleMode = (UCHAR)Adapter->IdleMode; 1114 + plink_state.bShutdownMode = Adapter->bShutStatus; 1115 + plink_state.ucLinkStatus = (UCHAR)Adapter->LinkStatus; 1116 + if (copy_to_user(IoBuffer.OutputBuffer, &plink_state, IoBuffer.OutputLength)) { 1118 1117 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); 1119 1118 Status = -EFAULT; 1120 1119 break; ··· 1344 1331 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy From User space failed. status :%d", Status); 1345 1332 return -EFAULT; 1346 1333 } 1347 - uiSectorSize = *((PUINT)(IoBuffer.InputBuffer)); /* FIXME: unchecked __user access */ 1334 + if (get_user(uiSectorSize, (unsigned int __user *)IoBuffer.InputBuffer)) 1335 + return -EFAULT; 1336 + 1348 1337 if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) 1349 1338 { 1350 1339
+1 -1
drivers/staging/brcm80211/README
··· 90 90 ============= 91 91 Brett Rudley brudley@broadcom.com 92 92 Henry Ptasinski henryp@broadcom.com 93 - Nohee Ko noheek@broadcom.com 93 + Dowan Kim dowan@broadcom.com 94 94
+1 -1
drivers/staging/brcm80211/TODO
··· 45 45 ===== 46 46 Brett Rudley <brudley@broadcom.com> 47 47 Henry Ptasinski <henryp@broadcom.com> 48 - Nohee Ko <noheek@broadcom.com> 48 + Dowan Kim <dowan@broadcom.com> 49 49
-2
drivers/staging/brcm80211/brcmfmac/dhd_linux.c
··· 2222 2222 ASSERT(net); 2223 2223 2224 2224 ASSERT(!net->netdev_ops); 2225 - net->netdev_ops = &dhd_ops_virt; 2226 - 2227 2225 net->netdev_ops = &dhd_ops_pri; 2228 2226 2229 2227 /*
+6 -6
drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
··· 95 95 struct net_device *dev, 96 96 u8 key_idx); 97 97 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, 98 - u8 key_idx, const u8 *mac_addr, 98 + u8 key_idx, bool pairwise, const u8 *mac_addr, 99 99 struct key_params *params); 100 100 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, 101 - u8 key_idx, const u8 *mac_addr); 101 + u8 key_idx, bool pairwise, const u8 *mac_addr); 102 102 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, 103 - u8 key_idx, const u8 *mac_addr, 103 + u8 key_idx, bool pairwise, const u8 *mac_addr, 104 104 void *cookie, void (*callback) (void *cookie, 105 105 struct 106 106 key_params * ··· 1615 1615 1616 1616 static s32 1617 1617 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, 1618 - u8 key_idx, const u8 *mac_addr, 1618 + u8 key_idx, bool pairwise, const u8 *mac_addr, 1619 1619 struct key_params *params) 1620 1620 { 1621 1621 struct wl_wsec_key key; ··· 1700 1700 1701 1701 static s32 1702 1702 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, 1703 - u8 key_idx, const u8 *mac_addr) 1703 + u8 key_idx, bool pairwise, const u8 *mac_addr) 1704 1704 { 1705 1705 struct wl_wsec_key key; 1706 1706 s32 err = 0; ··· 1756 1756 1757 1757 static s32 1758 1758 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, 1759 - u8 key_idx, const u8 *mac_addr, void *cookie, 1759 + u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, 1760 1760 void (*callback) (void *cookie, struct key_params * params)) 1761 1761 { 1762 1762 struct key_params params;
+1 -5
drivers/staging/cpia/cpia.c
··· 3184 3184 goto oops; 3185 3185 } 3186 3186 3187 - err = -EINTR; 3188 - if(signal_pending(current)) 3189 - goto oops; 3190 - 3191 3187 /* Set ownership of /proc/cpia/videoX to current user */ 3192 3188 if(cam->proc_entry) 3193 - cam->proc_entry->uid = current_uid(); 3189 + cam->proc_entry->uid = current_euid(); 3194 3190 3195 3191 /* set mark for loading first frame uncompressed */ 3196 3192 cam->first_frame = 1;
-1
drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c
··· 286 286 pid = kernel_thread (exec_mknod, (void *)info, 0); 287 287 288 288 // initialize application information 289 - info->appcnt = 0; 290 289 291 290 // if (ft1000_flarion_cnt == 0) { 292 291 //
-3
drivers/staging/hv/hv_utils.c
··· 212 212 recvlen, requestid); 213 213 214 214 icmsghdrp = (struct icmsg_hdr *)&buf[ 215 - sizeof(struct vmbuspipe_hdr)]; 216 - 217 - icmsghdrp = (struct icmsg_hdr *)&buf[ 218 215 sizeof(struct vmbuspipe_hdr)]; 219 216 220 217 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+169 -127
drivers/staging/intel_sst/intel_sst_app_interface.c
··· 244 244 int retval, i; 245 245 struct stream_info *stream; 246 246 struct snd_sst_mmap_buff_entry *buf_entry; 247 + struct snd_sst_mmap_buff_entry *tmp_buf; 247 248 248 249 pr_debug("sst:called for str_id %d\n", str_id); 249 250 retval = sst_validate_strid(str_id); 250 251 if (retval) 251 252 return -EINVAL; 252 - BUG_ON(!mmap_buf); 253 253 254 254 stream = &sst_drv_ctx->streams[str_id]; 255 255 if (stream->mmapped != true) ··· 262 262 stream->curr_bytes = 0; 263 263 stream->cumm_bytes = 0; 264 264 265 + tmp_buf = kcalloc(mmap_buf->entries, sizeof(*tmp_buf), GFP_KERNEL); 266 + if (!tmp_buf) 267 + return -ENOMEM; 268 + if (copy_from_user(tmp_buf, (void __user *)mmap_buf->buff, 269 + mmap_buf->entries * sizeof(*tmp_buf))) { 270 + retval = -EFAULT; 271 + goto out_free; 272 + } 273 + 265 274 pr_debug("sst:new buffers count %d status %d\n", 266 275 mmap_buf->entries, stream->status); 267 - buf_entry = mmap_buf->buff; 276 + buf_entry = tmp_buf; 268 277 for (i = 0; i < mmap_buf->entries; i++) { 269 - BUG_ON(!buf_entry); 270 278 bufs = kzalloc(sizeof(*bufs), GFP_KERNEL); 271 - if (!bufs) 272 - return -ENOMEM; 279 + if (!bufs) { 280 + retval = -ENOMEM; 281 + goto out_free; 282 + } 273 283 bufs->size = buf_entry->size; 274 284 bufs->offset = buf_entry->offset; 275 285 bufs->addr = sst_drv_ctx->mmap_mem; ··· 303 293 if (sst_play_frame(str_id) < 0) { 304 294 pr_warn("sst: play frames fail\n"); 305 295 mutex_unlock(&stream->lock); 306 - return -EIO; 296 + retval = -EIO; 297 + goto out_free; 307 298 } 308 299 } else if (stream->ops == STREAM_OPS_CAPTURE) { 309 300 if (sst_capture_frame(str_id) < 0) { 310 301 pr_warn("sst: capture frame fail\n"); 311 302 mutex_unlock(&stream->lock); 312 - return -EIO; 303 + retval = -EIO; 304 + goto out_free; 313 305 } 314 306 } 315 307 } ··· 326 314 if (retval >= 0) 327 315 retval = stream->cumm_bytes; 328 316 pr_debug("sst:end of play/rec ioctl bytes = %d!!\n", retval); 317 + 318 + out_free: 319 + kfree(tmp_buf); 329 320 return retval; 330 321 } 331 322 ··· 392 377 { 393 378 struct sst_stream_bufs *stream_bufs; 394 379 unsigned long index, mmap_len; 395 - unsigned char *bufp; 380 + unsigned char __user *bufp; 396 381 unsigned long size, copied_size; 397 382 int retval = 0, add_to_list = 0; 398 383 static int sent_offset; ··· 527 512 /* copy to user */ 528 513 list_for_each_entry_safe(entry, _entry, 529 514 copy_to_list, node) { 530 - if (copy_to_user((void *) 531 - iovec[entry->iov_index].iov_base + 532 - entry->iov_offset, 515 + if (copy_to_user(iovec[entry->iov_index].iov_base + entry->iov_offset, 533 516 kbufs->addr + entry->offset, 534 517 entry->size)) { 535 518 /* Clean up the list and return error */ ··· 603 590 buf, (int) count, (int) stream->status); 604 591 605 592 stream->buf_type = SST_BUF_USER_STATIC; 606 - iovec.iov_base = (void *)buf; 593 + iovec.iov_base = buf; 607 594 iovec.iov_len = count; 608 595 nr_segs = 1; 609 596 ··· 851 838 break; 852 839 853 840 case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): { 854 - struct snd_sst_params *str_param = (struct snd_sst_params *)arg; 841 + struct snd_sst_params str_param; 855 842 856 843 pr_debug("sst: IOCTL_SET_PARAMS recieved!\n"); 857 844 if (minor != STREAM_MODULE) { ··· 859 846 break; 860 847 } 861 848 849 + if (copy_from_user(&str_param, (void __user *)arg, 850 + sizeof(str_param))) { 851 + retval = -EFAULT; 852 + break; 853 + } 854 + 862 855 if (!str_id) { 863 856 864 - retval = sst_get_stream(str_param); 857 + retval = sst_get_stream(&str_param); 865 858 if (retval > 0) { 866 859 struct stream_info *str_info; 860 + char __user *dest; 861 + 867 862 sst_drv_ctx->stream_cnt++; 868 863 data->str_id = retval; 869 864 str_info = &sst_drv_ctx->streams[retval]; 870 865 str_info->src = SST_DRV; 871 - retval = copy_to_user(&str_param->stream_id, 872 - &retval, sizeof(__u32)); 866 + dest = (char __user *)arg + offsetof(struct snd_sst_params, stream_id); 867 + retval = copy_to_user(dest, &retval, sizeof(__u32)); 873 868 if (retval) 874 869 retval = -EFAULT; 875 870 } else { ··· 887 866 } else { 888 867 pr_debug("sst: SET_STREAM_PARAMS recieved!\n"); 889 868 /* allocated set params only */ 890 - retval = sst_set_stream_param(str_id, str_param); 869 + retval = sst_set_stream_param(str_id, &str_param); 891 870 /* Block the call for reply */ 892 871 if (!retval) { 893 872 int sfreq = 0, word_size = 0, num_channel = 0; 894 - sfreq = str_param->sparams.uc.pcm_params.sfreq; 895 - word_size = str_param->sparams. 896 - uc.pcm_params.pcm_wd_sz; 897 - num_channel = str_param-> 898 - sparams.uc.pcm_params.num_chan; 899 - if (str_param->ops == STREAM_OPS_CAPTURE) { 873 + sfreq = str_param.sparams.uc.pcm_params.sfreq; 874 + word_size = str_param.sparams.uc.pcm_params.pcm_wd_sz; 875 + num_channel = str_param.sparams.uc.pcm_params.num_chan; 876 + if (str_param.ops == STREAM_OPS_CAPTURE) { 900 877 sst_drv_ctx->scard_ops->\ 901 878 set_pcm_audio_params(sfreq, 902 879 word_size, num_channel); ··· 904 885 break; 905 886 } 906 887 case _IOC_NR(SNDRV_SST_SET_VOL): { 907 - struct snd_sst_vol *set_vol; 908 - struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg; 909 - pr_debug("sst: SET_VOLUME recieved for %d!\n", 910 - rec_vol->stream_id); 911 - if (minor == STREAM_MODULE && rec_vol->stream_id == 0) { 912 - pr_debug("sst: invalid operation!\n"); 913 - retval = -EPERM; 914 - break; 915 - } 916 - set_vol = kzalloc(sizeof(*set_vol), GFP_ATOMIC); 917 - if (!set_vol) { 918 - pr_debug("sst: mem allocation failed\n"); 919 - retval = -ENOMEM; 920 - break; 921 - } 922 - if (copy_from_user(set_vol, rec_vol, sizeof(*set_vol))) { 888 + struct snd_sst_vol set_vol; 889 + 890 + if (copy_from_user(&set_vol, (void __user *)arg, 891 + sizeof(set_vol))) { 923 892 pr_debug("sst: copy failed\n"); 924 893 retval = -EFAULT; 925 894 break; 926 895 } 927 - retval = sst_set_vol(set_vol); 928 - kfree(set_vol); 929 - break; 930 - } 931 - case _IOC_NR(SNDRV_SST_GET_VOL): { 932 - struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg; 933 - struct snd_sst_vol get_vol; 934 - pr_debug("sst: IOCTL_GET_VOLUME recieved for stream = %d!\n", 935 - rec_vol->stream_id); 936 - if (minor == STREAM_MODULE && rec_vol->stream_id == 0) { 896 + pr_debug("sst: SET_VOLUME recieved for %d!\n", 897 + set_vol.stream_id); 898 + if (minor == STREAM_MODULE && set_vol.stream_id == 0) { 937 899 pr_debug("sst: invalid operation!\n"); 938 900 retval = -EPERM; 939 901 break; 940 902 } 941 - get_vol.stream_id = rec_vol->stream_id; 903 + retval = sst_set_vol(&set_vol); 904 + break; 905 + } 906 + case _IOC_NR(SNDRV_SST_GET_VOL): { 907 + struct snd_sst_vol get_vol; 908 + 909 + if (copy_from_user(&get_vol, (void __user *)arg, 910 + sizeof(get_vol))) { 911 + retval = -EFAULT; 912 + break; 913 + } 914 + pr_debug("sst: IOCTL_GET_VOLUME recieved for stream = %d!\n", 915 + get_vol.stream_id); 916 + if (minor == STREAM_MODULE && get_vol.stream_id == 0) { 917 + pr_debug("sst: invalid operation!\n"); 918 + retval = -EPERM; 919 + break; 920 + } 942 921 retval = sst_get_vol(&get_vol); 943 922 if (retval) { 944 923 retval = -EIO; ··· 945 928 pr_debug("sst: id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n", 946 929 get_vol.stream_id, get_vol.volume, 947 930 get_vol.ramp_duration, get_vol.ramp_type); 948 - if (copy_to_user((struct snd_sst_vol *)arg, 931 + if (copy_to_user((struct snd_sst_vol __user *)arg, 949 932 &get_vol, sizeof(get_vol))) { 950 933 retval = -EFAULT; 951 934 break; ··· 955 938 } 956 939 957 940 case _IOC_NR(SNDRV_SST_MUTE): { 958 - struct snd_sst_mute *set_mute; 959 - struct snd_sst_vol *rec_mute = (struct snd_sst_vol *)arg; 960 - pr_debug("sst: SNDRV_SST_SET_VOLUME recieved for %d!\n", 961 - rec_mute->stream_id); 962 - if (minor == STREAM_MODULE && rec_mute->stream_id == 0) { 963 - retval = -EPERM; 964 - break; 965 - } 966 - set_mute = kzalloc(sizeof(*set_mute), GFP_ATOMIC); 967 - if (!set_mute) { 968 - retval = -ENOMEM; 969 - break; 970 - } 971 - if (copy_from_user(set_mute, rec_mute, sizeof(*set_mute))) { 941 + struct snd_sst_mute set_mute; 942 + 943 + if (copy_from_user(&set_mute, (void __user *)arg, 944 + sizeof(set_mute))) { 972 945 retval = -EFAULT; 973 946 break; 974 947 } 975 - retval = sst_set_mute(set_mute); 976 - kfree(set_mute); 948 + pr_debug("sst: SNDRV_SST_SET_VOLUME recieved for %d!\n", 949 + set_mute.stream_id); 950 + if (minor == STREAM_MODULE && set_mute.stream_id == 0) { 951 + retval = -EPERM; 952 + break; 953 + } 954 + retval = sst_set_mute(&set_mute); 977 955 break; 978 956 } 979 957 case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): { ··· 985 973 retval = -EIO; 986 974 break; 987 975 } 988 - if (copy_to_user((struct snd_sst_get_stream_params *)arg, 976 + if (copy_to_user((struct snd_sst_get_stream_params __user *)arg, 989 977 &get_params, sizeof(get_params))) { 990 978 retval = -EFAULT; 991 979 break; ··· 995 983 } 996 984 997 985 case _IOC_NR(SNDRV_SST_MMAP_PLAY): 998 - case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): 986 + case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): { 987 + struct snd_sst_mmap_buffs mmap_buf; 988 + 999 989 pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n"); 1000 990 if (minor != STREAM_MODULE) { 1001 991 retval = -EBADRQC; 1002 992 break; 1003 993 } 1004 - retval = intel_sst_mmap_play_capture(str_id, 1005 - (struct snd_sst_mmap_buffs *)arg); 994 + if (copy_from_user(&mmap_buf, (void __user *)arg, 995 + sizeof(mmap_buf))) { 996 + retval = -EFAULT; 997 + break; 998 + } 999 + retval = intel_sst_mmap_play_capture(str_id, &mmap_buf); 1006 1000 break; 1007 - 1001 + } 1008 1002 case _IOC_NR(SNDRV_SST_STREAM_DROP): 1009 1003 pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n"); 1010 1004 if (minor != STREAM_MODULE) { ··· 1021 1003 break; 1022 1004 1023 1005 case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): { 1024 - unsigned long long *ms = (unsigned long long *)arg; 1025 1006 struct snd_sst_tstamp tstamp = {0}; 1026 1007 unsigned long long time, freq, mod; 1027 1008 ··· 1030 1013 break; 1031 1014 } 1032 1015 memcpy_fromio(&tstamp, 1033 - ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP) 1034 - +(str_id * sizeof(tstamp))), 1016 + sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp), 1035 1017 sizeof(tstamp)); 1036 1018 time = tstamp.samples_rendered; 1037 1019 freq = (unsigned long long) tstamp.sampling_frequency; 1038 1020 time = time * 1000; /* converting it to ms */ 1039 1021 mod = do_div(time, freq); 1040 - if (copy_to_user(ms, &time, sizeof(*ms))) 1022 + if (copy_to_user((void __user *)arg, &time, 1023 + sizeof(unsigned long long))) 1041 1024 retval = -EFAULT; 1042 1025 break; 1043 1026 } ··· 1082 1065 } 1083 1066 1084 1067 case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): { 1085 - struct snd_sst_target_device *target_device; 1068 + struct snd_sst_target_device target_device; 1086 1069 1087 1070 pr_debug("sst: SET_TARGET_DEVICE recieved!\n"); 1088 - target_device = (struct snd_sst_target_device *)arg; 1089 - BUG_ON(!target_device); 1071 + if (copy_from_user(&target_device, (void __user *)arg, 1072 + sizeof(target_device))) { 1073 + retval = -EFAULT; 1074 + break; 1075 + } 1090 1076 if (minor != AM_MODULE) { 1091 1077 retval = -EBADRQC; 1092 1078 break; 1093 1079 } 1094 - retval = sst_target_device_select(target_device); 1080 + retval = sst_target_device_select(&target_device); 1095 1081 break; 1096 1082 } 1097 1083 1098 1084 case _IOC_NR(SNDRV_SST_DRIVER_INFO): { 1099 - struct snd_sst_driver_info *info = 1100 - (struct snd_sst_driver_info *)arg; 1085 + struct snd_sst_driver_info info; 1101 1086 1102 1087 pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n"); 1103 - info->version = SST_VERSION_NUM; 1088 + info.version = SST_VERSION_NUM; 1104 1089 /* hard coding, shud get sumhow later */ 1105 - info->active_pcm_streams = sst_drv_ctx->stream_cnt - 1090 + info.active_pcm_streams = sst_drv_ctx->stream_cnt - 1106 1091 sst_drv_ctx->encoded_cnt; 1107 - info->active_enc_streams = sst_drv_ctx->encoded_cnt; 1108 - info->max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM; 1109 - info->max_enc_streams = MAX_ENC_STREAM; 1110 - info->buf_per_stream = sst_drv_ctx->mmap_len; 1092 + info.active_enc_streams = sst_drv_ctx->encoded_cnt; 1093 + info.max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM; 1094 + info.max_enc_streams = MAX_ENC_STREAM; 1095 + info.buf_per_stream = sst_drv_ctx->mmap_len; 1096 + if (copy_to_user((void __user *)arg, &info, 1097 + sizeof(info))) 1098 + retval = -EFAULT; 1111 1099 break; 1112 1100 } 1113 1101 1114 1102 case _IOC_NR(SNDRV_SST_STREAM_DECODE): { 1115 - struct snd_sst_dbufs *param = 1116 - (struct snd_sst_dbufs *)arg, dbufs_local; 1117 - int i; 1103 + struct snd_sst_dbufs param; 1104 + struct snd_sst_dbufs dbufs_local; 1118 1105 struct snd_sst_buffs ibufs, obufs; 1119 - struct snd_sst_buff_entry ibuf_temp[param->ibufs->entries], 1120 - obuf_temp[param->obufs->entries]; 1106 + struct snd_sst_buff_entry *ibuf_tmp, *obuf_tmp; 1107 + char __user *dest; 1121 1108 1122 1109 pr_debug("sst: SNDRV_SST_STREAM_DECODE recived\n"); 1123 1110 if (minor != STREAM_MODULE) { 1124 1111 retval = -EBADRQC; 1125 1112 break; 1126 1113 } 1127 - if (!param) { 1128 - retval = -EINVAL; 1114 + if (copy_from_user(&param, (void __user *)arg, 1115 + sizeof(param))) { 1116 + retval = -EFAULT; 1129 1117 break; 1130 1118 } 1131 1119 1132 - dbufs_local.input_bytes_consumed = param->input_bytes_consumed; 1120 + dbufs_local.input_bytes_consumed = param.input_bytes_consumed; 1133 1121 dbufs_local.output_bytes_produced = 1134 - param->output_bytes_produced; 1135 - dbufs_local.ibufs = &ibufs; 1136 - dbufs_local.obufs = &obufs; 1137 - dbufs_local.ibufs->entries = param->ibufs->entries; 1138 - dbufs_local.ibufs->type = param->ibufs->type; 1139 - dbufs_local.obufs->entries = param->obufs->entries; 1140 - dbufs_local.obufs->type = param->obufs->type; 1122 + param.output_bytes_produced; 1141 1123 1142 - dbufs_local.ibufs->buff_entry = ibuf_temp; 1143 - for (i = 0; i < dbufs_local.ibufs->entries; i++) { 1144 - ibuf_temp[i].buffer = 1145 - param->ibufs->buff_entry[i].buffer; 1146 - ibuf_temp[i].size = 1147 - param->ibufs->buff_entry[i].size; 1124 + if (copy_from_user(&ibufs, (void __user *)param.ibufs, sizeof(ibufs))) { 1125 + retval = -EFAULT; 1126 + break; 1148 1127 } 1149 - dbufs_local.obufs->buff_entry = obuf_temp; 1150 - for (i = 0; i < dbufs_local.obufs->entries; i++) { 1151 - obuf_temp[i].buffer = 1152 - param->obufs->buff_entry[i].buffer; 1153 - obuf_temp[i].size = 1154 - param->obufs->buff_entry[i].size; 1128 + if (copy_from_user(&obufs, (void __user *)param.obufs, sizeof(obufs))) { 1129 + retval = -EFAULT; 1130 + break; 1155 1131 } 1132 + 1133 + ibuf_tmp = kcalloc(ibufs.entries, sizeof(*ibuf_tmp), GFP_KERNEL); 1134 + obuf_tmp = kcalloc(obufs.entries, sizeof(*obuf_tmp), GFP_KERNEL); 1135 + if (!ibuf_tmp || !obuf_tmp) { 1136 + retval = -ENOMEM; 1137 + goto free_iobufs; 1138 + } 1139 + 1140 + if (copy_from_user(ibuf_tmp, (void __user *)ibufs.buff_entry, 1141 + ibufs.entries * sizeof(*ibuf_tmp))) { 1142 + retval = -EFAULT; 1143 + goto free_iobufs; 1144 + } 1145 + ibufs.buff_entry = ibuf_tmp; 1146 + dbufs_local.ibufs = &ibufs; 1147 + 1148 + if (copy_from_user(obuf_tmp, (void __user *)obufs.buff_entry, 1149 + obufs.entries * sizeof(*obuf_tmp))) { 1150 + retval = -EFAULT; 1151 + goto free_iobufs; 1152 + } 1153 + obufs.buff_entry = obuf_tmp; 1154 + dbufs_local.obufs = &obufs; 1155 + 1156 1156 retval = sst_decode(str_id, &dbufs_local); 1157 - if (retval) 1158 - retval = -EAGAIN; 1159 - if (copy_to_user(&param->input_bytes_consumed, 1157 + if (retval) { 1158 + retval = -EAGAIN; 1159 + goto free_iobufs; 1160 + } 1161 + 1162 + dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed); 1163 + if (copy_to_user(dest, 1160 1164 &dbufs_local.input_bytes_consumed, 1161 1165 sizeof(unsigned long long))) { 1162 - retval = -EFAULT; 1163 - break; 1166 + retval = -EFAULT; 1167 + goto free_iobufs; 1164 1168 } 1165 - if (copy_to_user(&param->output_bytes_produced, 1169 + 1170 + dest = (char __user *)arg + offsetof(struct snd_sst_dbufs, input_bytes_consumed); 1171 + if (copy_to_user(dest, 1166 1172 &dbufs_local.output_bytes_produced, 1167 1173 sizeof(unsigned long long))) { 1168 - retval = -EFAULT; 1169 - break; 1174 + retval = -EFAULT; 1175 + goto free_iobufs; 1170 1176 } 1177 + free_iobufs: 1178 + kfree(ibuf_tmp); 1179 + kfree(obuf_tmp); 1171 1180 break; 1172 1181 } 1173 1182 ··· 1207 1164 break; 1208 1165 1209 1166 case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): { 1210 - unsigned long long *bytes = (unsigned long long *)arg; 1167 + unsigned long long __user *bytes = (unsigned long long __user *)arg; 1211 1168 struct snd_sst_tstamp tstamp = {0}; 1212 1169 1213 1170 pr_debug("sst: STREAM_BYTES_DECODED recieved!\n"); ··· 1216 1173 break; 1217 1174 } 1218 1175 memcpy_fromio(&tstamp, 1219 - ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP) 1220 - +(str_id * sizeof(tstamp))), 1176 + sst_drv_ctx->mailbox + SST_TIME_STAMP + str_id * sizeof(tstamp), 1221 1177 sizeof(tstamp)); 1222 1178 if (copy_to_user(bytes, &tstamp.bytes_processed, 1223 1179 sizeof(*bytes))) ··· 1239 1197 kfree(fw_info); 1240 1198 break; 1241 1199 } 1242 - if (copy_to_user((struct snd_sst_dbufs *)arg, 1200 + if (copy_to_user((struct snd_sst_dbufs __user *)arg, 1243 1201 fw_info, sizeof(*fw_info))) { 1244 1202 kfree(fw_info); 1245 1203 retval = -EFAULT;
+2 -2
drivers/staging/intel_sst/intel_sst_common.h
··· 231 231 spinlock_t pcm_lock; 232 232 bool mmapped; 233 233 unsigned int sg_index; /* current buf Index */ 234 - unsigned char *cur_ptr; /* Current static bufs */ 235 - struct snd_sst_buf_entry *buf_entry; 234 + unsigned char __user *cur_ptr; /* Current static bufs */ 235 + struct snd_sst_buf_entry __user *buf_entry; 236 236 struct sst_block data_blk; /* stream ops block */ 237 237 struct sst_block ctrl_blk; /* stream control cmd block */ 238 238 enum snd_sst_buf_type buf_type;
+9 -9
drivers/staging/keucr/init.c
··· 22 22 int result; 23 23 BYTE MiscReg03 = 0; 24 24 25 - printk("--- Initial Nedia ---\n"); 25 + printk("--- Init Media ---\n"); 26 26 result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03); 27 27 if (result != USB_STOR_XFER_GOOD) 28 28 { ··· 64 64 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; 65 65 int result; 66 66 67 - memset(bcb, 0, sizeof(bcb)); 67 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 68 68 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 69 69 bcb->DataTransferLength = 0x01; 70 70 bcb->Flags = 0x80; ··· 92 92 return USB_STOR_TRANSPORT_ERROR; 93 93 } 94 94 95 - memset(bcb, 0, sizeof(bcb)); 95 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 96 96 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 97 97 bcb->Flags = 0x80; 98 98 bcb->CDB[0] = 0xF2; ··· 112 112 return USB_STOR_TRANSPORT_ERROR; 113 113 } 114 114 115 - memset(bcb, 0, sizeof(bcb)); 115 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 116 116 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 117 117 bcb->DataTransferLength = 0x200; 118 118 bcb->Flags = 0x80; ··· 161 161 return USB_STOR_TRANSPORT_ERROR; 162 162 } 163 163 164 - memset(bcb, 0, sizeof(bcb)); 164 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 165 165 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 166 166 bcb->DataTransferLength = 0x200; 167 167 bcb->Flags = 0x80; ··· 219 219 return USB_STOR_TRANSPORT_ERROR; 220 220 } 221 221 222 - memset(bcb, 0, sizeof(bcb)); 222 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 223 223 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 224 224 bcb->DataTransferLength = 0x200; 225 225 bcb->Flags = 0x80; ··· 341 341 break; 342 342 } 343 343 344 - memset(bcb, 0, sizeof(bcb)); 344 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 345 345 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 346 346 bcb->DataTransferLength = 0x800; 347 347 bcb->Flags =0x00; ··· 433 433 434 434 //printk("transport --- ENE_Read_Data\n"); 435 435 // set up the command wrapper 436 - memset(bcb, 0, sizeof(bcb)); 436 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 437 437 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 438 438 bcb->DataTransferLength = length; 439 439 bcb->Flags =0x80; ··· 470 470 471 471 //printk("transport --- ENE_Write_Data\n"); 472 472 // set up the command wrapper 473 - memset(bcb, 0, sizeof(bcb)); 473 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 474 474 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 475 475 bcb->DataTransferLength = length; 476 476 bcb->Flags =0x00;
+7 -7
drivers/staging/keucr/ms.c
··· 15 15 if (result != USB_STOR_XFER_GOOD) 16 16 return USB_STOR_TRANSPORT_ERROR; 17 17 18 - memset(bcb, 0, sizeof(bcb)); 18 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 19 19 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 20 20 bcb->DataTransferLength = 0x200*len; 21 21 bcb->Flags = 0x00; ··· 53 53 return USB_STOR_TRANSPORT_ERROR; 54 54 55 55 // Read Page Data 56 - memset(bcb, 0, sizeof(bcb)); 56 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 57 57 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 58 58 bcb->DataTransferLength = 0x200; 59 59 bcb->Flags = 0x80; ··· 69 69 return USB_STOR_TRANSPORT_ERROR; 70 70 71 71 // Read Extra Data 72 - memset(bcb, 0, sizeof(bcb)); 72 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 73 73 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 74 74 bcb->DataTransferLength = 0x4; 75 75 bcb->Flags = 0x80; ··· 108 108 if (result != USB_STOR_XFER_GOOD) 109 109 return USB_STOR_TRANSPORT_ERROR; 110 110 111 - memset(bcb, 0, sizeof(bcb)); 111 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 112 112 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 113 113 bcb->DataTransferLength = 0x200; 114 114 bcb->Flags = 0x80; ··· 673 673 //printk("MS_LibReadExtraBlock --- PhyBlock = %x, PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen); 674 674 675 675 // Read Extra Data 676 - memset(bcb, 0, sizeof(bcb)); 676 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 677 677 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 678 678 bcb->DataTransferLength = 0x4 * blen; 679 679 bcb->Flags = 0x80; ··· 700 700 BYTE ExtBuf[4]; 701 701 702 702 //printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); 703 - memset(bcb, 0, sizeof(bcb)); 703 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 704 704 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 705 705 bcb->DataTransferLength = 0x4; 706 706 bcb->Flags = 0x80; ··· 807 807 if (result != USB_STOR_XFER_GOOD) 808 808 return USB_STOR_TRANSPORT_ERROR; 809 809 810 - memset(bcb, 0, sizeof(bcb)); 810 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 811 811 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 812 812 bcb->DataTransferLength = 0x4; 813 813 bcb->Flags = 0x80;
+3 -3
drivers/staging/keucr/msscsi.c
··· 145 145 } 146 146 147 147 // set up the command wrapper 148 - memset(bcb, 0, sizeof(bcb)); 148 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 149 149 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 150 150 bcb->DataTransferLength = blenByte; 151 151 bcb->Flags = 0x80; ··· 193 193 blkno = phyblk * 0x20 + PageNum; 194 194 195 195 // set up the command wrapper 196 - memset(bcb, 0, sizeof(bcb)); 196 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 197 197 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 198 198 bcb->DataTransferLength = 0x200 * len; 199 199 bcb->Flags = 0x80; ··· 250 250 } 251 251 252 252 // set up the command wrapper 253 - memset(bcb, 0, sizeof(bcb)); 253 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 254 254 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 255 255 bcb->DataTransferLength = blenByte; 256 256 bcb->Flags = 0x00;
+2 -2
drivers/staging/keucr/sdscsi.c
··· 152 152 bnByte = bn; 153 153 154 154 // set up the command wrapper 155 - memset(bcb, 0, sizeof(bcb)); 155 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 156 156 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 157 157 bcb->DataTransferLength = blenByte; 158 158 bcb->Flags = 0x80; ··· 192 192 bnByte = bn; 193 193 194 194 // set up the command wrapper 195 - memset(bcb, 0, sizeof(bcb)); 195 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 196 196 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 197 197 bcb->DataTransferLength = blenByte; 198 198 bcb->Flags = 0x00;
+9 -9
drivers/staging/keucr/smilsub.c
··· 266 266 addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; 267 267 268 268 // Read sect data 269 - memset(bcb, 0, sizeof(bcb)); 269 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 270 270 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 271 271 bcb->DataTransferLength = 0x200; 272 272 bcb->Flags = 0x80; ··· 281 281 return USB_STOR_TRANSPORT_ERROR; 282 282 283 283 // Read redundant 284 - memset(bcb, 0, sizeof(bcb)); 284 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 285 285 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 286 286 bcb->DataTransferLength = 0x10; 287 287 bcb->Flags = 0x80; ··· 319 319 addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; 320 320 321 321 // Read sect data 322 - memset(bcb, 0, sizeof(bcb)); 322 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 323 323 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 324 324 bcb->DataTransferLength = 0x200*count; 325 325 bcb->Flags = 0x80; ··· 334 334 return USB_STOR_TRANSPORT_ERROR; 335 335 336 336 // Read redundant 337 - memset(bcb, 0, sizeof(bcb)); 337 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 338 338 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 339 339 bcb->DataTransferLength = 0x10; 340 340 bcb->Flags = 0x80; ··· 536 536 WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors; 537 537 538 538 // Write sect data 539 - memset(bcb, 0, sizeof(bcb)); 539 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 540 540 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 541 541 bcb->DataTransferLength = 0x200*count; 542 542 bcb->Flags = 0x00; ··· 754 754 addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; 755 755 756 756 // Write sect data 757 - memset(bcb, 0, sizeof(bcb)); 757 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 758 758 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 759 759 bcb->DataTransferLength = 0x200; 760 760 bcb->Flags = 0x00; ··· 791 791 addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; 792 792 addr=addr*(WORD)Ssfdc.MaxSectors; 793 793 794 - memset(bcb, 0, sizeof(bcb)); 794 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 795 795 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 796 796 bcb->DataTransferLength = 0x200; 797 797 bcb->Flags = 0x80; ··· 827 827 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; 828 828 addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; 829 829 830 - memset(bcb, 0, sizeof(bcb)); 830 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 831 831 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 832 832 bcb->DataTransferLength = 0x10; 833 833 bcb->Flags = 0x80; ··· 870 870 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock; 871 871 addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector; 872 872 873 - memset(bcb, 0, sizeof(bcb)); 873 + memset(bcb, 0, sizeof(struct bulk_cb_wrap)); 874 874 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); 875 875 bcb->DataTransferLength = 0x10; 876 876 bcb->Flags = 0x80;
+1 -1
drivers/staging/keucr/transport.c
··· 40 40 us->current_urb->error_count = 0; 41 41 us->current_urb->status = 0; 42 42 43 - // us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP; 43 + us->current_urb->transfer_flags = 0; 44 44 if (us->current_urb->transfer_buffer == us->iobuf) 45 45 us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 46 46 us->current_urb->transfer_dma = us->iobuf_dma;
-2
drivers/staging/rt2860/common/cmm_aes.c
··· 330 330 for (i = 8; i < 14; i++) 331 331 mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ 332 332 #endif 333 - i = (payload_length / 256); 334 - i = (payload_length % 256); 335 333 mic_iv[14] = (unsigned char)(payload_length / 256); 336 334 mic_iv[15] = (unsigned char)(payload_length % 256); 337 335
+1
drivers/staging/rt2860/usb_main_dev.c
··· 65 65 {USB_DEVICE(0x14B2, 0x3C07)}, /* AL */ 66 66 {USB_DEVICE(0x050D, 0x8053)}, /* Belkin */ 67 67 {USB_DEVICE(0x050D, 0x825B)}, /* Belkin */ 68 + {USB_DEVICE(0x050D, 0x935A)}, /* Belkin F6D4050 v1 */ 68 69 {USB_DEVICE(0x050D, 0x935B)}, /* Belkin F6D4050 v2 */ 69 70 {USB_DEVICE(0x14B2, 0x3C23)}, /* Airlink */ 70 71 {USB_DEVICE(0x14B2, 0x3C27)}, /* Airlink */
+3
drivers/staging/rtl8192e/r8192E_core.c
··· 5829 5829 } 5830 5830 } 5831 5831 5832 + pci_unmap_single(priv->pdev, *((dma_addr_t *) skb->cb), 5833 + priv->rxbuffersize, PCI_DMA_FROMDEVICE); 5834 + 5832 5835 skb = new_skb; 5833 5836 priv->rx_buf[priv->rx_idx] = skb; 5834 5837 *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+10 -1
drivers/staging/stradis/stradis.c
··· 1286 1286 case VIDIOCGCAP: 1287 1287 { 1288 1288 struct video_capability b; 1289 + memset(&b, 0, sizeof(b)); 1289 1290 strcpy(b.name, saa->video_dev.name); 1290 1291 b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | 1291 1292 VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | ··· 1417 1416 case VIDIOCGWIN: 1418 1417 { 1419 1418 struct video_window vw; 1419 + memset(&vw, 0, sizeof(vw)); 1420 1420 vw.x = saa->win.x; 1421 1421 vw.y = saa->win.y; 1422 1422 vw.width = saa->win.width; ··· 1450 1448 case VIDIOCGFBUF: 1451 1449 { 1452 1450 struct video_buffer v; 1451 + memset(&v, 0, sizeof(v)); 1453 1452 v.base = (void *)saa->win.vidadr; 1454 1453 v.height = saa->win.sheight; 1455 1454 v.width = saa->win.swidth; ··· 1495 1492 case VIDIOCGAUDIO: 1496 1493 { 1497 1494 struct video_audio v; 1495 + memset(&v, 0, sizeof(v)); 1498 1496 v = saa->audio_dev; 1499 1497 v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); 1500 1498 v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; ··· 1538 1534 case VIDIOCGUNIT: 1539 1535 { 1540 1536 struct video_unit vu; 1537 + memset(&vu, 0, sizeof(vu)); 1541 1538 vu.video = saa->video_dev.minor; 1542 1539 vu.vbi = VIDEO_NO_UNIT; 1543 1540 vu.radio = VIDEO_NO_UNIT; ··· 1893 1888 1894 1889 saa->user++; 1895 1890 if (saa->user > 1) { 1891 + saa->user--; 1896 1892 unlock_kernel(); 1897 1893 return 0; /* device open already, don't reset */ 1898 1894 } ··· 2006 2000 if (retval < 0) { 2007 2001 dev_err(&pdev->dev, "%d: error in registering video device!\n", 2008 2002 num); 2009 - goto errio; 2003 + goto errirq; 2010 2004 } 2011 2005 2012 2006 return 0; 2007 + 2008 + errirq: 2009 + free_irq(saa->irq, saa); 2013 2010 errio: 2014 2011 iounmap(saa->saa7146_mem); 2015 2012 err:
-1
drivers/staging/tidspbridge/Kconfig
··· 6 6 tristate "DSP Bridge driver" 7 7 depends on ARCH_OMAP3 8 8 select OMAP_MBOX_FWK 9 - select OMAP_IOMMU 10 9 help 11 10 DSP/BIOS Bridge is designed for platforms that contain a GPP and 12 11 one or more attached DSPs. The GPP is considered the master or
+4 -3
drivers/staging/tidspbridge/Makefile
··· 2 2 3 3 libgen = gen/gb.o gen/gs.o gen/gh.o gen/uuidutil.o 4 4 libcore = core/chnl_sm.o core/msg_sm.o core/io_sm.o core/tiomap3430.o \ 5 - core/tiomap3430_pwr.o core/tiomap_io.o core/dsp-mmu.o \ 5 + core/tiomap3430_pwr.o core/tiomap_io.o \ 6 6 core/ue_deh.o core/wdt.o core/dsp-clock.o core/sync.o 7 7 libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/dspapi.o \ 8 - pmgr/cmm.o pmgr/dbll.o 8 + pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o 9 9 librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \ 10 10 rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \ 11 11 rmgr/nldr.o rmgr/drv_interface.o 12 12 libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o \ 13 13 dynload/tramp.o 14 + libhw = hw/hw_mmu.o 14 15 15 16 bridgedriver-y := $(libgen) $(libservices) $(libcore) $(libpmgr) $(librmgr) \ 16 - $(libdload) 17 + $(libdload) $(libhw) 17 18 18 19 #Machine dependent 19 20 ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
+3 -2
drivers/staging/tidspbridge/core/_deh.h
··· 27 27 struct deh_mgr { 28 28 struct bridge_dev_context *hbridge_context; /* Bridge context. */ 29 29 struct ntfy_object *ntfy_obj; /* NTFY object */ 30 - }; 31 30 32 - int mmu_fault_isr(struct iommu *mmu); 31 + /* MMU Fault DPC */ 32 + struct tasklet_struct dpc_tasklet; 33 + }; 33 34 34 35 #endif /* _DEH_ */
+4 -15
drivers/staging/tidspbridge/core/_tiomap.h
··· 23 23 #include <plat/clockdomain.h> 24 24 #include <mach-omap2/prm-regbits-34xx.h> 25 25 #include <mach-omap2/cm-regbits-34xx.h> 26 - #include <dspbridge/dsp-mmu.h> 27 26 #include <dspbridge/devdefs.h> 27 + #include <hw_defs.h> 28 28 #include <dspbridge/dspioctl.h> /* for bridge_ioctl_extproc defn */ 29 29 #include <dspbridge/sync.h> 30 30 #include <dspbridge/clk.h> ··· 306 306 307 307 #define CLEAR_BIT_INDEX(reg, index) (reg &= ~(1 << (index))) 308 308 309 - struct shm_segs { 310 - u32 seg0_da; 311 - u32 seg0_pa; 312 - u32 seg0_va; 313 - u32 seg0_size; 314 - u32 seg1_da; 315 - u32 seg1_pa; 316 - u32 seg1_va; 317 - u32 seg1_size; 318 - }; 319 - 320 - 321 309 /* This Bridge driver's device context: */ 322 310 struct bridge_dev_context { 323 311 struct dev_object *hdev_obj; /* Handle to Bridge device object. */ ··· 316 328 */ 317 329 u32 dw_dsp_ext_base_addr; /* See the comment above */ 318 330 u32 dw_api_reg_base; /* API mem map'd registers */ 331 + void __iomem *dw_dsp_mmu_base; /* DSP MMU Mapped registers */ 319 332 u32 dw_api_clk_base; /* CLK Registers */ 320 333 u32 dw_dsp_clk_m2_base; /* DSP Clock Module m2 */ 321 334 u32 dw_public_rhea; /* Pub Rhea */ ··· 328 339 u32 dw_internal_size; /* Internal memory size */ 329 340 330 341 struct omap_mbox *mbox; /* Mail box handle */ 331 - struct iommu *dsp_mmu; /* iommu for iva2 handler */ 332 - struct shm_segs sh_s; 342 + 333 343 struct cfg_hostres *resources; /* Host Resources */ 334 344 335 345 /* ··· 341 353 342 354 /* TC Settings */ 343 355 bool tc_word_swap_on; /* Traffic Controller Word Swap */ 356 + struct pg_table_attrs *pt_attrs; 344 357 u32 dsp_per_clks; 345 358 }; 346 359
-317
drivers/staging/tidspbridge/core/dsp-mmu.c
··· 1 - /* 2 - * dsp-mmu.c 3 - * 4 - * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 - * 6 - * DSP iommu. 7 - * 8 - * Copyright (C) 2010 Texas Instruments, Inc. 9 - * 10 - * This package is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License version 2 as 12 - * published by the Free Software Foundation. 13 - * 14 - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 - */ 18 - 19 - #include <dspbridge/host_os.h> 20 - #include <plat/dmtimer.h> 21 - #include <dspbridge/dbdefs.h> 22 - #include <dspbridge/dev.h> 23 - #include <dspbridge/io_sm.h> 24 - #include <dspbridge/dspdeh.h> 25 - #include "_tiomap.h" 26 - 27 - #include <dspbridge/dsp-mmu.h> 28 - 29 - #define MMU_CNTL_TWL_EN (1 << 2) 30 - 31 - static struct tasklet_struct mmu_tasklet; 32 - 33 - #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE 34 - static void mmu_fault_print_stack(struct bridge_dev_context *dev_context) 35 - { 36 - void *dummy_addr; 37 - u32 fa, tmp; 38 - struct iotlb_entry e; 39 - struct iommu *mmu = dev_context->dsp_mmu; 40 - dummy_addr = (void *)__get_free_page(GFP_ATOMIC); 41 - 42 - /* 43 - * Before acking the MMU fault, let's make sure MMU can only 44 - * access entry #0. Then add a new entry so that the DSP OS 45 - * can continue in order to dump the stack. 46 - */ 47 - tmp = iommu_read_reg(mmu, MMU_CNTL); 48 - tmp &= ~MMU_CNTL_TWL_EN; 49 - iommu_write_reg(mmu, tmp, MMU_CNTL); 50 - fa = iommu_read_reg(mmu, MMU_FAULT_AD); 51 - e.da = fa & PAGE_MASK; 52 - e.pa = virt_to_phys(dummy_addr); 53 - e.valid = 1; 54 - e.prsvd = 1; 55 - e.pgsz = IOVMF_PGSZ_4K & MMU_CAM_PGSZ_MASK; 56 - e.endian = MMU_RAM_ENDIAN_LITTLE; 57 - e.elsz = MMU_RAM_ELSZ_32; 58 - e.mixed = 0; 59 - 60 - load_iotlb_entry(mmu, &e); 61 - 62 - dsp_clk_enable(DSP_CLK_GPT8); 63 - 64 - dsp_gpt_wait_overflow(DSP_CLK_GPT8, 0xfffffffe); 65 - 66 - /* Clear MMU interrupt */ 67 - tmp = iommu_read_reg(mmu, MMU_IRQSTATUS); 68 - iommu_write_reg(mmu, tmp, MMU_IRQSTATUS); 69 - 70 - dump_dsp_stack(dev_context); 71 - dsp_clk_disable(DSP_CLK_GPT8); 72 - 73 - iopgtable_clear_entry(mmu, fa); 74 - free_page((unsigned long)dummy_addr); 75 - } 76 - #endif 77 - 78 - 79 - static void fault_tasklet(unsigned long data) 80 - { 81 - struct iommu *mmu = (struct iommu *)data; 82 - struct bridge_dev_context *dev_ctx; 83 - struct deh_mgr *dm; 84 - u32 fa; 85 - dev_get_deh_mgr(dev_get_first(), &dm); 86 - dev_get_bridge_context(dev_get_first(), &dev_ctx); 87 - 88 - if (!dm || !dev_ctx) 89 - return; 90 - 91 - fa = iommu_read_reg(mmu, MMU_FAULT_AD); 92 - 93 - #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE 94 - print_dsp_trace_buffer(dev_ctx); 95 - dump_dl_modules(dev_ctx); 96 - mmu_fault_print_stack(dev_ctx); 97 - #endif 98 - 99 - bridge_deh_notify(dm, DSP_MMUFAULT, fa); 100 - } 101 - 102 - /* 103 - * ======== mmu_fault_isr ======== 104 - * ISR to be triggered by a DSP MMU fault interrupt. 105 - */ 106 - static int mmu_fault_callback(struct iommu *mmu) 107 - { 108 - if (!mmu) 109 - return -EPERM; 110 - 111 - iommu_write_reg(mmu, 0, MMU_IRQENABLE); 112 - tasklet_schedule(&mmu_tasklet); 113 - return 0; 114 - } 115 - 116 - /** 117 - * dsp_mmu_init() - initialize dsp_mmu module and returns a handle 118 - * 119 - * This function initialize dsp mmu module and returns a struct iommu 120 - * handle to use it for dsp maps. 121 - * 122 - */ 123 - struct iommu *dsp_mmu_init() 124 - { 125 - struct iommu *mmu; 126 - 127 - mmu = iommu_get("iva2"); 128 - 129 - if (!IS_ERR(mmu)) { 130 - tasklet_init(&mmu_tasklet, fault_tasklet, (unsigned long)mmu); 131 - mmu->isr = mmu_fault_callback; 132 - } 133 - 134 - return mmu; 135 - } 136 - 137 - /** 138 - * dsp_mmu_exit() - destroy dsp mmu module 139 - * @mmu: Pointer to iommu handle. 140 - * 141 - * This function destroys dsp mmu module. 142 - * 143 - */ 144 - void dsp_mmu_exit(struct iommu *mmu) 145 - { 146 - if (mmu) 147 - iommu_put(mmu); 148 - tasklet_kill(&mmu_tasklet); 149 - } 150 - 151 - /** 152 - * user_va2_pa() - get physical address from userspace address. 153 - * @mm: mm_struct Pointer of the process. 154 - * @address: Virtual user space address. 155 - * 156 - */ 157 - static u32 user_va2_pa(struct mm_struct *mm, u32 address) 158 - { 159 - pgd_t *pgd; 160 - pmd_t *pmd; 161 - pte_t *ptep, pte; 162 - 163 - pgd = pgd_offset(mm, address); 164 - if (!(pgd_none(*pgd) || pgd_bad(*pgd))) { 165 - pmd = pmd_offset(pgd, address); 166 - if (!(pmd_none(*pmd) || pmd_bad(*pmd))) { 167 - ptep = pte_offset_map(pmd, address); 168 - if (ptep) { 169 - pte = *ptep; 170 - if (pte_present(pte)) 171 - return pte & PAGE_MASK; 172 - } 173 - } 174 - } 175 - 176 - return 0; 177 - } 178 - 179 - /** 180 - * get_io_pages() - pin and get pages of io user's buffer. 181 - * @mm: mm_struct Pointer of the process. 182 - * @uva: Virtual user space address. 183 - * @pages Pages to be pined. 184 - * @usr_pgs struct page array pointer where the user pages will be stored 185 - * 186 - */ 187 - static int get_io_pages(struct mm_struct *mm, u32 uva, unsigned pages, 188 - struct page **usr_pgs) 189 - { 190 - u32 pa; 191 - int i; 192 - struct page *pg; 193 - 194 - for (i = 0; i < pages; i++) { 195 - pa = user_va2_pa(mm, uva); 196 - 197 - if (!pfn_valid(__phys_to_pfn(pa))) 198 - break; 199 - 200 - pg = phys_to_page(pa); 201 - usr_pgs[i] = pg; 202 - get_page(pg); 203 - } 204 - return i; 205 - } 206 - 207 - /** 208 - * user_to_dsp_map() - maps user to dsp virtual address 209 - * @mmu: Pointer to iommu handle. 210 - * @uva: Virtual user space address. 211 - * @da DSP address 212 - * @size Buffer size to map. 213 - * @usr_pgs struct page array pointer where the user pages will be stored 214 - * 215 - * This function maps a user space buffer into DSP virtual address. 216 - * 217 - */ 218 - u32 user_to_dsp_map(struct iommu *mmu, u32 uva, u32 da, u32 size, 219 - struct page **usr_pgs) 220 - { 221 - int res, w; 222 - unsigned pages; 223 - int i; 224 - struct vm_area_struct *vma; 225 - struct mm_struct *mm = current->mm; 226 - struct sg_table *sgt; 227 - struct scatterlist *sg; 228 - 229 - if (!size || !usr_pgs) 230 - return -EINVAL; 231 - 232 - pages = size / PG_SIZE4K; 233 - 234 - down_read(&mm->mmap_sem); 235 - vma = find_vma(mm, uva); 236 - while (vma && (uva + size > vma->vm_end)) 237 - vma = find_vma(mm, vma->vm_end + 1); 238 - 239 - if (!vma) { 240 - pr_err("%s: Failed to get VMA region for 0x%x (%d)\n", 241 - __func__, uva, size); 242 - up_read(&mm->mmap_sem); 243 - return -EINVAL; 244 - } 245 - if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) 246 - w = 1; 247 - 248 - if (vma->vm_flags & VM_IO) 249 - i = get_io_pages(mm, uva, pages, usr_pgs); 250 - else 251 - i = get_user_pages(current, mm, uva, pages, w, 1, 252 - usr_pgs, NULL); 253 - up_read(&mm->mmap_sem); 254 - 255 - if (i < 0) 256 - return i; 257 - 258 - if (i < pages) { 259 - res = -EFAULT; 260 - goto err_pages; 261 - } 262 - 263 - sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); 264 - if (!sgt) { 265 - res = -ENOMEM; 266 - goto err_pages; 267 - } 268 - 269 - res = sg_alloc_table(sgt, pages, GFP_KERNEL); 270 - 271 - if (res < 0) 272 - goto err_sg; 273 - 274 - for_each_sg(sgt->sgl, sg, sgt->nents, i) 275 - sg_set_page(sg, usr_pgs[i], PAGE_SIZE, 0); 276 - 277 - da = iommu_vmap(mmu, da, sgt, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32); 278 - 279 - if (!IS_ERR_VALUE(da)) 280 - return da; 281 - res = (int)da; 282 - 283 - sg_free_table(sgt); 284 - err_sg: 285 - kfree(sgt); 286 - i = pages; 287 - err_pages: 288 - while (i--) 289 - put_page(usr_pgs[i]); 290 - return res; 291 - } 292 - 293 - /** 294 - * user_to_dsp_unmap() - unmaps DSP virtual buffer. 295 - * @mmu: Pointer to iommu handle. 296 - * @da DSP address 297 - * 298 - * This function unmaps a user space buffer into DSP virtual address. 299 - * 300 - */ 301 - int user_to_dsp_unmap(struct iommu *mmu, u32 da) 302 - { 303 - unsigned i; 304 - struct sg_table *sgt; 305 - struct scatterlist *sg; 306 - 307 - sgt = iommu_vunmap(mmu, da); 308 - if (!sgt) 309 - return -EFAULT; 310 - 311 - for_each_sg(sgt->sgl, sg, sgt->nents, i) 312 - put_page(sg_page(sg)); 313 - sg_free_table(sgt); 314 - kfree(sgt); 315 - 316 - return 0; 317 - }
+166 -14
drivers/staging/tidspbridge/core/io_sm.c
··· 39 39 #include <dspbridge/ntfy.h> 40 40 #include <dspbridge/sync.h> 41 41 42 + /* Hardware Abstraction Layer */ 43 + #include <hw_defs.h> 44 + #include <hw_mmu.h> 45 + 42 46 /* Bridge Driver */ 43 47 #include <dspbridge/dspdeh.h> 44 48 #include <dspbridge/dspio.h> ··· 291 287 struct cod_manager *cod_man; 292 288 struct chnl_mgr *hchnl_mgr; 293 289 struct msg_mgr *hmsg_mgr; 294 - struct shm_segs *sm_sg; 295 290 u32 ul_shm_base; 296 291 u32 ul_shm_base_offset; 297 292 u32 ul_shm_limit; ··· 313 310 struct bridge_ioctl_extproc ae_proc[BRDIOCTL_NUMOFMMUTLB]; 314 311 struct cfg_hostres *host_res; 315 312 struct bridge_dev_context *pbridge_context; 313 + u32 map_attrs; 316 314 u32 shm0_end; 317 315 u32 ul_dyn_ext_base; 318 316 u32 ul_seg1_size = 0; 317 + u32 pa_curr = 0; 318 + u32 va_curr = 0; 319 + u32 gpp_va_curr = 0; 320 + u32 num_bytes = 0; 321 + u32 all_bits = 0; 322 + u32 page_size[] = { HW_PAGE_SIZE16MB, HW_PAGE_SIZE1MB, 323 + HW_PAGE_SIZE64KB, HW_PAGE_SIZE4KB 324 + }; 319 325 320 326 status = dev_get_bridge_context(hio_mgr->hdev_obj, &pbridge_context); 321 327 if (!pbridge_context) { ··· 337 325 status = -EFAULT; 338 326 goto func_end; 339 327 } 340 - sm_sg = &pbridge_context->sh_s; 341 - 342 328 status = dev_get_cod_mgr(hio_mgr->hdev_obj, &cod_man); 343 329 if (!cod_man) { 344 330 status = -EFAULT; ··· 471 461 if (status) 472 462 goto func_end; 473 463 474 - sm_sg->seg1_pa = ul_gpp_pa; 475 - sm_sg->seg1_da = ul_dyn_ext_base; 476 - sm_sg->seg1_va = ul_gpp_va; 477 - sm_sg->seg1_size = ul_seg1_size; 478 - sm_sg->seg0_pa = ul_gpp_pa + ul_pad_size + ul_seg1_size; 479 - sm_sg->seg0_da = ul_dsp_va; 480 - sm_sg->seg0_va = ul_gpp_va + ul_pad_size + ul_seg1_size; 481 - sm_sg->seg0_size = ul_seg_size; 464 + pa_curr = ul_gpp_pa; 465 + va_curr = ul_dyn_ext_base * hio_mgr->word_size; 466 + gpp_va_curr = ul_gpp_va; 467 + num_bytes = ul_seg1_size; 468 + 469 + /* 470 + * Try to fit into TLB entries. If not possible, push them to page 471 + * tables. It is quite possible that if sections are not on 472 + * bigger page boundary, we may end up making several small pages. 473 + * So, push them onto page tables, if that is the case. 474 + */ 475 + map_attrs = 0x00000000; 476 + map_attrs = DSP_MAPLITTLEENDIAN; 477 + map_attrs |= DSP_MAPPHYSICALADDR; 478 + map_attrs |= DSP_MAPELEMSIZE32; 479 + map_attrs |= DSP_MAPDONOTLOCK; 480 + 481 + while (num_bytes) { 482 + /* 483 + * To find the max. page size with which both PA & VA are 484 + * aligned. 485 + */ 486 + all_bits = pa_curr | va_curr; 487 + dev_dbg(bridge, "all_bits %x, pa_curr %x, va_curr %x, " 488 + "num_bytes %x\n", all_bits, pa_curr, va_curr, 489 + num_bytes); 490 + for (i = 0; i < 4; i++) { 491 + if ((num_bytes >= page_size[i]) && ((all_bits & 492 + (page_size[i] - 493 + 1)) == 0)) { 494 + status = 495 + hio_mgr->intf_fxns-> 496 + pfn_brd_mem_map(hio_mgr->hbridge_context, 497 + pa_curr, va_curr, 498 + page_size[i], map_attrs, 499 + NULL); 500 + if (status) 501 + goto func_end; 502 + pa_curr += page_size[i]; 503 + va_curr += page_size[i]; 504 + gpp_va_curr += page_size[i]; 505 + num_bytes -= page_size[i]; 506 + /* 507 + * Don't try smaller sizes. Hopefully we have 508 + * reached an address aligned to a bigger page 509 + * size. 510 + */ 511 + break; 512 + } 513 + } 514 + } 515 + pa_curr += ul_pad_size; 516 + va_curr += ul_pad_size; 517 + gpp_va_curr += ul_pad_size; 518 + 519 + /* Configure the TLB entries for the next cacheable segment */ 520 + num_bytes = ul_seg_size; 521 + va_curr = ul_dsp_va * hio_mgr->word_size; 522 + while (num_bytes) { 523 + /* 524 + * To find the max. page size with which both PA & VA are 525 + * aligned. 526 + */ 527 + all_bits = pa_curr | va_curr; 528 + dev_dbg(bridge, "all_bits for Seg1 %x, pa_curr %x, " 529 + "va_curr %x, num_bytes %x\n", all_bits, pa_curr, 530 + va_curr, num_bytes); 531 + for (i = 0; i < 4; i++) { 532 + if (!(num_bytes >= page_size[i]) || 533 + !((all_bits & (page_size[i] - 1)) == 0)) 534 + continue; 535 + if (ndx < MAX_LOCK_TLB_ENTRIES) { 536 + /* 537 + * This is the physical address written to 538 + * DSP MMU. 539 + */ 540 + ae_proc[ndx].ul_gpp_pa = pa_curr; 541 + /* 542 + * This is the virtual uncached ioremapped 543 + * address!!! 544 + */ 545 + ae_proc[ndx].ul_gpp_va = gpp_va_curr; 546 + ae_proc[ndx].ul_dsp_va = 547 + va_curr / hio_mgr->word_size; 548 + ae_proc[ndx].ul_size = page_size[i]; 549 + ae_proc[ndx].endianism = HW_LITTLE_ENDIAN; 550 + ae_proc[ndx].elem_size = HW_ELEM_SIZE16BIT; 551 + ae_proc[ndx].mixed_mode = HW_MMU_CPUES; 552 + dev_dbg(bridge, "shm MMU TLB entry PA %x" 553 + " VA %x DSP_VA %x Size %x\n", 554 + ae_proc[ndx].ul_gpp_pa, 555 + ae_proc[ndx].ul_gpp_va, 556 + ae_proc[ndx].ul_dsp_va * 557 + hio_mgr->word_size, page_size[i]); 558 + ndx++; 559 + } else { 560 + status = 561 + hio_mgr->intf_fxns-> 562 + pfn_brd_mem_map(hio_mgr->hbridge_context, 563 + pa_curr, va_curr, 564 + page_size[i], map_attrs, 565 + NULL); 566 + dev_dbg(bridge, 567 + "shm MMU PTE entry PA %x" 568 + " VA %x DSP_VA %x Size %x\n", 569 + ae_proc[ndx].ul_gpp_pa, 570 + ae_proc[ndx].ul_gpp_va, 571 + ae_proc[ndx].ul_dsp_va * 572 + hio_mgr->word_size, page_size[i]); 573 + if (status) 574 + goto func_end; 575 + } 576 + pa_curr += page_size[i]; 577 + va_curr += page_size[i]; 578 + gpp_va_curr += page_size[i]; 579 + num_bytes -= page_size[i]; 580 + /* 581 + * Don't try smaller sizes. Hopefully we have reached 582 + * an address aligned to a bigger page size. 583 + */ 584 + break; 585 + } 586 + } 482 587 483 588 /* 484 589 * Copy remaining entries from CDB. All entries are 1 MB and ··· 634 509 "DSP_VA 0x%x\n", ae_proc[ndx].ul_gpp_pa, 635 510 ae_proc[ndx].ul_dsp_va); 636 511 ndx++; 512 + } else { 513 + status = hio_mgr->intf_fxns->pfn_brd_mem_map 514 + (hio_mgr->hbridge_context, 515 + hio_mgr->ext_proc_info.ty_tlb[i]. 516 + ul_gpp_phys, 517 + hio_mgr->ext_proc_info.ty_tlb[i]. 518 + ul_dsp_virt, 0x100000, map_attrs, 519 + NULL); 637 520 } 638 521 } 639 522 if (status) 640 523 goto func_end; 524 + } 525 + 526 + map_attrs = 0x00000000; 527 + map_attrs = DSP_MAPLITTLEENDIAN; 528 + map_attrs |= DSP_MAPPHYSICALADDR; 529 + map_attrs |= DSP_MAPELEMSIZE32; 530 + map_attrs |= DSP_MAPDONOTLOCK; 531 + 532 + /* Map the L4 peripherals */ 533 + i = 0; 534 + while (l4_peripheral_table[i].phys_addr) { 535 + status = hio_mgr->intf_fxns->pfn_brd_mem_map 536 + (hio_mgr->hbridge_context, l4_peripheral_table[i].phys_addr, 537 + l4_peripheral_table[i].dsp_virt_addr, HW_PAGE_SIZE4KB, 538 + map_attrs, NULL); 539 + if (status) 540 + goto func_end; 541 + i++; 641 542 } 642 543 643 544 for (i = ndx; i < BRDIOCTL_NUMOFMMUTLB; i++) { ··· 688 537 status = -EFAULT; 689 538 goto func_end; 690 539 } else { 691 - if (sm_sg->seg0_da > ul_shm_base) { 540 + if (ae_proc[0].ul_dsp_va > ul_shm_base) { 692 541 status = -EPERM; 693 542 goto func_end; 694 543 } 695 544 /* ul_shm_base may not be at ul_dsp_va address */ 696 - ul_shm_base_offset = (ul_shm_base - sm_sg->seg0_da) * 545 + ul_shm_base_offset = (ul_shm_base - ae_proc[0].ul_dsp_va) * 697 546 hio_mgr->word_size; 698 547 /* 699 548 * bridge_dev_ctrl() will set dev context dsp-mmu info. In ··· 717 566 goto func_end; 718 567 } 719 568 /* Register SM */ 720 - status = register_shm_segs(hio_mgr, cod_man, sm_sg->seg0_pa); 569 + status = 570 + register_shm_segs(hio_mgr, cod_man, ae_proc[0].ul_gpp_pa); 721 571 } 722 572 723 573 hio_mgr->shared_mem = (struct shm *)ul_shm_base;
+974 -107
drivers/staging/tidspbridge/core/tiomap3430.c
··· 23 23 #include <dspbridge/host_os.h> 24 24 #include <linux/mm.h> 25 25 #include <linux/mmzone.h> 26 - #include <plat/control.h> 27 26 28 27 /* ----------------------------------- DSP/BIOS Bridge */ 29 28 #include <dspbridge/dbdefs.h> ··· 33 34 /* ----------------------------------- OS Adaptation Layer */ 34 35 #include <dspbridge/drv.h> 35 36 #include <dspbridge/sync.h> 37 + 38 + /* ------------------------------------ Hardware Abstraction Layer */ 39 + #include <hw_defs.h> 40 + #include <hw_mmu.h> 36 41 37 42 /* ----------------------------------- Link Driver */ 38 43 #include <dspbridge/dspdefs.h> ··· 50 47 /* ----------------------------------- Platform Manager */ 51 48 #include <dspbridge/dev.h> 52 49 #include <dspbridge/dspapi.h> 50 + #include <dspbridge/dmm.h> 53 51 #include <dspbridge/wdt.h> 54 52 55 53 /* ----------------------------------- Local */ ··· 71 67 #define MMU_SMALL_PAGE_MASK 0xFFFFF000 72 68 #define OMAP3_IVA2_BOOTADDR_MASK 0xFFFFFC00 73 69 #define PAGES_II_LVL_TABLE 512 70 + #define PHYS_TO_PAGE(phys) pfn_to_page((phys) >> PAGE_SHIFT) 71 + 72 + /* 73 + * This is a totally ugly layer violation, but needed until 74 + * omap_ctrl_set_dsp_boot*() are provided. 75 + */ 76 + #define OMAP3_IVA2_BOOTMOD_IDLE 1 77 + #define OMAP2_CONTROL_GENERAL 0x270 78 + #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) 79 + #define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) 80 + 81 + #define OMAP343X_CTRL_REGADDR(reg) \ 82 + OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) 83 + 74 84 75 85 /* Forward Declarations: */ 76 86 static int bridge_brd_monitor(struct bridge_dev_context *dev_ctxt); ··· 109 91 static int bridge_brd_mem_write(struct bridge_dev_context *dev_ctxt, 110 92 u8 *host_buff, u32 dsp_addr, 111 93 u32 ul_num_bytes, u32 mem_type); 94 + static int bridge_brd_mem_map(struct bridge_dev_context *dev_ctxt, 95 + u32 ul_mpu_addr, u32 virt_addr, 96 + u32 ul_num_bytes, u32 ul_map_attr, 97 + struct page **mapped_pages); 98 + static int bridge_brd_mem_un_map(struct bridge_dev_context *dev_ctxt, 99 + u32 virt_addr, u32 ul_num_bytes); 112 100 static int bridge_dev_create(struct bridge_dev_context 113 101 **dev_cntxt, 114 102 struct dev_object *hdev_obj, ··· 122 98 static int bridge_dev_ctrl(struct bridge_dev_context *dev_context, 123 99 u32 dw_cmd, void *pargs); 124 100 static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt); 101 + static u32 user_va2_pa(struct mm_struct *mm, u32 address); 102 + static int pte_update(struct bridge_dev_context *dev_ctxt, u32 pa, 103 + u32 va, u32 size, 104 + struct hw_mmu_map_attrs_t *map_attrs); 105 + static int pte_set(struct pg_table_attrs *pt, u32 pa, u32 va, 106 + u32 size, struct hw_mmu_map_attrs_t *attrs); 107 + static int mem_map_vmalloc(struct bridge_dev_context *dev_context, 108 + u32 ul_mpu_addr, u32 virt_addr, 109 + u32 ul_num_bytes, 110 + struct hw_mmu_map_attrs_t *hw_attrs); 111 + 125 112 bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr); 113 + 114 + /* ----------------------------------- Globals */ 115 + 116 + /* Attributes of L2 page tables for DSP MMU */ 117 + struct page_info { 118 + u32 num_entries; /* Number of valid PTEs in the L2 PT */ 119 + }; 120 + 121 + /* Attributes used to manage the DSP MMU page tables */ 122 + struct pg_table_attrs { 123 + spinlock_t pg_lock; /* Critical section object handle */ 124 + 125 + u32 l1_base_pa; /* Physical address of the L1 PT */ 126 + u32 l1_base_va; /* Virtual address of the L1 PT */ 127 + u32 l1_size; /* Size of the L1 PT */ 128 + u32 l1_tbl_alloc_pa; 129 + /* Physical address of Allocated mem for L1 table. May not be aligned */ 130 + u32 l1_tbl_alloc_va; 131 + /* Virtual address of Allocated mem for L1 table. May not be aligned */ 132 + u32 l1_tbl_alloc_sz; 133 + /* Size of consistent memory allocated for L1 table. 134 + * May not be aligned */ 135 + 136 + u32 l2_base_pa; /* Physical address of the L2 PT */ 137 + u32 l2_base_va; /* Virtual address of the L2 PT */ 138 + u32 l2_size; /* Size of the L2 PT */ 139 + u32 l2_tbl_alloc_pa; 140 + /* Physical address of Allocated mem for L2 table. May not be aligned */ 141 + u32 l2_tbl_alloc_va; 142 + /* Virtual address of Allocated mem for L2 table. May not be aligned */ 143 + u32 l2_tbl_alloc_sz; 144 + /* Size of consistent memory allocated for L2 table. 145 + * May not be aligned */ 146 + 147 + u32 l2_num_pages; /* Number of allocated L2 PT */ 148 + /* Array [l2_num_pages] of L2 PT info structs */ 149 + struct page_info *pg_info; 150 + }; 126 151 127 152 /* 128 153 * This Bridge driver's function interface table. ··· 192 119 bridge_brd_set_state, 193 120 bridge_brd_mem_copy, 194 121 bridge_brd_mem_write, 122 + bridge_brd_mem_map, 123 + bridge_brd_mem_un_map, 195 124 /* The following CHNL functions are provided by chnl_io.lib: */ 196 125 bridge_chnl_create, 197 126 bridge_chnl_destroy, ··· 222 147 bridge_msg_register_notify, 223 148 bridge_msg_set_queue_id, 224 149 }; 150 + 151 + static inline void flush_all(struct bridge_dev_context *dev_context) 152 + { 153 + if (dev_context->dw_brd_state == BRD_DSP_HIBERNATION || 154 + dev_context->dw_brd_state == BRD_HIBERNATION) 155 + wake_dsp(dev_context, NULL); 156 + 157 + hw_mmu_tlb_flush_all(dev_context->dw_dsp_mmu_base); 158 + } 159 + 160 + static void bad_page_dump(u32 pa, struct page *pg) 161 + { 162 + pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa); 163 + pr_emerg("Bad page state in process '%s'\n" 164 + "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n" 165 + "Backtrace:\n", 166 + current->comm, pg, (int)(2 * sizeof(unsigned long)), 167 + (unsigned long)pg->flags, pg->mapping, 168 + page_mapcount(pg), page_count(pg)); 169 + dump_stack(); 170 + } 225 171 226 172 /* 227 173 * ======== bridge_drv_entry ======== ··· 299 203 (*pdata->dsp_cm_write)(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, 300 204 OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL); 301 205 } 302 - 206 + (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, 0, 207 + OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); 303 208 dsp_clk_enable(DSP_CLK_IVA2); 304 209 305 210 /* set the device state to IDLE */ ··· 371 274 { 372 275 int status = 0; 373 276 struct bridge_dev_context *dev_context = dev_ctxt; 374 - struct iommu *mmu = NULL; 375 - struct shm_segs *sm_sg; 376 - int l4_i = 0, tlb_i = 0; 377 - u32 sg0_da = 0, sg1_da = 0; 378 - struct bridge_ioctl_extproc *tlb = dev_context->atlb_entry; 379 277 u32 dw_sync_addr = 0; 380 278 u32 ul_shm_base; /* Gpp Phys SM base addr(byte) */ 381 279 u32 ul_shm_base_virt; /* Dsp Virt SM base addr */ 382 280 u32 ul_tlb_base_virt; /* Base of MMU TLB entry */ 383 281 /* Offset of shm_base_virt from tlb_base_virt */ 384 282 u32 ul_shm_offset_virt; 283 + s32 entry_ndx; 284 + s32 itmp_entry_ndx = 0; /* DSP-MMU TLB entry base address */ 385 285 struct cfg_hostres *resources = NULL; 386 286 u32 temp; 387 287 u32 ul_dsp_clk_rate; ··· 399 305 ul_shm_base_virt *= DSPWORDSIZE; 400 306 DBC_ASSERT(ul_shm_base_virt != 0); 401 307 /* DSP Virtual address */ 402 - ul_tlb_base_virt = dev_context->sh_s.seg0_da; 308 + ul_tlb_base_virt = dev_context->atlb_entry[0].ul_dsp_va; 403 309 DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt); 404 310 ul_shm_offset_virt = 405 311 ul_shm_base_virt - (ul_tlb_base_virt * DSPWORDSIZE); 406 312 /* Kernel logical address */ 407 - ul_shm_base = dev_context->sh_s.seg0_va + ul_shm_offset_virt; 313 + ul_shm_base = dev_context->atlb_entry[0].ul_gpp_va + ul_shm_offset_virt; 408 314 409 315 DBC_ASSERT(ul_shm_base != 0); 410 316 /* 2nd wd is used as sync field */ ··· 439 345 OMAP343X_CONTROL_IVA2_BOOTMOD)); 440 346 } 441 347 } 442 - 443 348 if (!status) { 349 + /* Reset and Unreset the RST2, so that BOOTADDR is copied to 350 + * IVA2 SYSC register */ 351 + (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, 352 + OMAP3430_RST2_IVA2_MASK, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); 353 + udelay(100); 444 354 (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, 0, 445 355 OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); 446 - mmu = dev_context->dsp_mmu; 447 - if (mmu) 448 - dsp_mmu_exit(mmu); 449 - mmu = dsp_mmu_init(); 450 - if (IS_ERR(mmu)) { 451 - dev_err(bridge, "dsp_mmu_init failed!\n"); 452 - dev_context->dsp_mmu = NULL; 453 - status = (int)mmu; 454 - } 455 - } 456 - if (!status) { 457 - dev_context->dsp_mmu = mmu; 458 - sm_sg = &dev_context->sh_s; 459 - sg0_da = iommu_kmap(mmu, sm_sg->seg0_da, sm_sg->seg0_pa, 460 - sm_sg->seg0_size, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32); 461 - if (IS_ERR_VALUE(sg0_da)) { 462 - status = (int)sg0_da; 463 - sg0_da = 0; 464 - } 465 - } 466 - if (!status) { 467 - sg1_da = iommu_kmap(mmu, sm_sg->seg1_da, sm_sg->seg1_pa, 468 - sm_sg->seg1_size, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32); 469 - if (IS_ERR_VALUE(sg1_da)) { 470 - status = (int)sg1_da; 471 - sg1_da = 0; 472 - } 473 - } 474 - if (!status) { 475 - u32 da; 476 - for (tlb_i = 0; tlb_i < BRDIOCTL_NUMOFMMUTLB; tlb_i++) { 477 - if (!tlb[tlb_i].ul_gpp_pa) 356 + udelay(100); 357 + 358 + /* Disbale the DSP MMU */ 359 + hw_mmu_disable(resources->dw_dmmu_base); 360 + /* Disable TWL */ 361 + hw_mmu_twl_disable(resources->dw_dmmu_base); 362 + 363 + /* Only make TLB entry if both addresses are non-zero */ 364 + for (entry_ndx = 0; entry_ndx < BRDIOCTL_NUMOFMMUTLB; 365 + entry_ndx++) { 366 + struct bridge_ioctl_extproc *e = &dev_context->atlb_entry[entry_ndx]; 367 + struct hw_mmu_map_attrs_t map_attrs = { 368 + .endianism = e->endianism, 369 + .element_size = e->elem_size, 370 + .mixed_size = e->mixed_mode, 371 + }; 372 + 373 + if (!e->ul_gpp_pa || !e->ul_dsp_va) 478 374 continue; 479 375 480 - dev_dbg(bridge, "IOMMU %d GppPa: 0x%x DspVa 0x%x Size" 481 - " 0x%x\n", tlb_i, tlb[tlb_i].ul_gpp_pa, 482 - tlb[tlb_i].ul_dsp_va, tlb[tlb_i].ul_size); 376 + dev_dbg(bridge, 377 + "MMU %d, pa: 0x%x, va: 0x%x, size: 0x%x", 378 + itmp_entry_ndx, 379 + e->ul_gpp_pa, 380 + e->ul_dsp_va, 381 + e->ul_size); 483 382 484 - da = iommu_kmap(mmu, tlb[tlb_i].ul_dsp_va, 485 - tlb[tlb_i].ul_gpp_pa, PAGE_SIZE, 486 - IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32); 487 - if (IS_ERR_VALUE(da)) { 488 - status = (int)da; 489 - break; 490 - } 491 - } 492 - } 493 - if (!status) { 494 - u32 da; 495 - l4_i = 0; 496 - while (l4_peripheral_table[l4_i].phys_addr) { 497 - da = iommu_kmap(mmu, l4_peripheral_table[l4_i]. 498 - dsp_virt_addr, l4_peripheral_table[l4_i]. 499 - phys_addr, PAGE_SIZE, 500 - IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32); 501 - if (IS_ERR_VALUE(da)) { 502 - status = (int)da; 503 - break; 504 - } 505 - l4_i++; 383 + hw_mmu_tlb_add(dev_context->dw_dsp_mmu_base, 384 + e->ul_gpp_pa, 385 + e->ul_dsp_va, 386 + e->ul_size, 387 + itmp_entry_ndx, 388 + &map_attrs, 1, 1); 389 + 390 + itmp_entry_ndx++; 506 391 } 507 392 } 508 393 509 394 /* Lock the above TLB entries and get the BIOS and load monitor timer 510 395 * information */ 511 396 if (!status) { 397 + hw_mmu_num_locked_set(resources->dw_dmmu_base, itmp_entry_ndx); 398 + hw_mmu_victim_num_set(resources->dw_dmmu_base, itmp_entry_ndx); 399 + hw_mmu_ttb_set(resources->dw_dmmu_base, 400 + dev_context->pt_attrs->l1_base_pa); 401 + hw_mmu_twl_enable(resources->dw_dmmu_base); 402 + /* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */ 403 + 404 + temp = __raw_readl((resources->dw_dmmu_base) + 0x10); 405 + temp = (temp & 0xFFFFFFEF) | 0x11; 406 + __raw_writel(temp, (resources->dw_dmmu_base) + 0x10); 407 + 408 + /* Let the DSP MMU run */ 409 + hw_mmu_enable(resources->dw_dmmu_base); 410 + 512 411 /* Enable the BIOS clock */ 513 412 (void)dev_get_symbol(dev_context->hdev_obj, 514 413 BRIDGEINIT_BIOSGPTIMER, &ul_bios_gp_timer); 515 414 (void)dev_get_symbol(dev_context->hdev_obj, 516 415 BRIDGEINIT_LOADMON_GPTIMER, 517 416 &ul_load_monitor_timer); 417 + } 518 418 419 + if (!status) { 519 420 if (ul_load_monitor_timer != 0xFFFF) { 520 421 clk_cmd = (BPWR_ENABLE_CLOCK << MBX_PM_CLK_CMDSHIFT) | 521 422 ul_load_monitor_timer; ··· 519 430 dev_dbg(bridge, "Not able to get the symbol for Load " 520 431 "Monitor Timer\n"); 521 432 } 433 + } 522 434 435 + if (!status) { 523 436 if (ul_bios_gp_timer != 0xFFFF) { 524 437 clk_cmd = (BPWR_ENABLE_CLOCK << MBX_PM_CLK_CMDSHIFT) | 525 438 ul_bios_gp_timer; ··· 530 439 dev_dbg(bridge, 531 440 "Not able to get the symbol for BIOS Timer\n"); 532 441 } 442 + } 533 443 444 + if (!status) { 534 445 /* Set the DSP clock rate */ 535 446 (void)dev_get_symbol(dev_context->hdev_obj, 536 447 "_BRIDGEINIT_DSP_FREQ", &ul_dsp_clk_addr); ··· 585 492 586 493 /* Let DSP go */ 587 494 dev_dbg(bridge, "%s Unreset\n", __func__); 495 + /* Enable DSP MMU Interrupts */ 496 + hw_mmu_event_enable(resources->dw_dmmu_base, 497 + HW_MMU_ALL_INTERRUPTS); 588 498 /* release the RST1, DSP starts executing now .. */ 589 499 (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0, 590 500 OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); ··· 617 521 618 522 /* update board state */ 619 523 dev_context->dw_brd_state = BRD_RUNNING; 620 - return 0; 524 + /* (void)chnlsm_enable_interrupt(dev_context); */ 621 525 } else { 622 526 dev_context->dw_brd_state = BRD_UNKNOWN; 623 527 } 624 528 } 625 - 626 - while (tlb_i--) { 627 - if (!tlb[tlb_i].ul_gpp_pa) 628 - continue; 629 - iommu_kunmap(mmu, tlb[tlb_i].ul_gpp_va); 630 - } 631 - while (l4_i--) 632 - iommu_kunmap(mmu, l4_peripheral_table[l4_i].dsp_virt_addr); 633 - if (sg0_da) 634 - iommu_kunmap(mmu, sg0_da); 635 - if (sg1_da) 636 - iommu_kunmap(mmu, sg1_da); 637 529 return status; 638 530 } 639 531 ··· 637 553 { 638 554 int status = 0; 639 555 struct bridge_dev_context *dev_context = dev_ctxt; 556 + struct pg_table_attrs *pt_attrs; 640 557 u32 dsp_pwr_state; 641 - int i; 642 - struct bridge_ioctl_extproc *tlb = dev_context->atlb_entry; 643 558 struct omap_dsp_platform_data *pdata = 644 559 omap_dspbridge_dev->dev.platform_data; 645 560 ··· 674 591 675 592 dsp_wdt_enable(false); 676 593 677 - /* Reset DSP */ 678 - (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 679 - OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); 680 - 594 + /* This is a good place to clear the MMU page tables as well */ 595 + if (dev_context->pt_attrs) { 596 + pt_attrs = dev_context->pt_attrs; 597 + memset((u8 *) pt_attrs->l1_base_va, 0x00, pt_attrs->l1_size); 598 + memset((u8 *) pt_attrs->l2_base_va, 0x00, pt_attrs->l2_size); 599 + memset((u8 *) pt_attrs->pg_info, 0x00, 600 + (pt_attrs->l2_num_pages * sizeof(struct page_info))); 601 + } 681 602 /* Disable the mailbox interrupts */ 682 603 if (dev_context->mbox) { 683 604 omap_mbox_disable_irq(dev_context->mbox, IRQ_RX); 684 605 omap_mbox_put(dev_context->mbox); 685 606 dev_context->mbox = NULL; 686 607 } 687 - if (dev_context->dsp_mmu) { 688 - pr_err("Proc stop mmu if statement\n"); 689 - for (i = 0; i < BRDIOCTL_NUMOFMMUTLB; i++) { 690 - if (!tlb[i].ul_gpp_pa) 691 - continue; 692 - iommu_kunmap(dev_context->dsp_mmu, tlb[i].ul_gpp_va); 693 - } 694 - i = 0; 695 - while (l4_peripheral_table[i].phys_addr) { 696 - iommu_kunmap(dev_context->dsp_mmu, 697 - l4_peripheral_table[i].dsp_virt_addr); 698 - i++; 699 - } 700 - iommu_kunmap(dev_context->dsp_mmu, dev_context->sh_s.seg0_da); 701 - iommu_kunmap(dev_context->dsp_mmu, dev_context->sh_s.seg1_da); 702 - dsp_mmu_exit(dev_context->dsp_mmu); 703 - dev_context->dsp_mmu = NULL; 704 - } 705 - /* Reset IVA IOMMU*/ 706 - (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, 707 - OMAP3430_RST2_IVA2_MASK, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); 608 + /* Reset IVA2 clocks*/ 609 + (*pdata->dsp_prm_write)(OMAP3430_RST1_IVA2_MASK | OMAP3430_RST2_IVA2_MASK | 610 + OMAP3430_RST3_IVA2_MASK, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); 708 611 709 612 dsp_clock_disable_all(dev_context->dsp_per_clks); 710 613 dsp_clk_disable(DSP_CLK_IVA2); ··· 750 681 struct bridge_dev_context *dev_context = NULL; 751 682 s32 entry_ndx; 752 683 struct cfg_hostres *resources = config_param; 684 + struct pg_table_attrs *pt_attrs; 685 + u32 pg_tbl_pa; 686 + u32 pg_tbl_va; 687 + u32 align_size; 753 688 struct drv_data *drv_datap = dev_get_drvdata(bridge); 754 689 755 690 /* Allocate and initialize a data structure to contain the bridge driver ··· 784 711 if (!dev_context->dw_dsp_base_addr) 785 712 status = -EPERM; 786 713 714 + pt_attrs = kzalloc(sizeof(struct pg_table_attrs), GFP_KERNEL); 715 + if (pt_attrs != NULL) { 716 + /* Assuming that we use only DSP's memory map 717 + * until 0x4000:0000 , we would need only 1024 718 + * L1 enties i.e L1 size = 4K */ 719 + pt_attrs->l1_size = 0x1000; 720 + align_size = pt_attrs->l1_size; 721 + /* Align sizes are expected to be power of 2 */ 722 + /* we like to get aligned on L1 table size */ 723 + pg_tbl_va = (u32) mem_alloc_phys_mem(pt_attrs->l1_size, 724 + align_size, &pg_tbl_pa); 725 + 726 + /* Check if the PA is aligned for us */ 727 + if ((pg_tbl_pa) & (align_size - 1)) { 728 + /* PA not aligned to page table size , 729 + * try with more allocation and align */ 730 + mem_free_phys_mem((void *)pg_tbl_va, pg_tbl_pa, 731 + pt_attrs->l1_size); 732 + /* we like to get aligned on L1 table size */ 733 + pg_tbl_va = 734 + (u32) mem_alloc_phys_mem((pt_attrs->l1_size) * 2, 735 + align_size, &pg_tbl_pa); 736 + /* We should be able to get aligned table now */ 737 + pt_attrs->l1_tbl_alloc_pa = pg_tbl_pa; 738 + pt_attrs->l1_tbl_alloc_va = pg_tbl_va; 739 + pt_attrs->l1_tbl_alloc_sz = pt_attrs->l1_size * 2; 740 + /* Align the PA to the next 'align' boundary */ 741 + pt_attrs->l1_base_pa = 742 + ((pg_tbl_pa) + 743 + (align_size - 1)) & (~(align_size - 1)); 744 + pt_attrs->l1_base_va = 745 + pg_tbl_va + (pt_attrs->l1_base_pa - pg_tbl_pa); 746 + } else { 747 + /* We got aligned PA, cool */ 748 + pt_attrs->l1_tbl_alloc_pa = pg_tbl_pa; 749 + pt_attrs->l1_tbl_alloc_va = pg_tbl_va; 750 + pt_attrs->l1_tbl_alloc_sz = pt_attrs->l1_size; 751 + pt_attrs->l1_base_pa = pg_tbl_pa; 752 + pt_attrs->l1_base_va = pg_tbl_va; 753 + } 754 + if (pt_attrs->l1_base_va) 755 + memset((u8 *) pt_attrs->l1_base_va, 0x00, 756 + pt_attrs->l1_size); 757 + 758 + /* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM + 759 + * L4 pages */ 760 + pt_attrs->l2_num_pages = ((DMMPOOLSIZE >> 20) + 6); 761 + pt_attrs->l2_size = HW_MMU_COARSE_PAGE_SIZE * 762 + pt_attrs->l2_num_pages; 763 + align_size = 4; /* Make it u32 aligned */ 764 + /* we like to get aligned on L1 table size */ 765 + pg_tbl_va = (u32) mem_alloc_phys_mem(pt_attrs->l2_size, 766 + align_size, &pg_tbl_pa); 767 + pt_attrs->l2_tbl_alloc_pa = pg_tbl_pa; 768 + pt_attrs->l2_tbl_alloc_va = pg_tbl_va; 769 + pt_attrs->l2_tbl_alloc_sz = pt_attrs->l2_size; 770 + pt_attrs->l2_base_pa = pg_tbl_pa; 771 + pt_attrs->l2_base_va = pg_tbl_va; 772 + 773 + if (pt_attrs->l2_base_va) 774 + memset((u8 *) pt_attrs->l2_base_va, 0x00, 775 + pt_attrs->l2_size); 776 + 777 + pt_attrs->pg_info = kzalloc(pt_attrs->l2_num_pages * 778 + sizeof(struct page_info), GFP_KERNEL); 779 + dev_dbg(bridge, 780 + "L1 pa %x, va %x, size %x\n L2 pa %x, va " 781 + "%x, size %x\n", pt_attrs->l1_base_pa, 782 + pt_attrs->l1_base_va, pt_attrs->l1_size, 783 + pt_attrs->l2_base_pa, pt_attrs->l2_base_va, 784 + pt_attrs->l2_size); 785 + dev_dbg(bridge, "pt_attrs %p L2 NumPages %x pg_info %p\n", 786 + pt_attrs, pt_attrs->l2_num_pages, pt_attrs->pg_info); 787 + } 788 + if ((pt_attrs != NULL) && (pt_attrs->l1_base_va != 0) && 789 + (pt_attrs->l2_base_va != 0) && (pt_attrs->pg_info != NULL)) 790 + dev_context->pt_attrs = pt_attrs; 791 + else 792 + status = -ENOMEM; 793 + 787 794 if (!status) { 795 + spin_lock_init(&pt_attrs->pg_lock); 788 796 dev_context->tc_word_swap_on = drv_datap->tc_wordswapon; 797 + 798 + /* Set the Clock Divisor for the DSP module */ 799 + udelay(5); 800 + /* MMU address is obtained from the host 801 + * resources struct */ 802 + dev_context->dw_dsp_mmu_base = resources->dw_dmmu_base; 803 + } 804 + if (!status) { 789 805 dev_context->hdev_obj = hdev_obj; 790 806 /* Store current board state. */ 791 807 dev_context->dw_brd_state = BRD_UNKNOWN; ··· 884 722 /* Return ptr to our device state to the DSP API for storage */ 885 723 *dev_cntxt = dev_context; 886 724 } else { 725 + if (pt_attrs != NULL) { 726 + kfree(pt_attrs->pg_info); 727 + 728 + if (pt_attrs->l2_tbl_alloc_va) { 729 + mem_free_phys_mem((void *) 730 + pt_attrs->l2_tbl_alloc_va, 731 + pt_attrs->l2_tbl_alloc_pa, 732 + pt_attrs->l2_tbl_alloc_sz); 733 + } 734 + if (pt_attrs->l1_tbl_alloc_va) { 735 + mem_free_phys_mem((void *) 736 + pt_attrs->l1_tbl_alloc_va, 737 + pt_attrs->l1_tbl_alloc_pa, 738 + pt_attrs->l1_tbl_alloc_sz); 739 + } 740 + } 741 + kfree(pt_attrs); 887 742 kfree(dev_context); 888 743 } 889 744 func_end: ··· 968 789 */ 969 790 static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt) 970 791 { 792 + struct pg_table_attrs *pt_attrs; 971 793 int status = 0; 972 794 struct bridge_dev_context *dev_context = (struct bridge_dev_context *) 973 795 dev_ctxt; ··· 982 802 983 803 /* first put the device to stop state */ 984 804 bridge_brd_stop(dev_context); 805 + if (dev_context->pt_attrs) { 806 + pt_attrs = dev_context->pt_attrs; 807 + kfree(pt_attrs->pg_info); 808 + 809 + if (pt_attrs->l2_tbl_alloc_va) { 810 + mem_free_phys_mem((void *)pt_attrs->l2_tbl_alloc_va, 811 + pt_attrs->l2_tbl_alloc_pa, 812 + pt_attrs->l2_tbl_alloc_sz); 813 + } 814 + if (pt_attrs->l1_tbl_alloc_va) { 815 + mem_free_phys_mem((void *)pt_attrs->l1_tbl_alloc_va, 816 + pt_attrs->l1_tbl_alloc_pa, 817 + pt_attrs->l1_tbl_alloc_sz); 818 + } 819 + kfree(pt_attrs); 820 + 821 + } 985 822 986 823 if (dev_context->resources) { 987 824 host_res = dev_context->resources; ··· 1029 832 iounmap((void *)host_res->dw_mem_base[3]); 1030 833 if (host_res->dw_mem_base[4]) 1031 834 iounmap((void *)host_res->dw_mem_base[4]); 835 + if (host_res->dw_dmmu_base) 836 + iounmap(host_res->dw_dmmu_base); 1032 837 if (host_res->dw_per_base) 1033 838 iounmap(host_res->dw_per_base); 1034 839 if (host_res->dw_per_pm_base) ··· 1044 845 host_res->dw_mem_base[2] = (u32) NULL; 1045 846 host_res->dw_mem_base[3] = (u32) NULL; 1046 847 host_res->dw_mem_base[4] = (u32) NULL; 848 + host_res->dw_dmmu_base = NULL; 1047 849 host_res->dw_sys_ctrl_base = NULL; 1048 850 1049 851 kfree(host_res); ··· 1124 924 dsp_addr += ul_bytes; 1125 925 host_buff = host_buff + ul_bytes; 1126 926 } 927 + return status; 928 + } 929 + 930 + /* 931 + * ======== bridge_brd_mem_map ======== 932 + * This function maps MPU buffer to the DSP address space. It performs 933 + * linear to physical address translation if required. It translates each 934 + * page since linear addresses can be physically non-contiguous 935 + * All address & size arguments are assumed to be page aligned (in proc.c) 936 + * 937 + * TODO: Disable MMU while updating the page tables (but that'll stall DSP) 938 + */ 939 + static int bridge_brd_mem_map(struct bridge_dev_context *dev_ctxt, 940 + u32 ul_mpu_addr, u32 virt_addr, 941 + u32 ul_num_bytes, u32 ul_map_attr, 942 + struct page **mapped_pages) 943 + { 944 + u32 attrs; 945 + int status = 0; 946 + struct bridge_dev_context *dev_context = dev_ctxt; 947 + struct hw_mmu_map_attrs_t hw_attrs; 948 + struct vm_area_struct *vma; 949 + struct mm_struct *mm = current->mm; 950 + u32 write = 0; 951 + u32 num_usr_pgs = 0; 952 + struct page *mapped_page, *pg; 953 + s32 pg_num; 954 + u32 va = virt_addr; 955 + struct task_struct *curr_task = current; 956 + u32 pg_i = 0; 957 + u32 mpu_addr, pa; 958 + 959 + dev_dbg(bridge, 960 + "%s hDevCtxt %p, pa %x, va %x, size %x, ul_map_attr %x\n", 961 + __func__, dev_ctxt, ul_mpu_addr, virt_addr, ul_num_bytes, 962 + ul_map_attr); 963 + if (ul_num_bytes == 0) 964 + return -EINVAL; 965 + 966 + if (ul_map_attr & DSP_MAP_DIR_MASK) { 967 + attrs = ul_map_attr; 968 + } else { 969 + /* Assign default attributes */ 970 + attrs = ul_map_attr | (DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16); 971 + } 972 + /* Take mapping properties */ 973 + if (attrs & DSP_MAPBIGENDIAN) 974 + hw_attrs.endianism = HW_BIG_ENDIAN; 975 + else 976 + hw_attrs.endianism = HW_LITTLE_ENDIAN; 977 + 978 + hw_attrs.mixed_size = (enum hw_mmu_mixed_size_t) 979 + ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2); 980 + /* Ignore element_size if mixed_size is enabled */ 981 + if (hw_attrs.mixed_size == 0) { 982 + if (attrs & DSP_MAPELEMSIZE8) { 983 + /* Size is 8 bit */ 984 + hw_attrs.element_size = HW_ELEM_SIZE8BIT; 985 + } else if (attrs & DSP_MAPELEMSIZE16) { 986 + /* Size is 16 bit */ 987 + hw_attrs.element_size = HW_ELEM_SIZE16BIT; 988 + } else if (attrs & DSP_MAPELEMSIZE32) { 989 + /* Size is 32 bit */ 990 + hw_attrs.element_size = HW_ELEM_SIZE32BIT; 991 + } else if (attrs & DSP_MAPELEMSIZE64) { 992 + /* Size is 64 bit */ 993 + hw_attrs.element_size = HW_ELEM_SIZE64BIT; 994 + } else { 995 + /* 996 + * Mixedsize isn't enabled, so size can't be 997 + * zero here 998 + */ 999 + return -EINVAL; 1000 + } 1001 + } 1002 + if (attrs & DSP_MAPDONOTLOCK) 1003 + hw_attrs.donotlockmpupage = 1; 1004 + else 1005 + hw_attrs.donotlockmpupage = 0; 1006 + 1007 + if (attrs & DSP_MAPVMALLOCADDR) { 1008 + return mem_map_vmalloc(dev_ctxt, ul_mpu_addr, virt_addr, 1009 + ul_num_bytes, &hw_attrs); 1010 + } 1011 + /* 1012 + * Do OS-specific user-va to pa translation. 1013 + * Combine physically contiguous regions to reduce TLBs. 1014 + * Pass the translated pa to pte_update. 1015 + */ 1016 + if ((attrs & DSP_MAPPHYSICALADDR)) { 1017 + status = pte_update(dev_context, ul_mpu_addr, virt_addr, 1018 + ul_num_bytes, &hw_attrs); 1019 + goto func_cont; 1020 + } 1021 + 1022 + /* 1023 + * Important Note: ul_mpu_addr is mapped from user application process 1024 + * to current process - it must lie completely within the current 1025 + * virtual memory address space in order to be of use to us here! 1026 + */ 1027 + down_read(&mm->mmap_sem); 1028 + vma = find_vma(mm, ul_mpu_addr); 1029 + if (vma) 1030 + dev_dbg(bridge, 1031 + "VMAfor UserBuf: ul_mpu_addr=%x, ul_num_bytes=%x, " 1032 + "vm_start=%lx, vm_end=%lx, vm_flags=%lx\n", ul_mpu_addr, 1033 + ul_num_bytes, vma->vm_start, vma->vm_end, 1034 + vma->vm_flags); 1035 + 1036 + /* 1037 + * It is observed that under some circumstances, the user buffer is 1038 + * spread across several VMAs. So loop through and check if the entire 1039 + * user buffer is covered 1040 + */ 1041 + while ((vma) && (ul_mpu_addr + ul_num_bytes > vma->vm_end)) { 1042 + /* jump to the next VMA region */ 1043 + vma = find_vma(mm, vma->vm_end + 1); 1044 + dev_dbg(bridge, 1045 + "VMA for UserBuf ul_mpu_addr=%x ul_num_bytes=%x, " 1046 + "vm_start=%lx, vm_end=%lx, vm_flags=%lx\n", ul_mpu_addr, 1047 + ul_num_bytes, vma->vm_start, vma->vm_end, 1048 + vma->vm_flags); 1049 + } 1050 + if (!vma) { 1051 + pr_err("%s: Failed to get VMA region for 0x%x (%d)\n", 1052 + __func__, ul_mpu_addr, ul_num_bytes); 1053 + status = -EINVAL; 1054 + up_read(&mm->mmap_sem); 1055 + goto func_cont; 1056 + } 1057 + 1058 + if (vma->vm_flags & VM_IO) { 1059 + num_usr_pgs = ul_num_bytes / PG_SIZE4K; 1060 + mpu_addr = ul_mpu_addr; 1061 + 1062 + /* Get the physical addresses for user buffer */ 1063 + for (pg_i = 0; pg_i < num_usr_pgs; pg_i++) { 1064 + pa = user_va2_pa(mm, mpu_addr); 1065 + if (!pa) { 1066 + status = -EPERM; 1067 + pr_err("DSPBRIDGE: VM_IO mapping physical" 1068 + "address is invalid\n"); 1069 + break; 1070 + } 1071 + if (pfn_valid(__phys_to_pfn(pa))) { 1072 + pg = PHYS_TO_PAGE(pa); 1073 + get_page(pg); 1074 + if (page_count(pg) < 1) { 1075 + pr_err("Bad page in VM_IO buffer\n"); 1076 + bad_page_dump(pa, pg); 1077 + } 1078 + } 1079 + status = pte_set(dev_context->pt_attrs, pa, 1080 + va, HW_PAGE_SIZE4KB, &hw_attrs); 1081 + if (status) 1082 + break; 1083 + 1084 + va += HW_PAGE_SIZE4KB; 1085 + mpu_addr += HW_PAGE_SIZE4KB; 1086 + pa += HW_PAGE_SIZE4KB; 1087 + } 1088 + } else { 1089 + num_usr_pgs = ul_num_bytes / PG_SIZE4K; 1090 + if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) 1091 + write = 1; 1092 + 1093 + for (pg_i = 0; pg_i < num_usr_pgs; pg_i++) { 1094 + pg_num = get_user_pages(curr_task, mm, ul_mpu_addr, 1, 1095 + write, 1, &mapped_page, NULL); 1096 + if (pg_num > 0) { 1097 + if (page_count(mapped_page) < 1) { 1098 + pr_err("Bad page count after doing" 1099 + "get_user_pages on" 1100 + "user buffer\n"); 1101 + bad_page_dump(page_to_phys(mapped_page), 1102 + mapped_page); 1103 + } 1104 + status = pte_set(dev_context->pt_attrs, 1105 + page_to_phys(mapped_page), va, 1106 + HW_PAGE_SIZE4KB, &hw_attrs); 1107 + if (status) 1108 + break; 1109 + 1110 + if (mapped_pages) 1111 + mapped_pages[pg_i] = mapped_page; 1112 + 1113 + va += HW_PAGE_SIZE4KB; 1114 + ul_mpu_addr += HW_PAGE_SIZE4KB; 1115 + } else { 1116 + pr_err("DSPBRIDGE: get_user_pages FAILED," 1117 + "MPU addr = 0x%x," 1118 + "vma->vm_flags = 0x%lx," 1119 + "get_user_pages Err" 1120 + "Value = %d, Buffer" 1121 + "size=0x%x\n", ul_mpu_addr, 1122 + vma->vm_flags, pg_num, ul_num_bytes); 1123 + status = -EPERM; 1124 + break; 1125 + } 1126 + } 1127 + } 1128 + up_read(&mm->mmap_sem); 1129 + func_cont: 1130 + if (status) { 1131 + /* 1132 + * Roll out the mapped pages incase it failed in middle of 1133 + * mapping 1134 + */ 1135 + if (pg_i) { 1136 + bridge_brd_mem_un_map(dev_context, virt_addr, 1137 + (pg_i * PG_SIZE4K)); 1138 + } 1139 + status = -EPERM; 1140 + } 1141 + /* 1142 + * In any case, flush the TLB 1143 + * This is called from here instead from pte_update to avoid unnecessary 1144 + * repetition while mapping non-contiguous physical regions of a virtual 1145 + * region 1146 + */ 1147 + flush_all(dev_context); 1148 + dev_dbg(bridge, "%s status %x\n", __func__, status); 1149 + return status; 1150 + } 1151 + 1152 + /* 1153 + * ======== bridge_brd_mem_un_map ======== 1154 + * Invalidate the PTEs for the DSP VA block to be unmapped. 1155 + * 1156 + * PTEs of a mapped memory block are contiguous in any page table 1157 + * So, instead of looking up the PTE address for every 4K block, 1158 + * we clear consecutive PTEs until we unmap all the bytes 1159 + */ 1160 + static int bridge_brd_mem_un_map(struct bridge_dev_context *dev_ctxt, 1161 + u32 virt_addr, u32 ul_num_bytes) 1162 + { 1163 + u32 l1_base_va; 1164 + u32 l2_base_va; 1165 + u32 l2_base_pa; 1166 + u32 l2_page_num; 1167 + u32 pte_val; 1168 + u32 pte_size; 1169 + u32 pte_count; 1170 + u32 pte_addr_l1; 1171 + u32 pte_addr_l2 = 0; 1172 + u32 rem_bytes; 1173 + u32 rem_bytes_l2; 1174 + u32 va_curr; 1175 + struct page *pg = NULL; 1176 + int status = 0; 1177 + struct bridge_dev_context *dev_context = dev_ctxt; 1178 + struct pg_table_attrs *pt = dev_context->pt_attrs; 1179 + u32 temp; 1180 + u32 paddr; 1181 + u32 numof4k_pages = 0; 1182 + 1183 + va_curr = virt_addr; 1184 + rem_bytes = ul_num_bytes; 1185 + rem_bytes_l2 = 0; 1186 + l1_base_va = pt->l1_base_va; 1187 + pte_addr_l1 = hw_mmu_pte_addr_l1(l1_base_va, va_curr); 1188 + dev_dbg(bridge, "%s dev_ctxt %p, va %x, NumBytes %x l1_base_va %x, " 1189 + "pte_addr_l1 %x\n", __func__, dev_ctxt, virt_addr, 1190 + ul_num_bytes, l1_base_va, pte_addr_l1); 1191 + 1192 + while (rem_bytes && !status) { 1193 + u32 va_curr_orig = va_curr; 1194 + /* Find whether the L1 PTE points to a valid L2 PT */ 1195 + pte_addr_l1 = hw_mmu_pte_addr_l1(l1_base_va, va_curr); 1196 + pte_val = *(u32 *) pte_addr_l1; 1197 + pte_size = hw_mmu_pte_size_l1(pte_val); 1198 + 1199 + if (pte_size != HW_MMU_COARSE_PAGE_SIZE) 1200 + goto skip_coarse_page; 1201 + 1202 + /* 1203 + * Get the L2 PA from the L1 PTE, and find 1204 + * corresponding L2 VA 1205 + */ 1206 + l2_base_pa = hw_mmu_pte_coarse_l1(pte_val); 1207 + l2_base_va = l2_base_pa - pt->l2_base_pa + pt->l2_base_va; 1208 + l2_page_num = 1209 + (l2_base_pa - pt->l2_base_pa) / HW_MMU_COARSE_PAGE_SIZE; 1210 + /* 1211 + * Find the L2 PTE address from which we will start 1212 + * clearing, the number of PTEs to be cleared on this 1213 + * page, and the size of VA space that needs to be 1214 + * cleared on this L2 page 1215 + */ 1216 + pte_addr_l2 = hw_mmu_pte_addr_l2(l2_base_va, va_curr); 1217 + pte_count = pte_addr_l2 & (HW_MMU_COARSE_PAGE_SIZE - 1); 1218 + pte_count = (HW_MMU_COARSE_PAGE_SIZE - pte_count) / sizeof(u32); 1219 + if (rem_bytes < (pte_count * PG_SIZE4K)) 1220 + pte_count = rem_bytes / PG_SIZE4K; 1221 + rem_bytes_l2 = pte_count * PG_SIZE4K; 1222 + 1223 + /* 1224 + * Unmap the VA space on this L2 PT. A quicker way 1225 + * would be to clear pte_count entries starting from 1226 + * pte_addr_l2. However, below code checks that we don't 1227 + * clear invalid entries or less than 64KB for a 64KB 1228 + * entry. Similar checking is done for L1 PTEs too 1229 + * below 1230 + */ 1231 + while (rem_bytes_l2 && !status) { 1232 + pte_val = *(u32 *) pte_addr_l2; 1233 + pte_size = hw_mmu_pte_size_l2(pte_val); 1234 + /* va_curr aligned to pte_size? */ 1235 + if (pte_size == 0 || rem_bytes_l2 < pte_size || 1236 + va_curr & (pte_size - 1)) { 1237 + status = -EPERM; 1238 + break; 1239 + } 1240 + 1241 + /* Collect Physical addresses from VA */ 1242 + paddr = (pte_val & ~(pte_size - 1)); 1243 + if (pte_size == HW_PAGE_SIZE64KB) 1244 + numof4k_pages = 16; 1245 + else 1246 + numof4k_pages = 1; 1247 + temp = 0; 1248 + while (temp++ < numof4k_pages) { 1249 + if (!pfn_valid(__phys_to_pfn(paddr))) { 1250 + paddr += HW_PAGE_SIZE4KB; 1251 + continue; 1252 + } 1253 + pg = PHYS_TO_PAGE(paddr); 1254 + if (page_count(pg) < 1) { 1255 + pr_info("DSPBRIDGE: UNMAP function: " 1256 + "COUNT 0 FOR PA 0x%x, size = " 1257 + "0x%x\n", paddr, ul_num_bytes); 1258 + bad_page_dump(paddr, pg); 1259 + } else { 1260 + set_page_dirty(pg); 1261 + page_cache_release(pg); 1262 + } 1263 + paddr += HW_PAGE_SIZE4KB; 1264 + } 1265 + if (hw_mmu_pte_clear(pte_addr_l2, va_curr, pte_size)) { 1266 + status = -EPERM; 1267 + goto EXIT_LOOP; 1268 + } 1269 + 1270 + status = 0; 1271 + rem_bytes_l2 -= pte_size; 1272 + va_curr += pte_size; 1273 + pte_addr_l2 += (pte_size >> 12) * sizeof(u32); 1274 + } 1275 + spin_lock(&pt->pg_lock); 1276 + if (rem_bytes_l2 == 0) { 1277 + pt->pg_info[l2_page_num].num_entries -= pte_count; 1278 + if (pt->pg_info[l2_page_num].num_entries == 0) { 1279 + /* 1280 + * Clear the L1 PTE pointing to the L2 PT 1281 + */ 1282 + if (!hw_mmu_pte_clear(l1_base_va, va_curr_orig, 1283 + HW_MMU_COARSE_PAGE_SIZE)) 1284 + status = 0; 1285 + else { 1286 + status = -EPERM; 1287 + spin_unlock(&pt->pg_lock); 1288 + goto EXIT_LOOP; 1289 + } 1290 + } 1291 + rem_bytes -= pte_count * PG_SIZE4K; 1292 + } else 1293 + status = -EPERM; 1294 + 1295 + spin_unlock(&pt->pg_lock); 1296 + continue; 1297 + skip_coarse_page: 1298 + /* va_curr aligned to pte_size? */ 1299 + /* pte_size = 1 MB or 16 MB */ 1300 + if (pte_size == 0 || rem_bytes < pte_size || 1301 + va_curr & (pte_size - 1)) { 1302 + status = -EPERM; 1303 + break; 1304 + } 1305 + 1306 + if (pte_size == HW_PAGE_SIZE1MB) 1307 + numof4k_pages = 256; 1308 + else 1309 + numof4k_pages = 4096; 1310 + temp = 0; 1311 + /* Collect Physical addresses from VA */ 1312 + paddr = (pte_val & ~(pte_size - 1)); 1313 + while (temp++ < numof4k_pages) { 1314 + if (pfn_valid(__phys_to_pfn(paddr))) { 1315 + pg = PHYS_TO_PAGE(paddr); 1316 + if (page_count(pg) < 1) { 1317 + pr_info("DSPBRIDGE: UNMAP function: " 1318 + "COUNT 0 FOR PA 0x%x, size = " 1319 + "0x%x\n", paddr, ul_num_bytes); 1320 + bad_page_dump(paddr, pg); 1321 + } else { 1322 + set_page_dirty(pg); 1323 + page_cache_release(pg); 1324 + } 1325 + } 1326 + paddr += HW_PAGE_SIZE4KB; 1327 + } 1328 + if (!hw_mmu_pte_clear(l1_base_va, va_curr, pte_size)) { 1329 + status = 0; 1330 + rem_bytes -= pte_size; 1331 + va_curr += pte_size; 1332 + } else { 1333 + status = -EPERM; 1334 + goto EXIT_LOOP; 1335 + } 1336 + } 1337 + /* 1338 + * It is better to flush the TLB here, so that any stale old entries 1339 + * get flushed 1340 + */ 1341 + EXIT_LOOP: 1342 + flush_all(dev_context); 1343 + dev_dbg(bridge, 1344 + "%s: va_curr %x, pte_addr_l1 %x pte_addr_l2 %x rem_bytes %x," 1345 + " rem_bytes_l2 %x status %x\n", __func__, va_curr, pte_addr_l1, 1346 + pte_addr_l2, rem_bytes, rem_bytes_l2, status); 1347 + return status; 1348 + } 1349 + 1350 + /* 1351 + * ======== user_va2_pa ======== 1352 + * Purpose: 1353 + * This function walks through the page tables to convert a userland 1354 + * virtual address to physical address 1355 + */ 1356 + static u32 user_va2_pa(struct mm_struct *mm, u32 address) 1357 + { 1358 + pgd_t *pgd; 1359 + pmd_t *pmd; 1360 + pte_t *ptep, pte; 1361 + 1362 + pgd = pgd_offset(mm, address); 1363 + if (!(pgd_none(*pgd) || pgd_bad(*pgd))) { 1364 + pmd = pmd_offset(pgd, address); 1365 + if (!(pmd_none(*pmd) || pmd_bad(*pmd))) { 1366 + ptep = pte_offset_map(pmd, address); 1367 + if (ptep) { 1368 + pte = *ptep; 1369 + if (pte_present(pte)) 1370 + return pte & PAGE_MASK; 1371 + } 1372 + } 1373 + } 1374 + 1375 + return 0; 1376 + } 1377 + 1378 + /* 1379 + * ======== pte_update ======== 1380 + * This function calculates the optimum page-aligned addresses and sizes 1381 + * Caller must pass page-aligned values 1382 + */ 1383 + static int pte_update(struct bridge_dev_context *dev_ctxt, u32 pa, 1384 + u32 va, u32 size, 1385 + struct hw_mmu_map_attrs_t *map_attrs) 1386 + { 1387 + u32 i; 1388 + u32 all_bits; 1389 + u32 pa_curr = pa; 1390 + u32 va_curr = va; 1391 + u32 num_bytes = size; 1392 + struct bridge_dev_context *dev_context = dev_ctxt; 1393 + int status = 0; 1394 + u32 page_size[] = { HW_PAGE_SIZE16MB, HW_PAGE_SIZE1MB, 1395 + HW_PAGE_SIZE64KB, HW_PAGE_SIZE4KB 1396 + }; 1397 + 1398 + while (num_bytes && !status) { 1399 + /* To find the max. page size with which both PA & VA are 1400 + * aligned */ 1401 + all_bits = pa_curr | va_curr; 1402 + 1403 + for (i = 0; i < 4; i++) { 1404 + if ((num_bytes >= page_size[i]) && ((all_bits & 1405 + (page_size[i] - 1406 + 1)) == 0)) { 1407 + status = 1408 + pte_set(dev_context->pt_attrs, pa_curr, 1409 + va_curr, page_size[i], map_attrs); 1410 + pa_curr += page_size[i]; 1411 + va_curr += page_size[i]; 1412 + num_bytes -= page_size[i]; 1413 + /* Don't try smaller sizes. Hopefully we have 1414 + * reached an address aligned to a bigger page 1415 + * size */ 1416 + break; 1417 + } 1418 + } 1419 + } 1420 + 1421 + return status; 1422 + } 1423 + 1424 + /* 1425 + * ======== pte_set ======== 1426 + * This function calculates PTE address (MPU virtual) to be updated 1427 + * It also manages the L2 page tables 1428 + */ 1429 + static int pte_set(struct pg_table_attrs *pt, u32 pa, u32 va, 1430 + u32 size, struct hw_mmu_map_attrs_t *attrs) 1431 + { 1432 + u32 i; 1433 + u32 pte_val; 1434 + u32 pte_addr_l1; 1435 + u32 pte_size; 1436 + /* Base address of the PT that will be updated */ 1437 + u32 pg_tbl_va; 1438 + u32 l1_base_va; 1439 + /* Compiler warns that the next three variables might be used 1440 + * uninitialized in this function. Doesn't seem so. Working around, 1441 + * anyways. */ 1442 + u32 l2_base_va = 0; 1443 + u32 l2_base_pa = 0; 1444 + u32 l2_page_num = 0; 1445 + int status = 0; 1446 + 1447 + l1_base_va = pt->l1_base_va; 1448 + pg_tbl_va = l1_base_va; 1449 + if ((size == HW_PAGE_SIZE64KB) || (size == HW_PAGE_SIZE4KB)) { 1450 + /* Find whether the L1 PTE points to a valid L2 PT */ 1451 + pte_addr_l1 = hw_mmu_pte_addr_l1(l1_base_va, va); 1452 + if (pte_addr_l1 <= (pt->l1_base_va + pt->l1_size)) { 1453 + pte_val = *(u32 *) pte_addr_l1; 1454 + pte_size = hw_mmu_pte_size_l1(pte_val); 1455 + } else { 1456 + return -EPERM; 1457 + } 1458 + spin_lock(&pt->pg_lock); 1459 + if (pte_size == HW_MMU_COARSE_PAGE_SIZE) { 1460 + /* Get the L2 PA from the L1 PTE, and find 1461 + * corresponding L2 VA */ 1462 + l2_base_pa = hw_mmu_pte_coarse_l1(pte_val); 1463 + l2_base_va = 1464 + l2_base_pa - pt->l2_base_pa + pt->l2_base_va; 1465 + l2_page_num = 1466 + (l2_base_pa - 1467 + pt->l2_base_pa) / HW_MMU_COARSE_PAGE_SIZE; 1468 + } else if (pte_size == 0) { 1469 + /* L1 PTE is invalid. Allocate a L2 PT and 1470 + * point the L1 PTE to it */ 1471 + /* Find a free L2 PT. */ 1472 + for (i = 0; (i < pt->l2_num_pages) && 1473 + (pt->pg_info[i].num_entries != 0); i++) 1474 + ;; 1475 + if (i < pt->l2_num_pages) { 1476 + l2_page_num = i; 1477 + l2_base_pa = pt->l2_base_pa + (l2_page_num * 1478 + HW_MMU_COARSE_PAGE_SIZE); 1479 + l2_base_va = pt->l2_base_va + (l2_page_num * 1480 + HW_MMU_COARSE_PAGE_SIZE); 1481 + /* Endianness attributes are ignored for 1482 + * HW_MMU_COARSE_PAGE_SIZE */ 1483 + status = 1484 + hw_mmu_pte_set(l1_base_va, l2_base_pa, va, 1485 + HW_MMU_COARSE_PAGE_SIZE, 1486 + attrs); 1487 + } else { 1488 + status = -ENOMEM; 1489 + } 1490 + } else { 1491 + /* Found valid L1 PTE of another size. 1492 + * Should not overwrite it. */ 1493 + status = -EPERM; 1494 + } 1495 + if (!status) { 1496 + pg_tbl_va = l2_base_va; 1497 + if (size == HW_PAGE_SIZE64KB) 1498 + pt->pg_info[l2_page_num].num_entries += 16; 1499 + else 1500 + pt->pg_info[l2_page_num].num_entries++; 1501 + dev_dbg(bridge, "PTE: L2 BaseVa %x, BasePa %x, PageNum " 1502 + "%x, num_entries %x\n", l2_base_va, 1503 + l2_base_pa, l2_page_num, 1504 + pt->pg_info[l2_page_num].num_entries); 1505 + } 1506 + spin_unlock(&pt->pg_lock); 1507 + } 1508 + if (!status) { 1509 + dev_dbg(bridge, "PTE: pg_tbl_va %x, pa %x, va %x, size %x\n", 1510 + pg_tbl_va, pa, va, size); 1511 + dev_dbg(bridge, "PTE: endianism %x, element_size %x, " 1512 + "mixed_size %x\n", attrs->endianism, 1513 + attrs->element_size, attrs->mixed_size); 1514 + status = hw_mmu_pte_set(pg_tbl_va, pa, va, size, attrs); 1515 + } 1516 + 1517 + return status; 1518 + } 1519 + 1520 + /* Memory map kernel VA -- memory allocated with vmalloc */ 1521 + static int mem_map_vmalloc(struct bridge_dev_context *dev_context, 1522 + u32 ul_mpu_addr, u32 virt_addr, 1523 + u32 ul_num_bytes, 1524 + struct hw_mmu_map_attrs_t *hw_attrs) 1525 + { 1526 + int status = 0; 1527 + struct page *page[1]; 1528 + u32 i; 1529 + u32 pa_curr; 1530 + u32 pa_next; 1531 + u32 va_curr; 1532 + u32 size_curr; 1533 + u32 num_pages; 1534 + u32 pa; 1535 + u32 num_of4k_pages; 1536 + u32 temp = 0; 1537 + 1538 + /* 1539 + * Do Kernel va to pa translation. 1540 + * Combine physically contiguous regions to reduce TLBs. 1541 + * Pass the translated pa to pte_update. 1542 + */ 1543 + num_pages = ul_num_bytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */ 1544 + i = 0; 1545 + va_curr = ul_mpu_addr; 1546 + page[0] = vmalloc_to_page((void *)va_curr); 1547 + pa_next = page_to_phys(page[0]); 1548 + while (!status && (i < num_pages)) { 1549 + /* 1550 + * Reuse pa_next from the previous iteraion to avoid 1551 + * an extra va2pa call 1552 + */ 1553 + pa_curr = pa_next; 1554 + size_curr = PAGE_SIZE; 1555 + /* 1556 + * If the next page is physically contiguous, 1557 + * map it with the current one by increasing 1558 + * the size of the region to be mapped 1559 + */ 1560 + while (++i < num_pages) { 1561 + page[0] = 1562 + vmalloc_to_page((void *)(va_curr + size_curr)); 1563 + pa_next = page_to_phys(page[0]); 1564 + 1565 + if (pa_next == (pa_curr + size_curr)) 1566 + size_curr += PAGE_SIZE; 1567 + else 1568 + break; 1569 + 1570 + } 1571 + if (pa_next == 0) { 1572 + status = -ENOMEM; 1573 + break; 1574 + } 1575 + pa = pa_curr; 1576 + num_of4k_pages = size_curr / HW_PAGE_SIZE4KB; 1577 + while (temp++ < num_of4k_pages) { 1578 + get_page(PHYS_TO_PAGE(pa)); 1579 + pa += HW_PAGE_SIZE4KB; 1580 + } 1581 + status = pte_update(dev_context, pa_curr, virt_addr + 1582 + (va_curr - ul_mpu_addr), size_curr, 1583 + hw_attrs); 1584 + va_curr += size_curr; 1585 + } 1586 + /* 1587 + * In any case, flush the TLB 1588 + * This is called from here instead from pte_update to avoid unnecessary 1589 + * repetition while mapping non-contiguous physical regions of a virtual 1590 + * region 1591 + */ 1592 + flush_all(dev_context); 1593 + dev_dbg(bridge, "%s status %x\n", __func__, status); 1127 1594 return status; 1128 1595 } 1129 1596
+4
drivers/staging/tidspbridge/core/tiomap3430_pwr.c
··· 31 31 #include <dspbridge/dev.h> 32 32 #include <dspbridge/iodefs.h> 33 33 34 + /* ------------------------------------ Hardware Abstraction Layer */ 35 + #include <hw_defs.h> 36 + #include <hw_mmu.h> 37 + 34 38 #include <dspbridge/pwr_sh.h> 35 39 36 40 /* ----------------------------------- Bridge Driver */
+9 -8
drivers/staging/tidspbridge/core/tiomap_io.c
··· 134 134 135 135 if (!status) { 136 136 ul_tlb_base_virt = 137 - dev_context->sh_s.seg0_da * DSPWORDSIZE; 137 + dev_context->atlb_entry[0].ul_dsp_va * DSPWORDSIZE; 138 138 DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt); 139 - dw_ext_prog_virt_mem = dev_context->sh_s.seg0_va; 139 + dw_ext_prog_virt_mem = 140 + dev_context->atlb_entry[0].ul_gpp_va; 140 141 141 142 if (!trace_read) { 142 143 ul_shm_offset_virt = 143 144 ul_shm_base_virt - ul_tlb_base_virt; 144 145 ul_shm_offset_virt += 145 146 PG_ALIGN_HIGH(ul_ext_end - ul_dyn_ext_base + 146 - 1, PAGE_SIZE * 16); 147 + 1, HW_PAGE_SIZE64KB); 147 148 dw_ext_prog_virt_mem -= ul_shm_offset_virt; 148 149 dw_ext_prog_virt_mem += 149 150 (ul_ext_base - ul_dyn_ext_base); ··· 318 317 ret = -EPERM; 319 318 320 319 if (!ret) { 321 - ul_tlb_base_virt = dev_context->sh_s.seg0_da * 322 - DSPWORDSIZE; 323 - 320 + ul_tlb_base_virt = 321 + dev_context->atlb_entry[0].ul_dsp_va * DSPWORDSIZE; 324 322 DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt); 325 323 326 324 if (symbols_reloaded) { ··· 337 337 ul_shm_base_virt - ul_tlb_base_virt; 338 338 if (trace_load) { 339 339 dw_ext_prog_virt_mem = 340 - dev_context->sh_s.seg0_va; 340 + dev_context->atlb_entry[0].ul_gpp_va; 341 341 } else { 342 342 dw_ext_prog_virt_mem = host_res->dw_mem_base[1]; 343 343 dw_ext_prog_virt_mem += ··· 393 393 omap_dspbridge_dev->dev.platform_data; 394 394 struct cfg_hostres *resources = dev_context->resources; 395 395 int status = 0; 396 + u32 temp; 396 397 397 398 if (!dev_context->mbox) 398 399 return 0; ··· 437 436 omap_mbox_restore_ctx(dev_context->mbox); 438 437 439 438 /* Access MMU SYS CONFIG register to generate a short wakeup */ 440 - iommu_read_reg(dev_context->dsp_mmu, MMU_SYSCONFIG); 439 + temp = readl(resources->dw_dmmu_base + 0x10); 441 440 442 441 dev_context->dw_brd_state = BRD_RUNNING; 443 442 } else if (dev_context->dw_brd_state == BRD_RETENTION) {
+114 -1
drivers/staging/tidspbridge/core/ue_deh.c
··· 31 31 #include <dspbridge/drv.h> 32 32 #include <dspbridge/wdt.h> 33 33 34 + static u32 fault_addr; 35 + 36 + static void mmu_fault_dpc(unsigned long data) 37 + { 38 + struct deh_mgr *deh = (void *)data; 39 + 40 + if (!deh) 41 + return; 42 + 43 + bridge_deh_notify(deh, DSP_MMUFAULT, 0); 44 + } 45 + 46 + static irqreturn_t mmu_fault_isr(int irq, void *data) 47 + { 48 + struct deh_mgr *deh = data; 49 + struct cfg_hostres *resources; 50 + u32 event; 51 + 52 + if (!deh) 53 + return IRQ_HANDLED; 54 + 55 + resources = deh->hbridge_context->resources; 56 + if (!resources) { 57 + dev_dbg(bridge, "%s: Failed to get Host Resources\n", 58 + __func__); 59 + return IRQ_HANDLED; 60 + } 61 + 62 + hw_mmu_event_status(resources->dw_dmmu_base, &event); 63 + if (event == HW_MMU_TRANSLATION_FAULT) { 64 + hw_mmu_fault_addr_read(resources->dw_dmmu_base, &fault_addr); 65 + dev_dbg(bridge, "%s: event=0x%x, fault_addr=0x%x\n", __func__, 66 + event, fault_addr); 67 + /* 68 + * Schedule a DPC directly. In the future, it may be 69 + * necessary to check if DSP MMU fault is intended for 70 + * Bridge. 71 + */ 72 + tasklet_schedule(&deh->dpc_tasklet); 73 + 74 + /* Disable the MMU events, else once we clear it will 75 + * start to raise INTs again */ 76 + hw_mmu_event_disable(resources->dw_dmmu_base, 77 + HW_MMU_TRANSLATION_FAULT); 78 + } else { 79 + hw_mmu_event_disable(resources->dw_dmmu_base, 80 + HW_MMU_ALL_INTERRUPTS); 81 + } 82 + return IRQ_HANDLED; 83 + } 84 + 34 85 int bridge_deh_create(struct deh_mgr **ret_deh, 35 86 struct dev_object *hdev_obj) 36 87 { ··· 109 58 } 110 59 ntfy_init(deh->ntfy_obj); 111 60 61 + /* Create a MMUfault DPC */ 62 + tasklet_init(&deh->dpc_tasklet, mmu_fault_dpc, (u32) deh); 63 + 112 64 /* Fill in context structure */ 113 65 deh->hbridge_context = hbridge_context; 66 + 67 + /* Install ISR function for DSP MMU fault */ 68 + status = request_irq(INT_DSP_MMU_IRQ, mmu_fault_isr, 0, 69 + "DspBridge\tiommu fault", deh); 70 + if (status < 0) 71 + goto err; 114 72 115 73 *ret_deh = deh; 116 74 return 0; ··· 140 80 ntfy_delete(deh->ntfy_obj); 141 81 kfree(deh->ntfy_obj); 142 82 } 83 + /* Disable DSP MMU fault */ 84 + free_irq(INT_DSP_MMU_IRQ, deh); 85 + 86 + /* Free DPC object */ 87 + tasklet_kill(&deh->dpc_tasklet); 143 88 144 89 /* Deallocate the DEH manager object */ 145 90 kfree(deh); ··· 165 100 else 166 101 return ntfy_unregister(deh->ntfy_obj, hnotification); 167 102 } 103 + 104 + #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE 105 + static void mmu_fault_print_stack(struct bridge_dev_context *dev_context) 106 + { 107 + struct cfg_hostres *resources; 108 + struct hw_mmu_map_attrs_t map_attrs = { 109 + .endianism = HW_LITTLE_ENDIAN, 110 + .element_size = HW_ELEM_SIZE16BIT, 111 + .mixed_size = HW_MMU_CPUES, 112 + }; 113 + void *dummy_va_addr; 114 + 115 + resources = dev_context->resources; 116 + dummy_va_addr = (void*)__get_free_page(GFP_ATOMIC); 117 + 118 + /* 119 + * Before acking the MMU fault, let's make sure MMU can only 120 + * access entry #0. Then add a new entry so that the DSP OS 121 + * can continue in order to dump the stack. 122 + */ 123 + hw_mmu_twl_disable(resources->dw_dmmu_base); 124 + hw_mmu_tlb_flush_all(resources->dw_dmmu_base); 125 + 126 + hw_mmu_tlb_add(resources->dw_dmmu_base, 127 + virt_to_phys(dummy_va_addr), fault_addr, 128 + HW_PAGE_SIZE4KB, 1, 129 + &map_attrs, HW_SET, HW_SET); 130 + 131 + dsp_clk_enable(DSP_CLK_GPT8); 132 + 133 + dsp_gpt_wait_overflow(DSP_CLK_GPT8, 0xfffffffe); 134 + 135 + /* Clear MMU interrupt */ 136 + hw_mmu_event_ack(resources->dw_dmmu_base, 137 + HW_MMU_TRANSLATION_FAULT); 138 + dump_dsp_stack(dev_context); 139 + dsp_clk_disable(DSP_CLK_GPT8); 140 + 141 + hw_mmu_disable(resources->dw_dmmu_base); 142 + free_page((unsigned long)dummy_va_addr); 143 + } 144 + #endif 168 145 169 146 static inline const char *event_to_string(int event) 170 147 { ··· 240 133 #endif 241 134 break; 242 135 case DSP_MMUFAULT: 243 - dev_err(bridge, "%s: %s, addr=0x%x", __func__, str, info); 136 + dev_err(bridge, "%s: %s, addr=0x%x", __func__, 137 + str, fault_addr); 138 + #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE 139 + print_dsp_trace_buffer(dev_context); 140 + dump_dl_modules(dev_context); 141 + mmu_fault_print_stack(dev_context); 142 + #endif 244 143 break; 245 144 default: 246 145 dev_err(bridge, "%s: %s", __func__, str);
+41
drivers/staging/tidspbridge/hw/EasiGlobal.h
··· 1 + /* 2 + * EasiGlobal.h 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * Copyright (C) 2007 Texas Instruments, Inc. 7 + * 8 + * This package is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 13 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 14 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 15 + */ 16 + 17 + #ifndef _EASIGLOBAL_H 18 + #define _EASIGLOBAL_H 19 + #include <linux/types.h> 20 + 21 + /* 22 + * DEFINE: READ_ONLY, WRITE_ONLY & READ_WRITE 23 + * 24 + * DESCRIPTION: Defines used to describe register types for EASI-checker tests. 25 + */ 26 + 27 + #define READ_ONLY 1 28 + #define WRITE_ONLY 2 29 + #define READ_WRITE 3 30 + 31 + /* 32 + * MACRO: _DEBUG_LEVEL1_EASI 33 + * 34 + * DESCRIPTION: A MACRO which can be used to indicate that a particular beach 35 + * register access function was called. 36 + * 37 + * NOTE: We currently dont use this functionality. 38 + */ 39 + #define _DEBUG_LEVEL1_EASI(easi_num) ((void)0) 40 + 41 + #endif /* _EASIGLOBAL_H */
+76
drivers/staging/tidspbridge/hw/MMUAccInt.h
··· 1 + /* 2 + * MMUAccInt.h 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * Copyright (C) 2007 Texas Instruments, Inc. 7 + * 8 + * This package is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 13 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 14 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 15 + */ 16 + 17 + #ifndef _MMU_ACC_INT_H 18 + #define _MMU_ACC_INT_H 19 + 20 + /* Mappings of level 1 EASI function numbers to function names */ 21 + 22 + #define EASIL1_MMUMMU_SYSCONFIG_READ_REGISTER32 (MMU_BASE_EASIL1 + 3) 23 + #define EASIL1_MMUMMU_SYSCONFIG_IDLE_MODE_WRITE32 (MMU_BASE_EASIL1 + 17) 24 + #define EASIL1_MMUMMU_SYSCONFIG_AUTO_IDLE_WRITE32 (MMU_BASE_EASIL1 + 39) 25 + #define EASIL1_MMUMMU_IRQSTATUS_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 51) 26 + #define EASIL1_MMUMMU_IRQENABLE_READ_REGISTER32 (MMU_BASE_EASIL1 + 102) 27 + #define EASIL1_MMUMMU_IRQENABLE_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 103) 28 + #define EASIL1_MMUMMU_WALKING_STTWL_RUNNING_READ32 (MMU_BASE_EASIL1 + 156) 29 + #define EASIL1_MMUMMU_CNTLTWL_ENABLE_READ32 (MMU_BASE_EASIL1 + 174) 30 + #define EASIL1_MMUMMU_CNTLTWL_ENABLE_WRITE32 (MMU_BASE_EASIL1 + 180) 31 + #define EASIL1_MMUMMU_CNTLMMU_ENABLE_WRITE32 (MMU_BASE_EASIL1 + 190) 32 + #define EASIL1_MMUMMU_FAULT_AD_READ_REGISTER32 (MMU_BASE_EASIL1 + 194) 33 + #define EASIL1_MMUMMU_TTB_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 198) 34 + #define EASIL1_MMUMMU_LOCK_READ_REGISTER32 (MMU_BASE_EASIL1 + 203) 35 + #define EASIL1_MMUMMU_LOCK_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 204) 36 + #define EASIL1_MMUMMU_LOCK_BASE_VALUE_READ32 (MMU_BASE_EASIL1 + 205) 37 + #define EASIL1_MMUMMU_LOCK_CURRENT_VICTIM_READ32 (MMU_BASE_EASIL1 + 209) 38 + #define EASIL1_MMUMMU_LOCK_CURRENT_VICTIM_WRITE32 (MMU_BASE_EASIL1 + 211) 39 + #define EASIL1_MMUMMU_LOCK_CURRENT_VICTIM_SET32 (MMU_BASE_EASIL1 + 212) 40 + #define EASIL1_MMUMMU_LD_TLB_READ_REGISTER32 (MMU_BASE_EASIL1 + 213) 41 + #define EASIL1_MMUMMU_LD_TLB_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 214) 42 + #define EASIL1_MMUMMU_CAM_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 226) 43 + #define EASIL1_MMUMMU_RAM_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 268) 44 + #define EASIL1_MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32 (MMU_BASE_EASIL1 + 322) 45 + 46 + /* Register offset address definitions */ 47 + #define MMU_MMU_SYSCONFIG_OFFSET 0x10 48 + #define MMU_MMU_IRQSTATUS_OFFSET 0x18 49 + #define MMU_MMU_IRQENABLE_OFFSET 0x1c 50 + #define MMU_MMU_WALKING_ST_OFFSET 0x40 51 + #define MMU_MMU_CNTL_OFFSET 0x44 52 + #define MMU_MMU_FAULT_AD_OFFSET 0x48 53 + #define MMU_MMU_TTB_OFFSET 0x4c 54 + #define MMU_MMU_LOCK_OFFSET 0x50 55 + #define MMU_MMU_LD_TLB_OFFSET 0x54 56 + #define MMU_MMU_CAM_OFFSET 0x58 57 + #define MMU_MMU_RAM_OFFSET 0x5c 58 + #define MMU_MMU_GFLUSH_OFFSET 0x60 59 + #define MMU_MMU_FLUSH_ENTRY_OFFSET 0x64 60 + /* Bitfield mask and offset declarations */ 61 + #define MMU_MMU_SYSCONFIG_IDLE_MODE_MASK 0x18 62 + #define MMU_MMU_SYSCONFIG_IDLE_MODE_OFFSET 3 63 + #define MMU_MMU_SYSCONFIG_AUTO_IDLE_MASK 0x1 64 + #define MMU_MMU_SYSCONFIG_AUTO_IDLE_OFFSET 0 65 + #define MMU_MMU_WALKING_ST_TWL_RUNNING_MASK 0x1 66 + #define MMU_MMU_WALKING_ST_TWL_RUNNING_OFFSET 0 67 + #define MMU_MMU_CNTL_TWL_ENABLE_MASK 0x4 68 + #define MMU_MMU_CNTL_TWL_ENABLE_OFFSET 2 69 + #define MMU_MMU_CNTL_MMU_ENABLE_MASK 0x2 70 + #define MMU_MMU_CNTL_MMU_ENABLE_OFFSET 1 71 + #define MMU_MMU_LOCK_BASE_VALUE_MASK 0xfc00 72 + #define MMU_MMU_LOCK_BASE_VALUE_OFFSET 10 73 + #define MMU_MMU_LOCK_CURRENT_VICTIM_MASK 0x3f0 74 + #define MMU_MMU_LOCK_CURRENT_VICTIM_OFFSET 4 75 + 76 + #endif /* _MMU_ACC_INT_H */
+225
drivers/staging/tidspbridge/hw/MMURegAcM.h
··· 1 + /* 2 + * MMURegAcM.h 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * Copyright (C) 2007 Texas Instruments, Inc. 7 + * 8 + * This package is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 13 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 14 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 15 + */ 16 + 17 + #ifndef _MMU_REG_ACM_H 18 + #define _MMU_REG_ACM_H 19 + 20 + #include <linux/io.h> 21 + #include <EasiGlobal.h> 22 + 23 + #include "MMUAccInt.h" 24 + 25 + #if defined(USE_LEVEL_1_MACROS) 26 + 27 + #define MMUMMU_SYSCONFIG_READ_REGISTER32(base_address)\ 28 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_SYSCONFIG_READ_REGISTER32),\ 29 + __raw_readl((base_address)+MMU_MMU_SYSCONFIG_OFFSET)) 30 + 31 + #define MMUMMU_SYSCONFIG_IDLE_MODE_WRITE32(base_address, value)\ 32 + {\ 33 + const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\ 34 + register u32 data = __raw_readl((base_address)+offset);\ 35 + register u32 new_value = (value);\ 36 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_SYSCONFIG_IDLE_MODE_WRITE32);\ 37 + data &= ~(MMU_MMU_SYSCONFIG_IDLE_MODE_MASK);\ 38 + new_value <<= MMU_MMU_SYSCONFIG_IDLE_MODE_OFFSET;\ 39 + new_value &= MMU_MMU_SYSCONFIG_IDLE_MODE_MASK;\ 40 + new_value |= data;\ 41 + __raw_writel(new_value, base_address+offset);\ 42 + } 43 + 44 + #define MMUMMU_SYSCONFIG_AUTO_IDLE_WRITE32(base_address, value)\ 45 + {\ 46 + const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\ 47 + register u32 data = __raw_readl((base_address)+offset);\ 48 + register u32 new_value = (value);\ 49 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_SYSCONFIG_AUTO_IDLE_WRITE32);\ 50 + data &= ~(MMU_MMU_SYSCONFIG_AUTO_IDLE_MASK);\ 51 + new_value <<= MMU_MMU_SYSCONFIG_AUTO_IDLE_OFFSET;\ 52 + new_value &= MMU_MMU_SYSCONFIG_AUTO_IDLE_MASK;\ 53 + new_value |= data;\ 54 + __raw_writel(new_value, base_address+offset);\ 55 + } 56 + 57 + #define MMUMMU_IRQSTATUS_READ_REGISTER32(base_address)\ 58 + (_DEBUG_LEVEL1_EASI(easil1_mmummu_irqstatus_read_register32),\ 59 + __raw_readl((base_address)+MMU_MMU_IRQSTATUS_OFFSET)) 60 + 61 + #define MMUMMU_IRQSTATUS_WRITE_REGISTER32(base_address, value)\ 62 + {\ 63 + const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\ 64 + register u32 new_value = (value);\ 65 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_IRQSTATUS_WRITE_REGISTER32);\ 66 + __raw_writel(new_value, (base_address)+offset);\ 67 + } 68 + 69 + #define MMUMMU_IRQENABLE_READ_REGISTER32(base_address)\ 70 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_IRQENABLE_READ_REGISTER32),\ 71 + __raw_readl((base_address)+MMU_MMU_IRQENABLE_OFFSET)) 72 + 73 + #define MMUMMU_IRQENABLE_WRITE_REGISTER32(base_address, value)\ 74 + {\ 75 + const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\ 76 + register u32 new_value = (value);\ 77 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_IRQENABLE_WRITE_REGISTER32);\ 78 + __raw_writel(new_value, (base_address)+offset);\ 79 + } 80 + 81 + #define MMUMMU_WALKING_STTWL_RUNNING_READ32(base_address)\ 82 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_WALKING_STTWL_RUNNING_READ32),\ 83 + (((__raw_readl(((base_address)+(MMU_MMU_WALKING_ST_OFFSET))))\ 84 + & MMU_MMU_WALKING_ST_TWL_RUNNING_MASK) >>\ 85 + MMU_MMU_WALKING_ST_TWL_RUNNING_OFFSET)) 86 + 87 + #define MMUMMU_CNTLTWL_ENABLE_READ32(base_address)\ 88 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_CNTLTWL_ENABLE_READ32),\ 89 + (((__raw_readl(((base_address)+(MMU_MMU_CNTL_OFFSET)))) &\ 90 + MMU_MMU_CNTL_TWL_ENABLE_MASK) >>\ 91 + MMU_MMU_CNTL_TWL_ENABLE_OFFSET)) 92 + 93 + #define MMUMMU_CNTLTWL_ENABLE_WRITE32(base_address, value)\ 94 + {\ 95 + const u32 offset = MMU_MMU_CNTL_OFFSET;\ 96 + register u32 data = __raw_readl((base_address)+offset);\ 97 + register u32 new_value = (value);\ 98 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_CNTLTWL_ENABLE_WRITE32);\ 99 + data &= ~(MMU_MMU_CNTL_TWL_ENABLE_MASK);\ 100 + new_value <<= MMU_MMU_CNTL_TWL_ENABLE_OFFSET;\ 101 + new_value &= MMU_MMU_CNTL_TWL_ENABLE_MASK;\ 102 + new_value |= data;\ 103 + __raw_writel(new_value, base_address+offset);\ 104 + } 105 + 106 + #define MMUMMU_CNTLMMU_ENABLE_WRITE32(base_address, value)\ 107 + {\ 108 + const u32 offset = MMU_MMU_CNTL_OFFSET;\ 109 + register u32 data = __raw_readl((base_address)+offset);\ 110 + register u32 new_value = (value);\ 111 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_CNTLMMU_ENABLE_WRITE32);\ 112 + data &= ~(MMU_MMU_CNTL_MMU_ENABLE_MASK);\ 113 + new_value <<= MMU_MMU_CNTL_MMU_ENABLE_OFFSET;\ 114 + new_value &= MMU_MMU_CNTL_MMU_ENABLE_MASK;\ 115 + new_value |= data;\ 116 + __raw_writel(new_value, base_address+offset);\ 117 + } 118 + 119 + #define MMUMMU_FAULT_AD_READ_REGISTER32(base_address)\ 120 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_FAULT_AD_READ_REGISTER32),\ 121 + __raw_readl((base_address)+MMU_MMU_FAULT_AD_OFFSET)) 122 + 123 + #define MMUMMU_TTB_WRITE_REGISTER32(base_address, value)\ 124 + {\ 125 + const u32 offset = MMU_MMU_TTB_OFFSET;\ 126 + register u32 new_value = (value);\ 127 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_TTB_WRITE_REGISTER32);\ 128 + __raw_writel(new_value, (base_address)+offset);\ 129 + } 130 + 131 + #define MMUMMU_LOCK_READ_REGISTER32(base_address)\ 132 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LOCK_READ_REGISTER32),\ 133 + __raw_readl((base_address)+MMU_MMU_LOCK_OFFSET)) 134 + 135 + #define MMUMMU_LOCK_WRITE_REGISTER32(base_address, value)\ 136 + {\ 137 + const u32 offset = MMU_MMU_LOCK_OFFSET;\ 138 + register u32 new_value = (value);\ 139 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LOCK_WRITE_REGISTER32);\ 140 + __raw_writel(new_value, (base_address)+offset);\ 141 + } 142 + 143 + #define MMUMMU_LOCK_BASE_VALUE_READ32(base_address)\ 144 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LOCK_BASE_VALUE_READ32),\ 145 + (((__raw_readl(((base_address)+(MMU_MMU_LOCK_OFFSET)))) &\ 146 + MMU_MMU_LOCK_BASE_VALUE_MASK) >>\ 147 + MMU_MMU_LOCK_BASE_VALUE_OFFSET)) 148 + 149 + #define MMUMMU_LOCK_BASE_VALUE_WRITE32(base_address, value)\ 150 + {\ 151 + const u32 offset = MMU_MMU_LOCK_OFFSET;\ 152 + register u32 data = __raw_readl((base_address)+offset);\ 153 + register u32 new_value = (value);\ 154 + _DEBUG_LEVEL1_EASI(easil1_mmummu_lock_base_value_write32);\ 155 + data &= ~(MMU_MMU_LOCK_BASE_VALUE_MASK);\ 156 + new_value <<= MMU_MMU_LOCK_BASE_VALUE_OFFSET;\ 157 + new_value &= MMU_MMU_LOCK_BASE_VALUE_MASK;\ 158 + new_value |= data;\ 159 + __raw_writel(new_value, base_address+offset);\ 160 + } 161 + 162 + #define MMUMMU_LOCK_CURRENT_VICTIM_READ32(base_address)\ 163 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LOCK_CURRENT_VICTIM_READ32),\ 164 + (((__raw_readl(((base_address)+(MMU_MMU_LOCK_OFFSET)))) &\ 165 + MMU_MMU_LOCK_CURRENT_VICTIM_MASK) >>\ 166 + MMU_MMU_LOCK_CURRENT_VICTIM_OFFSET)) 167 + 168 + #define MMUMMU_LOCK_CURRENT_VICTIM_WRITE32(base_address, value)\ 169 + {\ 170 + const u32 offset = MMU_MMU_LOCK_OFFSET;\ 171 + register u32 data = __raw_readl((base_address)+offset);\ 172 + register u32 new_value = (value);\ 173 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LOCK_CURRENT_VICTIM_WRITE32);\ 174 + data &= ~(MMU_MMU_LOCK_CURRENT_VICTIM_MASK);\ 175 + new_value <<= MMU_MMU_LOCK_CURRENT_VICTIM_OFFSET;\ 176 + new_value &= MMU_MMU_LOCK_CURRENT_VICTIM_MASK;\ 177 + new_value |= data;\ 178 + __raw_writel(new_value, base_address+offset);\ 179 + } 180 + 181 + #define MMUMMU_LOCK_CURRENT_VICTIM_SET32(var, value)\ 182 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LOCK_CURRENT_VICTIM_SET32),\ 183 + (((var) & ~(MMU_MMU_LOCK_CURRENT_VICTIM_MASK)) |\ 184 + (((value) << MMU_MMU_LOCK_CURRENT_VICTIM_OFFSET) &\ 185 + MMU_MMU_LOCK_CURRENT_VICTIM_MASK))) 186 + 187 + #define MMUMMU_LD_TLB_READ_REGISTER32(base_address)\ 188 + (_DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LD_TLB_READ_REGISTER32),\ 189 + __raw_readl((base_address)+MMU_MMU_LD_TLB_OFFSET)) 190 + 191 + #define MMUMMU_LD_TLB_WRITE_REGISTER32(base_address, value)\ 192 + {\ 193 + const u32 offset = MMU_MMU_LD_TLB_OFFSET;\ 194 + register u32 new_value = (value);\ 195 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_LD_TLB_WRITE_REGISTER32);\ 196 + __raw_writel(new_value, (base_address)+offset);\ 197 + } 198 + 199 + #define MMUMMU_CAM_WRITE_REGISTER32(base_address, value)\ 200 + {\ 201 + const u32 offset = MMU_MMU_CAM_OFFSET;\ 202 + register u32 new_value = (value);\ 203 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_CAM_WRITE_REGISTER32);\ 204 + __raw_writel(new_value, (base_address)+offset);\ 205 + } 206 + 207 + #define MMUMMU_RAM_WRITE_REGISTER32(base_address, value)\ 208 + {\ 209 + const u32 offset = MMU_MMU_RAM_OFFSET;\ 210 + register u32 new_value = (value);\ 211 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_RAM_WRITE_REGISTER32);\ 212 + __raw_writel(new_value, (base_address)+offset);\ 213 + } 214 + 215 + #define MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, value)\ 216 + {\ 217 + const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\ 218 + register u32 new_value = (value);\ 219 + _DEBUG_LEVEL1_EASI(EASIL1_MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32);\ 220 + __raw_writel(new_value, (base_address)+offset);\ 221 + } 222 + 223 + #endif /* USE_LEVEL_1_MACROS */ 224 + 225 + #endif /* _MMU_REG_ACM_H */
+58
drivers/staging/tidspbridge/hw/hw_defs.h
··· 1 + /* 2 + * hw_defs.h 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * Global HW definitions 7 + * 8 + * Copyright (C) 2007 Texas Instruments, Inc. 9 + * 10 + * This package is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 + */ 18 + 19 + #ifndef _HW_DEFS_H 20 + #define _HW_DEFS_H 21 + 22 + /* Page size */ 23 + #define HW_PAGE_SIZE4KB 0x1000 24 + #define HW_PAGE_SIZE64KB 0x10000 25 + #define HW_PAGE_SIZE1MB 0x100000 26 + #define HW_PAGE_SIZE16MB 0x1000000 27 + 28 + /* hw_status: return type for HW API */ 29 + typedef long hw_status; 30 + 31 + /* Macro used to set and clear any bit */ 32 + #define HW_CLEAR 0 33 + #define HW_SET 1 34 + 35 + /* hw_endianism_t: Enumerated Type used to specify the endianism 36 + * Do NOT change these values. They are used as bit fields. */ 37 + enum hw_endianism_t { 38 + HW_LITTLE_ENDIAN, 39 + HW_BIG_ENDIAN 40 + }; 41 + 42 + /* hw_element_size_t: Enumerated Type used to specify the element size 43 + * Do NOT change these values. They are used as bit fields. */ 44 + enum hw_element_size_t { 45 + HW_ELEM_SIZE8BIT, 46 + HW_ELEM_SIZE16BIT, 47 + HW_ELEM_SIZE32BIT, 48 + HW_ELEM_SIZE64BIT 49 + }; 50 + 51 + /* hw_idle_mode_t: Enumerated Type used to specify Idle modes */ 52 + enum hw_idle_mode_t { 53 + HW_FORCE_IDLE, 54 + HW_NO_IDLE, 55 + HW_SMART_IDLE 56 + }; 57 + 58 + #endif /* _HW_DEFS_H */
+562
drivers/staging/tidspbridge/hw/hw_mmu.c
··· 1 + /* 2 + * hw_mmu.c 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * API definitions to setup MMU TLB and PTE 7 + * 8 + * Copyright (C) 2007 Texas Instruments, Inc. 9 + * 10 + * This package is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 + */ 18 + 19 + #include <linux/io.h> 20 + #include "MMURegAcM.h" 21 + #include <hw_defs.h> 22 + #include <hw_mmu.h> 23 + #include <linux/types.h> 24 + #include <linux/err.h> 25 + 26 + #define MMU_BASE_VAL_MASK 0xFC00 27 + #define MMU_PAGE_MAX 3 28 + #define MMU_ELEMENTSIZE_MAX 3 29 + #define MMU_ADDR_MASK 0xFFFFF000 30 + #define MMU_TTB_MASK 0xFFFFC000 31 + #define MMU_SECTION_ADDR_MASK 0xFFF00000 32 + #define MMU_SSECTION_ADDR_MASK 0xFF000000 33 + #define MMU_PAGE_TABLE_MASK 0xFFFFFC00 34 + #define MMU_LARGE_PAGE_MASK 0xFFFF0000 35 + #define MMU_SMALL_PAGE_MASK 0xFFFFF000 36 + 37 + #define MMU_LOAD_TLB 0x00000001 38 + #define MMU_GFLUSH 0x60 39 + 40 + /* 41 + * hw_mmu_page_size_t: Enumerated Type used to specify the MMU Page Size(SLSS) 42 + */ 43 + enum hw_mmu_page_size_t { 44 + HW_MMU_SECTION, 45 + HW_MMU_LARGE_PAGE, 46 + HW_MMU_SMALL_PAGE, 47 + HW_MMU_SUPERSECTION 48 + }; 49 + 50 + /* 51 + * FUNCTION : mmu_flush_entry 52 + * 53 + * INPUTS: 54 + * 55 + * Identifier : base_address 56 + * Type : const u32 57 + * Description : Base Address of instance of MMU module 58 + * 59 + * RETURNS: 60 + * 61 + * Type : hw_status 62 + * Description : 0 -- No errors occured 63 + * RET_BAD_NULL_PARAM -- A Pointer 64 + * Paramater was set to NULL 65 + * 66 + * PURPOSE: : Flush the TLB entry pointed by the 67 + * lock counter register 68 + * even if this entry is set protected 69 + * 70 + * METHOD: : Check the Input parameter and Flush a 71 + * single entry in the TLB. 72 + */ 73 + static hw_status mmu_flush_entry(const void __iomem *base_address); 74 + 75 + /* 76 + * FUNCTION : mmu_set_cam_entry 77 + * 78 + * INPUTS: 79 + * 80 + * Identifier : base_address 81 + * TypE : const u32 82 + * Description : Base Address of instance of MMU module 83 + * 84 + * Identifier : page_sz 85 + * TypE : const u32 86 + * Description : It indicates the page size 87 + * 88 + * Identifier : preserved_bit 89 + * Type : const u32 90 + * Description : It indicates the TLB entry is preserved entry 91 + * or not 92 + * 93 + * Identifier : valid_bit 94 + * Type : const u32 95 + * Description : It indicates the TLB entry is valid entry or not 96 + * 97 + * 98 + * Identifier : virtual_addr_tag 99 + * Type : const u32 100 + * Description : virtual Address 101 + * 102 + * RETURNS: 103 + * 104 + * Type : hw_status 105 + * Description : 0 -- No errors occured 106 + * RET_BAD_NULL_PARAM -- A Pointer Paramater 107 + * was set to NULL 108 + * RET_PARAM_OUT_OF_RANGE -- Input Parameter out 109 + * of Range 110 + * 111 + * PURPOSE: : Set MMU_CAM reg 112 + * 113 + * METHOD: : Check the Input parameters and set the CAM entry. 114 + */ 115 + static hw_status mmu_set_cam_entry(const void __iomem *base_address, 116 + const u32 page_sz, 117 + const u32 preserved_bit, 118 + const u32 valid_bit, 119 + const u32 virtual_addr_tag); 120 + 121 + /* 122 + * FUNCTION : mmu_set_ram_entry 123 + * 124 + * INPUTS: 125 + * 126 + * Identifier : base_address 127 + * Type : const u32 128 + * Description : Base Address of instance of MMU module 129 + * 130 + * Identifier : physical_addr 131 + * Type : const u32 132 + * Description : Physical Address to which the corresponding 133 + * virtual Address shouldpoint 134 + * 135 + * Identifier : endianism 136 + * Type : hw_endianism_t 137 + * Description : endianism for the given page 138 + * 139 + * Identifier : element_size 140 + * Type : hw_element_size_t 141 + * Description : The element size ( 8,16, 32 or 64 bit) 142 + * 143 + * Identifier : mixed_size 144 + * Type : hw_mmu_mixed_size_t 145 + * Description : Element Size to follow CPU or TLB 146 + * 147 + * RETURNS: 148 + * 149 + * Type : hw_status 150 + * Description : 0 -- No errors occured 151 + * RET_BAD_NULL_PARAM -- A Pointer Paramater 152 + * was set to NULL 153 + * RET_PARAM_OUT_OF_RANGE -- Input Parameter 154 + * out of Range 155 + * 156 + * PURPOSE: : Set MMU_CAM reg 157 + * 158 + * METHOD: : Check the Input parameters and set the RAM entry. 159 + */ 160 + static hw_status mmu_set_ram_entry(const void __iomem *base_address, 161 + const u32 physical_addr, 162 + enum hw_endianism_t endianism, 163 + enum hw_element_size_t element_size, 164 + enum hw_mmu_mixed_size_t mixed_size); 165 + 166 + /* HW FUNCTIONS */ 167 + 168 + hw_status hw_mmu_enable(const void __iomem *base_address) 169 + { 170 + hw_status status = 0; 171 + 172 + MMUMMU_CNTLMMU_ENABLE_WRITE32(base_address, HW_SET); 173 + 174 + return status; 175 + } 176 + 177 + hw_status hw_mmu_disable(const void __iomem *base_address) 178 + { 179 + hw_status status = 0; 180 + 181 + MMUMMU_CNTLMMU_ENABLE_WRITE32(base_address, HW_CLEAR); 182 + 183 + return status; 184 + } 185 + 186 + hw_status hw_mmu_num_locked_set(const void __iomem *base_address, 187 + u32 num_locked_entries) 188 + { 189 + hw_status status = 0; 190 + 191 + MMUMMU_LOCK_BASE_VALUE_WRITE32(base_address, num_locked_entries); 192 + 193 + return status; 194 + } 195 + 196 + hw_status hw_mmu_victim_num_set(const void __iomem *base_address, 197 + u32 victim_entry_num) 198 + { 199 + hw_status status = 0; 200 + 201 + MMUMMU_LOCK_CURRENT_VICTIM_WRITE32(base_address, victim_entry_num); 202 + 203 + return status; 204 + } 205 + 206 + hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask) 207 + { 208 + hw_status status = 0; 209 + 210 + MMUMMU_IRQSTATUS_WRITE_REGISTER32(base_address, irq_mask); 211 + 212 + return status; 213 + } 214 + 215 + hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask) 216 + { 217 + hw_status status = 0; 218 + u32 irq_reg; 219 + 220 + irq_reg = MMUMMU_IRQENABLE_READ_REGISTER32(base_address); 221 + 222 + MMUMMU_IRQENABLE_WRITE_REGISTER32(base_address, irq_reg & ~irq_mask); 223 + 224 + return status; 225 + } 226 + 227 + hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask) 228 + { 229 + hw_status status = 0; 230 + u32 irq_reg; 231 + 232 + irq_reg = MMUMMU_IRQENABLE_READ_REGISTER32(base_address); 233 + 234 + MMUMMU_IRQENABLE_WRITE_REGISTER32(base_address, irq_reg | irq_mask); 235 + 236 + return status; 237 + } 238 + 239 + hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask) 240 + { 241 + hw_status status = 0; 242 + 243 + *irq_mask = MMUMMU_IRQSTATUS_READ_REGISTER32(base_address); 244 + 245 + return status; 246 + } 247 + 248 + hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr) 249 + { 250 + hw_status status = 0; 251 + 252 + /* read values from register */ 253 + *addr = MMUMMU_FAULT_AD_READ_REGISTER32(base_address); 254 + 255 + return status; 256 + } 257 + 258 + hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr) 259 + { 260 + hw_status status = 0; 261 + u32 load_ttb; 262 + 263 + load_ttb = ttb_phys_addr & ~0x7FUL; 264 + /* write values to register */ 265 + MMUMMU_TTB_WRITE_REGISTER32(base_address, load_ttb); 266 + 267 + return status; 268 + } 269 + 270 + hw_status hw_mmu_twl_enable(const void __iomem *base_address) 271 + { 272 + hw_status status = 0; 273 + 274 + MMUMMU_CNTLTWL_ENABLE_WRITE32(base_address, HW_SET); 275 + 276 + return status; 277 + } 278 + 279 + hw_status hw_mmu_twl_disable(const void __iomem *base_address) 280 + { 281 + hw_status status = 0; 282 + 283 + MMUMMU_CNTLTWL_ENABLE_WRITE32(base_address, HW_CLEAR); 284 + 285 + return status; 286 + } 287 + 288 + hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr, 289 + u32 page_sz) 290 + { 291 + hw_status status = 0; 292 + u32 virtual_addr_tag; 293 + enum hw_mmu_page_size_t pg_size_bits; 294 + 295 + switch (page_sz) { 296 + case HW_PAGE_SIZE4KB: 297 + pg_size_bits = HW_MMU_SMALL_PAGE; 298 + break; 299 + 300 + case HW_PAGE_SIZE64KB: 301 + pg_size_bits = HW_MMU_LARGE_PAGE; 302 + break; 303 + 304 + case HW_PAGE_SIZE1MB: 305 + pg_size_bits = HW_MMU_SECTION; 306 + break; 307 + 308 + case HW_PAGE_SIZE16MB: 309 + pg_size_bits = HW_MMU_SUPERSECTION; 310 + break; 311 + 312 + default: 313 + return -EINVAL; 314 + } 315 + 316 + /* Generate the 20-bit tag from virtual address */ 317 + virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12); 318 + 319 + mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag); 320 + 321 + mmu_flush_entry(base_address); 322 + 323 + return status; 324 + } 325 + 326 + hw_status hw_mmu_tlb_add(const void __iomem *base_address, 327 + u32 physical_addr, 328 + u32 virtual_addr, 329 + u32 page_sz, 330 + u32 entry_num, 331 + struct hw_mmu_map_attrs_t *map_attrs, 332 + s8 preserved_bit, s8 valid_bit) 333 + { 334 + hw_status status = 0; 335 + u32 lock_reg; 336 + u32 virtual_addr_tag; 337 + enum hw_mmu_page_size_t mmu_pg_size; 338 + 339 + /*Check the input Parameters */ 340 + switch (page_sz) { 341 + case HW_PAGE_SIZE4KB: 342 + mmu_pg_size = HW_MMU_SMALL_PAGE; 343 + break; 344 + 345 + case HW_PAGE_SIZE64KB: 346 + mmu_pg_size = HW_MMU_LARGE_PAGE; 347 + break; 348 + 349 + case HW_PAGE_SIZE1MB: 350 + mmu_pg_size = HW_MMU_SECTION; 351 + break; 352 + 353 + case HW_PAGE_SIZE16MB: 354 + mmu_pg_size = HW_MMU_SUPERSECTION; 355 + break; 356 + 357 + default: 358 + return -EINVAL; 359 + } 360 + 361 + lock_reg = MMUMMU_LOCK_READ_REGISTER32(base_address); 362 + 363 + /* Generate the 20-bit tag from virtual address */ 364 + virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12); 365 + 366 + /* Write the fields in the CAM Entry Register */ 367 + mmu_set_cam_entry(base_address, mmu_pg_size, preserved_bit, valid_bit, 368 + virtual_addr_tag); 369 + 370 + /* Write the different fields of the RAM Entry Register */ 371 + /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit) */ 372 + mmu_set_ram_entry(base_address, physical_addr, map_attrs->endianism, 373 + map_attrs->element_size, map_attrs->mixed_size); 374 + 375 + /* Update the MMU Lock Register */ 376 + /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1) */ 377 + MMUMMU_LOCK_CURRENT_VICTIM_WRITE32(base_address, entry_num); 378 + 379 + /* Enable loading of an entry in TLB by writing 1 380 + into LD_TLB_REG register */ 381 + MMUMMU_LD_TLB_WRITE_REGISTER32(base_address, MMU_LOAD_TLB); 382 + 383 + MMUMMU_LOCK_WRITE_REGISTER32(base_address, lock_reg); 384 + 385 + return status; 386 + } 387 + 388 + hw_status hw_mmu_pte_set(const u32 pg_tbl_va, 389 + u32 physical_addr, 390 + u32 virtual_addr, 391 + u32 page_sz, struct hw_mmu_map_attrs_t *map_attrs) 392 + { 393 + hw_status status = 0; 394 + u32 pte_addr, pte_val; 395 + s32 num_entries = 1; 396 + 397 + switch (page_sz) { 398 + case HW_PAGE_SIZE4KB: 399 + pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va, 400 + virtual_addr & 401 + MMU_SMALL_PAGE_MASK); 402 + pte_val = 403 + ((physical_addr & MMU_SMALL_PAGE_MASK) | 404 + (map_attrs->endianism << 9) | (map_attrs-> 405 + element_size << 4) | 406 + (map_attrs->mixed_size << 11) | 2); 407 + break; 408 + 409 + case HW_PAGE_SIZE64KB: 410 + num_entries = 16; 411 + pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va, 412 + virtual_addr & 413 + MMU_LARGE_PAGE_MASK); 414 + pte_val = 415 + ((physical_addr & MMU_LARGE_PAGE_MASK) | 416 + (map_attrs->endianism << 9) | (map_attrs-> 417 + element_size << 4) | 418 + (map_attrs->mixed_size << 11) | 1); 419 + break; 420 + 421 + case HW_PAGE_SIZE1MB: 422 + pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, 423 + virtual_addr & 424 + MMU_SECTION_ADDR_MASK); 425 + pte_val = 426 + ((((physical_addr & MMU_SECTION_ADDR_MASK) | 427 + (map_attrs->endianism << 15) | (map_attrs-> 428 + element_size << 10) | 429 + (map_attrs->mixed_size << 17)) & ~0x40000) | 0x2); 430 + break; 431 + 432 + case HW_PAGE_SIZE16MB: 433 + num_entries = 16; 434 + pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, 435 + virtual_addr & 436 + MMU_SSECTION_ADDR_MASK); 437 + pte_val = 438 + (((physical_addr & MMU_SSECTION_ADDR_MASK) | 439 + (map_attrs->endianism << 15) | (map_attrs-> 440 + element_size << 10) | 441 + (map_attrs->mixed_size << 17) 442 + ) | 0x40000 | 0x2); 443 + break; 444 + 445 + case HW_MMU_COARSE_PAGE_SIZE: 446 + pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, 447 + virtual_addr & 448 + MMU_SECTION_ADDR_MASK); 449 + pte_val = (physical_addr & MMU_PAGE_TABLE_MASK) | 1; 450 + break; 451 + 452 + default: 453 + return -EINVAL; 454 + } 455 + 456 + while (--num_entries >= 0) 457 + ((u32 *) pte_addr)[num_entries] = pte_val; 458 + 459 + return status; 460 + } 461 + 462 + hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size) 463 + { 464 + hw_status status = 0; 465 + u32 pte_addr; 466 + s32 num_entries = 1; 467 + 468 + switch (page_size) { 469 + case HW_PAGE_SIZE4KB: 470 + pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va, 471 + virtual_addr & 472 + MMU_SMALL_PAGE_MASK); 473 + break; 474 + 475 + case HW_PAGE_SIZE64KB: 476 + num_entries = 16; 477 + pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va, 478 + virtual_addr & 479 + MMU_LARGE_PAGE_MASK); 480 + break; 481 + 482 + case HW_PAGE_SIZE1MB: 483 + case HW_MMU_COARSE_PAGE_SIZE: 484 + pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, 485 + virtual_addr & 486 + MMU_SECTION_ADDR_MASK); 487 + break; 488 + 489 + case HW_PAGE_SIZE16MB: 490 + num_entries = 16; 491 + pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va, 492 + virtual_addr & 493 + MMU_SSECTION_ADDR_MASK); 494 + break; 495 + 496 + default: 497 + return -EINVAL; 498 + } 499 + 500 + while (--num_entries >= 0) 501 + ((u32 *) pte_addr)[num_entries] = 0; 502 + 503 + return status; 504 + } 505 + 506 + /* mmu_flush_entry */ 507 + static hw_status mmu_flush_entry(const void __iomem *base_address) 508 + { 509 + hw_status status = 0; 510 + u32 flush_entry_data = 0x1; 511 + 512 + /* write values to register */ 513 + MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data); 514 + 515 + return status; 516 + } 517 + 518 + /* mmu_set_cam_entry */ 519 + static hw_status mmu_set_cam_entry(const void __iomem *base_address, 520 + const u32 page_sz, 521 + const u32 preserved_bit, 522 + const u32 valid_bit, 523 + const u32 virtual_addr_tag) 524 + { 525 + hw_status status = 0; 526 + u32 mmu_cam_reg; 527 + 528 + mmu_cam_reg = (virtual_addr_tag << 12); 529 + mmu_cam_reg = (mmu_cam_reg) | (page_sz) | (valid_bit << 2) | 530 + (preserved_bit << 3); 531 + 532 + /* write values to register */ 533 + MMUMMU_CAM_WRITE_REGISTER32(base_address, mmu_cam_reg); 534 + 535 + return status; 536 + } 537 + 538 + /* mmu_set_ram_entry */ 539 + static hw_status mmu_set_ram_entry(const void __iomem *base_address, 540 + const u32 physical_addr, 541 + enum hw_endianism_t endianism, 542 + enum hw_element_size_t element_size, 543 + enum hw_mmu_mixed_size_t mixed_size) 544 + { 545 + hw_status status = 0; 546 + u32 mmu_ram_reg; 547 + 548 + mmu_ram_reg = (physical_addr & MMU_ADDR_MASK); 549 + mmu_ram_reg = (mmu_ram_reg) | ((endianism << 9) | (element_size << 7) | 550 + (mixed_size << 6)); 551 + 552 + /* write values to register */ 553 + MMUMMU_RAM_WRITE_REGISTER32(base_address, mmu_ram_reg); 554 + 555 + return status; 556 + 557 + } 558 + 559 + void hw_mmu_tlb_flush_all(const void __iomem *base) 560 + { 561 + __raw_writeb(1, base + MMU_GFLUSH); 562 + }
+163
drivers/staging/tidspbridge/hw/hw_mmu.h
··· 1 + /* 2 + * hw_mmu.h 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * MMU types and API declarations 7 + * 8 + * Copyright (C) 2007 Texas Instruments, Inc. 9 + * 10 + * This package is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 + */ 18 + 19 + #ifndef _HW_MMU_H 20 + #define _HW_MMU_H 21 + 22 + #include <linux/types.h> 23 + 24 + /* Bitmasks for interrupt sources */ 25 + #define HW_MMU_TRANSLATION_FAULT 0x2 26 + #define HW_MMU_ALL_INTERRUPTS 0x1F 27 + 28 + #define HW_MMU_COARSE_PAGE_SIZE 0x400 29 + 30 + /* hw_mmu_mixed_size_t: Enumerated Type used to specify whether to follow 31 + CPU/TLB Element size */ 32 + enum hw_mmu_mixed_size_t { 33 + HW_MMU_TLBES, 34 + HW_MMU_CPUES 35 + }; 36 + 37 + /* hw_mmu_map_attrs_t: Struct containing MMU mapping attributes */ 38 + struct hw_mmu_map_attrs_t { 39 + enum hw_endianism_t endianism; 40 + enum hw_element_size_t element_size; 41 + enum hw_mmu_mixed_size_t mixed_size; 42 + bool donotlockmpupage; 43 + }; 44 + 45 + extern hw_status hw_mmu_enable(const void __iomem *base_address); 46 + 47 + extern hw_status hw_mmu_disable(const void __iomem *base_address); 48 + 49 + extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address, 50 + u32 num_locked_entries); 51 + 52 + extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address, 53 + u32 victim_entry_num); 54 + 55 + /* For MMU faults */ 56 + extern hw_status hw_mmu_event_ack(const void __iomem *base_address, 57 + u32 irq_mask); 58 + 59 + extern hw_status hw_mmu_event_disable(const void __iomem *base_address, 60 + u32 irq_mask); 61 + 62 + extern hw_status hw_mmu_event_enable(const void __iomem *base_address, 63 + u32 irq_mask); 64 + 65 + extern hw_status hw_mmu_event_status(const void __iomem *base_address, 66 + u32 *irq_mask); 67 + 68 + extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, 69 + u32 *addr); 70 + 71 + /* Set the TT base address */ 72 + extern hw_status hw_mmu_ttb_set(const void __iomem *base_address, 73 + u32 ttb_phys_addr); 74 + 75 + extern hw_status hw_mmu_twl_enable(const void __iomem *base_address); 76 + 77 + extern hw_status hw_mmu_twl_disable(const void __iomem *base_address); 78 + 79 + extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address, 80 + u32 virtual_addr, u32 page_sz); 81 + 82 + extern hw_status hw_mmu_tlb_add(const void __iomem *base_address, 83 + u32 physical_addr, 84 + u32 virtual_addr, 85 + u32 page_sz, 86 + u32 entry_num, 87 + struct hw_mmu_map_attrs_t *map_attrs, 88 + s8 preserved_bit, s8 valid_bit); 89 + 90 + /* For PTEs */ 91 + extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va, 92 + u32 physical_addr, 93 + u32 virtual_addr, 94 + u32 page_sz, 95 + struct hw_mmu_map_attrs_t *map_attrs); 96 + 97 + extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, 98 + u32 virtual_addr, u32 page_size); 99 + 100 + void hw_mmu_tlb_flush_all(const void __iomem *base); 101 + 102 + static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va) 103 + { 104 + u32 pte_addr; 105 + u32 va31_to20; 106 + 107 + va31_to20 = va >> (20 - 2); /* Left-shift by 2 here itself */ 108 + va31_to20 &= 0xFFFFFFFCUL; 109 + pte_addr = l1_base + va31_to20; 110 + 111 + return pte_addr; 112 + } 113 + 114 + static inline u32 hw_mmu_pte_addr_l2(u32 l2_base, u32 va) 115 + { 116 + u32 pte_addr; 117 + 118 + pte_addr = (l2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC); 119 + 120 + return pte_addr; 121 + } 122 + 123 + static inline u32 hw_mmu_pte_coarse_l1(u32 pte_val) 124 + { 125 + u32 pte_coarse; 126 + 127 + pte_coarse = pte_val & 0xFFFFFC00; 128 + 129 + return pte_coarse; 130 + } 131 + 132 + static inline u32 hw_mmu_pte_size_l1(u32 pte_val) 133 + { 134 + u32 pte_size = 0; 135 + 136 + if ((pte_val & 0x3) == 0x1) { 137 + /* Points to L2 PT */ 138 + pte_size = HW_MMU_COARSE_PAGE_SIZE; 139 + } 140 + 141 + if ((pte_val & 0x3) == 0x2) { 142 + if (pte_val & (1 << 18)) 143 + pte_size = HW_PAGE_SIZE16MB; 144 + else 145 + pte_size = HW_PAGE_SIZE1MB; 146 + } 147 + 148 + return pte_size; 149 + } 150 + 151 + static inline u32 hw_mmu_pte_size_l2(u32 pte_val) 152 + { 153 + u32 pte_size = 0; 154 + 155 + if (pte_val & 0x2) 156 + pte_size = HW_PAGE_SIZE4KB; 157 + else if (pte_val & 0x1) 158 + pte_size = HW_PAGE_SIZE64KB; 159 + 160 + return pte_size; 161 + } 162 + 163 + #endif /* _HW_MMU_H */
+1
drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
··· 68 68 void __iomem *dw_per_base; 69 69 u32 dw_per_pm_base; 70 70 u32 dw_core_pm_base; 71 + void __iomem *dw_dmmu_base; 71 72 void __iomem *dw_sys_ctrl_base; 72 73 }; 73 74
+24
drivers/staging/tidspbridge/include/dspbridge/dev.h
··· 27 27 #include <dspbridge/nodedefs.h> 28 28 #include <dspbridge/dispdefs.h> 29 29 #include <dspbridge/dspdefs.h> 30 + #include <dspbridge/dmm.h> 30 31 #include <dspbridge/host_os.h> 31 32 32 33 /* ----------------------------------- This */ ··· 232 231 */ 233 232 extern int dev_get_cmm_mgr(struct dev_object *hdev_obj, 234 233 struct cmm_object **mgr); 234 + 235 + /* 236 + * ======== dev_get_dmm_mgr ======== 237 + * Purpose: 238 + * Retrieve the handle to the dynamic memory manager created for this 239 + * device. 240 + * Parameters: 241 + * hdev_obj: Handle to device object created with 242 + * dev_create_device(). 243 + * *mgr: Ptr to location to store handle. 244 + * Returns: 245 + * 0: Success. 246 + * -EFAULT: Invalid hdev_obj. 247 + * Requires: 248 + * mgr != NULL. 249 + * DEV Initialized. 250 + * Ensures: 251 + * 0: *mgr contains a handle to a channel manager object, 252 + * or NULL. 253 + * else: *mgr is NULL. 254 + */ 255 + extern int dev_get_dmm_mgr(struct dev_object *hdev_obj, 256 + struct dmm_object **mgr); 235 257 236 258 /* 237 259 * ======== dev_get_cod_mgr ========
+75
drivers/staging/tidspbridge/include/dspbridge/dmm.h
··· 1 + /* 2 + * dmm.h 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address 7 + * space that can be directly mapped to any MPU buffer or memory region. 8 + * 9 + * Copyright (C) 2005-2006 Texas Instruments, Inc. 10 + * 11 + * This package is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License version 2 as 13 + * published by the Free Software Foundation. 14 + * 15 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 16 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 17 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18 + */ 19 + 20 + #ifndef DMM_ 21 + #define DMM_ 22 + 23 + #include <dspbridge/dbdefs.h> 24 + 25 + struct dmm_object; 26 + 27 + /* DMM attributes used in dmm_create() */ 28 + struct dmm_mgrattrs { 29 + u32 reserved; 30 + }; 31 + 32 + #define DMMPOOLSIZE 0x4000000 33 + 34 + /* 35 + * ======== dmm_get_handle ======== 36 + * Purpose: 37 + * Return the dynamic memory manager object for this device. 38 + * This is typically called from the client process. 39 + */ 40 + 41 + extern int dmm_get_handle(void *hprocessor, 42 + struct dmm_object **dmm_manager); 43 + 44 + extern int dmm_reserve_memory(struct dmm_object *dmm_mgr, 45 + u32 size, u32 *prsv_addr); 46 + 47 + extern int dmm_un_reserve_memory(struct dmm_object *dmm_mgr, 48 + u32 rsv_addr); 49 + 50 + extern int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr, 51 + u32 size); 52 + 53 + extern int dmm_un_map_memory(struct dmm_object *dmm_mgr, 54 + u32 addr, u32 *psize); 55 + 56 + extern int dmm_destroy(struct dmm_object *dmm_mgr); 57 + 58 + extern int dmm_delete_tables(struct dmm_object *dmm_mgr); 59 + 60 + extern int dmm_create(struct dmm_object **dmm_manager, 61 + struct dev_object *hdev_obj, 62 + const struct dmm_mgrattrs *mgr_attrts); 63 + 64 + extern bool dmm_init(void); 65 + 66 + extern void dmm_exit(void); 67 + 68 + extern int dmm_create_tables(struct dmm_object *dmm_mgr, 69 + u32 addr, u32 size); 70 + 71 + #ifdef DSP_DMM_DEBUG 72 + u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr); 73 + #endif 74 + 75 + #endif /* DMM_ */
+10
drivers/staging/tidspbridge/include/dspbridge/drv.h
··· 108 108 struct bridge_dma_map_info dma_info; 109 109 }; 110 110 111 + /* Used for DMM reserved memory accounting */ 112 + struct dmm_rsv_object { 113 + struct list_head link; 114 + u32 dsp_reserved_addr; 115 + }; 116 + 111 117 /* New structure (member of process context) abstracts DMM resource info */ 112 118 struct dspheap_res_object { 113 119 s32 heap_allocated; /* DMM status */ ··· 164 158 /* DMM mapped memory resources */ 165 159 struct list_head dmm_map_list; 166 160 spinlock_t dmm_map_lock; 161 + 162 + /* DMM reserved memory resources */ 163 + struct list_head dmm_rsv_list; 164 + spinlock_t dmm_rsv_lock; 167 165 168 166 /* DSP Heap resources */ 169 167 struct dspheap_res_object *pdspheap_list;
-67
drivers/staging/tidspbridge/include/dspbridge/dsp-mmu.h
··· 1 - /* 2 - * dsp-mmu.h 3 - * 4 - * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 - * 6 - * DSP iommu. 7 - * 8 - * Copyright (C) 2005-2010 Texas Instruments, Inc. 9 - * 10 - * This package is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License version 2 as 12 - * published by the Free Software Foundation. 13 - * 14 - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 - */ 18 - 19 - #ifndef _DSP_MMU_ 20 - #define _DSP_MMU_ 21 - 22 - #include <plat/iommu.h> 23 - #include <plat/iovmm.h> 24 - 25 - /** 26 - * dsp_mmu_init() - initialize dsp_mmu module and returns a handle 27 - * 28 - * This function initialize dsp mmu module and returns a struct iommu 29 - * handle to use it for dsp maps. 30 - * 31 - */ 32 - struct iommu *dsp_mmu_init(void); 33 - 34 - /** 35 - * dsp_mmu_exit() - destroy dsp mmu module 36 - * @mmu: Pointer to iommu handle. 37 - * 38 - * This function destroys dsp mmu module. 39 - * 40 - */ 41 - void dsp_mmu_exit(struct iommu *mmu); 42 - 43 - /** 44 - * user_to_dsp_map() - maps user to dsp virtual address 45 - * @mmu: Pointer to iommu handle. 46 - * @uva: Virtual user space address. 47 - * @da DSP address 48 - * @size Buffer size to map. 49 - * @usr_pgs struct page array pointer where the user pages will be stored 50 - * 51 - * This function maps a user space buffer into DSP virtual address. 52 - * 53 - */ 54 - u32 user_to_dsp_map(struct iommu *mmu, u32 uva, u32 da, u32 size, 55 - struct page **usr_pgs); 56 - 57 - /** 58 - * user_to_dsp_unmap() - unmaps DSP virtual buffer. 59 - * @mmu: Pointer to iommu handle. 60 - * @da DSP address 61 - * 62 - * This function unmaps a user space buffer into DSP virtual address. 63 - * 64 - */ 65 - int user_to_dsp_unmap(struct iommu *mmu, u32 da); 66 - 67 - #endif
+44
drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
··· 162 162 u32 mem_type); 163 163 164 164 /* 165 + * ======== bridge_brd_mem_map ======== 166 + * Purpose: 167 + * Map a MPU memory region to a DSP/IVA memory space 168 + * Parameters: 169 + * dev_ctxt: Handle to Bridge driver defined device info. 170 + * ul_mpu_addr: MPU memory region start address. 171 + * virt_addr: DSP/IVA memory region u8 address. 172 + * ul_num_bytes: Number of bytes to map. 173 + * map_attrs: Mapping attributes (e.g. endianness). 174 + * Returns: 175 + * 0: Success. 176 + * -EPERM: Other, unspecified error. 177 + * Requires: 178 + * dev_ctxt != NULL; 179 + * Ensures: 180 + */ 181 + typedef int(*fxn_brd_memmap) (struct bridge_dev_context 182 + * dev_ctxt, u32 ul_mpu_addr, 183 + u32 virt_addr, u32 ul_num_bytes, 184 + u32 map_attr, 185 + struct page **mapped_pages); 186 + 187 + /* 188 + * ======== bridge_brd_mem_un_map ======== 189 + * Purpose: 190 + * UnMap an MPU memory region from DSP/IVA memory space 191 + * Parameters: 192 + * dev_ctxt: Handle to Bridge driver defined device info. 193 + * virt_addr: DSP/IVA memory region u8 address. 194 + * ul_num_bytes: Number of bytes to unmap. 195 + * Returns: 196 + * 0: Success. 197 + * -EPERM: Other, unspecified error. 198 + * Requires: 199 + * dev_ctxt != NULL; 200 + * Ensures: 201 + */ 202 + typedef int(*fxn_brd_memunmap) (struct bridge_dev_context 203 + * dev_ctxt, 204 + u32 virt_addr, u32 ul_num_bytes); 205 + 206 + /* 165 207 * ======== bridge_brd_stop ======== 166 208 * Purpose: 167 209 * Bring board to the BRD_STOPPED state. ··· 993 951 fxn_brd_setstate pfn_brd_set_state; /* Sets the Board State */ 994 952 fxn_brd_memcopy pfn_brd_mem_copy; /* Copies DSP Memory */ 995 953 fxn_brd_memwrite pfn_brd_mem_write; /* Write DSP Memory w/o halt */ 954 + fxn_brd_memmap pfn_brd_mem_map; /* Maps MPU mem to DSP mem */ 955 + fxn_brd_memunmap pfn_brd_mem_un_map; /* Unmaps MPU mem to DSP mem */ 996 956 fxn_chnl_create pfn_chnl_create; /* Create channel manager. */ 997 957 fxn_chnl_destroy pfn_chnl_destroy; /* Destroy channel manager. */ 998 958 fxn_chnl_open pfn_chnl_open; /* Create a new channel. */
+7
drivers/staging/tidspbridge/include/dspbridge/dspioctl.h
··· 19 19 #ifndef DSPIOCTL_ 20 20 #define DSPIOCTL_ 21 21 22 + /* ------------------------------------ Hardware Abstraction Layer */ 23 + #include <hw_defs.h> 24 + #include <hw_mmu.h> 25 + 22 26 /* 23 27 * Any IOCTLS at or above this value are reserved for standard Bridge driver 24 28 * interfaces. ··· 65 61 /* GPP virtual address. __va does not work for ioremapped addresses */ 66 62 u32 ul_gpp_va; 67 63 u32 ul_size; /* Size of the mapped memory in bytes */ 64 + enum hw_endianism_t endianism; 65 + enum hw_mmu_mixed_size_t mixed_mode; 66 + enum hw_element_size_t elem_size; 68 67 }; 69 68 70 69 #endif /* DSPIOCTL_ */
+46
drivers/staging/tidspbridge/include/dspbridge/proc.h
··· 551 551 struct process_context *pr_ctxt); 552 552 553 553 /* 554 + * ======== proc_reserve_memory ======== 555 + * Purpose: 556 + * Reserve a virtually contiguous region of DSP address space. 557 + * Parameters: 558 + * hprocessor : The processor handle. 559 + * ul_size : Size of the address space to reserve. 560 + * pp_rsv_addr : Ptr to DSP side reserved u8 address. 561 + * Returns: 562 + * 0 : Success. 563 + * -EFAULT : Invalid processor handle. 564 + * -EPERM : General failure. 565 + * -ENOMEM : Cannot reserve chunk of this size. 566 + * Requires: 567 + * pp_rsv_addr is not NULL 568 + * PROC Initialized. 569 + * Ensures: 570 + * Details: 571 + */ 572 + extern int proc_reserve_memory(void *hprocessor, 573 + u32 ul_size, void **pp_rsv_addr, 574 + struct process_context *pr_ctxt); 575 + 576 + /* 554 577 * ======== proc_un_map ======== 555 578 * Purpose: 556 579 * Removes a MPU buffer mapping from the DSP address space. ··· 594 571 */ 595 572 extern int proc_un_map(void *hprocessor, void *map_addr, 596 573 struct process_context *pr_ctxt); 574 + 575 + /* 576 + * ======== proc_un_reserve_memory ======== 577 + * Purpose: 578 + * Frees a previously reserved region of DSP address space. 579 + * Parameters: 580 + * hprocessor : The processor handle. 581 + * prsv_addr : Ptr to DSP side reservedBYTE address. 582 + * Returns: 583 + * 0 : Success. 584 + * -EFAULT : Invalid processor handle. 585 + * -EPERM : General failure. 586 + * -ENOENT : Cannot find a reserved region starting with this 587 + * : address. 588 + * Requires: 589 + * prsv_addr is not NULL 590 + * PROC Initialized. 591 + * Ensures: 592 + * Details: 593 + */ 594 + extern int proc_un_reserve_memory(void *hprocessor, 595 + void *prsv_addr, 596 + struct process_context *pr_ctxt); 597 597 598 598 #endif /* PROC_ */
+59 -4
drivers/staging/tidspbridge/pmgr/dev.c
··· 34 34 #include <dspbridge/cod.h> 35 35 #include <dspbridge/drv.h> 36 36 #include <dspbridge/proc.h> 37 + #include <dspbridge/dmm.h> 37 38 38 39 /* ----------------------------------- Resource Manager */ 39 40 #include <dspbridge/mgr.h> ··· 75 74 struct msg_mgr *hmsg_mgr; /* Message manager. */ 76 75 struct io_mgr *hio_mgr; /* IO manager (CHNL, msg_ctrl) */ 77 76 struct cmm_object *hcmm_mgr; /* SM memory manager. */ 77 + struct dmm_object *dmm_mgr; /* Dynamic memory manager. */ 78 78 struct ldr_module *module_obj; /* Bridge Module handle. */ 79 79 u32 word_size; /* DSP word size: quick access. */ 80 80 struct drv_object *hdrv_obj; /* Driver Object */ ··· 250 248 /* Instantiate the DEH module */ 251 249 status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj); 252 250 } 251 + /* Create DMM mgr . */ 252 + status = dmm_create(&dev_obj->dmm_mgr, 253 + (struct dev_object *)dev_obj, NULL); 253 254 } 254 255 /* Add the new DEV_Object to the global list: */ 255 256 if (!status) { ··· 278 273 kfree(dev_obj->proc_list); 279 274 if (dev_obj->cod_mgr) 280 275 cod_delete(dev_obj->cod_mgr); 276 + if (dev_obj->dmm_mgr) 277 + dmm_destroy(dev_obj->dmm_mgr); 281 278 kfree(dev_obj); 282 279 } 283 280 ··· 389 382 dev_obj->hcmm_mgr = NULL; 390 383 } 391 384 385 + if (dev_obj->dmm_mgr) { 386 + dmm_destroy(dev_obj->dmm_mgr); 387 + dev_obj->dmm_mgr = NULL; 388 + } 389 + 392 390 /* Call the driver's bridge_dev_destroy() function: */ 393 391 /* Require of DevDestroy */ 394 392 if (dev_obj->hbridge_context) { ··· 464 452 465 453 if (hdev_obj) { 466 454 *mgr = dev_obj->hcmm_mgr; 455 + } else { 456 + *mgr = NULL; 457 + status = -EFAULT; 458 + } 459 + 460 + DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); 461 + return status; 462 + } 463 + 464 + /* 465 + * ======== dev_get_dmm_mgr ======== 466 + * Purpose: 467 + * Retrieve the handle to the dynamic memory manager created for this 468 + * device. 469 + */ 470 + int dev_get_dmm_mgr(struct dev_object *hdev_obj, 471 + struct dmm_object **mgr) 472 + { 473 + int status = 0; 474 + struct dev_object *dev_obj = hdev_obj; 475 + 476 + DBC_REQUIRE(refs > 0); 477 + DBC_REQUIRE(mgr != NULL); 478 + 479 + if (hdev_obj) { 480 + *mgr = dev_obj->dmm_mgr; 467 481 } else { 468 482 *mgr = NULL; 469 483 status = -EFAULT; ··· 751 713 752 714 refs--; 753 715 754 - if (refs == 0) 716 + if (refs == 0) { 755 717 cmm_exit(); 718 + dmm_exit(); 719 + } 756 720 757 721 DBC_ENSURE(refs >= 0); 758 722 } ··· 766 726 */ 767 727 bool dev_init(void) 768 728 { 769 - bool ret = true; 729 + bool cmm_ret, dmm_ret, ret = true; 770 730 771 731 DBC_REQUIRE(refs >= 0); 772 732 773 - if (refs == 0) 774 - ret = cmm_init(); 733 + if (refs == 0) { 734 + cmm_ret = cmm_init(); 735 + dmm_ret = dmm_init(); 736 + 737 + ret = cmm_ret && dmm_ret; 738 + 739 + if (!ret) { 740 + if (cmm_ret) 741 + cmm_exit(); 742 + 743 + if (dmm_ret) 744 + dmm_exit(); 745 + 746 + } 747 + } 775 748 776 749 if (ret) 777 750 refs++; ··· 1118 1065 STORE_FXN(fxn_brd_setstate, pfn_brd_set_state); 1119 1066 STORE_FXN(fxn_brd_memcopy, pfn_brd_mem_copy); 1120 1067 STORE_FXN(fxn_brd_memwrite, pfn_brd_mem_write); 1068 + STORE_FXN(fxn_brd_memmap, pfn_brd_mem_map); 1069 + STORE_FXN(fxn_brd_memunmap, pfn_brd_mem_un_map); 1121 1070 STORE_FXN(fxn_chnl_create, pfn_chnl_create); 1122 1071 STORE_FXN(fxn_chnl_destroy, pfn_chnl_destroy); 1123 1072 STORE_FXN(fxn_chnl_open, pfn_chnl_open);
+533
drivers/staging/tidspbridge/pmgr/dmm.c
··· 1 + /* 2 + * dmm.c 3 + * 4 + * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 + * 6 + * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address 7 + * space that can be directly mapped to any MPU buffer or memory region 8 + * 9 + * Notes: 10 + * Region: Generic memory entitiy having a start address and a size 11 + * Chunk: Reserved region 12 + * 13 + * Copyright (C) 2005-2006 Texas Instruments, Inc. 14 + * 15 + * This package is free software; you can redistribute it and/or modify 16 + * it under the terms of the GNU General Public License version 2 as 17 + * published by the Free Software Foundation. 18 + * 19 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 20 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 21 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 + */ 23 + #include <linux/types.h> 24 + 25 + /* ----------------------------------- Host OS */ 26 + #include <dspbridge/host_os.h> 27 + 28 + /* ----------------------------------- DSP/BIOS Bridge */ 29 + #include <dspbridge/dbdefs.h> 30 + 31 + /* ----------------------------------- Trace & Debug */ 32 + #include <dspbridge/dbc.h> 33 + 34 + /* ----------------------------------- OS Adaptation Layer */ 35 + #include <dspbridge/sync.h> 36 + 37 + /* ----------------------------------- Platform Manager */ 38 + #include <dspbridge/dev.h> 39 + #include <dspbridge/proc.h> 40 + 41 + /* ----------------------------------- This */ 42 + #include <dspbridge/dmm.h> 43 + 44 + /* ----------------------------------- Defines, Data Structures, Typedefs */ 45 + #define DMM_ADDR_VIRTUAL(a) \ 46 + (((struct map_page *)(a) - virtual_mapping_table) * PG_SIZE4K +\ 47 + dyn_mem_map_beg) 48 + #define DMM_ADDR_TO_INDEX(a) (((a) - dyn_mem_map_beg) / PG_SIZE4K) 49 + 50 + /* DMM Mgr */ 51 + struct dmm_object { 52 + /* Dmm Lock is used to serialize access mem manager for 53 + * multi-threads. */ 54 + spinlock_t dmm_lock; /* Lock to access dmm mgr */ 55 + }; 56 + 57 + /* ----------------------------------- Globals */ 58 + static u32 refs; /* module reference count */ 59 + struct map_page { 60 + u32 region_size:15; 61 + u32 mapped_size:15; 62 + u32 reserved:1; 63 + u32 mapped:1; 64 + }; 65 + 66 + /* Create the free list */ 67 + static struct map_page *virtual_mapping_table; 68 + static u32 free_region; /* The index of free region */ 69 + static u32 free_size; 70 + static u32 dyn_mem_map_beg; /* The Beginning of dynamic memory mapping */ 71 + static u32 table_size; /* The size of virt and phys pages tables */ 72 + 73 + /* ----------------------------------- Function Prototypes */ 74 + static struct map_page *get_region(u32 addr); 75 + static struct map_page *get_free_region(u32 len); 76 + static struct map_page *get_mapped_region(u32 addrs); 77 + 78 + /* ======== dmm_create_tables ======== 79 + * Purpose: 80 + * Create table to hold the information of physical address 81 + * the buffer pages that is passed by the user, and the table 82 + * to hold the information of the virtual memory that is reserved 83 + * for DSP. 84 + */ 85 + int dmm_create_tables(struct dmm_object *dmm_mgr, u32 addr, u32 size) 86 + { 87 + struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; 88 + int status = 0; 89 + 90 + status = dmm_delete_tables(dmm_obj); 91 + if (!status) { 92 + dyn_mem_map_beg = addr; 93 + table_size = PG_ALIGN_HIGH(size, PG_SIZE4K) / PG_SIZE4K; 94 + /* Create the free list */ 95 + virtual_mapping_table = __vmalloc(table_size * 96 + sizeof(struct map_page), GFP_KERNEL | 97 + __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); 98 + if (virtual_mapping_table == NULL) 99 + status = -ENOMEM; 100 + else { 101 + /* On successful allocation, 102 + * all entries are zero ('free') */ 103 + free_region = 0; 104 + free_size = table_size * PG_SIZE4K; 105 + virtual_mapping_table[0].region_size = table_size; 106 + } 107 + } 108 + 109 + if (status) 110 + pr_err("%s: failure, status 0x%x\n", __func__, status); 111 + 112 + return status; 113 + } 114 + 115 + /* 116 + * ======== dmm_create ======== 117 + * Purpose: 118 + * Create a dynamic memory manager object. 119 + */ 120 + int dmm_create(struct dmm_object **dmm_manager, 121 + struct dev_object *hdev_obj, 122 + const struct dmm_mgrattrs *mgr_attrts) 123 + { 124 + struct dmm_object *dmm_obj = NULL; 125 + int status = 0; 126 + DBC_REQUIRE(refs > 0); 127 + DBC_REQUIRE(dmm_manager != NULL); 128 + 129 + *dmm_manager = NULL; 130 + /* create, zero, and tag a cmm mgr object */ 131 + dmm_obj = kzalloc(sizeof(struct dmm_object), GFP_KERNEL); 132 + if (dmm_obj != NULL) { 133 + spin_lock_init(&dmm_obj->dmm_lock); 134 + *dmm_manager = dmm_obj; 135 + } else { 136 + status = -ENOMEM; 137 + } 138 + 139 + return status; 140 + } 141 + 142 + /* 143 + * ======== dmm_destroy ======== 144 + * Purpose: 145 + * Release the communication memory manager resources. 146 + */ 147 + int dmm_destroy(struct dmm_object *dmm_mgr) 148 + { 149 + struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; 150 + int status = 0; 151 + 152 + DBC_REQUIRE(refs > 0); 153 + if (dmm_mgr) { 154 + status = dmm_delete_tables(dmm_obj); 155 + if (!status) 156 + kfree(dmm_obj); 157 + } else 158 + status = -EFAULT; 159 + 160 + return status; 161 + } 162 + 163 + /* 164 + * ======== dmm_delete_tables ======== 165 + * Purpose: 166 + * Delete DMM Tables. 167 + */ 168 + int dmm_delete_tables(struct dmm_object *dmm_mgr) 169 + { 170 + int status = 0; 171 + 172 + DBC_REQUIRE(refs > 0); 173 + /* Delete all DMM tables */ 174 + if (dmm_mgr) 175 + vfree(virtual_mapping_table); 176 + else 177 + status = -EFAULT; 178 + return status; 179 + } 180 + 181 + /* 182 + * ======== dmm_exit ======== 183 + * Purpose: 184 + * Discontinue usage of module; free resources when reference count 185 + * reaches 0. 186 + */ 187 + void dmm_exit(void) 188 + { 189 + DBC_REQUIRE(refs > 0); 190 + 191 + refs--; 192 + } 193 + 194 + /* 195 + * ======== dmm_get_handle ======== 196 + * Purpose: 197 + * Return the dynamic memory manager object for this device. 198 + * This is typically called from the client process. 199 + */ 200 + int dmm_get_handle(void *hprocessor, struct dmm_object **dmm_manager) 201 + { 202 + int status = 0; 203 + struct dev_object *hdev_obj; 204 + 205 + DBC_REQUIRE(refs > 0); 206 + DBC_REQUIRE(dmm_manager != NULL); 207 + if (hprocessor != NULL) 208 + status = proc_get_dev_object(hprocessor, &hdev_obj); 209 + else 210 + hdev_obj = dev_get_first(); /* default */ 211 + 212 + if (!status) 213 + status = dev_get_dmm_mgr(hdev_obj, dmm_manager); 214 + 215 + return status; 216 + } 217 + 218 + /* 219 + * ======== dmm_init ======== 220 + * Purpose: 221 + * Initializes private state of DMM module. 222 + */ 223 + bool dmm_init(void) 224 + { 225 + bool ret = true; 226 + 227 + DBC_REQUIRE(refs >= 0); 228 + 229 + if (ret) 230 + refs++; 231 + 232 + DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); 233 + 234 + virtual_mapping_table = NULL; 235 + table_size = 0; 236 + 237 + return ret; 238 + } 239 + 240 + /* 241 + * ======== dmm_map_memory ======== 242 + * Purpose: 243 + * Add a mapping block to the reserved chunk. DMM assumes that this block 244 + * will be mapped in the DSP/IVA's address space. DMM returns an error if a 245 + * mapping overlaps another one. This function stores the info that will be 246 + * required later while unmapping the block. 247 + */ 248 + int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 size) 249 + { 250 + struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; 251 + struct map_page *chunk; 252 + int status = 0; 253 + 254 + spin_lock(&dmm_obj->dmm_lock); 255 + /* Find the Reserved memory chunk containing the DSP block to 256 + * be mapped */ 257 + chunk = (struct map_page *)get_region(addr); 258 + if (chunk != NULL) { 259 + /* Mark the region 'mapped', leave the 'reserved' info as-is */ 260 + chunk->mapped = true; 261 + chunk->mapped_size = (size / PG_SIZE4K); 262 + } else 263 + status = -ENOENT; 264 + spin_unlock(&dmm_obj->dmm_lock); 265 + 266 + dev_dbg(bridge, "%s dmm_mgr %p, addr %x, size %x\n\tstatus %x, " 267 + "chunk %p", __func__, dmm_mgr, addr, size, status, chunk); 268 + 269 + return status; 270 + } 271 + 272 + /* 273 + * ======== dmm_reserve_memory ======== 274 + * Purpose: 275 + * Reserve a chunk of virtually contiguous DSP/IVA address space. 276 + */ 277 + int dmm_reserve_memory(struct dmm_object *dmm_mgr, u32 size, 278 + u32 *prsv_addr) 279 + { 280 + int status = 0; 281 + struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; 282 + struct map_page *node; 283 + u32 rsv_addr = 0; 284 + u32 rsv_size = 0; 285 + 286 + spin_lock(&dmm_obj->dmm_lock); 287 + 288 + /* Try to get a DSP chunk from the free list */ 289 + node = get_free_region(size); 290 + if (node != NULL) { 291 + /* DSP chunk of given size is available. */ 292 + rsv_addr = DMM_ADDR_VIRTUAL(node); 293 + /* Calculate the number entries to use */ 294 + rsv_size = size / PG_SIZE4K; 295 + if (rsv_size < node->region_size) { 296 + /* Mark remainder of free region */ 297 + node[rsv_size].mapped = false; 298 + node[rsv_size].reserved = false; 299 + node[rsv_size].region_size = 300 + node->region_size - rsv_size; 301 + node[rsv_size].mapped_size = 0; 302 + } 303 + /* get_region will return first fit chunk. But we only use what 304 + is requested. */ 305 + node->mapped = false; 306 + node->reserved = true; 307 + node->region_size = rsv_size; 308 + node->mapped_size = 0; 309 + /* Return the chunk's starting address */ 310 + *prsv_addr = rsv_addr; 311 + } else 312 + /*dSP chunk of given size is not available */ 313 + status = -ENOMEM; 314 + 315 + spin_unlock(&dmm_obj->dmm_lock); 316 + 317 + dev_dbg(bridge, "%s dmm_mgr %p, size %x, prsv_addr %p\n\tstatus %x, " 318 + "rsv_addr %x, rsv_size %x\n", __func__, dmm_mgr, size, 319 + prsv_addr, status, rsv_addr, rsv_size); 320 + 321 + return status; 322 + } 323 + 324 + /* 325 + * ======== dmm_un_map_memory ======== 326 + * Purpose: 327 + * Remove the mapped block from the reserved chunk. 328 + */ 329 + int dmm_un_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 *psize) 330 + { 331 + struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; 332 + struct map_page *chunk; 333 + int status = 0; 334 + 335 + spin_lock(&dmm_obj->dmm_lock); 336 + chunk = get_mapped_region(addr); 337 + if (chunk == NULL) 338 + status = -ENOENT; 339 + 340 + if (!status) { 341 + /* Unmap the region */ 342 + *psize = chunk->mapped_size * PG_SIZE4K; 343 + chunk->mapped = false; 344 + chunk->mapped_size = 0; 345 + } 346 + spin_unlock(&dmm_obj->dmm_lock); 347 + 348 + dev_dbg(bridge, "%s: dmm_mgr %p, addr %x, psize %p\n\tstatus %x, " 349 + "chunk %p\n", __func__, dmm_mgr, addr, psize, status, chunk); 350 + 351 + return status; 352 + } 353 + 354 + /* 355 + * ======== dmm_un_reserve_memory ======== 356 + * Purpose: 357 + * Free a chunk of reserved DSP/IVA address space. 358 + */ 359 + int dmm_un_reserve_memory(struct dmm_object *dmm_mgr, u32 rsv_addr) 360 + { 361 + struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr; 362 + struct map_page *chunk; 363 + u32 i; 364 + int status = 0; 365 + u32 chunk_size; 366 + 367 + spin_lock(&dmm_obj->dmm_lock); 368 + 369 + /* Find the chunk containing the reserved address */ 370 + chunk = get_mapped_region(rsv_addr); 371 + if (chunk == NULL) 372 + status = -ENOENT; 373 + 374 + if (!status) { 375 + /* Free all the mapped pages for this reserved region */ 376 + i = 0; 377 + while (i < chunk->region_size) { 378 + if (chunk[i].mapped) { 379 + /* Remove mapping from the page tables. */ 380 + chunk_size = chunk[i].mapped_size; 381 + /* Clear the mapping flags */ 382 + chunk[i].mapped = false; 383 + chunk[i].mapped_size = 0; 384 + i += chunk_size; 385 + } else 386 + i++; 387 + } 388 + /* Clear the flags (mark the region 'free') */ 389 + chunk->reserved = false; 390 + /* NOTE: We do NOT coalesce free regions here. 391 + * Free regions are coalesced in get_region(), as it traverses 392 + *the whole mapping table 393 + */ 394 + } 395 + spin_unlock(&dmm_obj->dmm_lock); 396 + 397 + dev_dbg(bridge, "%s: dmm_mgr %p, rsv_addr %x\n\tstatus %x chunk %p", 398 + __func__, dmm_mgr, rsv_addr, status, chunk); 399 + 400 + return status; 401 + } 402 + 403 + /* 404 + * ======== get_region ======== 405 + * Purpose: 406 + * Returns a region containing the specified memory region 407 + */ 408 + static struct map_page *get_region(u32 addr) 409 + { 410 + struct map_page *curr_region = NULL; 411 + u32 i = 0; 412 + 413 + if (virtual_mapping_table != NULL) { 414 + /* find page mapped by this address */ 415 + i = DMM_ADDR_TO_INDEX(addr); 416 + if (i < table_size) 417 + curr_region = virtual_mapping_table + i; 418 + } 419 + 420 + dev_dbg(bridge, "%s: curr_region %p, free_region %d, free_size %d\n", 421 + __func__, curr_region, free_region, free_size); 422 + return curr_region; 423 + } 424 + 425 + /* 426 + * ======== get_free_region ======== 427 + * Purpose: 428 + * Returns the requested free region 429 + */ 430 + static struct map_page *get_free_region(u32 len) 431 + { 432 + struct map_page *curr_region = NULL; 433 + u32 i = 0; 434 + u32 region_size = 0; 435 + u32 next_i = 0; 436 + 437 + if (virtual_mapping_table == NULL) 438 + return curr_region; 439 + if (len > free_size) { 440 + /* Find the largest free region 441 + * (coalesce during the traversal) */ 442 + while (i < table_size) { 443 + region_size = virtual_mapping_table[i].region_size; 444 + next_i = i + region_size; 445 + if (virtual_mapping_table[i].reserved == false) { 446 + /* Coalesce, if possible */ 447 + if (next_i < table_size && 448 + virtual_mapping_table[next_i].reserved 449 + == false) { 450 + virtual_mapping_table[i].region_size += 451 + virtual_mapping_table 452 + [next_i].region_size; 453 + continue; 454 + } 455 + region_size *= PG_SIZE4K; 456 + if (region_size > free_size) { 457 + free_region = i; 458 + free_size = region_size; 459 + } 460 + } 461 + i = next_i; 462 + } 463 + } 464 + if (len <= free_size) { 465 + curr_region = virtual_mapping_table + free_region; 466 + free_region += (len / PG_SIZE4K); 467 + free_size -= len; 468 + } 469 + return curr_region; 470 + } 471 + 472 + /* 473 + * ======== get_mapped_region ======== 474 + * Purpose: 475 + * Returns the requestedmapped region 476 + */ 477 + static struct map_page *get_mapped_region(u32 addrs) 478 + { 479 + u32 i = 0; 480 + struct map_page *curr_region = NULL; 481 + 482 + if (virtual_mapping_table == NULL) 483 + return curr_region; 484 + 485 + i = DMM_ADDR_TO_INDEX(addrs); 486 + if (i < table_size && (virtual_mapping_table[i].mapped || 487 + virtual_mapping_table[i].reserved)) 488 + curr_region = virtual_mapping_table + i; 489 + return curr_region; 490 + } 491 + 492 + #ifdef DSP_DMM_DEBUG 493 + u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr) 494 + { 495 + struct map_page *curr_node = NULL; 496 + u32 i; 497 + u32 freemem = 0; 498 + u32 bigsize = 0; 499 + 500 + spin_lock(&dmm_mgr->dmm_lock); 501 + 502 + if (virtual_mapping_table != NULL) { 503 + for (i = 0; i < table_size; i += 504 + virtual_mapping_table[i].region_size) { 505 + curr_node = virtual_mapping_table + i; 506 + if (curr_node->reserved) { 507 + /*printk("RESERVED size = 0x%x, " 508 + "Map size = 0x%x\n", 509 + (curr_node->region_size * PG_SIZE4K), 510 + (curr_node->mapped == false) ? 0 : 511 + (curr_node->mapped_size * PG_SIZE4K)); 512 + */ 513 + } else { 514 + /* printk("UNRESERVED size = 0x%x\n", 515 + (curr_node->region_size * PG_SIZE4K)); 516 + */ 517 + freemem += (curr_node->region_size * PG_SIZE4K); 518 + if (curr_node->region_size > bigsize) 519 + bigsize = curr_node->region_size; 520 + } 521 + } 522 + } 523 + spin_unlock(&dmm_mgr->dmm_lock); 524 + printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n", 525 + freemem / (1024 * 1024)); 526 + printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n", 527 + (((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024)); 528 + printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n", 529 + (bigsize * PG_SIZE4K / (1024 * 1024))); 530 + 531 + return 0; 532 + } 533 + #endif
+28 -6
drivers/staging/tidspbridge/pmgr/dspapi.c
··· 993 993 /* 994 994 * ======== procwrap_reserve_memory ======== 995 995 */ 996 - u32 __deprecated procwrap_reserve_memory(union trapped_args *args, 997 - void *pr_ctxt) 996 + u32 procwrap_reserve_memory(union trapped_args *args, void *pr_ctxt) 998 997 { 999 - return 0; 998 + int status; 999 + void *prsv_addr; 1000 + void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 1001 + 1002 + if ((args->args_proc_rsvmem.ul_size <= 0) || 1003 + (args->args_proc_rsvmem.ul_size & (PG_SIZE4K - 1)) != 0) 1004 + return -EINVAL; 1005 + 1006 + status = proc_reserve_memory(hprocessor, 1007 + args->args_proc_rsvmem.ul_size, &prsv_addr, 1008 + pr_ctxt); 1009 + if (!status) { 1010 + if (put_user(prsv_addr, args->args_proc_rsvmem.pp_rsv_addr)) { 1011 + status = -EINVAL; 1012 + proc_un_reserve_memory(args->args_proc_rsvmem. 1013 + hprocessor, prsv_addr, pr_ctxt); 1014 + } 1015 + } 1016 + return status; 1000 1017 } 1001 1018 1002 1019 /* ··· 1042 1025 /* 1043 1026 * ======== procwrap_un_reserve_memory ======== 1044 1027 */ 1045 - u32 __deprecated procwrap_un_reserve_memory(union trapped_args *args, 1046 - void *pr_ctxt) 1028 + u32 procwrap_un_reserve_memory(union trapped_args *args, void *pr_ctxt) 1047 1029 { 1048 - return 0; 1030 + int status; 1031 + void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor; 1032 + 1033 + status = proc_un_reserve_memory(hprocessor, 1034 + args->args_proc_unrsvmem.prsv_addr, 1035 + pr_ctxt); 1036 + return status; 1049 1037 } 1050 1038 1051 1039 /*
+15
drivers/staging/tidspbridge/rmgr/drv.c
··· 146 146 struct process_context *ctxt = (struct process_context *)process_ctxt; 147 147 int status = 0; 148 148 struct dmm_map_object *temp_map, *map_obj; 149 + struct dmm_rsv_object *temp_rsv, *rsv_obj; 149 150 150 151 /* Free DMM mapped memory resources */ 151 152 list_for_each_entry_safe(map_obj, temp_map, &ctxt->dmm_map_list, link) { ··· 154 153 (void *)map_obj->dsp_addr, ctxt); 155 154 if (status) 156 155 pr_err("%s: proc_un_map failed!" 156 + " status = 0x%xn", __func__, status); 157 + } 158 + 159 + /* Free DMM reserved memory resources */ 160 + list_for_each_entry_safe(rsv_obj, temp_rsv, &ctxt->dmm_rsv_list, link) { 161 + status = proc_un_reserve_memory(ctxt->hprocessor, (void *) 162 + rsv_obj->dsp_reserved_addr, 163 + ctxt); 164 + if (status) 165 + pr_err("%s: proc_un_reserve_memory failed!" 157 166 " status = 0x%xn", __func__, status); 158 167 } 159 168 return status; ··· 743 732 host_res->dw_sys_ctrl_base = ioremap(OMAP_SYSC_BASE, OMAP_SYSC_SIZE); 744 733 dev_dbg(bridge, "dw_mem_base[0] 0x%x\n", host_res->dw_mem_base[0]); 745 734 dev_dbg(bridge, "dw_mem_base[3] 0x%x\n", host_res->dw_mem_base[3]); 735 + dev_dbg(bridge, "dw_dmmu_base %p\n", host_res->dw_dmmu_base); 746 736 747 737 /* for 24xx base port is not mapping the mamory for DSP 748 738 * internal memory TODO Do a ioremap here */ ··· 797 785 OMAP_PER_PRM_SIZE); 798 786 host_res->dw_core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE, 799 787 OMAP_CORE_PRM_SIZE); 788 + host_res->dw_dmmu_base = ioremap(OMAP_DMMU_BASE, 789 + OMAP_DMMU_SIZE); 800 790 801 791 dev_dbg(bridge, "dw_mem_base[0] 0x%x\n", 802 792 host_res->dw_mem_base[0]); ··· 810 796 host_res->dw_mem_base[3]); 811 797 dev_dbg(bridge, "dw_mem_base[4] 0x%x\n", 812 798 host_res->dw_mem_base[4]); 799 + dev_dbg(bridge, "dw_dmmu_base %p\n", host_res->dw_dmmu_base); 813 800 814 801 shm_size = drv_datap->shm_size; 815 802 if (shm_size >= 0x10000) {
+2
drivers/staging/tidspbridge/rmgr/drv_interface.c
··· 509 509 pr_ctxt->res_state = PROC_RES_ALLOCATED; 510 510 spin_lock_init(&pr_ctxt->dmm_map_lock); 511 511 INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); 512 + spin_lock_init(&pr_ctxt->dmm_rsv_lock); 513 + INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); 512 514 513 515 pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); 514 516 if (pr_ctxt->node_id) {
+46 -2
drivers/staging/tidspbridge/rmgr/node.c
··· 56 56 /* ----------------------------------- This */ 57 57 #include <dspbridge/nodepriv.h> 58 58 #include <dspbridge/node.h> 59 + #include <dspbridge/dmm.h> 59 60 60 61 /* Static/Dynamic Loader includes */ 61 62 #include <dspbridge/dbll.h> ··· 317 316 u32 mapped_addr = 0; 318 317 u32 map_attrs = 0x0; 319 318 struct dsp_processorstate proc_state; 319 + #ifdef DSP_DMM_DEBUG 320 + struct dmm_object *dmm_mgr; 321 + struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 322 + #endif 320 323 321 324 void *node_res; 322 325 ··· 430 425 if (status) 431 426 goto func_cont; 432 427 428 + status = proc_reserve_memory(hprocessor, 429 + pnode->create_args.asa.task_arg_obj. 430 + heap_size + PAGE_SIZE, 431 + (void **)&(pnode->create_args.asa. 432 + task_arg_obj.udsp_heap_res_addr), 433 + pr_ctxt); 434 + if (status) { 435 + pr_err("%s: Failed to reserve memory for heap: 0x%x\n", 436 + __func__, status); 437 + goto func_cont; 438 + } 439 + #ifdef DSP_DMM_DEBUG 440 + status = dmm_get_handle(p_proc_object, &dmm_mgr); 441 + if (!dmm_mgr) { 442 + status = DSP_EHANDLE; 443 + goto func_cont; 444 + } 445 + 446 + dmm_mem_map_dump(dmm_mgr); 447 + #endif 448 + 433 449 map_attrs |= DSP_MAPLITTLEENDIAN; 434 450 map_attrs |= DSP_MAPELEMSIZE32; 435 451 map_attrs |= DSP_MAPVIRTUALADDR; 436 452 status = proc_map(hprocessor, (void *)attr_in->pgpp_virt_addr, 437 453 pnode->create_args.asa.task_arg_obj.heap_size, 438 - NULL, (void **)&mapped_addr, map_attrs, 454 + (void *)pnode->create_args.asa.task_arg_obj. 455 + udsp_heap_res_addr, (void **)&mapped_addr, map_attrs, 439 456 pr_ctxt); 440 457 if (status) 441 458 pr_err("%s: Failed to map memory for Heap: 0x%x\n", ··· 2511 2484 struct stream_chnl stream; 2512 2485 struct node_msgargs node_msg_args; 2513 2486 struct node_taskargs task_arg_obj; 2514 - 2487 + #ifdef DSP_DMM_DEBUG 2488 + struct dmm_object *dmm_mgr; 2489 + struct proc_object *p_proc_object = 2490 + (struct proc_object *)hnode->hprocessor; 2491 + #endif 2515 2492 int status; 2516 2493 if (!hnode) 2517 2494 goto func_end; ··· 2576 2545 status = proc_un_map(hnode->hprocessor, (void *) 2577 2546 task_arg_obj.udsp_heap_addr, 2578 2547 pr_ctxt); 2548 + 2549 + status = proc_un_reserve_memory(hnode->hprocessor, 2550 + (void *) 2551 + task_arg_obj. 2552 + udsp_heap_res_addr, 2553 + pr_ctxt); 2554 + #ifdef DSP_DMM_DEBUG 2555 + status = dmm_get_handle(p_proc_object, &dmm_mgr); 2556 + if (dmm_mgr) 2557 + dmm_mem_map_dump(dmm_mgr); 2558 + else 2559 + status = DSP_EHANDLE; 2560 + #endif 2579 2561 } 2580 2562 } 2581 2563 if (node_type != NODE_MESSAGE) {
+174 -23
drivers/staging/tidspbridge/rmgr/proc.c
··· 39 39 #include <dspbridge/cod.h> 40 40 #include <dspbridge/dev.h> 41 41 #include <dspbridge/procpriv.h> 42 + #include <dspbridge/dmm.h> 42 43 43 44 /* ----------------------------------- Resource Manager */ 44 45 #include <dspbridge/mgr.h> ··· 52 51 #include <dspbridge/msg.h> 53 52 #include <dspbridge/dspioctl.h> 54 53 #include <dspbridge/drv.h> 55 - #include <_tiomap.h> 56 54 57 55 /* ----------------------------------- This */ 58 56 #include <dspbridge/proc.h> ··· 151 151 return map_obj; 152 152 } 153 153 154 + static int match_exact_map_obj(struct dmm_map_object *map_obj, 155 + u32 dsp_addr, u32 size) 156 + { 157 + if (map_obj->dsp_addr == dsp_addr && map_obj->size != size) 158 + pr_err("%s: addr match (0x%x), size don't (0x%x != 0x%x)\n", 159 + __func__, dsp_addr, map_obj->size, size); 160 + 161 + return map_obj->dsp_addr == dsp_addr && 162 + map_obj->size == size; 163 + } 164 + 154 165 static void remove_mapping_information(struct process_context *pr_ctxt, 155 - u32 dsp_addr) 166 + u32 dsp_addr, u32 size) 156 167 { 157 168 struct dmm_map_object *map_obj; 158 169 159 - pr_debug("%s: looking for virt 0x%x\n", __func__, dsp_addr); 170 + pr_debug("%s: looking for virt 0x%x size 0x%x\n", __func__, 171 + dsp_addr, size); 160 172 161 173 spin_lock(&pr_ctxt->dmm_map_lock); 162 174 list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) { 163 - pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x\n", 175 + pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n", 164 176 __func__, 165 177 map_obj->mpu_addr, 166 - map_obj->dsp_addr); 178 + map_obj->dsp_addr, 179 + map_obj->size); 167 180 168 - if (map_obj->dsp_addr == dsp_addr) { 181 + if (match_exact_map_obj(map_obj, dsp_addr, size)) { 169 182 pr_debug("%s: match, deleting map info\n", __func__); 170 183 list_del(&map_obj->link); 171 184 kfree(map_obj->dma_info.sg); ··· 1090 1077 s32 cnew_envp; /* " " in new_envp[] */ 1091 1078 s32 nproc_id = 0; /* Anticipate MP version. */ 1092 1079 struct dcd_manager *hdcd_handle; 1080 + struct dmm_object *dmm_mgr; 1093 1081 u32 dw_ext_end; 1094 1082 u32 proc_id; 1095 1083 int brd_state; ··· 1281 1267 if (!status) 1282 1268 status = cod_get_sym_value(cod_mgr, EXTEND, 1283 1269 &dw_ext_end); 1270 + 1271 + /* Reset DMM structs and add an initial free chunk */ 1272 + if (!status) { 1273 + status = 1274 + dev_get_dmm_mgr(p_proc_object->hdev_obj, 1275 + &dmm_mgr); 1276 + if (dmm_mgr) { 1277 + /* Set dw_ext_end to DMM START u8 1278 + * address */ 1279 + dw_ext_end = 1280 + (dw_ext_end + 1) * DSPWORDSIZE; 1281 + /* DMM memory is from EXT_END */ 1282 + status = dmm_create_tables(dmm_mgr, 1283 + dw_ext_end, 1284 + DMMPOOLSIZE); 1285 + } else { 1286 + status = -EFAULT; 1287 + } 1288 + } 1284 1289 } 1285 1290 } 1286 1291 /* Restore the original argv[0] */ ··· 1352 1319 { 1353 1320 u32 va_align; 1354 1321 u32 pa_align; 1322 + struct dmm_object *dmm_mgr; 1355 1323 u32 size_align; 1356 1324 int status = 0; 1357 1325 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1358 1326 struct dmm_map_object *map_obj; 1327 + u32 tmp_addr = 0; 1359 1328 1360 1329 #ifdef CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK 1361 1330 if ((ul_map_attr & BUFMODE_MASK) != RBUF) { ··· 1382 1347 } 1383 1348 /* Critical section */ 1384 1349 mutex_lock(&proc_lock); 1350 + dmm_get_handle(p_proc_object, &dmm_mgr); 1351 + if (dmm_mgr) 1352 + status = dmm_map_memory(dmm_mgr, va_align, size_align); 1353 + else 1354 + status = -EFAULT; 1385 1355 1386 1356 /* Add mapping to the page tables. */ 1387 1357 if (!status) { 1358 + 1359 + /* Mapped address = MSB of VA | LSB of PA */ 1360 + tmp_addr = (va_align | ((u32) pmpu_addr & (PG_SIZE4K - 1))); 1388 1361 /* mapped memory resource tracking */ 1389 - map_obj = add_mapping_info(pr_ctxt, pa_align, va_align, 1362 + map_obj = add_mapping_info(pr_ctxt, pa_align, tmp_addr, 1390 1363 size_align); 1391 - if (!map_obj) { 1364 + if (!map_obj) 1392 1365 status = -ENOMEM; 1393 - } else { 1394 - va_align = user_to_dsp_map( 1395 - p_proc_object->hbridge_context->dsp_mmu, 1396 - pa_align, va_align, size_align, 1397 - map_obj->pages); 1398 - if (IS_ERR_VALUE(va_align)) 1399 - status = (int)va_align; 1400 - } 1366 + else 1367 + status = (*p_proc_object->intf_fxns->pfn_brd_mem_map) 1368 + (p_proc_object->hbridge_context, pa_align, va_align, 1369 + size_align, ul_map_attr, map_obj->pages); 1401 1370 } 1402 1371 if (!status) { 1403 1372 /* Mapped address = MSB of VA | LSB of PA */ 1404 - map_obj->dsp_addr = (va_align | 1405 - ((u32)pmpu_addr & (PG_SIZE4K - 1))); 1406 - *pp_map_addr = (void *)map_obj->dsp_addr; 1373 + *pp_map_addr = (void *) tmp_addr; 1407 1374 } else { 1408 - remove_mapping_information(pr_ctxt, va_align); 1375 + remove_mapping_information(pr_ctxt, tmp_addr, size_align); 1376 + dmm_un_map_memory(dmm_mgr, va_align, &size_align); 1409 1377 } 1410 1378 mutex_unlock(&proc_lock); 1411 1379 ··· 1497 1459 } 1498 1460 } 1499 1461 func_end: 1462 + return status; 1463 + } 1464 + 1465 + /* 1466 + * ======== proc_reserve_memory ======== 1467 + * Purpose: 1468 + * Reserve a virtually contiguous region of DSP address space. 1469 + */ 1470 + int proc_reserve_memory(void *hprocessor, u32 ul_size, 1471 + void **pp_rsv_addr, 1472 + struct process_context *pr_ctxt) 1473 + { 1474 + struct dmm_object *dmm_mgr; 1475 + int status = 0; 1476 + struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1477 + struct dmm_rsv_object *rsv_obj; 1478 + 1479 + if (!p_proc_object) { 1480 + status = -EFAULT; 1481 + goto func_end; 1482 + } 1483 + 1484 + status = dmm_get_handle(p_proc_object, &dmm_mgr); 1485 + if (!dmm_mgr) { 1486 + status = -EFAULT; 1487 + goto func_end; 1488 + } 1489 + 1490 + status = dmm_reserve_memory(dmm_mgr, ul_size, (u32 *) pp_rsv_addr); 1491 + if (status != 0) 1492 + goto func_end; 1493 + 1494 + /* 1495 + * A successful reserve should be followed by insertion of rsv_obj 1496 + * into dmm_rsv_list, so that reserved memory resource tracking 1497 + * remains uptodate 1498 + */ 1499 + rsv_obj = kmalloc(sizeof(struct dmm_rsv_object), GFP_KERNEL); 1500 + if (rsv_obj) { 1501 + rsv_obj->dsp_reserved_addr = (u32) *pp_rsv_addr; 1502 + spin_lock(&pr_ctxt->dmm_rsv_lock); 1503 + list_add(&rsv_obj->link, &pr_ctxt->dmm_rsv_list); 1504 + spin_unlock(&pr_ctxt->dmm_rsv_lock); 1505 + } 1506 + 1507 + func_end: 1508 + dev_dbg(bridge, "%s: hprocessor: 0x%p ul_size: 0x%x pp_rsv_addr: 0x%p " 1509 + "status 0x%x\n", __func__, hprocessor, 1510 + ul_size, pp_rsv_addr, status); 1500 1511 return status; 1501 1512 } 1502 1513 ··· 1697 1610 { 1698 1611 int status = 0; 1699 1612 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1613 + struct dmm_object *dmm_mgr; 1700 1614 u32 va_align; 1615 + u32 size_align; 1701 1616 1702 1617 va_align = PG_ALIGN_LOW((u32) map_addr, PG_SIZE4K); 1703 1618 if (!p_proc_object) { ··· 1707 1618 goto func_end; 1708 1619 } 1709 1620 1621 + status = dmm_get_handle(hprocessor, &dmm_mgr); 1622 + if (!dmm_mgr) { 1623 + status = -EFAULT; 1624 + goto func_end; 1625 + } 1626 + 1710 1627 /* Critical section */ 1711 1628 mutex_lock(&proc_lock); 1629 + /* 1630 + * Update DMM structures. Get the size to unmap. 1631 + * This function returns error if the VA is not mapped 1632 + */ 1633 + status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align); 1712 1634 /* Remove mapping from the page tables. */ 1713 - status = user_to_dsp_unmap(p_proc_object->hbridge_context->dsp_mmu, 1714 - va_align); 1635 + if (!status) { 1636 + status = (*p_proc_object->intf_fxns->pfn_brd_mem_un_map) 1637 + (p_proc_object->hbridge_context, va_align, size_align); 1638 + } 1715 1639 1716 1640 mutex_unlock(&proc_lock); 1717 1641 if (status) ··· 1735 1633 * from dmm_map_list, so that mapped memory resource tracking 1736 1634 * remains uptodate 1737 1635 */ 1738 - remove_mapping_information(pr_ctxt, (u32) map_addr); 1636 + remove_mapping_information(pr_ctxt, (u32) map_addr, size_align); 1739 1637 1740 1638 func_end: 1741 1639 dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n", 1742 1640 __func__, hprocessor, map_addr, status); 1641 + return status; 1642 + } 1643 + 1644 + /* 1645 + * ======== proc_un_reserve_memory ======== 1646 + * Purpose: 1647 + * Frees a previously reserved region of DSP address space. 1648 + */ 1649 + int proc_un_reserve_memory(void *hprocessor, void *prsv_addr, 1650 + struct process_context *pr_ctxt) 1651 + { 1652 + struct dmm_object *dmm_mgr; 1653 + int status = 0; 1654 + struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1655 + struct dmm_rsv_object *rsv_obj; 1656 + 1657 + if (!p_proc_object) { 1658 + status = -EFAULT; 1659 + goto func_end; 1660 + } 1661 + 1662 + status = dmm_get_handle(p_proc_object, &dmm_mgr); 1663 + if (!dmm_mgr) { 1664 + status = -EFAULT; 1665 + goto func_end; 1666 + } 1667 + 1668 + status = dmm_un_reserve_memory(dmm_mgr, (u32) prsv_addr); 1669 + if (status != 0) 1670 + goto func_end; 1671 + 1672 + /* 1673 + * A successful unreserve should be followed by removal of rsv_obj 1674 + * from dmm_rsv_list, so that reserved memory resource tracking 1675 + * remains uptodate 1676 + */ 1677 + spin_lock(&pr_ctxt->dmm_rsv_lock); 1678 + list_for_each_entry(rsv_obj, &pr_ctxt->dmm_rsv_list, link) { 1679 + if (rsv_obj->dsp_reserved_addr == (u32) prsv_addr) { 1680 + list_del(&rsv_obj->link); 1681 + kfree(rsv_obj); 1682 + break; 1683 + } 1684 + } 1685 + spin_unlock(&pr_ctxt->dmm_rsv_lock); 1686 + 1687 + func_end: 1688 + dev_dbg(bridge, "%s: hprocessor: 0x%p prsv_addr: 0x%p status: 0x%x\n", 1689 + __func__, hprocessor, prsv_addr, status); 1743 1690 return status; 1744 1691 } 1745 1692
+1 -1
drivers/staging/udlfb/udlfb.c
··· 887 887 888 888 struct fb_deferred_io *fbdefio; 889 889 890 - fbdefio = kmalloc(GFP_KERNEL, sizeof(struct fb_deferred_io)); 890 + fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); 891 891 892 892 if (fbdefio) { 893 893 fbdefio->delay = DL_DEFIO_WRITE_DELAY;
+2 -1
drivers/staging/vt6656/main_usb.c
··· 1675 1675 1676 1676 { 1677 1677 char essid[IW_ESSID_MAX_SIZE+1]; 1678 - if (wrq->u.essid.pointer) 1678 + if (wrq->u.essid.pointer) { 1679 1679 rc = iwctl_giwessid(dev, NULL, 1680 1680 &(wrq->u.essid), essid); 1681 1681 if (copy_to_user(wrq->u.essid.pointer, 1682 1682 essid, 1683 1683 wrq->u.essid.length) ) 1684 1684 rc = -EFAULT; 1685 + } 1685 1686 } 1686 1687 break; 1687 1688
-1
drivers/staging/westbridge/astoria/api/src/cyasusb.c
··· 1417 1417 */ 1418 1418 bus_mask = 0; 1419 1419 media_mask = 0; 1420 - media_mask = 0; 1421 1420 for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) { 1422 1421 for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++) { 1423 1422 if (config_p->devices_to_enumerate[bus][device] ==
+3 -3
drivers/staging/wlan-ng/cfg80211.c
··· 139 139 } 140 140 141 141 int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, 142 - u8 key_index, const u8 *mac_addr, 142 + u8 key_index, bool pairwise, const u8 *mac_addr, 143 143 struct key_params *params) 144 144 { 145 145 wlandevice_t *wlandev = dev->ml_priv; ··· 198 198 } 199 199 200 200 int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, 201 - u8 key_index, const u8 *mac_addr, void *cookie, 201 + u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, 202 202 void (*callback)(void *cookie, struct key_params*)) 203 203 { 204 204 wlandevice_t *wlandev = dev->ml_priv; ··· 227 227 } 228 228 229 229 int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, 230 - u8 key_index, const u8 *mac_addr) 230 + u8 key_index, bool pairwise, const u8 *mac_addr) 231 231 { 232 232 wlandevice_t *wlandev = dev->ml_priv; 233 233 u32 did;
+1 -1
drivers/staging/wlan-ng/p80211netdev.c
··· 522 522 if (copy_to_user(useraddr, &edata, sizeof(edata))) 523 523 return -EFAULT; 524 524 return 0; 525 - } 526 525 #endif 526 + } 527 527 528 528 return -EOPNOTSUPP; 529 529 }